File manager - Edit - /home/verseaumee/maze/wp-content/plugins/woocommerce-paypal-payments/modules/ppcp-button/src/ButtonModule.php
Back
<?php /** * The button module. * * @package WooCommerce\PayPalCommerce\Button */ declare (strict_types=1); namespace WooCommerce\PayPalCommerce\Button; use WC_Order; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Factory\ReturnUrlFactory; use WooCommerce\PayPalCommerce\Button\Assets\SmartButtonInterface; use WooCommerce\PayPalCommerce\Button\Endpoint\ApproveOrderEndpoint; use WooCommerce\PayPalCommerce\Button\Endpoint\ApproveSubscriptionEndpoint; use WooCommerce\PayPalCommerce\Button\Endpoint\CartScriptParamsEndpoint; use WooCommerce\PayPalCommerce\Button\Endpoint\ChangeCartEndpoint; use WooCommerce\PayPalCommerce\Button\Endpoint\CreateOrderEndpoint; use WooCommerce\PayPalCommerce\Button\Endpoint\DataClientIdEndpoint; use WooCommerce\PayPalCommerce\Button\Endpoint\GetOrderEndpoint; use WooCommerce\PayPalCommerce\Button\Endpoint\SaveCheckoutFormEndpoint; use WooCommerce\PayPalCommerce\Button\Endpoint\SimulateCartEndpoint; use WooCommerce\PayPalCommerce\Button\Endpoint\ValidateCheckoutEndpoint; use WooCommerce\PayPalCommerce\Button\Helper\EarlyOrderHandler; use WooCommerce\PayPalCommerce\Button\Helper\WooCommerceOrderCreator; use WooCommerce\PayPalCommerce\Button\Session\CartDataTransientStorage; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; /** * Class ButtonModule */ class ButtonModule implements ServiceModule, ExecutableModule { use ModuleClassNameIdTrait; /** * {@inheritDoc} */ public function services(): array { return require __DIR__ . '/../services.php'; } /** * {@inheritDoc} */ public function run(ContainerInterface $c): bool { add_action('wp', static function () use ($c) { if (is_admin()) { return; } $smart_button = $c->get('button.smart-button'); /** * The Smart Button. * * @var SmartButtonInterface $smart_button */ $smart_button->render_wrapper(); }); add_action('wp_enqueue_scripts', static function () use ($c) { $smart_button = $c->get('button.smart-button'); assert($smart_button instanceof SmartButtonInterface); if ($smart_button->should_load_ppcp_script()) { $smart_button->enqueue(); } }); add_filter('woocommerce_create_order', static function ($value) use ($c) { $early_order_handler = $c->get('button.helper.early-order-handler'); if (!is_null($value)) { $value = (int) $value; } /** * The Early Order Handler * * @var EarlyOrderHandler $early_order_handler */ return $early_order_handler->determine_wc_order_id($value); }); $this->register_ajax_endpoints($c); $this->register_appswitch_crossbrowser_handler($c); return \true; } /** * Registers the Ajax Endpoints. * * @param ContainerInterface $container The Container. */ private function register_ajax_endpoints(ContainerInterface $container): void { add_action('wc_ajax_' . DataClientIdEndpoint::ENDPOINT, static function () use ($container) { $endpoint = $container->get('button.endpoint.data-client-id'); /** * The Data Client ID Endpoint. * * @var DataClientIdEndpoint $endpoint */ $endpoint->handle_request(); }); add_action('wc_ajax_' . SimulateCartEndpoint::ENDPOINT, static function () use ($container) { $endpoint = $container->get('button.endpoint.simulate-cart'); /** * The Simulate Cart Endpoint. * * @var SimulateCartEndpoint $endpoint */ $endpoint->handle_request(); }); add_action('wc_ajax_' . ChangeCartEndpoint::ENDPOINT, static function () use ($container) { $endpoint = $container->get('button.endpoint.change-cart'); /** * The Change Cart Endpoint. * * @var ChangeCartEndpoint $endpoint */ $endpoint->handle_request(); }); add_action('wc_ajax_' . ApproveOrderEndpoint::ENDPOINT, static function () use ($container) { $endpoint = $container->get('button.endpoint.approve-order'); /** * The Approve Order Endpoint. * * @var ApproveOrderEndpoint $endpoint */ $endpoint->handle_request(); }); add_action('wc_ajax_' . ApproveSubscriptionEndpoint::ENDPOINT, static function () use ($container) { $endpoint = $container->get('button.endpoint.approve-subscription'); assert($endpoint instanceof ApproveSubscriptionEndpoint); $endpoint->handle_request(); }); add_action('wc_ajax_' . CreateOrderEndpoint::ENDPOINT, static function () use ($container) { $endpoint = $container->get('button.endpoint.create-order'); /** * The Create Order Endpoint. * * @var CreateOrderEndpoint $endpoint */ $endpoint->handle_request(); }); add_action('wc_ajax_' . SaveCheckoutFormEndpoint::ENDPOINT, static function () use ($container) { $endpoint = $container->get('button.endpoint.save-checkout-form'); assert($endpoint instanceof SaveCheckoutFormEndpoint); $endpoint->handle_request(); }); add_action('wc_ajax_' . ValidateCheckoutEndpoint::ENDPOINT, static function () use ($container) { $endpoint = $container->get('button.endpoint.validate-checkout'); assert($endpoint instanceof ValidateCheckoutEndpoint); $endpoint->handle_request(); }); add_action('wc_ajax_' . CartScriptParamsEndpoint::ENDPOINT, static function () use ($container) { $endpoint = $container->get('button.endpoint.cart-script-params'); assert($endpoint instanceof CartScriptParamsEndpoint); $endpoint->handle_request(); }); add_action('wc_ajax_' . GetOrderEndpoint::ENDPOINT, static function () use ($container) { $endpoint = $container->get('button.endpoint.get-order'); assert($endpoint instanceof GetOrderEndpoint); $endpoint->handle_request(); }); } private static function is_cross_browser_order(WC_Order $wc_order): bool { return wc_string_to_bool($wc_order->get_meta(PayPalGateway::CROSS_BROWSER_APPSWITCH_META_KEY)); } private function register_appswitch_crossbrowser_handler(ContainerInterface $container): void { if (!$container->get('wcgateway.appswitch-enabled')) { return; } // After returning from cross-browser AppSwitch (started in non-default browser, then redirected to the default one) // we need to retrieve the saved cart and PayPal order, create a WC order and redirect to Pay for order. add_action('wp', static function () use ($container) { // phpcs:ignore WordPress.Security.NonceVerification if (!isset($_GET[ReturnUrlFactory::PCP_QUERY_ARG])) { return; } if (is_checkout_pay_page()) { return; } // phpcs:ignore WordPress.Security.NonceVerification if (!isset($_GET[CreateOrderEndpoint::RETURN_URL_CART_QUERY_ARG])) { return; } // phpcs:ignore WordPress.Security.NonceVerification $cart_key = wc_clean(wp_unslash($_GET[CreateOrderEndpoint::RETURN_URL_CART_QUERY_ARG])); if (!is_string($cart_key)) { return; } $card_data_storage = $container->get('button.session.storage.card-data.transient'); assert($card_data_storage instanceof CartDataTransientStorage); $cart_data = $card_data_storage->get($cart_key); if (!$cart_data) { return; } // Delete the data to avoid accidentally triggering it again, duplicating orders etc. $card_data_storage->remove($cart_data); if (!WC()->cart) { return; } // The current cart is the same, so we don't need to do anything (probably not cross-browser). if (WC()->cart->get_cart_hash() === $cart_data->cart_hash()) { return; } $paypal_order_id = $cart_data->paypal_order_id(); if (empty($paypal_order_id)) { return; } $order_endpoint = $container->get('api.endpoint.order'); assert($order_endpoint instanceof OrderEndpoint); $paypal_order = $order_endpoint->order($paypal_order_id); $wc_order_creator = $container->get('button.helper.wc-order-creator'); assert($wc_order_creator instanceof WooCommerceOrderCreator); $wc_order = $wc_order_creator->create_from_paypal_order($paypal_order, $cart_data); $wc_order->update_meta_data(PayPalGateway::CROSS_BROWSER_APPSWITCH_META_KEY, wc_bool_to_string(\true)); $wc_order->save(); // Redirect via JS because we need to keep the # parameters which are not accessible on the server side. // phpcs:ignore WordPress.Security.EscapeOutput echo "<script>location.href = '" . $wc_order->get_checkout_payment_url() . "' + location.hash;</script>"; }); /** * Restore PayPal as the chosen payment method when returning from an App Switch flow. * * Context: * -------- * When Fastlane (AXO) is active, AxoModule forces the chosen payment method to * AxoGateway on every checkout page load. This causes a problem when the customer * initiated checkout with PayPal and was redirected to the PayPal app * (App Switch): after resuming, the checkout would incorrectly show AxoGateway, * leading to validation errors and failed payments. * * Solution: * --------- * This handler runs after the AxoModule one (priority 20). It checks for the * PayPal return URL query arguments that indicate an App Switch resume, and if * present, forces the chosen method back to PayPalGateway. This ensures the * resumed PayPal flow continues as expected. */ add_action('template_redirect', function () { // phpcs:ignore WordPress.Security.NonceVerification if (!isset($_GET[ReturnUrlFactory::PCP_QUERY_ARG])) { return; } if (is_checkout_pay_page()) { return; } // phpcs:ignore WordPress.Security.NonceVerification if (!isset($_GET[CreateOrderEndpoint::RETURN_URL_CART_QUERY_ARG])) { return; } WC()->session->set('chosen_payment_method', PayPalGateway::ID); }, 20); /** * By default, WC asks to log in when opening a non-guest Pay for order page as a guest, * so we disable this for cross-browser AppSwitch. * * @param array<string, bool> $allcaps Array of key/value pairs where keys represent a capability name * and boolean values represent whether the user has that capability. * @param string[] $caps Required primitive capabilities for the requested capability. * @param array $args { * Arguments that accompany the requested capability check. * * @type string $0 Requested capability. * @type int $1 Concerned user ID. * @type mixed ...$2 Optional second and further parameters, typically object ID. * } * * @returns array<string, bool> * * @psalm-suppress MissingClosureParamType */ add_filter('user_has_cap', static function ($allcaps, $cap, $args) { if (!in_array('pay_for_order', $cap, \true)) { return $allcaps; } $wc_order_id = $args[2] ?? null; if (!is_int($wc_order_id)) { return $allcaps; } $wc_order = wc_get_order($wc_order_id); if (!$wc_order instanceof WC_Order) { return $allcaps; } if (!self::is_cross_browser_order($wc_order)) { return $allcaps; } return array_merge($allcaps, array('pay_for_order' => \true)); }, 10, 3); /** * By default, WC asks to log in when opening a non-guest order received page as a guest, * so we disable this for cross-browser AppSwitch. * * @param bool $result * * @psalm-suppress MissingClosureParamType */ add_filter('woocommerce_order_received_verify_known_shoppers', static function ($result) { if (!is_order_received_page()) { return $result; } $wc_order = null; // phpcs:disable WordPress.Security.NonceVerification if (isset($_GET['key']) && is_string($_GET['key'])) { $wc_order_key = sanitize_text_field(wp_unslash($_GET['key'])); // phpcs:enable WordPress.Security.NonceVerification $wc_order_id = wc_get_order_id_by_order_key($wc_order_key); $wc_order = wc_get_order($wc_order_id); } if (!$wc_order instanceof WC_Order) { return $result; } if (!self::is_cross_browser_order($wc_order)) { return $result; } return \false; }); /** * Disabling the email prompt on Pay for order page for guests. * Should not affect anything in most cases because it is skipped for just created orders (< 10 min). * * @param bool $email_verification_required * @param WC_Order $order * * @returns bool * * @psalm-suppress MissingClosureParamType */ add_filter('woocommerce_order_email_verification_required', static function ($email_verification_required, $order) { if (!$order instanceof WC_Order) { return $email_verification_required; } if (!self::is_cross_browser_order($order)) { return $email_verification_required; } return \false; }, 10, 2); } }
| ver. 1.4 |
Github
|
.
| PHP 8.5.7 | Generation time: 0 |
proxy
|
phpinfo
|
Settings