From c1e84f4be519a224b5788ff8e9a6ac04051adae4 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Wed, 18 Oct 2023 19:22:09 +0400 Subject: [PATCH 01/22] disable tracking if payment is not captured --- .../src/TrackingAvailabilityTrait.php | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/modules/ppcp-order-tracking/src/TrackingAvailabilityTrait.php b/modules/ppcp-order-tracking/src/TrackingAvailabilityTrait.php index d3bde378c..b149259a3 100644 --- a/modules/ppcp-order-tracking/src/TrackingAvailabilityTrait.php +++ b/modules/ppcp-order-tracking/src/TrackingAvailabilityTrait.php @@ -9,25 +9,40 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\OrderTracking; +use WC_Order; use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; -use WooCommerce\PayPalCommerce\Compat\AdminContextTrait; +use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; +use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor; trait TrackingAvailabilityTrait { - use AdminContextTrait; - /** - * Checks if tracking is enabled. + * Checks if tracking should be enabled for current post. * * @param Bearer $bearer The Bearer. * @return bool */ protected function is_tracking_enabled( Bearer $bearer ): bool { + $post_id = (int) wc_clean( wp_unslash( $_GET['id'] ?? $_GET['post'] ?? '' ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended + if ( ! $post_id ) { + return false; + } + + $order = wc_get_order( $post_id ); + if ( ! is_a( $order, WC_Order::class ) ) { + return false; + } + + $captured = $order->get_meta( AuthorizedPaymentsProcessor::CAPTURED_META_KEY ); + $is_captured = empty( $captured ) || wc_string_to_bool( $captured ); + $is_paypal_order_edit_page = $order->get_meta( PayPalGateway::ORDER_ID_META_KEY ) && ! empty( $order->get_transaction_id() ); + try { $token = $bearer->bearer(); - return $token->is_tracking_available() - && $this->is_paypal_order_edit_page() + return $is_paypal_order_edit_page + && $is_captured + && $token->is_tracking_available() && apply_filters( 'woocommerce_paypal_payments_shipment_tracking_enabled', true ); } catch ( RuntimeException $exception ) { return false; From ddc50e98404584ad1ec49d587a4b13c8cb357b4f Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Wed, 18 Oct 2023 16:25:35 +0100 Subject: [PATCH 02/22] Fix ApplePay setting values with invalid types --- modules/ppcp-applepay/src/Assets/ApplePayDataObjectHttp.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/ppcp-applepay/src/Assets/ApplePayDataObjectHttp.php b/modules/ppcp-applepay/src/Assets/ApplePayDataObjectHttp.php index b14675f16..7b93ab088 100644 --- a/modules/ppcp-applepay/src/Assets/ApplePayDataObjectHttp.php +++ b/modules/ppcp-applepay/src/Assets/ApplePayDataObjectHttp.php @@ -300,6 +300,9 @@ class ApplePayDataObjectHttp { */ protected function assign_data_object_values( array $data ): void { foreach ( $data as $key => $value ) { + if ( null === $value ) { + continue; + } if ( $key === 'woocommerce-process-checkout-nonce' ) { $key = 'nonce'; } From 92422a40eb38ee2c7331c8a69d81c6efa8c5b995 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Wed, 18 Oct 2023 16:48:24 +0100 Subject: [PATCH 03/22] Fix lint --- modules/ppcp-applepay/src/Assets/ApplePayButton.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ppcp-applepay/src/Assets/ApplePayButton.php b/modules/ppcp-applepay/src/Assets/ApplePayButton.php index bbac0fe13..a4ff3ca67 100644 --- a/modules/ppcp-applepay/src/Assets/ApplePayButton.php +++ b/modules/ppcp-applepay/src/Assets/ApplePayButton.php @@ -422,7 +422,7 @@ class ApplePayButton implements ButtonInterface { } $applepay_request_data_object->order_data( $context ); $this->update_posted_data( $applepay_request_data_object ); - if ( $context == 'product' ) { + if ( $context === 'product' ) { $cart_item_key = $this->prepare_cart( $applepay_request_data_object ); $cart = WC()->cart; $address = $applepay_request_data_object->shipping_address(); From ec2ecfcd160ecbc6e0cf8360d95766f2064718cb Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Wed, 18 Oct 2023 16:53:23 +0100 Subject: [PATCH 04/22] Extend eligible ApplePay countries. --- modules/ppcp-applepay/services.php | 36 ++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/modules/ppcp-applepay/services.php b/modules/ppcp-applepay/services.php index de5c22943..24960ad45 100644 --- a/modules/ppcp-applepay/services.php +++ b/modules/ppcp-applepay/services.php @@ -117,6 +117,24 @@ return array( return apply_filters( 'woocommerce_paypal_payments_applepay_supported_country_currency_matrix', array( + 'GB' => array( + 'AUD', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'JPY', + 'NOK', + 'NZD', + 'PLN', + 'SEK', + 'SGD', + 'USD', + ), 'US' => array( 'AUD', 'CAD', @@ -125,6 +143,24 @@ return array( 'JPY', 'USD', ), + 'CA' => array( + 'AUD', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'JPY', + 'NOK', + 'NZD', + 'PLN', + 'SEK', + 'SGD', + 'USD', + ), ) ); }, From 234795f559aad0bcdae46c54869ad4c3b12e4661 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Wed, 18 Oct 2023 16:54:31 +0100 Subject: [PATCH 05/22] Fix lint --- modules/ppcp-applepay/src/Assets/ApplePayButton.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ppcp-applepay/src/Assets/ApplePayButton.php b/modules/ppcp-applepay/src/Assets/ApplePayButton.php index bbac0fe13..a4ff3ca67 100644 --- a/modules/ppcp-applepay/src/Assets/ApplePayButton.php +++ b/modules/ppcp-applepay/src/Assets/ApplePayButton.php @@ -422,7 +422,7 @@ class ApplePayButton implements ButtonInterface { } $applepay_request_data_object->order_data( $context ); $this->update_posted_data( $applepay_request_data_object ); - if ( $context == 'product' ) { + if ( $context === 'product' ) { $cart_item_key = $this->prepare_cart( $applepay_request_data_object ); $cart = WC()->cart; $address = $applepay_request_data_object->shipping_address(); From 20f64d63ed0f6b044c64e5ae748ae6f7343bd862 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Thu, 19 Oct 2023 11:32:12 +0100 Subject: [PATCH 06/22] Refactor ApplePay notices Refactor AppleProductStatus --- modules/ppcp-applepay/extensions.php | 2 +- modules/ppcp-applepay/services.php | 27 +- modules/ppcp-applepay/src/ApplepayModule.php | 146 ++++----- .../src/Assets/ApplePayButton.php | 19 +- .../src/Assets/AppleProductStatus.php | 115 ++++--- .../src/Helper/AvailabilityNotice.php | 281 ++++++++++++++++++ .../ppcp-googlepay/src/GooglepayModule.php | 1 - .../src/Helper/AvailabilityNotice.php | 2 - 8 files changed, 438 insertions(+), 155 deletions(-) create mode 100644 modules/ppcp-applepay/src/Helper/AvailabilityNotice.php diff --git a/modules/ppcp-applepay/extensions.php b/modules/ppcp-applepay/extensions.php index 38955fba0..39aa3ed81 100644 --- a/modules/ppcp-applepay/extensions.php +++ b/modules/ppcp-applepay/extensions.php @@ -24,7 +24,7 @@ return array( return $fields; } - $is_available = $container->get( 'applepay.enabled' ); + $is_available = $container->get( 'applepay.available' ); $is_referral = $container->get( 'applepay.is_referral' ); $insert_after = function ( array $array, string $key, array $new ): array { diff --git a/modules/ppcp-applepay/services.php b/modules/ppcp-applepay/services.php index de5c22943..3304ce132 100644 --- a/modules/ppcp-applepay/services.php +++ b/modules/ppcp-applepay/services.php @@ -16,11 +16,10 @@ use WooCommerce\PayPalCommerce\Applepay\Assets\AppleProductStatus; use WooCommerce\PayPalCommerce\Applepay\Assets\DataToAppleButtonScripts; use WooCommerce\PayPalCommerce\Applepay\Assets\BlocksPaymentMethod; use WooCommerce\PayPalCommerce\Applepay\Helper\ApmApplies; -use WooCommerce\PayPalCommerce\Googlepay\Helper\ApmProductStatus; +use WooCommerce\PayPalCommerce\Applepay\Helper\AvailabilityNotice; use WooCommerce\PayPalCommerce\Onboarding\Environment; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; -use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; return array( 'applepay.eligible' => static function ( ContainerInterface $container ): bool { @@ -47,23 +46,37 @@ return array( return ! $status->has_request_failure(); }, + + 'applepay.availability_notice' => static function ( ContainerInterface $container ): AvailabilityNotice { + $settings = $container->get( 'wcgateway.settings' ); + + return new AvailabilityNotice( + $container->get( 'applepay.apple-product-status' ), + $container->get( 'wcgateway.is-wc-gateways-list-page' ), + $container->get( 'wcgateway.is-ppcp-settings-page' ), + $container->get( 'applepay.available' ) || ( ! $container->get( 'applepay.is_referral' ) ), + $container->get( 'applepay.server_supported' ), + $settings->has( 'applepay_validated' ) ? $settings->get( 'applepay_validated' ) === true : false, + $container->get( 'applepay.button' ) + ); + }, + 'applepay.apple-product-status' => static function( ContainerInterface $container ): AppleProductStatus { return new AppleProductStatus( $container->get( 'wcgateway.settings' ), $container->get( 'api.endpoint.partners' ), - $container->get( 'applepay.status-cache' ), $container->get( 'onboarding.state' ), $container->get( 'api.helper.failure-registry' ) ); }, - 'applepay.enabled' => static function ( ContainerInterface $container ): bool { - if ( apply_filters( 'woocommerce_paypal_payments_applepay_validate_product_status', false ) ) { + 'applepay.available' => static function ( ContainerInterface $container ): bool { + if ( apply_filters( 'woocommerce_paypal_payments_applepay_validate_product_status', true ) ) { $status = $container->get( 'applepay.apple-product-status' ); assert( $status instanceof AppleProductStatus ); /** * If merchant isn't onboarded via /v1/customer/partner-referrals this returns false as the API call fails. */ - return apply_filters( 'woocommerce_paypal_payments_applepay_product_status', $status->apple_is_active() ); + return apply_filters( 'woocommerce_paypal_payments_applepay_product_status', $status->is_active() ); } return true; }, @@ -149,7 +162,7 @@ return array( $environment = $container->get( 'onboarding.environment' ); assert( $environment instanceof Environment ); - $enabled = $product_status->apple_is_active(); + $enabled = $product_status->is_active(); $enabled_status_text = esc_html__( 'Status: Available', 'woocommerce-paypal-payments' ); $disabled_status_text = esc_html__( 'Status: Not yet enabled', 'woocommerce-paypal-payments' ); diff --git a/modules/ppcp-applepay/src/ApplepayModule.php b/modules/ppcp-applepay/src/ApplepayModule.php index c941797e2..925f0e789 100644 --- a/modules/ppcp-applepay/src/ApplepayModule.php +++ b/modules/ppcp-applepay/src/ApplepayModule.php @@ -10,11 +10,11 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Applepay; use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry; -use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache; use WooCommerce\PayPalCommerce\Applepay\Assets\ApplePayButton; use WooCommerce\PayPalCommerce\Applepay\Assets\AppleProductStatus; use WooCommerce\PayPalCommerce\Button\Assets\ButtonInterface; use WooCommerce\PayPalCommerce\Button\Assets\SmartButtonInterface; +use WooCommerce\PayPalCommerce\Applepay\Helper\AvailabilityNotice; use WooCommerce\PayPalCommerce\Onboarding\Environment; use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; @@ -40,59 +40,49 @@ class ApplepayModule implements ModuleInterface { * {@inheritDoc} */ public function run( ContainerInterface $c ): void { + + // Clears product status when appropriate. + add_action( + 'woocommerce_paypal_payments_clear_apm_product_status', + function( Settings $settings = null ) use ( $c ): void { + $apm_status = $c->get( 'applepay.apple-product-status' ); + assert( $apm_status instanceof AppleProductStatus ); + $apm_status->clear( $settings ); + } + ); + + // Check if the module is applicable, correct country, currency, ... etc. + if ( ! $c->get( 'applepay.eligible' ) ) { + return; + } + + // Load the button handler. $apple_payment_method = $c->get( 'applepay.button' ); // add onboarding and referrals hooks. - $apple_payment_method->initialize(); - if ( ! $c->get( 'applepay.enabled' ) ) { - return; - } - if ( ! $c->get( 'applepay.server_supported' ) ) { - add_action( - 'admin_notices', - static function () { - ?> -
-

- -

-
- get( 'wcgateway.settings' ); - $merchant_validated = $settings->has( 'applepay_validated' ) ? $settings->get( 'applepay_validated' ) === true : false; - if ( ! $merchant_validated ) { - add_action( - 'admin_notices', - static function () { - ?> -
-

- -

-
- load_assets( $c ); - $this->handle_validation_file( $c ); - $this->render_buttons( $c ); assert( $apple_payment_method instanceof ApplepayButton ); - $apple_payment_method->bootstrap_ajax_request(); + $apple_payment_method->initialize(); - $this->remove_status_cache( $c ); + // Show notice if there are product availability issues. + $availability_notice = $c->get( 'applepay.availability_notice' ); + assert( $availability_notice instanceof AvailabilityNotice ); + $availability_notice->execute(); + + // Return if server not supported. + if ( ! $c->get( 'applepay.server_supported' ) ) { + return; + } + + // Check if this merchant can activate / use the buttons. + // We allow non referral merchants as they can potentially still use ApplePay, we just have no way of checking the capability. + if ( ( ! $c->get( 'applepay.available' ) ) && $c->get( 'applepay.is_referral' ) ) { + return; + } + + $this->load_assets( $c, $apple_payment_method ); + $this->handle_validation_file( $c ); + $this->render_buttons( $c, $apple_payment_method ); + + $apple_payment_method->bootstrap_ajax_request(); } /** @@ -126,14 +116,17 @@ class ApplepayModule implements ModuleInterface { * Registers and enqueues the assets. * * @param ContainerInterface $c The container. + * @param ApplePayButton $button The button. * @return void */ - public function load_assets( ContainerInterface $c ): void { + public function load_assets( ContainerInterface $c, ApplePayButton $button ): void { + if ( ! $button->is_enabled() ) { + return; + } + add_action( 'wp_enqueue_scripts', - function () use ( $c ) { - $button = $c->get( 'applepay.button' ); - assert( $button instanceof ApplePayButton ); + function () use ( $c, $button ) { $smart_button = $c->get( 'button.smart-button' ); assert( $smart_button instanceof SmartButtonInterface ); $page_has_block = has_block( 'woocommerce/checkout' ) || has_block( 'woocommerce/cart' ); @@ -154,9 +147,14 @@ class ApplepayModule implements ModuleInterface { * Renders the Apple Pay buttons in the enabled places. * * @param ContainerInterface $c The container. + * @param ApplePayButton $button The button. * @return void */ - public function render_buttons( ContainerInterface $c ): void { + public function render_buttons( ContainerInterface $c, ApplePayButton $button ): void { + if ( ! $button->is_enabled() ) { + return; + } + add_action( 'wp', static function () use ( $c ) { @@ -175,44 +173,6 @@ class ApplepayModule implements ModuleInterface { ); } - /** - * Removes the status cache. - * - * @param ContainerInterface $c The container. - * - * @return void - */ - public function remove_status_cache( ContainerInterface $c ): void { - add_action( - 'woocommerce_paypal_payments_gateway_migrate_on_update', - static function () use ( $c ) { - $apple_status_cache = $c->get( 'applepay.status-cache' ); - assert( $apple_status_cache instanceof Cache ); - - $apple_status_cache->delete( AppleProductStatus::APPLE_STATUS_CACHE_KEY ); - - $settings = $c->get( 'wcgateway.settings' ); - $settings->set( 'products_apple_enabled', false ); - $settings->persist(); - - // Update caches. - $apple_status = $c->get( 'applepay.apple-product-status' ); - assert( $apple_status instanceof AppleProductStatus ); - $apple_status->apple_is_active(); - } - ); - - add_action( - 'woocommerce_paypal_payments_on_listening_request', - static function () use ( $c ) { - $apple_status = $c->get( 'applepay.status-cache' ); - if ( $apple_status->has( AppleProductStatus::APPLE_STATUS_CACHE_KEY ) ) { - $apple_status->delete( AppleProductStatus::APPLE_STATUS_CACHE_KEY ); - } - } - ); - } - /** * Handles the validation file. * diff --git a/modules/ppcp-applepay/src/Assets/ApplePayButton.php b/modules/ppcp-applepay/src/Assets/ApplePayButton.php index bbac0fe13..4e8bb17fc 100644 --- a/modules/ppcp-applepay/src/Assets/ApplePayButton.php +++ b/modules/ppcp-applepay/src/Assets/ApplePayButton.php @@ -422,7 +422,7 @@ class ApplePayButton implements ButtonInterface { } $applepay_request_data_object->order_data( $context ); $this->update_posted_data( $applepay_request_data_object ); - if ( $context == 'product' ) { + if ( $context === 'product' ) { $cart_item_key = $this->prepare_cart( $applepay_request_data_object ); $cart = WC()->cart; $address = $applepay_request_data_object->shipping_address(); @@ -902,15 +902,19 @@ class ApplePayButton implements ButtonInterface { * Renders the Apple Pay button on the page * * @return bool + * + * @psalm-suppress RedundantCondition */ public function render(): bool { - $is_applepay_button_enabled = $this->settings->has( 'applepay_button_enabled' ) ? $this->settings->get( 'applepay_button_enabled' ) : false; + if ( ! $this->is_enabled() ) { + return true; + } - $button_enabled_product = $is_applepay_button_enabled && $this->settings_status->is_smart_button_enabled_for_location( 'product' ); - $button_enabled_cart = $is_applepay_button_enabled && $this->settings_status->is_smart_button_enabled_for_location( 'cart' ); - $button_enabled_checkout = $is_applepay_button_enabled; - $button_enabled_payorder = $is_applepay_button_enabled; - $button_enabled_minicart = $is_applepay_button_enabled && $this->settings_status->is_smart_button_enabled_for_location( 'mini-cart' ); + $button_enabled_product = $this->settings_status->is_smart_button_enabled_for_location( 'product' ); + $button_enabled_cart = $this->settings_status->is_smart_button_enabled_for_location( 'cart' ); + $button_enabled_checkout = true; + $button_enabled_payorder = true; + $button_enabled_minicart = $this->settings_status->is_smart_button_enabled_for_location( 'mini-cart' ); add_filter( 'woocommerce_paypal_payments_sdk_components_hook', @@ -1054,7 +1058,6 @@ class ApplePayButton implements ButtonInterface { */ public function is_enabled(): bool { try { - // todo add also onboarded apple and enabled buttons. return $this->settings->has( 'applepay_button_enabled' ) && $this->settings->get( 'applepay_button_enabled' ); } catch ( Exception $e ) { return false; diff --git a/modules/ppcp-applepay/src/Assets/AppleProductStatus.php b/modules/ppcp-applepay/src/Assets/AppleProductStatus.php index 83b6e7942..2c00ba59e 100644 --- a/modules/ppcp-applepay/src/Assets/AppleProductStatus.php +++ b/modules/ppcp-applepay/src/Assets/AppleProductStatus.php @@ -1,41 +1,37 @@ settings = $settings; $this->partners_endpoint = $partners_endpoint; - $this->cache = $cache; $this->onboarding_state = $onboarding_state; $this->api_failure_registry = $api_failure_registry; } @@ -100,55 +93,71 @@ class AppleProductStatus { * * @return bool */ - public function apple_is_active() : bool { - if ( $this->onboarding_state->current_state() < State::STATE_ONBOARDED ) { + public function is_active() : bool { + + // If not onboarded then makes no sense to check status. + if ( ! $this->is_onboarded() ) { return false; } - if ( $this->cache->has( self::APPLE_STATUS_CACHE_KEY ) ) { - return $this->cache->get( self::APPLE_STATUS_CACHE_KEY ) === 'true'; + // If status was already checked on this request return the same result. + if ( null !== $this->current_status ) { + return $this->current_status; } - if ( $this->current_status_cache === true ) { - return $this->current_status_cache; - } - if ( $this->settings->has( 'products_apple_enabled' ) && $this->settings->get( 'products_apple_enabled' ) === true ) { - $this->current_status_cache = true; - return true; + // Check if status was checked on previous requests. + if ( $this->settings->has( self::SETTINGS_KEY ) && ( $this->settings->get( self::SETTINGS_KEY ) ) ) { + $this->current_status = wc_string_to_bool( $this->settings->get( self::SETTINGS_KEY ) ); + return $this->current_status; } // Check API failure registry to prevent multiple failed API requests. if ( $this->api_failure_registry->has_failure_in_timeframe( FailureRegistry::SELLER_STATUS_KEY, HOUR_IN_SECONDS ) ) { - $this->has_request_failure = true; - $this->current_status_cache = false; - return $this->current_status_cache; + $this->has_request_failure = true; + $this->current_status = false; + return $this->current_status; } + // Request seller status via PayPal API. try { $seller_status = $this->partners_endpoint->seller_status(); } catch ( Throwable $error ) { - $this->has_request_failure = true; - $this->current_status_cache = false; - return false; + $this->has_request_failure = true; + $this->current_status = false; + return $this->current_status; } + // Check the seller status for the intended capability. foreach ( $seller_status->products() as $product ) { if ( $product->name() !== 'PAYMENT_METHODS' ) { continue; } - if ( in_array( 'APPLE_PAY', $product->capabilities(), true ) ) { - $this->settings->set( 'products_apple_enabled', true ); + if ( in_array( self::CAPABILITY_NAME, $product->capabilities(), true ) ) { + // Capability found, persist status and return true. + $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_ENABLED ); $this->settings->persist(); - $this->current_status_cache = true; - $this->cache->set( self::APPLE_STATUS_CACHE_KEY, 'true', 3 * MONTH_IN_SECONDS ); - return true; + + $this->current_status = true; + return $this->current_status; } } - $this->cache->set( self::APPLE_STATUS_CACHE_KEY, 'false', 3 * MONTH_IN_SECONDS ); - $this->current_status_cache = false; - return false; + // Capability not found, persist status and return false. + $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_DISABLED ); + $this->settings->persist(); + + $this->current_status = false; + return $this->current_status; + } + + /** + * Returns if the seller is onboarded. + * + * @return bool + */ + public function is_onboarded(): bool { + return $this->onboarding_state->current_state() >= State::STATE_ONBOARDED; } /** @@ -160,4 +169,24 @@ class AppleProductStatus { return $this->has_request_failure; } + /** + * Clears the persisted result to force a recheck. + * + * @param Settings|null $settings The settings object. + * We accept a Settings object to don't override other sequential settings that are being updated elsewhere. + * @return void + */ + public function clear( Settings $settings = null ): void { + if ( null === $settings ) { + $settings = $this->settings; + } + + $this->current_status = null; + + if ( $settings->has( self::SETTINGS_KEY ) ) { + $settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_UNDEFINED ); + $settings->persist(); + } + } + } diff --git a/modules/ppcp-applepay/src/Helper/AvailabilityNotice.php b/modules/ppcp-applepay/src/Helper/AvailabilityNotice.php new file mode 100644 index 000000000..6717d6be8 --- /dev/null +++ b/modules/ppcp-applepay/src/Helper/AvailabilityNotice.php @@ -0,0 +1,281 @@ +product_status = $product_status; + $this->is_wc_gateways_list_page = $is_wc_gateways_list_page; + $this->is_ppcp_settings_page = $is_ppcp_settings_page; + $this->is_available = $is_available; + $this->is_server_supported = $is_server_supported; + $this->is_merchant_validated = $is_merchant_validated; + $this->button = $button; + } + + /** + * Adds availability notice if applicable. + * + * @return void + */ + public function execute(): void { + if ( ! $this->should_display() ) { + return; + } + + // We need to check is active before checking failure requests, otherwise failure status won't be set. + $is_active = $this->product_status->is_active(); + + if ( $this->product_status->has_request_failure() ) { + $this->add_seller_status_failure_notice(); + } elseif ( ! $is_active ) { + $this->add_not_available_notice(); + } + + if ( ! $this->is_available ) { + return; + } + + if ( ! $this->is_server_supported ) { + $this->add_server_not_supported_notice(); + } + + if ( ! $this->button->is_enabled() ) { + return; + } + + if ( ! $this->is_merchant_validated ) { + $this->add_merchant_not_validated_notice(); + } + + } + + /** + * Whether the message should display. + * + * @return bool + */ + protected function should_display(): bool { + if ( ! $this->product_status->is_onboarded() ) { + return false; + } + if ( ! $this->is_wc_gateways_list_page && ! $this->is_ppcp_settings_page ) { + return false; + } + return true; + } + + /** + * Adds seller status failure notice. + * + * @return void + */ + private function add_seller_status_failure_notice(): void { + add_filter( + Repository::NOTICES_FILTER, + /** + * Adds seller status notice. + * + * @param array $notices The notices. + * @return array + * + * @psalm-suppress MissingClosureParamType + */ + static function ( $notices ): array { + $message = sprintf( + // translators: %1$s and %2$s are the opening and closing of HTML tag. + __( + '

Notice: We could not determine your PayPal seller status to list your available features. Disconnect and reconnect your PayPal account through our %1$sonboarding process%2$s to resolve this.

Don\'t worry if you cannot use the %1$sonboarding process%2$s; most functionalities available to your account should work.

', + 'woocommerce-paypal-payments' + ), + '
', + '' + ); + + // Name the key so it can be overridden in other modules. + $notices['error_product_status'] = new Message( $message, 'warning', true, 'ppcp-notice-wrapper' ); + return $notices; + } + ); + } + + /** + * Adds not available notice. + * + * @return void + */ + private function add_not_available_notice(): void { + add_filter( + Repository::NOTICES_FILTER, + /** + * Adds ApplePay not available notice. + * + * @param array $notices The notices. + * @return array + * + * @psalm-suppress MissingClosureParamType + */ + static function ( $notices ): array { + $message = sprintf( + __( + 'Apple Pay is not available on your PayPal seller account.', + 'woocommerce-paypal-payments' + ) + ); + + $notices[] = new Message( $message, 'warning', true, 'ppcp-notice-wrapper' ); + return $notices; + } + ); + } + + /** + * Adds ApplePay server not supported notice. + * + * @return void + */ + private function add_server_not_supported_notice(): void { + add_filter( + Repository::NOTICES_FILTER, + /** + * Adds ApplePay server not supported notice. + * + * @param array $notices The notices. + * @return array + * + * @psalm-suppress MissingClosureParamType + */ + static function ( $notices ): array { + $message = sprintf( + __( + 'Apple Pay is not supported on this server. Please contact your hosting provider to enable it.', + 'woocommerce-paypal-payments' + ) + ); + + $notices[] = new Message( $message, 'error', true, 'ppcp-notice-wrapper' ); + return $notices; + } + ); + } + + /** + * Adds ApplePay merchant not validated notice. + * + * @return void + */ + private function add_merchant_not_validated_notice(): void { + add_filter( + Repository::NOTICES_FILTER, + /** + * Adds ApplePay merchant not validated notice. + * + * @param array $notices The notices. + * @return array + * + * @psalm-suppress MissingClosureParamType + */ + static function ( $notices ): array { + $message = sprintf( + // translators: %1$s and %2$s are the opening and closing of HTML tag for the well-known file, %3$s and %4$s are the opening and closing of HTML tag for the help document. + __( + 'Apple Pay Validation Error. Please ensure the presentment of the correct %1$sdomain association file%2$s for Apple to validate your domain. %3$sLearn more%4$s about the Apple Pay requirements', + 'woocommerce-paypal-payments' + ), + '', + '', + '', + '' + ); + + $notices[] = new Message( $message, 'error', true, 'ppcp-notice-wrapper' ); + return $notices; + } + ); + } + +} diff --git a/modules/ppcp-googlepay/src/GooglepayModule.php b/modules/ppcp-googlepay/src/GooglepayModule.php index 86c967694..99dc93465 100644 --- a/modules/ppcp-googlepay/src/GooglepayModule.php +++ b/modules/ppcp-googlepay/src/GooglepayModule.php @@ -45,7 +45,6 @@ class GooglepayModule implements ModuleInterface { function( Settings $settings = null ) use ( $c ): void { $apm_status = $c->get( 'googlepay.helpers.apm-product-status' ); assert( $apm_status instanceof ApmProductStatus ); - $apm_status->clear( $settings ); } ); diff --git a/modules/ppcp-googlepay/src/Helper/AvailabilityNotice.php b/modules/ppcp-googlepay/src/Helper/AvailabilityNotice.php index 9cadbc91a..df31bdf26 100644 --- a/modules/ppcp-googlepay/src/Helper/AvailabilityNotice.php +++ b/modules/ppcp-googlepay/src/Helper/AvailabilityNotice.php @@ -107,7 +107,6 @@ class AvailabilityNotice { * @psalm-suppress MissingClosureParamType */ static function ( $notices ): array { - $message = sprintf( // translators: %1$s and %2$s are the opening and closing of HTML tag. __( @@ -142,7 +141,6 @@ class AvailabilityNotice { * @psalm-suppress MissingClosureParamType */ static function ( $notices ): array { - $message = sprintf( __( 'Google Pay is not available on your PayPal seller account.', From bb927924202b2d4d4820226b522c5155d4837d44 Mon Sep 17 00:00:00 2001 From: Alex P Date: Thu, 19 Oct 2023 15:55:57 +0300 Subject: [PATCH 07/22] Update deprecated event name --- modules/ppcp-blocks/resources/js/checkout-block.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/ppcp-blocks/resources/js/checkout-block.js b/modules/ppcp-blocks/resources/js/checkout-block.js index 2ec60bfb3..b1073dfb2 100644 --- a/modules/ppcp-blocks/resources/js/checkout-block.js +++ b/modules/ppcp-blocks/resources/js/checkout-block.js @@ -19,7 +19,7 @@ const PayPalComponent = ({ shippingData, isEditing, }) => { - const {onPaymentSetup, onCheckoutAfterProcessingWithError, onCheckoutValidation} = eventRegistration; + const {onPaymentSetup, onCheckoutFail, onCheckoutValidation} = eventRegistration; const {responseTypes} = emitResponse; const [paypalOrder, setPaypalOrder] = useState(null); @@ -253,7 +253,7 @@ const PayPalComponent = ({ }, [onPaymentSetup, paypalOrder, activePaymentMethod]); useEffect(() => { - const unsubscribe = onCheckoutAfterProcessingWithError(({ processingResponse }) => { + const unsubscribe = onCheckoutFail(({ processingResponse }) => { if (onClose) { onClose(); } @@ -267,7 +267,7 @@ const PayPalComponent = ({ return true; }); return unsubscribe; - }, [onCheckoutAfterProcessingWithError, onClose]); + }, [onCheckoutFail, onClose]); if (config.scriptData.continuation) { return ( From f13fc1d987a04c8d51ab831515966effbdcf314c Mon Sep 17 00:00:00 2001 From: Alex P Date: Thu, 19 Oct 2023 16:56:07 +0300 Subject: [PATCH 08/22] Redirect to continuation on block server error --- .../ppcp-blocks/resources/js/checkout-block.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/modules/ppcp-blocks/resources/js/checkout-block.js b/modules/ppcp-blocks/resources/js/checkout-block.js index b1073dfb2..85bcd278f 100644 --- a/modules/ppcp-blocks/resources/js/checkout-block.js +++ b/modules/ppcp-blocks/resources/js/checkout-block.js @@ -253,21 +253,24 @@ const PayPalComponent = ({ }, [onPaymentSetup, paypalOrder, activePaymentMethod]); useEffect(() => { + if (activePaymentMethod !== config.id) { + return; + } const unsubscribe = onCheckoutFail(({ processingResponse }) => { + console.error(processingResponse) if (onClose) { onClose(); } - if (processingResponse?.paymentDetails?.errorMessage) { - return { - type: emitResponse.responseTypes.ERROR, - message: processingResponse.paymentDetails.errorMessage, - messageContext: config.scriptData.continuation ? emitResponse.noticeContexts.PAYMENTS : emitResponse.noticeContexts.EXPRESS_PAYMENTS, - }; + if (config.scriptData.continuation) { + return true; + } + if (!config.finalReviewEnabled) { + location.href = getCheckoutRedirectUrl(); } return true; }); return unsubscribe; - }, [onCheckoutFail, onClose]); + }, [onCheckoutFail, onClose, activePaymentMethod]); if (config.scriptData.continuation) { return ( From 567a7a206595737fcef1dfe483fd6b1ca9b71ddd Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Thu, 19 Oct 2023 15:12:31 +0100 Subject: [PATCH 09/22] Add some validations to GooglePay scripts --- modules/ppcp-applepay/src/Assets/ApplePayButton.php | 2 +- modules/ppcp-googlepay/resources/js/boot.js | 4 +++- modules/ppcp-googlepay/src/GooglepayModule.php | 7 +++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/modules/ppcp-applepay/src/Assets/ApplePayButton.php b/modules/ppcp-applepay/src/Assets/ApplePayButton.php index bbac0fe13..a4ff3ca67 100644 --- a/modules/ppcp-applepay/src/Assets/ApplePayButton.php +++ b/modules/ppcp-applepay/src/Assets/ApplePayButton.php @@ -422,7 +422,7 @@ class ApplePayButton implements ButtonInterface { } $applepay_request_data_object->order_data( $context ); $this->update_posted_data( $applepay_request_data_object ); - if ( $context == 'product' ) { + if ( $context === 'product' ) { $cart_item_key = $this->prepare_cart( $applepay_request_data_object ); $cart = WC()->cart; $address = $applepay_request_data_object->shipping_address(); diff --git a/modules/ppcp-googlepay/resources/js/boot.js b/modules/ppcp-googlepay/resources/js/boot.js index 387822e67..731f78d80 100644 --- a/modules/ppcp-googlepay/resources/js/boot.js +++ b/modules/ppcp-googlepay/resources/js/boot.js @@ -16,7 +16,9 @@ import GooglepayManager from "./GooglepayManager"; }; jQuery(document.body).on('updated_cart_totals updated_checkout', () => { - manager.reinit(); + if (manager) { + manager.reinit(); + } }); document.addEventListener( diff --git a/modules/ppcp-googlepay/src/GooglepayModule.php b/modules/ppcp-googlepay/src/GooglepayModule.php index 86c967694..614647181 100644 --- a/modules/ppcp-googlepay/src/GooglepayModule.php +++ b/modules/ppcp-googlepay/src/GooglepayModule.php @@ -11,6 +11,7 @@ namespace WooCommerce\PayPalCommerce\Googlepay; use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry; use WooCommerce\PayPalCommerce\Button\Assets\ButtonInterface; +use WooCommerce\PayPalCommerce\Button\Assets\SmartButtonInterface; use WooCommerce\PayPalCommerce\Googlepay\Endpoint\UpdatePaymentDataEndpoint; use WooCommerce\PayPalCommerce\Googlepay\Helper\ApmProductStatus; use WooCommerce\PayPalCommerce\Googlepay\Helper\AvailabilityNotice; @@ -86,6 +87,12 @@ class GooglepayModule implements ModuleInterface { add_action( 'wp_enqueue_scripts', static function () use ( $c, $button ) { + $smart_button = $c->get( 'button.smart-button' ); + assert( $smart_button instanceof SmartButtonInterface ); + $page_has_block = has_block( 'woocommerce/checkout' ) || has_block( 'woocommerce/cart' ); + if ( ! $smart_button->should_load_ppcp_script() && ! $page_has_block ) { + return; + } $button->enqueue(); } ); From b4d07e7025847ebe00694e4ce0164db0d78327fd Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Thu, 19 Oct 2023 16:21:14 +0100 Subject: [PATCH 10/22] Fix ApplePay live validation file. --- modules/ppcp-applepay/src/ApplepayModule.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/modules/ppcp-applepay/src/ApplepayModule.php b/modules/ppcp-applepay/src/ApplepayModule.php index c941797e2..3274b9004 100644 --- a/modules/ppcp-applepay/src/ApplepayModule.php +++ b/modules/ppcp-applepay/src/ApplepayModule.php @@ -244,7 +244,10 @@ class ApplepayModule implements ModuleInterface { * @return string */ private function sandbox_validation_string(): string { - return '7B227073704964223A2241443631324543383841333039314132314539434132433035304439454130353741414535444341304542413237424243333838463239344231353534434233222C2276657273696F6E223A312C22637265617465644F6E223A313632343438393037393630362C227369676E6174757265223A2233303830303630393261383634383836663730643031303730326130383033303830303230313031333130663330306430363039363038363438303136353033303430323031303530303330383030363039326138363438383666373064303130373031303030306130383033303832303365343330383230333862613030333032303130323032303835396438613162636161663465336364333030613036303832613836343863653364303430333032333037613331326533303263303630333535303430333063323534313730373036633635323034313730373036633639363336313734363936663665323034393665373436353637373236313734363936663665323034333431323032643230343733333331323633303234303630333535303430623063316434313730373036633635323034333635373237343639363636393633363137343639366636653230343137353734363836663732363937343739333131333330313130363033353530343061306330613431373037303663363532303439366536333265333130623330303930363033353530343036313330323535353333303165313730643332333133303334333233303331333933333337333033303561313730643332333633303334333133393331333933333336333533393561333036323331323833303236303630333535303430333063316636353633363332643733366437303264363237323666366236353732326437333639363736653566353534333334326435333431346534343432346635383331313433303132303630333535303430623063306236393466353332303533373937333734363536643733333131333330313130363033353530343061306330613431373037303663363532303439366536333265333130623330303930363033353530343036313330323535353333303539333031333036303732613836343863653364303230313036303832613836343863653364303330313037303334323030303438323330666461626333396366373565323032633530643939623435313265363337653261393031646436636233653062316364346235323637393866386366346562646538316132356138633231653463333364646365386532613936633266366166613139333033343563346538376134343236636539353162313239356133383230323131333038323032306433303063303630333535316431333031303166663034303233303030333031663036303335353164323330343138333031363830313432336632343963343466393365346566323765366334663632383663336661326262666432653462333034353036303832623036303130353035303730313031303433393330333733303335303630383262303630313035303530373330303138363239363837343734373033613266326636663633373337303265363137303730366336353265363336663664326636663633373337303330333432643631373037303663363536313639363336313333333033323330383230313164303630333535316432303034383230313134333038323031313033303832303130633036303932613836343838366637363336343035303133303831666533303831633330363038326230363031303530353037303230323330383162363063383162333532363536633639363136653633363532303666366532303734363836393733323036333635373237343639363636393633363137343635323036323739323036313665373932303730363137323734373932303631373337333735366436353733323036313633363336353730373436313665363336353230366636363230373436383635323037343638363536653230363137303730366336393633363136323663363532303733373436313665363436313732363432303734363537323664373332303631366536343230363336663665363436393734363936663665373332303666363632303735373336353263323036333635373237343639363636393633363137343635323037303666366336393633373932303631366536343230363336353732373436393636363936333631373436393666366532303730373236313633373436393633363532303733373436313734363536643635366537343733326533303336303630383262303630313035303530373032303131363261363837343734373033613266326637373737373732653631373037303663363532653633366636643266363336353732373436393636363936333631373436353631373537343638366637323639373437393266333033343036303335353164316630343264333032623330323961303237613032353836323336383734373437303361326632663633373236633265363137303730366336353265363336663664326636313730373036633635363136393633363133333265363337323663333031643036303335353164306530343136303431343032323433303062396165656564343633313937613461363561323939653432373138323163343533303065303630333535316430663031303166663034303430333032303738303330306630363039326138363438383666373633363430363164303430323035303033303061303630383261383634386365336430343033303230333437303033303434303232303734613162333234646234323439343330646433323734633530373463343830386439613166343830653361383563356331333632353636333235666263613330323230363933363930353361626635306235613532663966363030346463353861616436633530613764363038363833373930653061373361643031653461643938313330383230326565333038323032373561303033303230313032303230383439366432666266336139386461393733303061303630383261383634386365336430343033303233303637333131623330313930363033353530343033306331323431373037303663363532303532366636663734323034333431323032643230343733333331323633303234303630333535303430623063316434313730373036633635323034333635373237343639363636393633363137343639366636653230343137353734363836663732363937343739333131333330313130363033353530343061306330613431373037303663363532303439366536333265333130623330303930363033353530343036313330323535353333303165313730643331333433303335333033363332333333343336333333303561313730643332333933303335333033363332333333343336333333303561333037613331326533303263303630333535303430333063323534313730373036633635323034313730373036633639363336313734363936663665323034393665373436353637373236313734363936663665323034333431323032643230343733333331323633303234303630333535303430623063316434313730373036633635323034333635373237343639363636393633363137343639366636653230343137353734363836663732363937343739333131333330313130363033353530343061306330613431373037303663363532303439366536333265333130623330303930363033353530343036313330323535353333303539333031333036303732613836343863653364303230313036303832613836343863653364303330313037303334323030303466303137313138343139643736343835643531613565323538313037373665383830613265666465376261653464653038646663346239336531333335366435363635623335616532326430393737363064323234653762626130386664373631376365383863623736626236363730626563386538323938346666353434356133383166373330383166343330343630363038326230363031303530353037303130313034336133303338333033363036303832623036303130353035303733303031383632613638373437343730336132663266366636333733373032653631373037303663363532653633366636643266366636333733373033303334326436313730373036633635373236663666373436333631363733333330316430363033353531643065303431363034313432336632343963343466393365346566323765366334663632383663336661326262666432653462333030663036303335353164313330313031666630343035333030333031303166663330316630363033353531643233303431383330313638303134626262306465613135383333383839616134386139396465626562646562616664616362323461623330333730363033353531643166303433303330326533303263613032616130323838363236363837343734373033613266326636333732366332653631373037303663363532653633366636643266363137303730366336353732366636663734363336313637333332653633373236633330306530363033353531643066303130316666303430343033303230313036333031303036306132613836343838366637363336343036303230653034303230353030333030613036303832613836343863653364303430333032303336373030333036343032333033616366373238333531313639396231383666623335633335366361363262666634313765646439306637353464613238656265663139633831356534326237383966383938663739623539396639386435343130643866396465396332666530323330333232646435343432316230613330353737366335646633333833623930363766643137376332633231366439363466633637323639383231323666353466383761376431623939636239623039383932313631303639393066303939323164303030303331383230313863333038323031383830323031303133303831383633303761333132653330326330363033353530343033306332353431373037303663363532303431373037303663363936333631373436393666366532303439366537343635363737323631373436393666366532303433343132303264323034373333333132363330323430363033353530343062306331643431373037303663363532303433363537323734363936363639363336313734363936663665323034313735373436383666373236393734373933313133333031313036303335353034306130633061343137303730366336353230343936653633326533313062333030393036303335353034303631333032353535333032303835396438613162636161663465336364333030643036303936303836343830313635303330343032303130353030613038313935333031383036303932613836343838366637306430313039303333313062303630393261383634383836663730643031303730313330316330363039326138363438383666373064303130393035333130663137306433323331333033363332333333323332333533373335333935613330326130363039326138363438383666373064303130393334333131643330316233303064303630393630383634383031363530333034303230313035303061313061303630383261383634386365336430343033303233303266303630393261383634383836663730643031303930343331323230343230343239323932333766306638303764346538373932333134643438393635623165626262633038636265386333333432643365643261333939623963336538353330306130363038326138363438636533643034303330323034343733303435303232313030643430333138326637626530396663386265393738316463646461613434623332663362353634386566353666323664323933363738343237393933616530383032323037646663306563316361306461343531653464663031386236376538326231366330313065313930373431363762666632363839356230336563336430396134303030303030303030303030227D'; + return apply_filters( + 'woocommerce_paypal_payments_applepay_sandbox_validation_string', + '7B227073704964223A2241443631324543383841333039314132314539434132433035304439454130353741414535444341304542413237424243333838463239344231353534434233222C2276657273696F6E223A312C22637265617465644F6E223A313632343438393037393630362C227369676E6174757265223A2233303830303630393261383634383836663730643031303730326130383033303830303230313031333130663330306430363039363038363438303136353033303430323031303530303330383030363039326138363438383666373064303130373031303030306130383033303832303365343330383230333862613030333032303130323032303835396438613162636161663465336364333030613036303832613836343863653364303430333032333037613331326533303263303630333535303430333063323534313730373036633635323034313730373036633639363336313734363936663665323034393665373436353637373236313734363936663665323034333431323032643230343733333331323633303234303630333535303430623063316434313730373036633635323034333635373237343639363636393633363137343639366636653230343137353734363836663732363937343739333131333330313130363033353530343061306330613431373037303663363532303439366536333265333130623330303930363033353530343036313330323535353333303165313730643332333133303334333233303331333933333337333033303561313730643332333633303334333133393331333933333336333533393561333036323331323833303236303630333535303430333063316636353633363332643733366437303264363237323666366236353732326437333639363736653566353534333334326435333431346534343432346635383331313433303132303630333535303430623063306236393466353332303533373937333734363536643733333131333330313130363033353530343061306330613431373037303663363532303439366536333265333130623330303930363033353530343036313330323535353333303539333031333036303732613836343863653364303230313036303832613836343863653364303330313037303334323030303438323330666461626333396366373565323032633530643939623435313265363337653261393031646436636233653062316364346235323637393866386366346562646538316132356138633231653463333364646365386532613936633266366166613139333033343563346538376134343236636539353162313239356133383230323131333038323032306433303063303630333535316431333031303166663034303233303030333031663036303335353164323330343138333031363830313432336632343963343466393365346566323765366334663632383663336661326262666432653462333034353036303832623036303130353035303730313031303433393330333733303335303630383262303630313035303530373330303138363239363837343734373033613266326636663633373337303265363137303730366336353265363336663664326636663633373337303330333432643631373037303663363536313639363336313333333033323330383230313164303630333535316432303034383230313134333038323031313033303832303130633036303932613836343838366637363336343035303133303831666533303831633330363038326230363031303530353037303230323330383162363063383162333532363536633639363136653633363532303666366532303734363836393733323036333635373237343639363636393633363137343635323036323739323036313665373932303730363137323734373932303631373337333735366436353733323036313633363336353730373436313665363336353230366636363230373436383635323037343638363536653230363137303730366336393633363136323663363532303733373436313665363436313732363432303734363537323664373332303631366536343230363336663665363436393734363936663665373332303666363632303735373336353263323036333635373237343639363636393633363137343635323037303666366336393633373932303631366536343230363336353732373436393636363936333631373436393666366532303730373236313633373436393633363532303733373436313734363536643635366537343733326533303336303630383262303630313035303530373032303131363261363837343734373033613266326637373737373732653631373037303663363532653633366636643266363336353732373436393636363936333631373436353631373537343638366637323639373437393266333033343036303335353164316630343264333032623330323961303237613032353836323336383734373437303361326632663633373236633265363137303730366336353265363336663664326636313730373036633635363136393633363133333265363337323663333031643036303335353164306530343136303431343032323433303062396165656564343633313937613461363561323939653432373138323163343533303065303630333535316430663031303166663034303430333032303738303330306630363039326138363438383666373633363430363164303430323035303033303061303630383261383634386365336430343033303230333437303033303434303232303734613162333234646234323439343330646433323734633530373463343830386439613166343830653361383563356331333632353636333235666263613330323230363933363930353361626635306235613532663966363030346463353861616436633530613764363038363833373930653061373361643031653461643938313330383230326565333038323032373561303033303230313032303230383439366432666266336139386461393733303061303630383261383634386365336430343033303233303637333131623330313930363033353530343033306331323431373037303663363532303532366636663734323034333431323032643230343733333331323633303234303630333535303430623063316434313730373036633635323034333635373237343639363636393633363137343639366636653230343137353734363836663732363937343739333131333330313130363033353530343061306330613431373037303663363532303439366536333265333130623330303930363033353530343036313330323535353333303165313730643331333433303335333033363332333333343336333333303561313730643332333933303335333033363332333333343336333333303561333037613331326533303263303630333535303430333063323534313730373036633635323034313730373036633639363336313734363936663665323034393665373436353637373236313734363936663665323034333431323032643230343733333331323633303234303630333535303430623063316434313730373036633635323034333635373237343639363636393633363137343639366636653230343137353734363836663732363937343739333131333330313130363033353530343061306330613431373037303663363532303439366536333265333130623330303930363033353530343036313330323535353333303539333031333036303732613836343863653364303230313036303832613836343863653364303330313037303334323030303466303137313138343139643736343835643531613565323538313037373665383830613265666465376261653464653038646663346239336531333335366435363635623335616532326430393737363064323234653762626130386664373631376365383863623736626236363730626563386538323938346666353434356133383166373330383166343330343630363038326230363031303530353037303130313034336133303338333033363036303832623036303130353035303733303031383632613638373437343730336132663266366636333733373032653631373037303663363532653633366636643266366636333733373033303334326436313730373036633635373236663666373436333631363733333330316430363033353531643065303431363034313432336632343963343466393365346566323765366334663632383663336661326262666432653462333030663036303335353164313330313031666630343035333030333031303166663330316630363033353531643233303431383330313638303134626262306465613135383333383839616134386139396465626562646562616664616362323461623330333730363033353531643166303433303330326533303263613032616130323838363236363837343734373033613266326636333732366332653631373037303663363532653633366636643266363137303730366336353732366636663734363336313637333332653633373236633330306530363033353531643066303130316666303430343033303230313036333031303036306132613836343838366637363336343036303230653034303230353030333030613036303832613836343863653364303430333032303336373030333036343032333033616366373238333531313639396231383666623335633335366361363262666634313765646439306637353464613238656265663139633831356534326237383966383938663739623539396639386435343130643866396465396332666530323330333232646435343432316230613330353737366335646633333833623930363766643137376332633231366439363466633637323639383231323666353466383761376431623939636239623039383932313631303639393066303939323164303030303331383230313863333038323031383830323031303133303831383633303761333132653330326330363033353530343033306332353431373037303663363532303431373037303663363936333631373436393666366532303439366537343635363737323631373436393666366532303433343132303264323034373333333132363330323430363033353530343062306331643431373037303663363532303433363537323734363936363639363336313734363936663665323034313735373436383666373236393734373933313133333031313036303335353034306130633061343137303730366336353230343936653633326533313062333030393036303335353034303631333032353535333032303835396438613162636161663465336364333030643036303936303836343830313635303330343032303130353030613038313935333031383036303932613836343838366637306430313039303333313062303630393261383634383836663730643031303730313330316330363039326138363438383666373064303130393035333130663137306433323331333033363332333333323332333533373335333935613330326130363039326138363438383666373064303130393334333131643330316233303064303630393630383634383031363530333034303230313035303061313061303630383261383634386365336430343033303233303266303630393261383634383836663730643031303930343331323230343230343239323932333766306638303764346538373932333134643438393635623165626262633038636265386333333432643365643261333939623963336538353330306130363038326138363438636533643034303330323034343733303435303232313030643430333138326637626530396663386265393738316463646461613434623332663362353634386566353666323664323933363738343237393933616530383032323037646663306563316361306461343531653464663031386236376538326231366330313065313930373431363762666632363839356230336563336430396134303030303030303030303030227D' + ); } /** @@ -253,6 +256,9 @@ class ApplepayModule implements ModuleInterface { * @return string */ private function live_validation_string(): string { - return 'MIIQYQYJKoZIhvcNAQcCoIIQUjCCEE4CAQExCzAJBgUrDgMCGgUAMHAGCSqGSIb3DQEHAaBjBGF7InRlYW1JZCI6IjcyN0s1NldWNjciLCJkb21haW4iOiJ3d3cucGF5cGFsLmNvbSIsImRhdGVDcmVhdGVkIjoiMjAyMy0wNS0yMiwxNjo1NzoyOCIsInZlcnNpb24iOjF9oIINPzCCBDQwggMcoAMCAQICCEc8TGHymYjUMA0GCSqGSIb3DQEBCwUAMHMxLTArBgNVBAMMJEFwcGxlIGlQaG9uZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEgMB4GA1UECwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEzARBgNVBAoMCkFwcGxlIEluYy4xCzAJBgNVBAYTAlVTMB4XDTIzMDQxMTIyMjM1OVoXDTI4MDQwOTIyMjM1OFowWTE1MDMGA1UEAwwsQXBwbGUgaVBob25lIE9TIFByb3Zpc2lvbmluZyBQcm9maWxlIFNpZ25pbmcxEzARBgNVBAoMCkFwcGxlIEluYy4xCzAJBgNVBAYTAlVTMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6kPk_NNTn7aAD_zGbW6KydbD0o773Zv3wEvh-0jpzfMsGDLG7izTMTAX0ahEwvmpZKPijuurp4OCLC3BhgKvBFdTmU0MN5BDdnZ7bpwbaxWx5AH9nZwVm3d_wPQj0a6gskT6IUvSTYi8apgD0VGldPJf7vu-WYFH409ie7ljpU_SjsoQTjFVje1ckUe29jfT3zbfLFvPF05NwwVRPfwZcJ8A-LWJ19fLMBXrudbtTXuSzF2Ayww7K0cNyFtxe7TB28bXZ9DXU4aQlwHe_wa9HZmFpNfP7upB5F7-CmdwIBUdlO40Zu5Cas_fo_UQSsSYstVcaEjt-5qncP4WmbMX9QIDAQABo4HlMIHiMAwGA1UdEwEB_wQCMAAwHwYDVR0jBBgwFoAUb_GVGGJc4Mjxxe1sGMng02RSmCAwQAYIKwYBBQUHAQEENDAyMDAGCCsGAQUFBzABhiRodHRwOi8vb2NzcC5hcHBsZS5jb20vb2NzcDAzLWFpcGNhMDcwLwYDVR0fBCgwJjAkoCKgIIYeaHR0cDovL2NybC5hcHBsZS5jb20vYWlwY2EuY3JsMB0GA1UdDgQWBBRPsztIfUSNaiCLQOVDMYL5hruH4jAOBgNVHQ8BAf8EBAMCB4AwDwYJKoZIhvdjZAY6BAIFADANBgkqhkiG9w0BAQsFAAOCAQEAP44cFOLwsvb_dVEWxh0DGYwdt-PnsJMYi76pcsUEhG4O2XscXyM6Iy-r_ILncpnbI6B1w2JOhGfLjsAsTsbilw_h0AdfXNiM93uQ7R3QAN6zZwIXbVs-82myx9PJV2TRrgJGzAt6I0LQcv11D6dZC_7VVGZFu6HlvcU9C0AQy19-ifAN32E-p3NBeGVWeZWGZRtm9QxOCq5uX-1HUrDyZ3YBpKIvhXNWFSARqVcSBWu8sPcbRjhdNf__mMZpCRNlH03Fuyutu6zgtIAu3gGzvhIn8SmRhyym5WGVP65-NQtcLg5N8jZPsYEIy6_ZYl6t7zppIJugeLueH3xKgW56JTCCBEQwggMsoAMCAQICCFxjyuRKN1PJMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAlVTMRMwEQYDVQQKEwpBcHBsZSBJbmMuMSYwJAYDVQQLEx1BcHBsZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEWMBQGA1UEAxMNQXBwbGUgUm9vdCBDQTAeFw0xNzA1MTAyMTI3MzBaFw0zMDEyMzEwMDAwMDBaMHMxLTArBgNVBAMMJEFwcGxlIGlQaG9uZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEgMB4GA1UECwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEzARBgNVBAoMCkFwcGxlIEluYy4xCzAJBgNVBAYTAlVTMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyUVqAQ8-gwSGx_y_3F7wHoHuFzBzYyYu3j16JM2TPk85R7p1vvPA0vFZoqsf_gqGPNktmgfyDmu5KZEaXyIKi_FyWAWuTEtExXmngDywiOCMDCeEXRnlhxk2y-PFdrew9EFyUfQFXINLom2mUbjxJt97Xq1lDMaymFGMu30bTMFOyAjH0u1kC7TdG41PQH0bj0iWklvz0Jh-2bykGQ6ZYbtBXQHMW3d6fSTQ3NNT_8PcxZQstlpNjhgjOb3ZxlI-0fL0JYqhKof92AxGKVH_7RdsiSVrh7-KaRSfd5_DFbdos4hFvYTmBgJBZA-tKii4FcngrKeKunIENLJ4jPiyhQIDAQABo4HsMIHpMA8GA1UdEwEB_wQFMAMBAf8wHwYDVR0jBBgwFoAUK9BpR5R2Cf70a40uQKb3R01_CF4wRAYIKwYBBQUHAQEEODA2MDQGCCsGAQUFBzABhihodHRwOi8vb2NzcC5hcHBsZS5jb20vb2NzcDAzLWFwcGxlcm9vdGNhMC4GA1UdHwQnMCUwI6AhoB-GHWh0dHA6Ly9jcmwuYXBwbGUuY29tL3Jvb3QuY3JsMB0GA1UdDgQWBBRv8ZUYYlzgyPHF7WwYyeDTZFKYIDAOBgNVHQ8BAf8EBAMCAQYwEAYKKoZIhvdjZAYCEgQCBQAwDQYJKoZIhvcNAQELBQADggEBADrPrJiNvpIgIQmtlfOxXCH6Ni1XIER0c2SSCLOWrPdtl_pbNDgnzxJG0zwR8AfJmZCx0egRCaXjpWtsYwg_niX61ZmcTOblzo6yTWjsi6ujok-KERU-3BQrHMZEtm9nxVtPlSkth1w_3IMed0_t2lSnLecTgcFjxFQLG0sKaigiCNQ3knx_Zyhfrz0_t6xZHTg0ZFruM0oZQkQpxMoYa-HBUy0t9E3CFfYzMhh48SZvik3rlEyj6P8PswOLZdrrLthlUJ_cn4rfMaiEVNxSUkHSshMdMUZHiF8-7sPyjCMEleusij6CbAafLuOLQ5piWzQN9JnPLO66coYZI6X8jrUwggS7MIIDo6ADAgECAgECMA0GCSqGSIb3DQEBBQUAMGIxCzAJBgNVBAYTAlVTMRMwEQYDVQQKEwpBcHBsZSBJbmMuMSYwJAYDVQQLEx1BcHBsZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEWMBQGA1UEAxMNQXBwbGUgUm9vdCBDQTAeFw0wNjA0MjUyMTQwMzZaFw0zNTAyMDkyMTQwMzZaMGIxCzAJBgNVBAYTAlVTMRMwEQYDVQQKEwpBcHBsZSBJbmMuMSYwJAYDVQQLEx1BcHBsZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEWMBQGA1UEAxMNQXBwbGUgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOSRqQkfkdseR1DrBe1eeYQt6zaiV0xV7IsZid75S2z1B6siMALoGD74UAnTf0GomPnRymacJGsR0KO75Bsqwx-VnnoMpEeLW9QWNzPLxA9NzhRp0ckZcvVdDtV_X5vyJQO6VY9NXQ3xZDUjFUsVWR2zlPf2nJ7PULrBWFBnjwi0IPfLrCwgb3C2PwEwjLdDzw-dPfMrSSgayP7OtbkO2V4c1ss9tTqt9A8OAJILsSEWLnTVPA3bYharo3GSR1NVwa8vQbP4--NwzeajTEV-H0xrUJZBicR0YgsQg0GHM4qBsTBY7FoEMoxos48d3mVz_2deZbxJ2HafMxRloXeUyS0CAwEAAaOCAXowggF2MA4GA1UdDwEB_wQEAwIBBjAPBgNVHRMBAf8EBTADAQH_MB0GA1UdDgQWBBQr0GlHlHYJ_vRrjS5ApvdHTX8IXjAfBgNVHSMEGDAWgBQr0GlHlHYJ_vRrjS5ApvdHTX8IXjCCAREGA1UdIASCAQgwggEEMIIBAAYJKoZIhvdjZAUBMIHyMCoGCCsGAQUFBwIBFh5odHRwczovL3d3dy5hcHBsZS5jb20vYXBwbGVjYS8wgcMGCCsGAQUFBwICMIG2GoGzUmVsaWFuY2Ugb24gdGhpcyBjZXJ0aWZpY2F0ZSBieSBhbnkgcGFydHkgYXNzdW1lcyBhY2NlcHRhbmNlIG9mIHRoZSB0aGVuIGFwcGxpY2FibGUgc3RhbmRhcmQgdGVybXMgYW5kIGNvbmRpdGlvbnMgb2YgdXNlLCBjZXJ0aWZpY2F0ZSBwb2xpY3kgYW5kIGNlcnRpZmljYXRpb24gcHJhY3RpY2Ugc3RhdGVtZW50cy4wDQYJKoZIhvcNAQEFBQADggEBAFw2mUwteLftjJvc83eb8nbSdzBPwR-Fg4UbmT1HN_Kpm0COLNSxkBLYvvRzm-7SZA_LeU802KI--Xj_a8gH7H05g4tTINM4xLG_mk8Ka_8r_FmnBQl8F0BWER5007eLIztHo9VvJOLr0bdw3w9F4SfK8W147ee1Fxeo3H4iNcol1dkP1mvUoiQjEfehrI9zgWDGG1sJL5Ky-ERI8GA4nhX1PSZnIIozavcNgs_e66Mv-VNqW2TAYzN39zoHLFbr2g8hDtq6cxlPtdk2f8GHVdmnmbkyQvvY1XGefqFStxu9k0IkEirHDx22TZxeY8hLgBdQqorV2uT80AkHN7B1dSExggKFMIICgQIBATB_MHMxLTArBgNVBAMMJEFwcGxlIGlQaG9uZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEgMB4GA1UECwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEzARBgNVBAoMCkFwcGxlIEluYy4xCzAJBgNVBAYTAlVTAghHPExh8pmI1DAJBgUrDgMCGgUAoIHcMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTIzMDUyMjE2NTcyOFowIwYJKoZIhvcNAQkEMRYEFBk0Jou5Q9k_Gz261EnWre3Q-OPtMCkGCSqGSIb3DQEJNDEcMBowCQYFKw4DAhoFAKENBgkqhkiG9w0BAQEFADBSBgkqhkiG9w0BCQ8xRTBDMAoGCCqGSIb3DQMHMA4GCCqGSIb3DQMCAgIAgDANBggqhkiG9w0DAgIBQDAHBgUrDgMCBzANBggqhkiG9w0DAgIBKDANBgkqhkiG9w0BAQEFAASCAQDjOe_MP0OcjbZQC0lu6X5sf4MoUVimMKvnJgNLVgYPtZXufz6-_P98rgh5EPtPb-UBi1MPh2w6mHr-i9qZxklMR3sa-CuVwlkFFrPthelMfZU0YsMBv2zAOD5ZWnUrMc1Tc4myrZEK4DoNVtSG5kS5TvU_F_Cd3gPuCML4DIzrfaRMW9u9h_VehOcQIlultruQn2Wl1ihmi2_D8Q5fXF4E1dXe-a5ohdKCLWCXa7IhW818nfFbophoVDN4ymAY_1bMXp4iLa06iXXfZqQJqHnG2rFsUSLsGX49qSnNtR-1N23EtHgJQMqQpTz8C6VKI93ySOC3ijSqvRnm4Dgdl0HZ'; + return apply_filters( + 'woocommerce_paypal_payments_applepay_live_validation_string', + '7B227073704964223A2246354246304143324336314131413238313043373531453439333444414433384346393037313041303935303844314133453241383436314141363232414145222C2276657273696F6E223A312C22637265617465644F6E223A313633343737323736393531342C227369676E6174757265223A223330383030363039326138363438383666373064303130373032613038303330383030323031303133313066333030643036303936303836343830313635303330343032303130353030333038303036303932613836343838366637306430313037303130303030613038303330383230336533333038323033383861303033303230313032303230383463333034313439353139643534333633303061303630383261383634386365336430343033303233303761333132653330326330363033353530343033306332353431373037303663363532303431373037303663363936333631373436393666366532303439366537343635363737323631373436393666366532303433343132303264323034373333333132363330323430363033353530343062306331643431373037303663363532303433363537323734363936363639363336313734363936663665323034313735373436383666373236393734373933313133333031313036303335353034306130633061343137303730366336353230343936653633326533313062333030393036303335353034303631333032353535333330316531373064333133393330333533313338333033313333333233353337356131373064333233343330333533313336333033313333333233353337356133303566333132353330323330363033353530343033306331633635363336333264373336643730326436323732366636623635373232643733363936373665356635353433333432643530353234663434333131343330313230363033353530343062306330623639346635333230353337393733373436353664373333313133333031313036303335353034306130633061343137303730366336353230343936653633326533313062333030393036303335353034303631333032353535333330353933303133303630373261383634386365336430323031303630383261383634386365336430333031303730333432303030346332313537376564656264366337623232313866363864643730393061313231386463376230626436663263323833643834363039356439346166346135343131623833343230656438313166333430376538333333316631633534633366376562333232306436626164356434656666343932383938393365376330663133613338323032313133303832303230643330306330363033353531643133303130316666303430323330303033303166303630333535316432333034313833303136383031343233663234396334346639336534656632376536633466363238366333666132626266643265346233303435303630383262303630313035303530373031303130343339333033373330333530363038326230363031303530353037333030313836323936383734373437303361326632663666363337333730326536313730373036633635326536333666366432663666363337333730333033343264363137303730366336353631363936333631333333303332333038323031316430363033353531643230303438323031313433303832303131303330383230313063303630393261383634383836663736333634303530313330383166653330383163333036303832623036303130353035303730323032333038316236306338316233353236353663363936313665363336353230366636653230373436383639373332303633363537323734363936363639363336313734363532303632373932303631366537393230373036313732373437393230363137333733373536643635373332303631363336333635373037343631366536333635323036663636323037343638363532303734363836353665323036313730373036633639363336313632366336353230373337343631366536343631373236343230373436353732366437333230363136653634323036333666366536343639373436393666366537333230366636363230373537333635326332303633363537323734363936363639363336313734363532303730366636633639363337393230363136653634323036333635373237343639363636393633363137343639366636653230373037323631363337343639363336353230373337343631373436353664363536653734373332653330333630363038326230363031303530353037303230313136326136383734373437303361326632663737373737373265363137303730366336353265363336663664326636333635373237343639363636393633363137343635363137353734363836663732363937343739326633303334303630333535316431663034326433303262333032396130323761303235383632333638373437343730336132663266363337323663326536313730373036633635326536333666366432663631373037303663363536313639363336313333326536333732366333303164303630333535316430653034313630343134393435376462366664353734383138363839383937363266376535373835303765373962353832343330306530363033353531643066303130316666303430343033303230373830333030663036303932613836343838366637363336343036316430343032303530303330306130363038326138363438636533643034303330323033343930303330343630323231303062653039353731666537316531653733356235356535616661636234633732666562343435663330313835323232633732353130303262363165626436663535303232313030643138623335306135646436646436656231373436303335623131656232636538376366613365366166366362643833383038393064633832636464616136333330383230326565333038323032373561303033303230313032303230383439366432666266336139386461393733303061303630383261383634386365336430343033303233303637333131623330313930363033353530343033306331323431373037303663363532303532366636663734323034333431323032643230343733333331323633303234303630333535303430623063316434313730373036633635323034333635373237343639363636393633363137343639366636653230343137353734363836663732363937343739333131333330313130363033353530343061306330613431373037303663363532303439366536333265333130623330303930363033353530343036313330323535353333303165313730643331333433303335333033363332333333343336333333303561313730643332333933303335333033363332333333343336333333303561333037613331326533303263303630333535303430333063323534313730373036633635323034313730373036633639363336313734363936663665323034393665373436353637373236313734363936663665323034333431323032643230343733333331323633303234303630333535303430623063316434313730373036633635323034333635373237343639363636393633363137343639366636653230343137353734363836663732363937343739333131333330313130363033353530343061306330613431373037303663363532303439366536333265333130623330303930363033353530343036313330323535353333303539333031333036303732613836343863653364303230313036303832613836343863653364303330313037303334323030303466303137313138343139643736343835643531613565323538313037373665383830613265666465376261653464653038646663346239336531333335366435363635623335616532326430393737363064323234653762626130386664373631376365383863623736626236363730626563386538323938346666353434356133383166373330383166343330343630363038326230363031303530353037303130313034336133303338333033363036303832623036303130353035303733303031383632613638373437343730336132663266366636333733373032653631373037303663363532653633366636643266366636333733373033303334326436313730373036633635373236663666373436333631363733333330316430363033353531643065303431363034313432336632343963343466393365346566323765366334663632383663336661326262666432653462333030663036303335353164313330313031666630343035333030333031303166663330316630363033353531643233303431383330313638303134626262306465613135383333383839616134386139396465626562646562616664616362323461623330333730363033353531643166303433303330326533303263613032616130323838363236363837343734373033613266326636333732366332653631373037303663363532653633366636643266363137303730366336353732366636663734363336313637333332653633373236633330306530363033353531643066303130316666303430343033303230313036333031303036306132613836343838366637363336343036303230653034303230353030333030613036303832613836343863653364303430333032303336373030333036343032333033616366373238333531313639396231383666623335633335366361363262666634313765646439306637353464613238656265663139633831356534326237383966383938663739623539396639386435343130643866396465396332666530323330333232646435343432316230613330353737366335646633333833623930363766643137376332633231366439363466633637323639383231323666353466383761376431623939636239623039383932313631303639393066303939323164303030303331383230313863333038323031383830323031303133303831383633303761333132653330326330363033353530343033306332353431373037303663363532303431373037303663363936333631373436393666366532303439366537343635363737323631373436393666366532303433343132303264323034373333333132363330323430363033353530343062306331643431373037303663363532303433363537323734363936363639363336313734363936663665323034313735373436383666373236393734373933313133333031313036303335353034306130633061343137303730366336353230343936653633326533313062333030393036303335353034303631333032353535333032303834633330343134393531396435343336333030643036303936303836343830313635303330343032303130353030613038313935333031383036303932613836343838366637306430313039303333313062303630393261383634383836663730643031303730313330316330363039326138363438383666373064303130393035333130663137306433323331333133303332333033323333333333323334333935613330326130363039326138363438383666373064303130393334333131643330316233303064303630393630383634383031363530333034303230313035303061313061303630383261383634386365336430343033303233303266303630393261383634383836663730643031303930343331323230343230623935666665303261316539316665656565396330623239616361656661643465333031396331666237626238313665366631623762343233346666306533353330306130363038326138363438636533643034303330323034343733303435303232303665356233363937366364383733653632623339326330353136633134326362356639303938663330323535656435343938633436393039356133636462346430323231303038396261626335356162626635653037393163633139373562306535383630633937336532336661313266643338343533303930353938343061326363363337303030303030303030303030227D' + ); } } From e8158d1ab393df7a0741781f09a238f5837e67ef Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Thu, 19 Oct 2023 17:43:51 +0100 Subject: [PATCH 11/22] Fix for ApplePay notice to reflect immediately upon save. --- .../ppcp-applepay/src/Helper/AvailabilityNotice.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/modules/ppcp-applepay/src/Helper/AvailabilityNotice.php b/modules/ppcp-applepay/src/Helper/AvailabilityNotice.php index 6717d6be8..e38f9a2c2 100644 --- a/modules/ppcp-applepay/src/Helper/AvailabilityNotice.php +++ b/modules/ppcp-applepay/src/Helper/AvailabilityNotice.php @@ -124,7 +124,17 @@ class AvailabilityNotice { $this->add_server_not_supported_notice(); } - if ( ! $this->button->is_enabled() ) { + $button_enabled = $this->button->is_enabled(); + + // We do this check on $_POST because this is called before settings are saved. + // phpcs:ignore WordPress.Security.NonceVerification.Missing + if ( isset( $_POST['ppcp'] ) ) { + // phpcs:ignore WordPress.Security.NonceVerification.Missing + $post_data = wc_clean( (array) wp_unslash( $_POST['ppcp'] ) ); + $button_enabled = wc_string_to_bool( $post_data['applepay_button_enabled'] ?? false ); + } + + if ( ! $button_enabled ) { return; } From b11a539c2402c82856fbee7bb6c31c7476cce7df Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Thu, 19 Oct 2023 18:44:44 +0100 Subject: [PATCH 12/22] Refactor styles loading on GooglePay and ApplePay Remove unnecessary console.log on GooglePay and ApplePay --- modules/ppcp-applepay/resources/js/boot.js | 1 - modules/ppcp-applepay/src/ApplepayModule.php | 12 +++++++-- .../src/Assets/ApplePayButton.php | 25 +++++++++++++------ .../resources/js/GooglepayButton.js | 1 - modules/ppcp-googlepay/src/Assets/Button.php | 23 ++++++++++++----- .../ppcp-googlepay/src/GooglepayModule.php | 15 ++++++++--- 6 files changed, 56 insertions(+), 21 deletions(-) diff --git a/modules/ppcp-applepay/resources/js/boot.js b/modules/ppcp-applepay/resources/js/boot.js index 3830929ef..42607e6da 100644 --- a/modules/ppcp-applepay/resources/js/boot.js +++ b/modules/ppcp-applepay/resources/js/boot.js @@ -20,7 +20,6 @@ import ApplepayManager from "./ApplepayManager"; (typeof (buttonConfig) === 'undefined') || (typeof (ppcpConfig) === 'undefined') ) { - console.error('PayPal button could not be configured.'); return; } const isMiniCart = ppcpConfig.mini_cart_buttons_enabled; diff --git a/modules/ppcp-applepay/src/ApplepayModule.php b/modules/ppcp-applepay/src/ApplepayModule.php index c941797e2..dee06dad6 100644 --- a/modules/ppcp-applepay/src/ApplepayModule.php +++ b/modules/ppcp-applepay/src/ApplepayModule.php @@ -136,10 +136,18 @@ class ApplepayModule implements ModuleInterface { assert( $button instanceof ApplePayButton ); $smart_button = $c->get( 'button.smart-button' ); assert( $smart_button instanceof SmartButtonInterface ); - $page_has_block = has_block( 'woocommerce/checkout' ) || has_block( 'woocommerce/cart' ); - if ( $smart_button->should_load_ppcp_script() || $page_has_block ) { + if ( $smart_button->should_load_ppcp_script() ) { $button->enqueue(); } + + if ( has_block( 'woocommerce/checkout' ) || has_block( 'woocommerce/cart' ) ) { + /** + * Should add this to the ButtonInterface. + * + * @psalm-suppress UndefinedInterfaceMethod + */ + $button->enqueue_styles(); + } } ); add_action( diff --git a/modules/ppcp-applepay/src/Assets/ApplePayButton.php b/modules/ppcp-applepay/src/Assets/ApplePayButton.php index a4ff3ca67..f27950fcd 100644 --- a/modules/ppcp-applepay/src/Assets/ApplePayButton.php +++ b/modules/ppcp-applepay/src/Assets/ApplePayButton.php @@ -1017,13 +1017,7 @@ class ApplePayButton implements ButtonInterface { ); wp_enqueue_script( 'wc-ppcp-applepay' ); - wp_register_style( - 'wc-ppcp-applepay', - untrailingslashit( $this->module_url ) . '/assets/css/styles.css', - array(), - $this->version - ); - wp_enqueue_style( 'wc-ppcp-applepay' ); + $this->enqueue_styles(); wp_localize_script( 'wc-ppcp-applepay', @@ -1038,6 +1032,23 @@ class ApplePayButton implements ButtonInterface { ); } + /** + * Enqueues styles. + */ + public function enqueue_styles(): void { + if ( ! $this->is_enabled() ) { + return; + } + + wp_register_style( + 'wc-ppcp-applepay', + untrailingslashit( $this->module_url ) . '/assets/css/styles.css', + array(), + $this->version + ); + wp_enqueue_style( 'wc-ppcp-applepay' ); + } + /** * Returns the script data. * diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index 57d29a75d..9ecb778d5 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -189,7 +189,6 @@ class GooglepayButton { callback(el); } else if (timeElapsed > timeout) { clearInterval(interval); - console.error('Waiting for wrapper timed out.', selector); } }, delay); } diff --git a/modules/ppcp-googlepay/src/Assets/Button.php b/modules/ppcp-googlepay/src/Assets/Button.php index b4ad9c297..6609ef0e1 100644 --- a/modules/ppcp-googlepay/src/Assets/Button.php +++ b/modules/ppcp-googlepay/src/Assets/Button.php @@ -363,6 +363,23 @@ class Button implements ButtonInterface { ); wp_enqueue_script( 'wc-ppcp-googlepay' ); + $this->enqueue_styles(); + + wp_localize_script( + 'wc-ppcp-googlepay', + 'wc_ppcp_googlepay', + $this->script_data() + ); + } + + /** + * Enqueues styles. + */ + public function enqueue_styles(): void { + if ( ! $this->is_enabled() ) { + return; + } + wp_register_style( 'wc-ppcp-googlepay', untrailingslashit( $this->module_url ) . '/assets/css/styles.css', @@ -370,12 +387,6 @@ class Button implements ButtonInterface { $this->version ); wp_enqueue_style( 'wc-ppcp-googlepay' ); - - wp_localize_script( - 'wc-ppcp-googlepay', - 'wc_ppcp_googlepay', - $this->script_data() - ); } /** diff --git a/modules/ppcp-googlepay/src/GooglepayModule.php b/modules/ppcp-googlepay/src/GooglepayModule.php index 614647181..2365ab23f 100644 --- a/modules/ppcp-googlepay/src/GooglepayModule.php +++ b/modules/ppcp-googlepay/src/GooglepayModule.php @@ -89,11 +89,18 @@ class GooglepayModule implements ModuleInterface { static function () use ( $c, $button ) { $smart_button = $c->get( 'button.smart-button' ); assert( $smart_button instanceof SmartButtonInterface ); - $page_has_block = has_block( 'woocommerce/checkout' ) || has_block( 'woocommerce/cart' ); - if ( ! $smart_button->should_load_ppcp_script() && ! $page_has_block ) { - return; + if ( $smart_button->should_load_ppcp_script() ) { + $button->enqueue(); + } + + if ( has_block( 'woocommerce/checkout' ) || has_block( 'woocommerce/cart' ) ) { + /** + * Should add this to the ButtonInterface. + * + * @psalm-suppress UndefinedInterfaceMethod + */ + $button->enqueue_styles(); } - $button->enqueue(); } ); From 3ccd38e4ddc99e397206c74f6dd5ac4784564956 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Fri, 20 Oct 2023 09:38:32 +0100 Subject: [PATCH 13/22] Fix disabling of clicks on disabled buttons --- modules/ppcp-button/resources/css/gateway.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/ppcp-button/resources/css/gateway.scss b/modules/ppcp-button/resources/css/gateway.scss index f78d1b5b9..42b216e92 100644 --- a/modules/ppcp-button/resources/css/gateway.scss +++ b/modules/ppcp-button/resources/css/gateway.scss @@ -6,6 +6,10 @@ cursor: not-allowed; -webkit-filter: grayscale(100%); filter: grayscale(100%); + + * { + pointer-events: none; + } } .ppc-button-wrapper #ppcp-messages:first-child { From 2154649a7bf6c5541a6622c769177fd6344f5965 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Fri, 20 Oct 2023 11:46:58 +0100 Subject: [PATCH 14/22] Fix GooglePay and ApplePay onboarding links. --- .../ppcp-applepay/src/Assets/ApplePayButton.php | 15 --------------- modules/ppcp-googlepay/src/Assets/Button.php | 15 --------------- 2 files changed, 30 deletions(-) diff --git a/modules/ppcp-applepay/src/Assets/ApplePayButton.php b/modules/ppcp-applepay/src/Assets/ApplePayButton.php index a4ff3ca67..6899e732d 100644 --- a/modules/ppcp-applepay/src/Assets/ApplePayButton.php +++ b/modules/ppcp-applepay/src/Assets/ApplePayButton.php @@ -178,21 +178,6 @@ class ApplePayButton implements ButtonInterface { $data['products'][0] = 'PAYMENT_METHODS'; } $data['capabilities'][] = 'APPLE_PAY'; - $data['operations'][] = array( - 'operation' => 'API_INTEGRATION', - 'api_integration_preference' => array( - 'rest_api_integration' => array( - 'integration_method' => 'PAYPAL', - 'integration_type' => 'THIRD_PARTY', - 'third_party_details' => array( - 'features' => array( - 'PAYMENT', - 'REFUND', - ), - ), - ), - ), - ); return $data; } diff --git a/modules/ppcp-googlepay/src/Assets/Button.php b/modules/ppcp-googlepay/src/Assets/Button.php index b4ad9c297..d8dc15cef 100644 --- a/modules/ppcp-googlepay/src/Assets/Button.php +++ b/modules/ppcp-googlepay/src/Assets/Button.php @@ -204,21 +204,6 @@ class Button implements ButtonInterface { } $data['capabilities'][] = 'GOOGLE_PAY'; - $data['operations'][] = array( - 'operation' => 'API_INTEGRATION', - 'api_integration_preference' => array( - 'rest_api_integration' => array( - 'integration_method' => 'PAYPAL', - 'integration_type' => 'THIRD_PARTY', - 'third_party_details' => array( - 'features' => array( - 'PAYMENT', - 'REFUND', - ), - ), - ), - ), - ); return $data; } From 7f2836845e6774c13096b083bb8aa93ba93b3698 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Fri, 20 Oct 2023 18:13:09 +0100 Subject: [PATCH 15/22] Fixes ApplePay payment process --- .../resources/js/ApplepayButton.js | 48 ++++++++++++++++++- .../resources/js/ApplepayManager.js | 6 +++ modules/ppcp-applepay/resources/js/boot.js | 10 +++- .../src/Assets/ApplePayButton.php | 9 +--- .../src/Assets/ApplePayDataObjectHttp.php | 1 + 5 files changed, 64 insertions(+), 10 deletions(-) diff --git a/modules/ppcp-applepay/resources/js/ApplepayButton.js b/modules/ppcp-applepay/resources/js/ApplepayButton.js index e0fe0992d..b98493b8c 100644 --- a/modules/ppcp-applepay/resources/js/ApplepayButton.js +++ b/modules/ppcp-applepay/resources/js/ApplepayButton.js @@ -43,6 +43,8 @@ class ApplepayButton { if (this.isInitialized) { return; } + + this.log('Init', this.context); this.initEventHandlers(); this.isInitialized = true; this.applePayConfig = config; @@ -76,6 +78,16 @@ class ApplepayButton { }); } } + + reinit() { + if (!this.applePayConfig) { + return; + } + + this.isInitialized = false; + this.init(this.applePayConfig); + } + async fetchTransactionInfo() { this.transactionInfo = await this.contextHandler.transactionInfo(); } @@ -123,6 +135,7 @@ class ApplepayButton { } applePaySession(paymentRequest) { + this.log('applePaySession', paymentRequest); const session = new ApplePaySession(4, paymentRequest) session.begin() @@ -172,6 +185,8 @@ class ApplepayButton { * Show Apple Pay payment sheet when Apple Pay payment button is clicked */ async onButtonClick() { + this.log('onButtonClick', this.context); + const paymentDataRequest = this.paymentDataRequest(); // trigger woocommerce validation if we are in the checkout page if (this.context === 'checkout') { @@ -247,11 +262,15 @@ class ApplepayButton { //------------------------ onvalidatemerchant(session) { + this.log('onvalidatemerchant', this.buttonConfig.ajax_url); return (applePayValidateMerchantEvent) => { + this.log('onvalidatemerchant call'); + paypal.Applepay().validateMerchant({ validationUrl: applePayValidateMerchantEvent.validationURL }) .then(validateResult => { + this.log('onvalidatemerchant ok'); session.completeMerchantValidation(validateResult.merchantSession); //call backend to update validation to true jQuery.ajax({ @@ -265,6 +284,7 @@ class ApplepayButton { }) }) .catch(validateError => { + this.log('onvalidatemerchant error', validateError); console.error(validateError); //call backend to update validation to false jQuery.ajax({ @@ -276,19 +296,24 @@ class ApplepayButton { 'woocommerce-process-checkout-nonce': this.nonce, } }) + this.log('onvalidatemerchant session abort'); session.abort(); }); }; } onshippingmethodselected(session) { + this.log('onshippingmethodselected', this.buttonConfig.ajax_url); const ajax_url = this.buttonConfig.ajax_url return (event) => { + this.log('onshippingmethodselected call'); + const data = this.getShippingMethodData(event); jQuery.ajax({ url: ajax_url, method: 'POST', data: data, success: (applePayShippingMethodUpdate, textStatus, jqXHR) => { + this.log('onshippingmethodselected ok'); let response = applePayShippingMethodUpdate.data if (applePayShippingMethodUpdate.success === false) { response.errors = createAppleErrors(response.errors) @@ -309,6 +334,7 @@ class ApplepayButton { session.completeShippingMethodSelection(response) }, error: (jqXHR, textStatus, errorThrown) => { + this.log('onshippingmethodselected error', textStatus); console.warn(textStatus, errorThrown) session.abort() }, @@ -316,14 +342,18 @@ class ApplepayButton { }; } onshippingcontactselected(session) { + this.log('onshippingcontactselected', this.buttonConfig.ajax_url); const ajax_url = this.buttonConfig.ajax_url return (event) => { + this.log('onshippingcontactselected call'); + const data = this.getShippingContactData(event); jQuery.ajax({ url: ajax_url, method: 'POST', data: data, success: (applePayShippingContactUpdate, textStatus, jqXHR) => { + this.log('onshippingcontactselected ok'); let response = applePayShippingContactUpdate.data this.updated_contact_info = event.shippingContact if (applePayShippingContactUpdate.success === false) { @@ -332,9 +362,9 @@ class ApplepayButton { if (response.newShippingMethods) { this.selectedShippingMethod = response.newShippingMethods[0] } - session.completeShippingContactSelection(response) }, error: (jqXHR, textStatus, errorThrown) => { + this.log('onshippingcontactselected error', textStatus); console.warn(textStatus, errorThrown) session.abort() }, @@ -397,7 +427,10 @@ class ApplepayButton { } onpaymentauthorized(session) { + this.log('onpaymentauthorized'); return async (event) => { + this.log('onpaymentauthorized call'); + function form() { return document.querySelector('form.cart'); } @@ -420,32 +453,45 @@ class ApplepayButton { '_wp_http_referer': '/?wc-ajax=update_order_review', 'paypal_order_id': data.paypal_order_id, }; + + this.log('onpaymentauthorized request', this.buttonConfig.ajax_url, data); + jQuery.ajax({ url: this.buttonConfig.ajax_url, method: 'POST', data: request_data, complete: (jqXHR, textStatus) => { + this.log('onpaymentauthorized complete'); }, success: (authorizationResult, textStatus, jqXHR) => { + this.log('onpaymentauthorized ok'); resolve(authorizationResult) }, error: (jqXHR, textStatus, errorThrown) => { + this.log('onpaymentauthorized error', textStatus); reject(new Error(errorThrown)); }, }) } catch (error) { + this.log('onpaymentauthorized catch', error); console.log(error) // handle error } }); } let id = await this.contextHandler.createOrder(); + + this.log('onpaymentauthorized paypal order ID', id, event.payment.token, event.payment.billingContact); + try { const confirmOrderResponse = await paypal.Applepay().confirmOrder({ orderId: id, token: event.payment.token, billingContact: event.payment.billingContact, }); + + this.log('onpaymentauthorized confirmOrderResponse', confirmOrderResponse); + if (confirmOrderResponse && confirmOrderResponse.approveApplePayPayment) { if (confirmOrderResponse.approveApplePayPayment.status === "APPROVED") { try { diff --git a/modules/ppcp-applepay/resources/js/ApplepayManager.js b/modules/ppcp-applepay/resources/js/ApplepayManager.js index 807ea941d..fa9622143 100644 --- a/modules/ppcp-applepay/resources/js/ApplepayManager.js +++ b/modules/ppcp-applepay/resources/js/ApplepayManager.js @@ -35,6 +35,12 @@ class ApplepayManager { })(); } + reinit() { + for (const button of this.buttons) { + button.reinit(); + } + } + /** * Gets ApplePay configuration of the PayPal merchant. * @returns {Promise} diff --git a/modules/ppcp-applepay/resources/js/boot.js b/modules/ppcp-applepay/resources/js/boot.js index 3830929ef..03ea7f857 100644 --- a/modules/ppcp-applepay/resources/js/boot.js +++ b/modules/ppcp-applepay/resources/js/boot.js @@ -8,11 +8,19 @@ import ApplepayManager from "./ApplepayManager"; jQuery }) { + let manager; + const bootstrap = function () { - const manager = new ApplepayManager(buttonConfig, ppcpConfig); + manager = new ApplepayManager(buttonConfig, ppcpConfig); manager.init(); }; + jQuery(document.body).on('updated_cart_totals updated_checkout', () => { + if (manager) { + manager.reinit(); + } + }); + document.addEventListener( 'DOMContentLoaded', () => { diff --git a/modules/ppcp-applepay/src/Assets/ApplePayButton.php b/modules/ppcp-applepay/src/Assets/ApplePayButton.php index 2237423d6..e7152b74c 100644 --- a/modules/ppcp-applepay/src/Assets/ApplePayButton.php +++ b/modules/ppcp-applepay/src/Assets/ApplePayButton.php @@ -12,23 +12,16 @@ namespace WooCommerce\PayPalCommerce\Applepay\Assets; use Exception; use Psr\Log\LoggerInterface; use WC_Cart; -use WC_Checkout; use WC_Order; -use WC_Session_Handler; -use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint; -use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus; use WooCommerce\PayPalCommerce\Button\Assets\ButtonInterface; -use WooCommerce\PayPalCommerce\Session\MemoryWcSession; -use WooCommerce\PayPalCommerce\Session\SessionHandler; use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException; -use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; use WooCommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus; use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderProcessor; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; use WooCommerce\PayPalCommerce\Webhooks\Handler\RequestHandlerTrait; /** - * Class PayPalPaymentMethod + * Class ApplePayButton */ class ApplePayButton implements ButtonInterface { use RequestHandlerTrait; diff --git a/modules/ppcp-applepay/src/Assets/ApplePayDataObjectHttp.php b/modules/ppcp-applepay/src/Assets/ApplePayDataObjectHttp.php index 7b93ab088..ddc05a9fe 100644 --- a/modules/ppcp-applepay/src/Assets/ApplePayDataObjectHttp.php +++ b/modules/ppcp-applepay/src/Assets/ApplePayDataObjectHttp.php @@ -300,6 +300,7 @@ class ApplePayDataObjectHttp { */ protected function assign_data_object_values( array $data ): void { foreach ( $data as $key => $value ) { + // Null values may give origin to type errors. If necessary replace condition this with a specialized field filter. if ( null === $value ) { continue; } From 6930422188ee5a1964fb6ca93f494d2d40965506 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Fri, 20 Oct 2023 19:07:07 +0100 Subject: [PATCH 16/22] Fix ApplePay button --- modules/ppcp-applepay/resources/js/ApplepayButton.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/ppcp-applepay/resources/js/ApplepayButton.js b/modules/ppcp-applepay/resources/js/ApplepayButton.js index b98493b8c..23b912fe5 100644 --- a/modules/ppcp-applepay/resources/js/ApplepayButton.js +++ b/modules/ppcp-applepay/resources/js/ApplepayButton.js @@ -362,6 +362,7 @@ class ApplepayButton { if (response.newShippingMethods) { this.selectedShippingMethod = response.newShippingMethods[0] } + session.completeShippingContactSelection(response) }, error: (jqXHR, textStatus, errorThrown) => { this.log('onshippingcontactselected error', textStatus); From 2eeff9a3bcba19bd7b8dff5c6e78d1e422cc8ea9 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Sun, 22 Oct 2023 17:32:21 +0100 Subject: [PATCH 17/22] Add ApplePay reactivity to product quantity --- .../resources/js/ApplepayButton.js | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/modules/ppcp-applepay/resources/js/ApplepayButton.js b/modules/ppcp-applepay/resources/js/ApplepayButton.js index 23b912fe5..15615d7ee 100644 --- a/modules/ppcp-applepay/resources/js/ApplepayButton.js +++ b/modules/ppcp-applepay/resources/js/ApplepayButton.js @@ -24,9 +24,7 @@ class ApplepayButton { ); //PRODUCT DETAIL PAGE - if(this.context === 'product') { - this.productQuantity = document.querySelector('input.qty').value - } + this.refreshContextData(); this.updated_contact_info = [] this.selectedShippingMethod = [] @@ -198,7 +196,8 @@ class ApplepayButton { try { const formData = new FormData(document.querySelector(checkoutFormSelector)); this.form_saved = Object.fromEntries(formData.entries()); - this.update_request_data_with_form(paymentDataRequest); + // This line should be reviewed, the paypal.Applepay().confirmOrder fails if we add it. + //this.update_request_data_with_form(paymentDataRequest); } catch (error) { console.error(error); } @@ -256,6 +255,14 @@ class ApplepayButton { return paymentDataRequest } + refreshContextData() { + switch (this.context) { + case 'product': + // Refresh product data that makes the price change. + this.productQuantity = document.querySelector('input.qty').value; + break; + } + } //------------------------ // Payment process @@ -375,6 +382,8 @@ class ApplepayButton { getShippingContactData(event) { const product_id = this.buttonConfig.product.id; + this.refreshContextData(); + switch (this.context) { case 'product': return { @@ -402,6 +411,9 @@ class ApplepayButton { } getShippingMethodData(event) { const product_id = this.buttonConfig.product.id; + + this.refreshContextData(); + switch (this.context) { case 'product': return { action: 'ppcp_update_shipping_method', From f47d7cec18bb87d0ff7ec9f5de2c9174f4136be2 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Tue, 24 Oct 2023 11:49:43 +0200 Subject: [PATCH 18/22] Remove payee from purchase units --- modules/ppcp-api-client/services.php | 4 --- .../src/Entity/PurchaseUnit.php | 23 --------------- .../src/Factory/PurchaseUnitFactory.php | 28 ------------------- .../Factory/PurchaseUnitFactoryTest.php | 26 ----------------- 4 files changed, 81 deletions(-) diff --git a/modules/ppcp-api-client/services.php b/modules/ppcp-api-client/services.php index a222f0782..bad667b78 100644 --- a/modules/ppcp-api-client/services.php +++ b/modules/ppcp-api-client/services.php @@ -309,8 +309,6 @@ return array( 'api.factory.purchase-unit' => static function ( ContainerInterface $container ): PurchaseUnitFactory { $amount_factory = $container->get( 'api.factory.amount' ); - $payee_repository = $container->get( 'api.repository.payee' ); - $payee_factory = $container->get( 'api.factory.payee' ); $item_factory = $container->get( 'api.factory.item' ); $shipping_factory = $container->get( 'api.factory.shipping' ); $payments_factory = $container->get( 'api.factory.payments' ); @@ -320,8 +318,6 @@ return array( return new PurchaseUnitFactory( $amount_factory, - $payee_repository, - $payee_factory, $item_factory, $shipping_factory, $payments_factory, diff --git a/modules/ppcp-api-client/src/Entity/PurchaseUnit.php b/modules/ppcp-api-client/src/Entity/PurchaseUnit.php index 820df82af..1f0c5572d 100644 --- a/modules/ppcp-api-client/src/Entity/PurchaseUnit.php +++ b/modules/ppcp-api-client/src/Entity/PurchaseUnit.php @@ -51,13 +51,6 @@ class PurchaseUnit { */ private $description; - /** - * The Payee. - * - * @var Payee|null - */ - private $payee; - /** * The custom id. * @@ -108,7 +101,6 @@ class PurchaseUnit { * @param Shipping|null $shipping The Shipping. * @param string $reference_id The reference ID. * @param string $description The description. - * @param Payee|null $payee The Payee. * @param string $custom_id The custom ID. * @param string $invoice_id The invoice ID. * @param string $soft_descriptor The soft descriptor. @@ -120,7 +112,6 @@ class PurchaseUnit { Shipping $shipping = null, string $reference_id = 'default', string $description = '', - Payee $payee = null, string $custom_id = '', string $invoice_id = '', string $soft_descriptor = '', @@ -150,7 +141,6 @@ class PurchaseUnit { } ) ); - $this->payee = $payee; $this->custom_id = $custom_id; $this->invoice_id = $invoice_id; $this->soft_descriptor = $soft_descriptor; @@ -257,15 +247,6 @@ class PurchaseUnit { return $this->soft_descriptor; } - /** - * Returns the Payee. - * - * @return Payee|null - */ - public function payee() { - return $this->payee; - } - /** * Returns the Payments. * @@ -314,10 +295,6 @@ class PurchaseUnit { ), ); - if ( $this->payee() ) { - $purchase_unit['payee'] = $this->payee()->to_array(); - } - if ( $this->payments() ) { $purchase_unit['payments'] = $this->payments()->to_array(); } diff --git a/modules/ppcp-api-client/src/Factory/PurchaseUnitFactory.php b/modules/ppcp-api-client/src/Factory/PurchaseUnitFactory.php index ecb35592b..7642401b1 100644 --- a/modules/ppcp-api-client/src/Factory/PurchaseUnitFactory.php +++ b/modules/ppcp-api-client/src/Factory/PurchaseUnitFactory.php @@ -14,7 +14,6 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\Item; use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\ApiClient\Helper\PurchaseUnitSanitizer; -use WooCommerce\PayPalCommerce\ApiClient\Repository\PayeeRepository; use WooCommerce\PayPalCommerce\Webhooks\CustomIds; /** @@ -29,20 +28,6 @@ class PurchaseUnitFactory { */ private $amount_factory; - /** - * The payee repository. - * - * @var PayeeRepository - */ - private $payee_repository; - - /** - * The payee factory. - * - * @var PayeeFactory - */ - private $payee_factory; - /** * The item factory. * @@ -89,8 +74,6 @@ class PurchaseUnitFactory { * PurchaseUnitFactory constructor. * * @param AmountFactory $amount_factory The amount factory. - * @param PayeeRepository $payee_repository The Payee repository. - * @param PayeeFactory $payee_factory The Payee factory. * @param ItemFactory $item_factory The item factory. * @param ShippingFactory $shipping_factory The shipping factory. * @param PaymentsFactory $payments_factory The payments factory. @@ -100,8 +83,6 @@ class PurchaseUnitFactory { */ public function __construct( AmountFactory $amount_factory, - PayeeRepository $payee_repository, - PayeeFactory $payee_factory, ItemFactory $item_factory, ShippingFactory $shipping_factory, PaymentsFactory $payments_factory, @@ -111,8 +92,6 @@ class PurchaseUnitFactory { ) { $this->amount_factory = $amount_factory; - $this->payee_repository = $payee_repository; - $this->payee_factory = $payee_factory; $this->item_factory = $item_factory; $this->shipping_factory = $shipping_factory; $this->payments_factory = $payments_factory; @@ -146,7 +125,6 @@ class PurchaseUnitFactory { } $reference_id = 'default'; $description = ''; - $payee = $this->payee_repository->payee(); $custom_id = (string) $order->get_id(); $invoice_id = $this->prefix . $order->get_order_number(); $soft_descriptor = $this->soft_descriptor; @@ -157,7 +135,6 @@ class PurchaseUnitFactory { $shipping, $reference_id, $description, - $payee, $custom_id, $invoice_id, $soft_descriptor @@ -211,8 +188,6 @@ class PurchaseUnitFactory { $reference_id = 'default'; $description = ''; - $payee = $this->payee_repository->payee(); - $custom_id = ''; $session = WC()->session; if ( $session instanceof WC_Session_Handler ) { @@ -229,7 +204,6 @@ class PurchaseUnitFactory { $shipping, $reference_id, $description, - $payee, $custom_id, $invoice_id, $soft_descriptor @@ -269,7 +243,6 @@ class PurchaseUnitFactory { $data->items ); } - $payee = isset( $data->payee ) ? $this->payee_factory->from_paypal_response( $data->payee ) : null; $shipping = null; try { if ( isset( $data->shipping ) ) { @@ -293,7 +266,6 @@ class PurchaseUnitFactory { $shipping, $data->reference_id, $description, - $payee, $custom_id, $invoice_id, $soft_descriptor, diff --git a/tests/PHPUnit/ApiClient/Factory/PurchaseUnitFactoryTest.php b/tests/PHPUnit/ApiClient/Factory/PurchaseUnitFactoryTest.php index a693bbb7b..0c3ba52b9 100644 --- a/tests/PHPUnit/ApiClient/Factory/PurchaseUnitFactoryTest.php +++ b/tests/PHPUnit/ApiClient/Factory/PurchaseUnitFactoryTest.php @@ -75,8 +75,6 @@ class PurchaseUnitFactoryTest extends TestCase $paymentsFacory = Mockery::mock(PaymentsFactory::class); $testee = new PurchaseUnitFactory( $amountFactory, - $payeeRepository, - $payeeFactory, $itemFactory, $shippingFactory, $paymentsFacory @@ -139,8 +137,6 @@ class PurchaseUnitFactoryTest extends TestCase $paymentsFacory = Mockery::mock(PaymentsFactory::class); $testee = new PurchaseUnitFactory( $amountFactory, - $payeeRepository, - $payeeFactory, $itemFactory, $shippingFactory, $paymentsFacory @@ -194,8 +190,6 @@ class PurchaseUnitFactoryTest extends TestCase $paymentsFacory = Mockery::mock(PaymentsFactory::class); $testee = new PurchaseUnitFactory( $amountFactory, - $payeeRepository, - $payeeFactory, $itemFactory, $shippingFactory, $paymentsFacory @@ -243,8 +237,6 @@ class PurchaseUnitFactoryTest extends TestCase $paymentsFacory = Mockery::mock(PaymentsFactory::class); $testee = new PurchaseUnitFactory( $amountFactory, - $payeeRepository, - $payeeFactory, $itemFactory, $shippingFactory, $paymentsFacory @@ -299,8 +291,6 @@ class PurchaseUnitFactoryTest extends TestCase $paymentsFacory = Mockery::mock(PaymentsFactory::class); $testee = new PurchaseUnitFactory( $amountFactory, - $payeeRepository, - $payeeFactory, $itemFactory, $shippingFactory, $paymentsFacory @@ -346,8 +336,6 @@ class PurchaseUnitFactoryTest extends TestCase $paymentsFacory = Mockery::mock(PaymentsFactory::class); $testee = new PurchaseUnitFactory( $amountFactory, - $payeeRepository, - $payeeFactory, $itemFactory, $shippingFactory, $paymentsFacory @@ -395,8 +383,6 @@ class PurchaseUnitFactoryTest extends TestCase $paymentsFacory = Mockery::mock(PaymentsFactory::class); $testee = new PurchaseUnitFactory( $amountFactory, - $payeeRepository, - $payeeFactory, $itemFactory, $shippingFactory, $paymentsFacory @@ -427,8 +413,6 @@ class PurchaseUnitFactoryTest extends TestCase $paymentsFacory = Mockery::mock(PaymentsFactory::class); $testee = new PurchaseUnitFactory( $amountFactory, - $payeeRepository, - $payeeFactory, $itemFactory, $shippingFactory, $paymentsFacory @@ -478,8 +462,6 @@ class PurchaseUnitFactoryTest extends TestCase $paymentsFacory = Mockery::mock(PaymentsFactory::class); $testee = new PurchaseUnitFactory( $amountFactory, - $payeeRepository, - $payeeFactory, $itemFactory, $shippingFactory, $paymentsFacory @@ -518,8 +500,6 @@ class PurchaseUnitFactoryTest extends TestCase $paymentsFacory = Mockery::mock(PaymentsFactory::class); $testee = new PurchaseUnitFactory( $amountFactory, - $payeeRepository, - $payeeFactory, $itemFactory, $shippingFactory, $paymentsFacory @@ -550,8 +530,6 @@ class PurchaseUnitFactoryTest extends TestCase $paymentsFacory = Mockery::mock(PaymentsFactory::class); $testee = new PurchaseUnitFactory( $amountFactory, - $payeeRepository, - $payeeFactory, $itemFactory, $shippingFactory, $paymentsFacory @@ -600,8 +578,6 @@ class PurchaseUnitFactoryTest extends TestCase $testee = new PurchaseUnitFactory( $amountFactory, - $payeeRepository, - $payeeFactory, $itemFactory, $shippingFactory, $paymentsFactory @@ -650,8 +626,6 @@ class PurchaseUnitFactoryTest extends TestCase $testee = new PurchaseUnitFactory( $amountFactory, - $payeeRepository, - $payeeFactory, $itemFactory, $shippingFactory, $paymentsFactory From db9852b535bbc237137cbbfe77f503a84468db8f Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Tue, 24 Oct 2023 12:02:24 +0200 Subject: [PATCH 19/22] Fix phpunit --- .../ApiClient/Entity/PurchaseUnitTest.php | 44 -------- .../Factory/PurchaseUnitFactoryTest.php | 106 ------------------ 2 files changed, 150 deletions(-) diff --git a/tests/PHPUnit/ApiClient/Entity/PurchaseUnitTest.php b/tests/PHPUnit/ApiClient/Entity/PurchaseUnitTest.php index c9d81f8aa..da3d988cb 100644 --- a/tests/PHPUnit/ApiClient/Entity/PurchaseUnitTest.php +++ b/tests/PHPUnit/ApiClient/Entity/PurchaseUnitTest.php @@ -45,7 +45,6 @@ class PurchaseUnitTest extends TestCase $shipping, 'referenceId', 'description', - null, 'customId', 'invoiceId', 'softDescriptor' @@ -54,7 +53,6 @@ class PurchaseUnitTest extends TestCase $this->assertEquals($amount, $testee->amount()); $this->assertEquals('referenceId', $testee->reference_id()); $this->assertEquals('description', $testee->description()); - $this->assertNull($testee->payee()); $this->assertEquals('customId', $testee->custom_id()); $this->assertEquals('invoiceId', $testee->invoice_id()); $this->assertEquals('softDescriptor', $testee->soft_descriptor()); @@ -808,46 +806,4 @@ class PurchaseUnitTest extends TestCase return $values; } - - public function testPayee() - { - $amount = Mockery::mock(Amount::class); - $amount->shouldReceive('breakdown')->andReturnNull(); - $amount->shouldReceive('to_array')->andReturn(['amount']); - $item1 = Mockery::mock(Item::class); - $item1->shouldReceive('to_array')->andReturn(['item1']); - $item2 = Mockery::mock(Item::class); - $item2->shouldReceive('to_array')->andReturn(['item2']); - $shipping = Mockery::mock(Shipping::class); - $shipping->shouldReceive('to_array')->andReturn(['shipping']); - $payee = Mockery::mock(Payee::class); - $payee->shouldReceive('to_array')->andReturn(['payee']); - $testee = new PurchaseUnit( - $amount, - [], - $shipping, - 'referenceId', - 'description', - $payee, - 'customId', - 'invoiceId', - 'softDescriptor' - ); - - $this->assertEquals($payee, $testee->payee()); - - $expected = [ - 'reference_id' => 'referenceId', - 'amount' => ['amount'], - 'description' => 'description', - 'items' => [], - 'shipping' => ['shipping'], - 'custom_id' => 'customId', - 'invoice_id' => 'invoiceId', - 'soft_descriptor' => 'softDescriptor', - 'payee' => ['payee'], - ]; - - $this->assertEquals($expected, $testee->to_array()); - } } diff --git a/tests/PHPUnit/ApiClient/Factory/PurchaseUnitFactoryTest.php b/tests/PHPUnit/ApiClient/Factory/PurchaseUnitFactoryTest.php index 0c3ba52b9..73d948c46 100644 --- a/tests/PHPUnit/ApiClient/Factory/PurchaseUnitFactoryTest.php +++ b/tests/PHPUnit/ApiClient/Factory/PurchaseUnitFactoryTest.php @@ -7,11 +7,9 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\Address; use WooCommerce\PayPalCommerce\ApiClient\Entity\Amount; use WooCommerce\PayPalCommerce\ApiClient\Entity\Item; use WooCommerce\PayPalCommerce\ApiClient\Entity\Money; -use WooCommerce\PayPalCommerce\ApiClient\Entity\Payee; use WooCommerce\PayPalCommerce\ApiClient\Entity\Payments; use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit; use WooCommerce\PayPalCommerce\ApiClient\Entity\Shipping; -use WooCommerce\PayPalCommerce\ApiClient\Repository\PayeeRepository; use WooCommerce\PayPalCommerce\TestCase; use Mockery; @@ -45,11 +43,6 @@ class PurchaseUnitFactoryTest extends TestCase ->shouldReceive('from_wc_order') ->with($wcOrder) ->andReturn($amount); - $payeeFactory = Mockery::mock(PayeeFactory::class); - $payeeRepository = Mockery::mock(PayeeRepository::class); - $payee = Mockery::mock(Payee::class); - $payeeRepository - ->shouldReceive('payee')->andReturn($payee); $itemFactory = Mockery::mock(ItemFactory::class); $itemFactory ->shouldReceive('from_wc_order') @@ -82,7 +75,6 @@ class PurchaseUnitFactoryTest extends TestCase $unit = $testee->from_wc_order($wcOrder); $this->assertTrue(is_a($unit, PurchaseUnit::class)); - $this->assertEquals($payee, $unit->payee()); $this->assertEquals('', $unit->description()); $this->assertEquals('default', $unit->reference_id()); $this->assertEquals($this->wcOrderId, $unit->custom_id()); @@ -104,11 +96,6 @@ class PurchaseUnitFactoryTest extends TestCase ->shouldReceive('from_wc_order') ->with($wcOrder) ->andReturn($amount); - $payeeFactory = Mockery::mock(PayeeFactory::class); - $payeeRepository = Mockery::mock(PayeeRepository::class); - $payee = Mockery::mock(Payee::class); - $payeeRepository - ->shouldReceive('payee')->andReturn($payee); $fee = Mockery::mock(Item::class, [ 'category' => Item::DIGITAL_GOODS, @@ -158,11 +145,6 @@ class PurchaseUnitFactoryTest extends TestCase ->expects('from_wc_order') ->with($wcOrder) ->andReturn($amount); - $payeeFactory = Mockery::mock(PayeeFactory::class); - $payeeRepository = Mockery::mock(PayeeRepository::class); - $payee = Mockery::mock(Payee::class); - $payeeRepository - ->expects('payee')->andReturn($payee); $itemFactory = Mockery::mock(ItemFactory::class); $itemFactory ->expects('from_wc_order') @@ -210,11 +192,6 @@ class PurchaseUnitFactoryTest extends TestCase ->expects('from_wc_order') ->with($wcOrder) ->andReturn($amount); - $payeeFactory = Mockery::mock(PayeeFactory::class); - $payeeRepository = Mockery::mock(PayeeRepository::class); - $payee = Mockery::mock(Payee::class); - $payeeRepository - ->expects('payee')->andReturn($payee); $itemFactory = Mockery::mock(ItemFactory::class); $itemFactory ->expects('from_wc_order') @@ -259,11 +236,6 @@ class PurchaseUnitFactoryTest extends TestCase ->expects('from_wc_cart') ->with($wcCart) ->andReturn($amount); - $payeeFactory = Mockery::mock(PayeeFactory::class); - $payeeRepository = Mockery::mock(PayeeRepository::class); - $payee = Mockery::mock(Payee::class); - $payeeRepository - ->expects('payee')->andReturn($payee); $itemFactory = Mockery::mock(ItemFactory::class); $itemFactory @@ -298,7 +270,6 @@ class PurchaseUnitFactoryTest extends TestCase $unit = $testee->from_wc_cart($wcCart); $this->assertTrue(is_a($unit, PurchaseUnit::class)); - $this->assertEquals($payee, $unit->payee()); $this->assertEquals('', $unit->description()); $this->assertEquals('default', $unit->reference_id()); $this->assertEquals('', $unit->custom_id()); @@ -321,11 +292,6 @@ class PurchaseUnitFactoryTest extends TestCase ->expects('from_wc_cart') ->with($wcCart) ->andReturn($amount); - $payeeFactory = Mockery::mock(PayeeFactory::class); - $payeeRepository = Mockery::mock(PayeeRepository::class); - $payee = Mockery::mock(Payee::class); - $payeeRepository - ->expects('payee')->andReturn($payee); $itemFactory = Mockery::mock(ItemFactory::class); $itemFactory @@ -357,11 +323,6 @@ class PurchaseUnitFactoryTest extends TestCase ->expects('from_wc_cart') ->with($wcCart) ->andReturn($amount); - $payeeFactory = Mockery::mock(PayeeFactory::class); - $payeeRepository = Mockery::mock(PayeeRepository::class); - $payee = Mockery::mock(Payee::class); - $payeeRepository - ->expects('payee')->andReturn($payee); $itemFactory = Mockery::mock(ItemFactory::class); $itemFactory ->expects('from_wc_cart') @@ -396,15 +357,10 @@ class PurchaseUnitFactoryTest extends TestCase { $rawItem = (object) ['items' => 1]; $rawAmount = (object) ['amount' => 1]; - $rawPayee = (object) ['payee' => 1]; $rawShipping = (object) ['shipping' => 1]; $amountFactory = Mockery::mock(AmountFactory::class); $amount = Mockery::mock(Amount::class); $amountFactory->expects('from_paypal_response')->with($rawAmount)->andReturn($amount); - $payeeFactory = Mockery::mock(PayeeFactory::class); - $payee = Mockery::mock(Payee::class); - $payeeFactory->expects('from_paypal_response')->with($rawPayee)->andReturn($payee); - $payeeRepository = Mockery::mock(PayeeRepository::class); $itemFactory = Mockery::mock(ItemFactory::class); $itemFactory->expects('from_paypal_response')->with($rawItem)->andReturn($this->item); $shippingFactory = Mockery::mock(ShippingFactory::class); @@ -426,13 +382,11 @@ class PurchaseUnitFactoryTest extends TestCase 'soft_descriptor' => 'softDescriptor', 'amount' => $rawAmount, 'items' => [$rawItem], - 'payee' => $rawPayee, 'shipping' => $rawShipping, ]; $unit = $testee->from_paypal_response($response); $this->assertTrue(is_a($unit, PurchaseUnit::class)); - $this->assertEquals($payee, $unit->payee()); $this->assertEquals('description', $unit->description()); $this->assertEquals('default', $unit->reference_id()); $this->assertEquals('customId', $unit->custom_id()); @@ -443,57 +397,13 @@ class PurchaseUnitFactoryTest extends TestCase $this->assertEquals($shipping, $unit->shipping()); } - public function testFromPayPalResponsePayeeIsNull() - { - $rawItem = (object) ['items' => 1]; - $rawAmount = (object) ['amount' => 1]; - $rawPayee = (object) ['payee' => 1]; - $rawShipping = (object) ['shipping' => 1]; - $amountFactory = Mockery::mock(AmountFactory::class); - $amount = Mockery::mock(Amount::class); - $amountFactory->expects('from_paypal_response')->with($rawAmount)->andReturn($amount); - $payeeFactory = Mockery::mock(PayeeFactory::class); - $payeeRepository = Mockery::mock(PayeeRepository::class); - $itemFactory = Mockery::mock(ItemFactory::class); - $itemFactory->expects('from_paypal_response')->with($rawItem)->andReturn($this->item); - $shippingFactory = Mockery::mock(ShippingFactory::class); - $shipping = Mockery::mock(Shipping::class); - $shippingFactory->expects('from_paypal_response')->with($rawShipping)->andReturn($shipping); - $paymentsFacory = Mockery::mock(PaymentsFactory::class); - $testee = new PurchaseUnitFactory( - $amountFactory, - $itemFactory, - $shippingFactory, - $paymentsFacory - ); - - $response = (object) [ - 'reference_id' => 'default', - 'description' => 'description', - 'customId' => 'customId', - 'invoiceId' => 'invoiceId', - 'softDescriptor' => 'softDescriptor', - 'amount' => $rawAmount, - 'items' => [$rawItem], - 'shipping' => $rawShipping, - ]; - - $unit = $testee->from_paypal_response($response); - $this->assertNull($unit->payee()); - } - public function testFromPayPalResponseShippingIsNull() { $rawItem = (object) ['items' => 1]; $rawAmount = (object) ['amount' => 1]; - $rawPayee = (object) ['payee' => 1]; $amountFactory = Mockery::mock(AmountFactory::class); $amount = Mockery::mock(Amount::class); $amountFactory->expects('from_paypal_response')->with($rawAmount)->andReturn($amount); - $payeeFactory = Mockery::mock(PayeeFactory::class); - $payee = Mockery::mock(Payee::class); - $payeeFactory->expects('from_paypal_response')->with($rawPayee)->andReturn($payee); - $payeeRepository = Mockery::mock(PayeeRepository::class); $itemFactory = Mockery::mock(ItemFactory::class); $itemFactory->expects('from_paypal_response')->with($rawItem)->andReturn($this->item); $shippingFactory = Mockery::mock(ShippingFactory::class); @@ -513,7 +423,6 @@ class PurchaseUnitFactoryTest extends TestCase 'softDescriptor' => 'softDescriptor', 'amount' => $rawAmount, 'items' => [$rawItem], - 'payee' => $rawPayee, ]; $unit = $testee->from_paypal_response($response); @@ -523,8 +432,6 @@ class PurchaseUnitFactoryTest extends TestCase public function testFromPayPalResponseNeedsReferenceId() { $amountFactory = Mockery::mock(AmountFactory::class); - $payeeFactory = Mockery::mock(PayeeFactory::class); - $payeeRepository = Mockery::mock(PayeeRepository::class); $itemFactory = Mockery::mock(ItemFactory::class); $shippingFactory = Mockery::mock(ShippingFactory::class); $paymentsFacory = Mockery::mock(PaymentsFactory::class); @@ -542,7 +449,6 @@ class PurchaseUnitFactoryTest extends TestCase 'softDescriptor' => 'softDescriptor', 'amount' => '', 'items' => [], - 'payee' => '', 'shipping' => '', ]; @@ -554,17 +460,12 @@ class PurchaseUnitFactoryTest extends TestCase { $rawItem = (object)['items' => 1]; $rawAmount = (object)['amount' => 1]; - $rawPayee = (object)['payee' => 1]; $rawShipping = (object)['shipping' => 1]; $rawPayments = (object)['payments' => 1]; $amountFactory = Mockery::mock(AmountFactory::class); $amount = Mockery::mock(Amount::class); $amountFactory->expects('from_paypal_response')->with($rawAmount)->andReturn($amount); - $payeeFactory = Mockery::mock(PayeeFactory::class); - $payee = Mockery::mock(Payee::class); - $payeeFactory->expects('from_paypal_response')->with($rawPayee)->andReturn($payee); - $payeeRepository = Mockery::mock(PayeeRepository::class); $itemFactory = Mockery::mock(ItemFactory::class); $item = Mockery::mock(Item::class, ['category' => Item::PHYSICAL_GOODS]); $itemFactory->expects('from_paypal_response')->with($rawItem)->andReturn($item); @@ -591,7 +492,6 @@ class PurchaseUnitFactoryTest extends TestCase 'softDescriptor' => 'softDescriptor', 'amount' => $rawAmount, 'items' => [$rawItem], - 'payee' => $rawPayee, 'shipping' => $rawShipping, 'payments' => $rawPayments, ]; @@ -604,17 +504,12 @@ class PurchaseUnitFactoryTest extends TestCase { $rawItem = (object)['items' => 1]; $rawAmount = (object)['amount' => 1]; - $rawPayee = (object)['payee' => 1]; $rawShipping = (object)['shipping' => 1]; $rawPayments = (object)['payments' => 1]; $amountFactory = Mockery::mock(AmountFactory::class); $amount = Mockery::mock(Amount::class); $amountFactory->expects('from_paypal_response')->with($rawAmount)->andReturn($amount); - $payeeFactory = Mockery::mock(PayeeFactory::class); - $payee = Mockery::mock(Payee::class); - $payeeFactory->expects('from_paypal_response')->with($rawPayee)->andReturn($payee); - $payeeRepository = Mockery::mock(PayeeRepository::class); $itemFactory = Mockery::mock(ItemFactory::class); $item = Mockery::mock(Item::class, ['category' => Item::PHYSICAL_GOODS]); $itemFactory->expects('from_paypal_response')->with($rawItem)->andReturn($item); @@ -639,7 +534,6 @@ class PurchaseUnitFactoryTest extends TestCase 'softDescriptor' => 'softDescriptor', 'amount' => $rawAmount, 'items' => [$rawItem], - 'payee' => $rawPayee, 'shipping' => $rawShipping, ]; From 03b2275386e41759baa765d7624ef7284a9b5af3 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Tue, 24 Oct 2023 14:33:50 +0200 Subject: [PATCH 20/22] Do not allow save partner merchant id --- modules/ppcp-wc-gateway/services.php | 2 + .../src/Settings/SettingsListener.php | 82 +++++++++++++------ 2 files changed, 59 insertions(+), 25 deletions(-) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index c5a1b3933..6c9eef157 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -318,6 +318,8 @@ return array( $pui_status_cache, $dcc_status_cache, $container->get( 'http.redirector' ), + $container->get( 'api.partner_merchant_id-production' ), + $container->get( 'api.partner_merchant_id-sandbox' ), $logger ); }, diff --git a/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php b/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php index 710e3290f..7c690c942 100644 --- a/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php +++ b/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php @@ -124,13 +124,6 @@ class SettingsListener { */ protected $redirector; - /** - * The logger. - * - * @var LoggerInterface - */ - private $logger; - /** * Max onboarding URL retries. * @@ -145,6 +138,27 @@ class SettingsListener { */ private $onboarding_retry_delay = 2; + /** + * Partner merchant ID production. + * + * @var string + */ + private $partner_merchant_id_production; + + /** + * Partner merchant ID sandbox. + * + * @var string + */ + private $partner_merchant_id_sandbox; + + /** + * The logger. + * + * @var LoggerInterface + */ + private $logger; + /** * SettingsListener constructor. * @@ -160,6 +174,8 @@ class SettingsListener { * @param Cache $pui_status_cache The PUI status cache. * @param Cache $dcc_status_cache The DCC status cache. * @param RedirectorInterface $redirector The HTTP redirector. + * @param string $partner_merchant_id_production Partner merchant ID production. + * @param string $partner_merchant_id_sandbox Partner merchant ID sandbox. * @param ?LoggerInterface $logger The logger. */ public function __construct( @@ -175,22 +191,26 @@ class SettingsListener { Cache $pui_status_cache, Cache $dcc_status_cache, RedirectorInterface $redirector, + string $partner_merchant_id_production, + string $partner_merchant_id_sandbox, LoggerInterface $logger = null ) { - $this->settings = $settings; - $this->setting_fields = $setting_fields; - $this->webhook_registrar = $webhook_registrar; - $this->cache = $cache; - $this->state = $state; - $this->bearer = $bearer; - $this->page_id = $page_id; - $this->signup_link_cache = $signup_link_cache; - $this->signup_link_ids = $signup_link_ids; - $this->pui_status_cache = $pui_status_cache; - $this->dcc_status_cache = $dcc_status_cache; - $this->redirector = $redirector; - $this->logger = $logger ?: new NullLogger(); + $this->settings = $settings; + $this->setting_fields = $setting_fields; + $this->webhook_registrar = $webhook_registrar; + $this->cache = $cache; + $this->state = $state; + $this->bearer = $bearer; + $this->page_id = $page_id; + $this->signup_link_cache = $signup_link_cache; + $this->signup_link_ids = $signup_link_ids; + $this->pui_status_cache = $pui_status_cache; + $this->dcc_status_cache = $dcc_status_cache; + $this->redirector = $redirector; + $this->partner_merchant_id_production = $partner_merchant_id_production; + $this->partner_merchant_id_sandbox = $partner_merchant_id_sandbox; + $this->logger = $logger ?: new NullLogger(); } /** @@ -210,7 +230,11 @@ class SettingsListener { return; } - $merchant_id = sanitize_text_field( wp_unslash( $_GET['merchantIdInPayPal'] ) ); + $merchant_id = sanitize_text_field( wp_unslash( $_GET['merchantIdInPayPal'] ) ); + if ( $merchant_id === $this->partner_merchant_id_production || $merchant_id === $this->partner_merchant_id_sandbox ) { + return; + } + $merchant_email = $this->sanitize_onboarding_email( sanitize_text_field( wp_unslash( $_GET['merchantId'] ) ) ); $onboarding_token = sanitize_text_field( wp_unslash( $_GET['ppcpToken'] ) ); $retry_count = isset( $_GET['ppcpRetry'] ) ? ( (int) sanitize_text_field( wp_unslash( $_GET['ppcpRetry'] ) ) ) : 0; @@ -498,10 +522,18 @@ class SettingsListener { if ( ! isset( $settings['client_id_sandbox'] ) && ! isset( $settings['client_id_production'] ) ) { return $settings; } - $is_sandbox = isset( $settings['sandbox_on'] ) && $settings['sandbox_on']; - $settings['client_id'] = $is_sandbox ? $settings['client_id_sandbox'] : $settings['client_id_production']; - $settings['client_secret'] = $is_sandbox ? $settings['client_secret_sandbox'] : $settings['client_secret_production']; - $settings['merchant_id'] = $is_sandbox ? $settings['merchant_id_sandbox'] : $settings['merchant_id_production']; + $is_sandbox = isset( $settings['sandbox_on'] ) && $settings['sandbox_on']; + $settings['client_id'] = $is_sandbox ? $settings['client_id_sandbox'] : $settings['client_id_production']; + $settings['client_secret'] = $is_sandbox ? $settings['client_secret_sandbox'] : $settings['client_secret_production']; + + if ( $settings['merchant_id_sandbox'] === $this->partner_merchant_id_sandbox || $settings['merchant_id_sandbox'] === $this->partner_merchant_id_production ) { + $settings['merchant_id_sandbox'] = ''; + } + if ( $settings['merchant_id_production'] === $this->partner_merchant_id_sandbox || $settings['merchant_id_sandbox'] === $this->partner_merchant_id_production ) { + $settings['merchant_id_production'] = ''; + } + $settings['merchant_id'] = $is_sandbox ? $settings['merchant_id_sandbox'] : $settings['merchant_id_production']; + $settings['merchant_email'] = $is_sandbox ? $settings['merchant_email_sandbox'] : $settings['merchant_email_production']; return $settings; } From ae6253bf0bfacab147d42a5b8b59680ad83159e9 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Tue, 24 Oct 2023 14:40:30 +0200 Subject: [PATCH 21/22] Fix phpunit --- tests/PHPUnit/WcGateway/Settings/SettingsListenerTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/PHPUnit/WcGateway/Settings/SettingsListenerTest.php b/tests/PHPUnit/WcGateway/Settings/SettingsListenerTest.php index 8b8a4e118..c66665bbc 100644 --- a/tests/PHPUnit/WcGateway/Settings/SettingsListenerTest.php +++ b/tests/PHPUnit/WcGateway/Settings/SettingsListenerTest.php @@ -53,7 +53,9 @@ class SettingsListenerTest extends ModularTestCase $signup_link_ids, $pui_status_cache, $dcc_status_cache, - new RedirectorStub() + new RedirectorStub(), + '', + '' ); $_GET['section'] = PayPalGateway::ID; From aca529934d76382515934f4b466b5449028c0f01 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Wed, 25 Oct 2023 11:03:36 +0200 Subject: [PATCH 22/22] Bump 2.4.0-rc2 version --- changelog.txt | 8 ++++++++ readme.txt | 9 +++++++++ woocommerce-paypal-payments.php | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 2ee0fb653..5bb4c9623 100644 --- a/changelog.txt +++ b/changelog.txt @@ -14,6 +14,14 @@ * Enhancement - Cart simulation improvements #1753 * Enhancement - Billing schedule fields not greyed out when PayPal Subscriptions product is connected #1755 * Enhancement - Check validation errors when submitting in block #1528 +* Enhancement - Improve handling of server error when submitting block #1785 +* Enhancement - Extend Apple Pay country eligibility #1781 +* Enhancement - Apple Pay validation notice improvements #1783 +* Enhancement - Apple Pay payment process issues #1789 +* Enhancement - Disable the tracking if payment is not captured #1780 +* Enhancement - Place order button remains - Could not retrieve order #1786 +* Enhancement - Google Pay for variable product greyed out but clickable #1788 +* Enhancement - Merchant credential validation & remove PAYEE object #1795 = 2.3.1 - 2023-09-26 = * Fix - Fatal error when saving product while WooCommerce Subscriptions plugin is not active #1731 diff --git a/readme.txt b/readme.txt index cc60615e4..8e13325fd 100644 --- a/readme.txt +++ b/readme.txt @@ -180,6 +180,7 @@ If you encounter issues with the PayPal buttons not appearing after an update, p == Changelog == += 2.4.0 - xxxx-xx-xx = * Fix - Mini-Cart Bug cause of wrong DOM-Structure in v2.3.1 #1735 * Fix - ACDC disappearing after plugin updates #1751 * Fix - Subscription module hooks #1748 @@ -193,6 +194,14 @@ If you encounter issues with the PayPal buttons not appearing after an update, p * Enhancement - Cart simulation improvements #1753 * Enhancement - Billing schedule fields not greyed out when PayPal Subscriptions product is connected #1755 * Enhancement - Check validation errors when submitting in block #1528 +* Enhancement - Improve handling of server error when submitting block #1785 +* Enhancement - Extend Apple Pay country eligibility #1781 +* Enhancement - Apple Pay validation notice improvements #1783 +* Enhancement - Apple Pay payment process issues #1789 +* Enhancement - Disable the tracking if payment is not captured #1780 +* Enhancement - Place order button remains - Could not retrieve order #1786 +* Enhancement - Google Pay for variable product greyed out but clickable #1788 +* Enhancement - Merchant credential validation & remove PAYEE object #1795 = 2.3.1 - 2023-09-26 = * Fix - Fatal error when saving product while WooCommerce Subscriptions plugin is not active #1731 diff --git a/woocommerce-paypal-payments.php b/woocommerce-paypal-payments.php index ac4082cd3..2092a9cee 100644 --- a/woocommerce-paypal-payments.php +++ b/woocommerce-paypal-payments.php @@ -23,7 +23,7 @@ use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; define( 'PAYPAL_API_URL', 'https://api-m.paypal.com' ); define( 'PAYPAL_SANDBOX_API_URL', 'https://api-m.sandbox.paypal.com' ); -define( 'PAYPAL_INTEGRATION_DATE', '2023-10-18' ); +define( 'PAYPAL_INTEGRATION_DATE', '2023-10-25' ); ! defined( 'CONNECT_WOO_CLIENT_ID' ) && define( 'CONNECT_WOO_CLIENT_ID', 'AcCAsWta_JTL__OfpjspNyH7c1GGHH332fLwonA5CwX4Y10mhybRZmHLA0GdRbwKwjQIhpDQy0pluX_P' ); ! defined( 'CONNECT_WOO_SANDBOX_CLIENT_ID' ) && define( 'CONNECT_WOO_SANDBOX_CLIENT_ID', 'AYmOHbt1VHg-OZ_oihPdzKEVbU3qg0qXonBcAztuzniQRaKE0w1Hr762cSFwd4n8wxOl-TCWohEa0XM_' );