/home/websdxuk/dannymattinezllc.com/wp-content/plugins/elementor-pro/modules/payments/module.php
<?php
namespace ElementorPro\Modules\Payments;

use Elementor\Settings;
use ElementorPro\Base\Module_Base;
use ElementorPro\Core\Utils;
use ElementorPro\Plugin;
use ElementorPro\Modules\Payments\Classes\Stripe_Handler;
use ElementorPro\License\API;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}

class Module extends Module_Base {

	const STRIPE_CHECKOUT_URL_EXT = 'checkout/sessions';
	const STRIPE_TEST_SECRET_KEY = 'pro_stripe_test_secret_key';
	const STRIPE_LIVE_SECRET_KEY = 'pro_stripe_live_secret_key';
	const STRIPE_TAX_ENDPOINT_URL = 'tax_rates';
	const WP_DASH_STRIPE_API_KEYS_LINK = 'https://go.elementor.com/wp-dash-stripe-api-keys/';
	const STRIPE_TRANSACTIONS_LINK = 'https://go.elementor.com/stripe-transaction/';
	const STRIPE_LICENCE_FEATURE_NAME = 'stripe-button';

	const WIDGET_NAME_CLASS_NAME_MAP = [
		'paypal-button' => 'Paypal_Button',
		self::STRIPE_LICENCE_FEATURE_NAME => 'Stripe_Button',
	];

	public $secret_key = '';
	private $stripe_handler;

	public function get_widgets() {
		return API::filter_active_features( static::WIDGET_NAME_CLASS_NAME_MAP );
	}

	/**
	 * Error handler
	 *
	 * @since 3.7.0
	 *
	 * @param integer $status_code
	 * @param string $error_massage
	 */
	protected function error_handler( $status_code, $error_massage ) {
		$resp['response']['code'] = $status_code;
		$resp['body'] = wp_json_encode(
			[ 'error' => [ 'message' => $error_massage ] ],
			JSON_PRETTY_PRINT
		);

		wp_send_json( $resp );
	}

	public function get_name() {
		return 'payments';
	}

	/**
	 * Reads secret test key from wp_options table
	 *
	 * @since 3.7.0
	 *
	 * @return string
	 */
	public static function get_global_stripe_test_secret_key() {
		return get_option( 'elementor_' . self::STRIPE_TEST_SECRET_KEY, '' );
	}

	/**
	 * Reads secret live key from wp_options table
	 *
	 * @since 3.7.0
	 *
	 * @return string
	 */
	public static function get_global_stripe_live_secret_key() {
		return get_option( 'elementor_' . self::STRIPE_LIVE_SECRET_KEY, '' );
	}

	/**
	 * Integrations page secret key validations' callback function
	 *
	 * @since 3.7.0
	 *
	 * @return void
	 */
	public function ajax_validate_secret_key() {
		// phpcs:ignore WordPress.Security.NonceVerification.Missing
		$action = Utils::_unstable_get_super_global_value( $_POST, 'action' );
		$nonce_action = ( ! strpos( $action, 'test' ) ? self::STRIPE_LIVE_SECRET_KEY : self::STRIPE_TEST_SECRET_KEY );

		// phpcs:ignore WordPress.Security.NonceVerification.Missing
		$nonce = Utils::_unstable_get_super_global_value( $_POST, '_nonce' );
		if ( ! $nonce || ! wp_verify_nonce( $nonce, $nonce_action ) ) {
			$this->error_handler( 403, esc_html__( 'Something went wrong, please refresh the page.', 'elementor-pro' ) );
			die();
		}

		if ( ! Utils::_unstable_get_super_global_value( $_POST, 'secret_key' ) ) {
			wp_send_json_error();
		} else {
			$this->secret_key = Utils::_unstable_get_super_global_value( $_POST, 'secret_key' );
		}

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( 'Permission denied' );
		}

		$stripe_handler = new Stripe_handler();
		$response = $stripe_handler->get( $this->secret_key, self::STRIPE_TAX_ENDPOINT_URL, [ 'limit' => 0 ] );
		$code = $response['response']['code'];

		if ( 200 !== $code ) {
			wp_send_json_error();
		} else {
			wp_send_json_success();
		}
	}

	/**
	 * Ajax callback
	 *
	 * Returns a list of tax rates
	 *
	 * @since 3.7.0
	 *
	 * @return array
	 */
	public function register_ajax_actions( $ajax ) {
		return $ajax->register_ajax_action( 'pro_get_stripe_tax_rates', [ $this, 'get_stripe_tax_rates' ] );
	}

	/**
	 * returns a list of tax rates
	 *
	 * if tax rates are set in stripe admin dashboard
	 * from here the tax rates array is implemented in
	 * tax rates select control
	 *
	 * @param array $data
	 *
	 * @return array - returns to js ajax function.
	 *
	 * @throws \Exception
	 * @since 3.7.0
	 *
	 */
	public function get_stripe_tax_rates( array $data ) {
		Utils::_unstable_get_document_for_edit( $data['editor_post_id'] );

		$tax_rates_lists = [];
		$tax_rates_lists['live_api_key'] = $this->get_tax_rates( $this->get_global_stripe_live_secret_key() );
		$tax_rates_lists['test_api_key'] = $this->get_tax_rates( $this->get_global_stripe_test_secret_key() );
		return $tax_rates_lists;
	}

	/**
	 * Get ajax tax rates from API
	 *
	 * Read all ajax tax rates from stripes API and
	 *
	 * @since 3.7.0
	 *
	 * @param string $secret_key
	 *
	 * @return array - returns to js ajax function.
	 *
	 */
	protected function tax_rates_result_funnel( $secret_key ) {
		$response = $this->stripe_handler->get( $secret_key, self::STRIPE_TAX_ENDPOINT_URL, [ 'active' => 'true' ] );

		// If there is no internet connection or no active tax rates in stripe
		if ( ! is_wp_error( $response ) ) {
			$decoded_response = json_decode( $response['body'], true );

			// If there is no API key or a wrong one in integrations page
			if ( isset( $decoded_response['error'] ) || 0 === count( $decoded_response['data'] ) ) {
				$data = [];
			} else {
				$data = $decoded_response['data'];
			}
		} else {
			$data = [];
		}

		return $data;
	}

	/**
	 * Gets and Organizes all tax rates in a
	 * list suitable for the select control
	 *
	 * @since 3.7.0
	 *
	 * @param string $secret_key
	 *
	 * @return array - returns to js ajax function.
	 *
	 */
	protected function get_tax_rates( $secret_key ) {
		$data = $this->tax_rates_result_funnel( $secret_key );
		return $this->tax_rates_options( $data );
	}

	/**
	 * Create options array for tax_rates controls
	 *
	 * This function can return two scenarios:
	 * 1. Show tax rates options.
	 * 2. There are no active tax rates or the user is working on a local environment.
	 *
	 * @since 3.7.0
	 *
	 * @param array $data the returned value of get_data_from_api() function
	 *
	 * @return array $tax_rates_options placed as the control options
	 */
	private function tax_rates_options( $data = [] ) {
		$tax_rates_options = [];
		if ( ! empty( $data ) ) {
			foreach ( $data as $k => $v ) {
				$is_inclusive = ( true === $v['inclusive'] ? 'inclusive' : 'exclusive' );
				$joint_tax_data = wp_json_encode( [ $v['id'], $is_inclusive ] );
				$display_name = $v['description'] ? $v['display_name'] . ' - ' . $v['description'] : $v['display_name'];
				$tax_rates_options[ $joint_tax_data ] = $display_name;
			}
			// Add 'None' value as the first element in $test_tax_rates_options array.
			return array_merge( [ '' => esc_html__( 'None', 'elementor-pro' ) ], $tax_rates_options );

		} else {
			$tax_rates_options = [ '' => esc_html__( 'None', 'elementor-pro' ) ];

		}
		return $tax_rates_options;
	}

	/**
	 * Create options array for tax_rates controls
	 *
	 * Zero decimal currencies by stripe https://stripe.com/docs/currencies#zero-decimal
	 * this option is zero decimal what means that only complete numbers bill pass to stripe.
	 * for example 555.55 will return product_price of 555.
	 *
	 * @since 3.7.0
	 *
	 * @param $currency string
	 * @param $product_price
	 *
	 * @return false|float $tax_rates_options placed as the control options
	 */
	public function currency_adaptation( $currency, $product_price ) {
		$zero_decimal = [ 'BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'UGX', 'VND', 'VUV', 'XAF', 'XOF', 'XPF' ];
		if ( in_array( $currency, $zero_decimal ) ) {
			// There is no need to multiply $product_price by 100
			return floor( $product_price );
		} else {
			return floor( $product_price * 100 );
		}
	}

	/**
	 * Secret key conditional function
	 *
	 * @since 3.7.0
	 *
	 * @param string $test_mode
	 *
	 * @return void
	 */
	public function set_secret_key_by_environment_state( $test_mode = 'no' ) {
		if ( ! $this->secret_key ) {
			if ( 'yes' === $test_mode ) {
				$this->secret_key = $this->get_global_stripe_test_secret_key();
			} else {
				$this->secret_key = $this->get_global_stripe_live_secret_key();
			}
		}
	}

	/**
	 * Ajax callback function - API stripe call .
	 *
	 * get stripe user data on widget load
	 * sends the product data and returns the product page checkout url.
	 *
	 * @since 3.7.0
	 */
	public function submit_stripe_form() {
		// phpcs:ignore WordPress.Security.NonceVerification.Missing
		$data = Utils::_unstable_get_super_global_value( $_POST, 'data' );
		if ( ! isset( $data['nonce'] ) || ! wp_verify_nonce( $data['nonce'], 'stripe_form_submit' ) ) {
			$this->error_handler( 403, esc_html__( 'Something went wrong, please refresh the page.', 'elementor-pro' ) );
			die();
		}
		$args = [];
		$widget_id = $data['widgetId'] ?? null;
		$args['page_url'] = $data['pageUrl'] ?? null;

		Plugin::elementor()->db->switch_to_post( $data['postId'] );
		$document = Plugin::elementor()->documents->get( $data['postId'] );

		// Retrieve data from widget document
		if ( $document ) {
			$widget = \ElementorPro\Modules\Forms\Module::find_element_recursive( $document->get_elements_data(), $widget_id );
			$widget_instance = Plugin::elementor()->elements_manager->create_element_instance( $widget );
			$widget_settings = $widget_instance->get_settings_for_display();

			$args['product_name'] = $widget_settings['product_name'] ? $widget_settings['product_name'] : 'Product';
			$product_price = $widget_settings['stripe_product_price'] ? $widget_settings['stripe_product_price'] : null;
			$args['currency'] = $widget['settings']['stripe_currency'] ? $widget['settings']['stripe_currency'] : 'USD';
			$args['quantity'] = $widget['settings']['stripe_quantity'] ? $widget['settings']['stripe_quantity'] : 1;
			$args['success_url'] = ( empty( $widget_settings['redirect_after_success']['url'] ) ? $args['page_url'] : $widget_settings['redirect_after_success']['url'] );
			$args['shipping_amount'] = $widget_settings['shipping_amount'] ? $widget_settings['shipping_amount'] * 100 : '';
			$this->stripe_test_mode = $widget['settings']['sandbox_mode'] ? $widget['settings']['sandbox_mode'] : 'no';
			$args['test_mode'] = $this->stripe_test_mode;
			$args['tax_rates'] = 'yes' === $args['test_mode'] ? $widget['settings']['stripe_test_env_tax_rates_list'] : $widget['settings']['stripe_live_env_tax_rates_list'];
		}

		$args['unit_amount'] = $this->currency_adaptation( $args['currency'], $product_price );

		$this->set_secret_key_by_environment_state( $args['test_mode'] );

		if ( ! empty( $this->secret_key ) ) {
			$headers = [ 'Authorization' => 'Bearer ' . $this->secret_key ];
			$body = $this->build_body_for_post_request( $args );
			$this->execute_post_request_to_stripe_api( $headers, $body );
		} else {
			$this->error_handler( 401, esc_html__( 'You have not entered a valid secret key for this environment, Please add a valid secret key', 'elementor-pro' ) );
		}
	}

	/**
	 * Builds the body for the API POST request.
	 *
	 * @since 3.7.0
	 *
	 * @param $args
	 *
	 * @return array
	 */
	public function build_body_for_post_request( $args ) {
		$body = [
			'cancel_url' => $args['page_url'],
			'payment_method_types' => [ 'card' ],
			'success_url' => $args['success_url'],
			'mode' => 'payment',
			'line_items[0][quantity]' => $args['quantity'],
			'line_items[0][price_data][currency]' => $args['currency'],
			'line_items[0][price_data][product_data][name]' => $args['product_name'],
			'line_items[0][price_data][unit_amount]' => $args['unit_amount'],
		];

		if ( $args['shipping_amount'] ) {
			$body['shipping_options'][0]['shipping_rate_data']['type'] = 'fixed_amount';
			$body['shipping_options'][0]['shipping_rate_data']['fixed_amount']['amount'] = $args['shipping_amount'];
			$body['shipping_options'][0]['shipping_rate_data']['fixed_amount']['currency'] = $args['currency'];
			$body['shipping_options'][0]['shipping_rate_data']['display_name'] = esc_html__( 'shipping fee', 'elementor-pro' );
		}

		if ( isset( $args['tax_rates'] ) ) {
			$tax_rate = json_decode( $args['tax_rates'] );
			$tax_id = [ $tax_rate[0] ];
			$tax_behavior = $tax_rate[1];

			if ( ! empty( $tax_behavior ) && ! empty( $tax_id ) ) {
				$body['line_items'][0]['price_data']['tax_behavior'] = $tax_behavior;
				$body['line_items'][0]['tax_rates'] = $tax_id;
			}
		}

		return $body;
	}

	/**
	 * API call handler
	 *
	 * @since 3.7.0
	 *
	 * @param $headers
	 * @param $body
	 *
	 * @return void
	 */
	public function execute_post_request_to_stripe_api( $headers, $body ) {
		$response = $this->stripe_handler->post( $headers, $body, self::STRIPE_CHECKOUT_URL_EXT );
		wp_send_json( $response );
	}

	/**
	 * Add secret_keys to Elementor integrations section
	 *
	 * @since 3.7.0
	 *
	 * @param Settings $settings
	 */
	public function register_admin_fields( Settings $settings ) {
		$settings->add_section( Settings::TAB_INTEGRATIONS, 'stripe_api_keys', [
			'callback' => function () {
				echo '<hr><h2 id="stripe-btn-integration">' . esc_html__( 'Stripe', 'elementor-pro' ) . '</h2>';
				echo '<p>' . esc_html__( 'Insert the API keys provided in the stripe admin dashboard to start collecting payments on your website using Stripe.', 'elementor-pro' ) . '<br />';
				echo esc_html__( 'These keys will serve as your default API key for all stripe implementations on your site.', 'elementor-pro' ) . '</p>';
			},
			'fields' => [
				self::STRIPE_TEST_SECRET_KEY => [
					'label' => esc_html__( 'Test Secret key', 'elementor-pro' ),
					'field_args' => [
						'type' => 'text',
						'desc' => sprintf(
							/* translators: 1: Link to stripe api key explanation, 2: Link closing tag. */
							esc_html__( 'Enter your test secret key %1$slink%2$s.', 'elementor-pro' ),
							'<a href=" ' . self::WP_DASH_STRIPE_API_KEYS_LINK . ' " target="_blank">',
							'</a>'
						),
					],
				],
				'validate_stripe_api_test_secret_key_button' => [
					'field_args' => [
						'type' => 'raw_html',
						'html' => sprintf( '<button data-action="%s" data-nonce="%s" class="button elementor-button-spinner" id="elementor_pro_stripe_test_secret_key_button">%s</button>', self::STRIPE_TEST_SECRET_KEY . '_validate', wp_create_nonce( self::STRIPE_TEST_SECRET_KEY ), esc_html__( 'Validate Test API Key', 'elementor-pro' ) ),
					],
				],
				self::STRIPE_LIVE_SECRET_KEY => [
					'label' => esc_html__( 'Live Secret key', 'elementor-pro' ),
					'field_args' => [
						'type' => 'text',
						'desc' => sprintf(
							/* translators: 1: Link to stripe api key explanation, 2: Link closing tag. */
							esc_html__( 'Enter your Live secret key %1$slink%2$s.', 'elementor-pro' ),
							'<a href=" ' . self::WP_DASH_STRIPE_API_KEYS_LINK . ' " target="_blank">',
							'</a>'
						),
					],
				],
				'validate_stripe_api_live_secret_key_button' => [
					'field_args' => [
						'type' => 'raw_html',
						'html' => sprintf( '<button data-action="%s" data-nonce="%s" class="button elementor-button-spinner" id="elementor_pro_stripe_live_secret_key_button">%s</button>', self::STRIPE_TEST_SECRET_KEY . '_validate', wp_create_nonce( self::STRIPE_TEST_SECRET_KEY ), esc_html__( 'Validate Live API Key', 'elementor-pro' ) ),
					],
				],
				'stripe_legal_disclaimer' => [
					'field_args' => [
						'type' => 'raw_html',
						'html' => sprintf(
							/* translators: %s: <br />. */
							esc_html__( 'Please note: The Stripe name and logos are trademarks or service marks of Stripe, Inc. or its affiliates in the U.S. and other countries. %s Other names may be trademarks of their respective owners.', 'elementor-pro' ),
							'<br />'
						),
					],
				],
			],
		] );
	}

	/**
	 * Get the base URL for assets.
	 *
	 * @return string
	 */
	public function get_assets_base_url(): string {
		return ELEMENTOR_PRO_URL;
	}

	public function __construct() {
		parent::__construct();

		$this->stripe_handler = new Stripe_Handler();

		add_action( 'wp_ajax_submit_stripe_form', [ $this, 'submit_stripe_form' ] );
		add_action( 'wp_ajax_nopriv_submit_stripe_form', [ $this, 'submit_stripe_form' ] );
		add_action( 'elementor/ajax/register_actions', [ $this, 'register_ajax_actions' ] );

		if ( current_user_can( 'administrator' ) && API::is_licence_has_feature( static::STRIPE_LICENCE_FEATURE_NAME, API::BC_VALIDATION_CALLBACK ) ) {
			add_action( 'elementor/admin/after_create_settings/' . Settings::PAGE_ID, [ $this, 'register_admin_fields' ], 999 );
		}
		add_action( 'wp_ajax_' . self::STRIPE_TEST_SECRET_KEY . '_validate', [ $this, 'ajax_validate_secret_key' ] );
		add_action( 'wp_ajax_' . self::STRIPE_LIVE_SECRET_KEY . '_validate', [ $this, 'ajax_validate_secret_key' ] );
	}
}
My Blog – My WordPress Blog

Navigating Your Journey, Relocating Your World

Elevate Your Move, Experience Seamless Relocations.

A leading innovator in orchestrating top-notch Moving Solutions and Ensuring Seamless Relocations across the USA.

Booked Your Movement

Goods Packing Service

Goods Unpacking Service

Moving Goods Service

Goods Unloading Service

Service

Choose Your Movement Service

Start From 10 USD/Hour

Complete Goods Packing Service for House

All aspects of your software assets including purchasing, deployment & maintenance.

Start From 15 USD/Hour

Complete Goods Unpacking Service for House

All aspects of your software assets including purchasing, deployment & maintenance.

Start From 100 USD/Month

Complete Storage Solution For Your Goods

All aspects of your software assets including purchasing, deployment & maintenance.

Start From 100 USD/Month

Complete Unloading Solution For Your Goods

All aspects of your software assets including purchasing, deployment & maintenance.

Get 10% Discount For Every First of Order. 

View All Our Service Here

WHY CHOOSE US

Explore Why Our Company is Preferable

At [Your Company Name], we pride ourselves on delivering exceptional value, unparalleled service, and innovative solutions tailored to meet your needs.

No Hidden Price

Free Unloading

Clean No Trash

Warehouse

Fast Truck

About Us

Swift Your Transitions With Unmatched Service

At [Your Company Name], we are more than just a business—we are a team of passionate professionals dedicated to delivering excellence. With [X] years of experience in [your industry], we’ve built a reputation for [key strengths, e.g., innovation, reliability, customer-centric solutions].

Thinking insights, verified driven research, and metrics data help you make the right decisions!

Achievments

Moving You Forward By Moving with Care

At [Your Company Name], we take pride in our milestones and the impact we’ve made. Our journey is marked by dedication, innovation, and a relentless pursuit of excellence. Here’s a glimpse of what we’ve accomplished:

Every achievement reflects our commitment to excellence and the trust our clients and partners place in us. We’re not just celebrating the past—we’re building an even brighter future.

0 +

Clients

0 +

Miles

0 +

Movers

Study Case

Learn Our Successfull Study Cases

Urban, Relocations

From City to Suburbs: A Smooth Urban Relocation

Corporate, Precision

Corporate Precision: Streamlining Office Moves

Senior, Transitions

Senior Transitions: Compassionate Moves for Aging Loved Onesz

Cross, Country

Cross-Country Adventure: A Transcontinental Move

Booked Form

Don't Let Your Back Hurt, Let Us Move Your Things!

Our easy-to-use booking form ensures a seamless experience, allowing you to choose your preferred date, time, and options without any hassle.

Why book with us?
✓ Instant Confirmation – Receive immediate booking details via email/SMS.
✓ Flexible Scheduling – Pick a slot that fits your schedule.
✓ 100% Secure – Your information is safe with us.

Booked Your Movement

Booked Your Movement