From 9ee14235d27809847ba27d73c939f0822e28ebbb Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Thu, 2 Nov 2023 15:12:20 +0000 Subject: [PATCH 01/10] Improves ApplePay eligibility configuration. --- modules/ppcp-applepay/extensions.php | 96 +++++++++++++++++++ modules/ppcp-applepay/services.php | 17 +++- .../src/Assets/PropertiesDictionary.php | 1 + 3 files changed, 113 insertions(+), 1 deletion(-) diff --git a/modules/ppcp-applepay/extensions.php b/modules/ppcp-applepay/extensions.php index 39aa3ed81..24f4cdb59 100644 --- a/modules/ppcp-applepay/extensions.php +++ b/modules/ppcp-applepay/extensions.php @@ -10,6 +10,7 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Applepay; use WooCommerce\PayPalCommerce\Applepay\Assets\PropertiesDictionary; +use WooCommerce\PayPalCommerce\Onboarding\Environment; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\WcGateway\Helper\DisplayManager; @@ -37,6 +38,34 @@ return array( $display_manager = $container->get( 'wcgateway.display-manager' ); assert( $display_manager instanceof DisplayManager ); + // Domain registration + $env = $container->get( 'onboarding.environment' ); + assert( $env instanceof Environment ); + + $domain_registration_url = 'https://www.paypal.com/uccservicing/apm/applepay'; + if ( $env->current_environment_is( Environment::SANDBOX ) ) { + $domain_registration_url = 'https://www.sandbox.paypal.com/uccservicing/apm/applepay'; + } + + // Domain validation + $domain_validation_text = __( 'Status: Domain validation failed ❌', 'woocommerce-paypal-payments' ); + if ( $container->get( 'applepay.is_validated' ) ) { + $domain_validation_text = __( 'Status: Domain successfully validated ✔️', 'woocommerce-paypal-payments' ); + } + + // Device eligibility + $device_eligibility_text = __( 'Your current browser/device does not seem to support Apple Pay ❌.', 'woocommerce-paypal-payments' ); + $device_eligibility_notes = sprintf( + // translators: %1$s and %2$s are the opening and closing of HTML tag. + __( 'Though the button may display in previews, it won\'t appear in the shop. For details, refer to the %1$sApple Pay requirements%2$s.', 'woocommerce-paypal-payments' ), + '', + '' + ); + if ( $container->get( 'applepay.is_browser_supported' ) ) { + $device_eligibility_text = __( 'Your browser/device supports Apple Pay ✔️.', 'woocommerce-paypal-payments' ); + $device_eligibility_notes = __( 'The Apple Pay button will be visible both in previews and below the PayPal buttons in the shop.', 'woocommerce-paypal-payments' ); + } + // Connection tab fields. $fields = $insert_after( $fields, @@ -122,6 +151,9 @@ return array( $display_manager ->rule() ->condition_element( 'applepay_button_enabled', '1' ) + ->action_visible( 'applepay_button_domain_registration' ) + ->action_visible( 'applepay_button_domain_validation' ) + ->action_visible( 'applepay_button_device_eligibility' ) ->action_visible( 'applepay_button_color' ) ->action_visible( 'applepay_button_type' ) ->action_visible( 'applepay_button_language' ) @@ -130,6 +162,70 @@ return array( ), ), ), + 'applepay_button_domain_registration' => array( + 'title' => str_repeat( ' ', 6 ) . __( 'Domain Registration', 'woocommerce-paypal-payments' ), + 'type' => 'ppcp-text', + 'text' => + '' + . __( 'Manage Domain Registration', 'woocommerce-paypal-payments' ) + . '' + . '

' + . __( 'Any (sub)domain names showing an Apple Pay button must be registered on the PayPal website. If the domain displaying the Apple Pay button isn\'t registered, the payment method won\'t work.', 'woocommerce-paypal-payments' ) + . '

', + 'desc_tip' => true, + 'description' => __( + 'Registering the website domain on the PayPal site is mandated by Apple. Payments will fail if the Apple Pay button is used on an unregistered domain.', + 'woocommerce-paypal-payments' + ), + 'class' => array(), + 'screens' => array( State::STATE_ONBOARDED ), + 'gateway' => 'paypal', + 'requirements' => array(), + ), + 'applepay_button_domain_validation' => array( + 'title' => str_repeat( ' ', 6 ) . __( 'Domain Validation', 'woocommerce-paypal-payments' ), + 'type' => 'ppcp-text', + 'text' => $domain_validation_text + . '

' + . sprintf( + // translators: %1$s and %2$s are the opening and closing of HTML tag. + __( 'Note: PayPal Payments automatically presents the %1$sdomain association file%2$s for Apple to validate your registered domain.', 'woocommerce-paypal-payments' ), + '', + '' + ) + . '

', + 'desc_tip' => true, + 'description' => __( + 'Apple requires the website domain to be registered and validated. PayPal Payments automatically presents your domain association file for Apple to validate the manually registered domain.', + 'woocommerce-paypal-payments' + ), + 'class' => array(), + 'screens' => array( State::STATE_ONBOARDED ), + 'gateway' => 'paypal', + 'requirements' => array(), + ), + 'applepay_button_device_eligibility' => array( + 'title' => str_repeat( ' ', 6 ) . __( 'Device Eligibility', 'woocommerce-paypal-payments' ), + 'type' => 'ppcp-text', + 'text' => $device_eligibility_text + . '

' + . $device_eligibility_notes + . '

', + 'desc_tip' => true, + 'description' => __( + 'Apple Pay demands certain Apple devices for secure payment execution. This helps determine if your current device is compliant.', + 'woocommerce-paypal-payments' + ), + 'class' => array(), + 'screens' => array( State::STATE_ONBOARDED ), + 'gateway' => 'paypal', + 'requirements' => array(), + ), + + + + + 'applepay_button_type' => array( 'title' => str_repeat( ' ', 6 ) . __( 'Button Label', 'woocommerce-paypal-payments' ), 'type' => 'select', diff --git a/modules/ppcp-applepay/services.php b/modules/ppcp-applepay/services.php index a49ab7fad..8717ff811 100644 --- a/modules/ppcp-applepay/services.php +++ b/modules/ppcp-applepay/services.php @@ -15,6 +15,7 @@ use WooCommerce\PayPalCommerce\Applepay\Assets\ApplePayButton; use WooCommerce\PayPalCommerce\Applepay\Assets\AppleProductStatus; use WooCommerce\PayPalCommerce\Applepay\Assets\DataToAppleButtonScripts; use WooCommerce\PayPalCommerce\Applepay\Assets\BlocksPaymentMethod; +use WooCommerce\PayPalCommerce\Applepay\Assets\PropertiesDictionary; use WooCommerce\PayPalCommerce\Applepay\Helper\ApmApplies; use WooCommerce\PayPalCommerce\Applepay\Helper\AvailabilityNotice; use WooCommerce\PayPalCommerce\Onboarding\Environment; @@ -56,11 +57,16 @@ return array( $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.is_validated' ), $container->get( 'applepay.button' ) ); }, + 'applepay.is_validated' => static function ( ContainerInterface $container ): bool { + $settings = $container->get( 'wcgateway.settings' ); + return $settings->has( 'applepay_validated' ) ? $settings->get( 'applepay_validated' ) === true : false; + }, + 'applepay.apple-product-status' => static function( ContainerInterface $container ): AppleProductStatus { return new AppleProductStatus( $container->get( 'wcgateway.settings' ), @@ -83,6 +89,15 @@ return array( 'applepay.server_supported' => static function ( ContainerInterface $container ): bool { return ! empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off'; }, + 'applepay.is_browser_supported' => static function ( ContainerInterface $container ): bool { + $user_agent = $_SERVER['HTTP_USER_AGENT'] ?? ''; + foreach ( PropertiesDictionary::ALLOWED_USER_AGENTS as $allowed_agent ) { + if (strpos($user_agent, $allowed_agent) !== false) { + return true; + } + } + return false; + }, 'applepay.url' => static function ( ContainerInterface $container ): string { $path = realpath( __FILE__ ); if ( false === $path ) { diff --git a/modules/ppcp-applepay/src/Assets/PropertiesDictionary.php b/modules/ppcp-applepay/src/Assets/PropertiesDictionary.php index 25227e11b..d1c388ffd 100644 --- a/modules/ppcp-applepay/src/Assets/PropertiesDictionary.php +++ b/modules/ppcp-applepay/src/Assets/PropertiesDictionary.php @@ -13,6 +13,7 @@ namespace WooCommerce\PayPalCommerce\Applepay\Assets; * Class PropertiesDictionary */ class PropertiesDictionary { + public const ALLOWED_USER_AGENTS = array( 'Safari', 'Macintosh', 'iPhone', 'iPad', 'iPod' ); public const BILLING_CONTACT_INVALID = 'billing Contact Invalid'; From eeb76a1df81bbbd04c50ff8ed12383fc793f1399 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Thu, 2 Nov 2023 15:39:42 +0000 Subject: [PATCH 02/10] Fix lint. --- modules/ppcp-applepay/extensions.php | 27 ++++++++----------- modules/ppcp-applepay/services.php | 11 +++++--- .../ppcp-compat/src/Assets/CompatAssets.php | 4 +-- 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/modules/ppcp-applepay/extensions.php b/modules/ppcp-applepay/extensions.php index 24f4cdb59..bdea5a19f 100644 --- a/modules/ppcp-applepay/extensions.php +++ b/modules/ppcp-applepay/extensions.php @@ -38,7 +38,7 @@ return array( $display_manager = $container->get( 'wcgateway.display-manager' ); assert( $display_manager instanceof DisplayManager ); - // Domain registration + // Domain registration. $env = $container->get( 'onboarding.environment' ); assert( $env instanceof Environment ); @@ -47,13 +47,13 @@ return array( $domain_registration_url = 'https://www.sandbox.paypal.com/uccservicing/apm/applepay'; } - // Domain validation + // Domain validation. $domain_validation_text = __( 'Status: Domain validation failed ❌', 'woocommerce-paypal-payments' ); if ( $container->get( 'applepay.is_validated' ) ) { $domain_validation_text = __( 'Status: Domain successfully validated ✔️', 'woocommerce-paypal-payments' ); } - // Device eligibility + // Device eligibility. $device_eligibility_text = __( 'Your current browser/device does not seem to support Apple Pay ❌.', 'woocommerce-paypal-payments' ); $device_eligibility_notes = sprintf( // translators: %1$s and %2$s are the opening and closing of HTML tag. @@ -129,7 +129,7 @@ return array( $fields, 'allow_card_button_gateway', array( - 'applepay_button_enabled' => array( + 'applepay_button_enabled' => array( 'title' => __( 'Apple Pay Button', 'woocommerce-paypal-payments' ), 'type' => 'checkbox', 'label' => __( 'Enable Apple Pay button', 'woocommerce-paypal-payments' ) @@ -162,10 +162,10 @@ return array( ), ), ), - 'applepay_button_domain_registration' => array( + 'applepay_button_domain_registration' => array( 'title' => str_repeat( ' ', 6 ) . __( 'Domain Registration', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-text', - 'text' => + 'text' => '' . __( 'Manage Domain Registration', 'woocommerce-paypal-payments' ) . '' @@ -182,7 +182,7 @@ return array( 'gateway' => 'paypal', 'requirements' => array(), ), - 'applepay_button_domain_validation' => array( + 'applepay_button_domain_validation' => array( 'title' => str_repeat( ' ', 6 ) . __( 'Domain Validation', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-text', 'text' => $domain_validation_text @@ -204,7 +204,7 @@ return array( 'gateway' => 'paypal', 'requirements' => array(), ), - 'applepay_button_device_eligibility' => array( + 'applepay_button_device_eligibility' => array( 'title' => str_repeat( ' ', 6 ) . __( 'Device Eligibility', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-text', 'text' => $device_eligibility_text @@ -221,12 +221,7 @@ return array( 'gateway' => 'paypal', 'requirements' => array(), ), - - - - - - 'applepay_button_type' => array( + 'applepay_button_type' => array( 'title' => str_repeat( ' ', 6 ) . __( 'Button Label', 'woocommerce-paypal-payments' ), 'type' => 'select', 'desc_tip' => true, @@ -242,7 +237,7 @@ return array( 'gateway' => 'paypal', 'requirements' => array(), ), - 'applepay_button_color' => array( + 'applepay_button_color' => array( 'title' => str_repeat( ' ', 6 ) . __( 'Button Color', 'woocommerce-paypal-payments' ), 'type' => 'select', 'desc_tip' => true, @@ -259,7 +254,7 @@ return array( 'gateway' => 'paypal', 'requirements' => array(), ), - 'applepay_button_language' => array( + 'applepay_button_language' => array( 'title' => str_repeat( ' ', 6 ) . __( 'Button Language', 'woocommerce-paypal-payments' ), 'type' => 'select', 'desc_tip' => true, diff --git a/modules/ppcp-applepay/services.php b/modules/ppcp-applepay/services.php index 8717ff811..e02691473 100644 --- a/modules/ppcp-applepay/services.php +++ b/modules/ppcp-applepay/services.php @@ -90,10 +90,13 @@ return array( return ! empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off'; }, 'applepay.is_browser_supported' => static function ( ContainerInterface $container ): bool { - $user_agent = $_SERVER['HTTP_USER_AGENT'] ?? ''; - foreach ( PropertiesDictionary::ALLOWED_USER_AGENTS as $allowed_agent ) { - if (strpos($user_agent, $allowed_agent) !== false) { - return true; + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized + $user_agent = wp_unslash( $_SERVER['HTTP_USER_AGENT'] ?? '' ); + if ( $user_agent ) { + foreach ( PropertiesDictionary::ALLOWED_USER_AGENTS as $allowed_agent ) { + if ( strpos( $user_agent, $allowed_agent ) !== false ) { + return true; + } } } return false; diff --git a/modules/ppcp-compat/src/Assets/CompatAssets.php b/modules/ppcp-compat/src/Assets/CompatAssets.php index 85e0bde7b..34b038048 100644 --- a/modules/ppcp-compat/src/Assets/CompatAssets.php +++ b/modules/ppcp-compat/src/Assets/CompatAssets.php @@ -107,8 +107,8 @@ class CompatAssets { 'ppcp-tracking-compat', 'PayPalCommerceGatewayOrderTrackingCompat', array( - 'gzd_sync_enabled' => apply_filters( 'woocommerce_paypal_payments_sync_gzd_tracking', true ) && $this->is_gzd_active, - 'wc_shipment_sync_enabled' => apply_filters( 'woocommerce_paypal_payments_sync_wc_shipment_tracking', true ) && $this->is_wc_shipment_active, + 'gzd_sync_enabled' => apply_filters( 'woocommerce_paypal_payments_sync_gzd_tracking', true ) && $this->is_gzd_active, + 'wc_shipment_sync_enabled' => apply_filters( 'woocommerce_paypal_payments_sync_wc_shipment_tracking', true ) && $this->is_wc_shipment_active, 'wc_shipping_tax_sync_enabled' => apply_filters( 'woocommerce_paypal_payments_sync_wc_shipping_tax', true ) && $this->is_wc_shipping_tax_active, ) ); From 489675c92182aa9a3c5beb5ee33e1a44825c9745 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Thu, 2 Nov 2023 16:44:05 +0100 Subject: [PATCH 03/10] Ensure payment method before saving payment token --- modules/ppcp-subscription/src/SubscriptionModule.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/modules/ppcp-subscription/src/SubscriptionModule.php b/modules/ppcp-subscription/src/SubscriptionModule.php index 88f5596a3..d6333da14 100644 --- a/modules/ppcp-subscription/src/SubscriptionModule.php +++ b/modules/ppcp-subscription/src/SubscriptionModule.php @@ -29,6 +29,7 @@ use WC_Subscription; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository; +use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway; use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; @@ -80,6 +81,14 @@ class SubscriptionModule implements ModuleInterface { add_action( 'woocommerce_subscription_payment_complete', function ( $subscription ) use ( $c ) { + if ( + $subscription->get_payment_method() !== PayPalGateway::ID + || $subscription->get_payment_method() !== CreditCardGateway::ID + || $subscription->get_payment_method() !== CardButtonGateway::ID + ) { + return; + } + $paypal_subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? ''; if ( $paypal_subscription_id ) { return; From 51968db850777befe873091d32a5b3f45a7d9eaa Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Fri, 3 Nov 2023 09:27:00 +0100 Subject: [PATCH 04/10] Ensure payment method before saving payment token --- modules/ppcp-subscription/src/SubscriptionModule.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/modules/ppcp-subscription/src/SubscriptionModule.php b/modules/ppcp-subscription/src/SubscriptionModule.php index d6333da14..f99a4fd8d 100644 --- a/modules/ppcp-subscription/src/SubscriptionModule.php +++ b/modules/ppcp-subscription/src/SubscriptionModule.php @@ -81,11 +81,7 @@ class SubscriptionModule implements ModuleInterface { add_action( 'woocommerce_subscription_payment_complete', function ( $subscription ) use ( $c ) { - if ( - $subscription->get_payment_method() !== PayPalGateway::ID - || $subscription->get_payment_method() !== CreditCardGateway::ID - || $subscription->get_payment_method() !== CardButtonGateway::ID - ) { + if ( ! in_array( $subscription->get_payment_method(), array( PayPalGateway::ID, CreditCardGateway::ID, CardButtonGateway::ID ), true ) ) { return; } From 118e49cfdef021935c70a0f3ea347300887b7bd8 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Fri, 3 Nov 2023 10:30:31 +0000 Subject: [PATCH 05/10] Add ApplePay preview in admin settings. --- .../ppcp-applepay/resources/css/styles.scss | 10 +- .../resources/js/ApplepayButton.js | 16 +- .../js/Context/ContextHandlerFactory.js | 3 + .../resources/js/Context/PreviewHandler.js | 37 +++++ .../ppcp-applepay/resources/js/boot-admin.js | 144 ++++++++++++++++++ modules/ppcp-applepay/src/ApplepayModule.php | 39 +++++ .../src/Assets/ApplePayButton.php | 45 +++++- .../src/Assets/DataToAppleButtonScripts.php | 63 ++++++++ modules/ppcp-applepay/webpack.config.js | 1 + .../resources/js/Context/PreviewHandler.js | 4 +- 10 files changed, 343 insertions(+), 19 deletions(-) create mode 100644 modules/ppcp-applepay/resources/js/Context/PreviewHandler.js create mode 100644 modules/ppcp-applepay/resources/js/boot-admin.js diff --git a/modules/ppcp-applepay/resources/css/styles.scss b/modules/ppcp-applepay/resources/css/styles.scss index d3f834119..0abd19451 100644 --- a/modules/ppcp-applepay/resources/css/styles.scss +++ b/modules/ppcp-applepay/resources/css/styles.scss @@ -1,11 +1,11 @@ -#applepay-container { +#applepay-container, .ppcp-button-applepay { --apple-pay-button-height: 45px; --apple-pay-button-min-height: 40px; --apple-pay-button-width: 100%; --apple-pay-button-max-width: 750px; --apple-pay-button-border-radius: 4px; --apple-pay-button-overflow: hidden; - --apple-pay-button-margin:7px 0; + margin:7px 0; &.ppcp-button-pill { --apple-pay-button-border-radius: 50px; } @@ -17,7 +17,7 @@ } .woocommerce-checkout { - #applepay-container { + #applepay-container, .ppcp-button-applepay { margin-top: 0.5em; --apple-pay-button-border-radius: 4px; --apple-pay-button-height: 45px; @@ -30,7 +30,7 @@ .ppcp-has-applepay-block { .wp-block-woocommerce-checkout { - #applepay-container { + #applepay-container, .ppcp-button-applepay { --apple-pay-button-margin: 0; --apple-pay-button-height: 40px; &.ppcp-button-pill { @@ -40,7 +40,7 @@ } .wp-block-woocommerce-cart { - #applepay-container { + #applepay-container, .ppcp-button-applepay { --apple-pay-button-margin: 0; --apple-pay-button-height: 40px; } diff --git a/modules/ppcp-applepay/resources/js/ApplepayButton.js b/modules/ppcp-applepay/resources/js/ApplepayButton.js index 19c03c5d2..6cab7d5ca 100644 --- a/modules/ppcp-applepay/resources/js/ApplepayButton.js +++ b/modules/ppcp-applepay/resources/js/ApplepayButton.js @@ -4,6 +4,7 @@ import {setVisible} from '../../../ppcp-button/resources/js/modules/Helper/Hidin import {setEnabled} from '../../../ppcp-button/resources/js/modules/Helper/ButtonDisabler'; import FormValidator from "../../../ppcp-button/resources/js/modules/Helper/FormValidator"; import ErrorHandler from '../../../ppcp-button/resources/js/modules/ErrorHandler'; +import widgetBuilder from "../../../ppcp-button/resources/js/modules/Renderer/WidgetBuilder"; class ApplepayButton { @@ -48,7 +49,7 @@ class ApplepayButton { const isEligible = this.applePayConfig.isEligible; if (isEligible) { this.fetchTransactionInfo().then(() => { - const isSubscriptionProduct = this.ppcpConfig.data_client_id.has_subscriptions === true; + const isSubscriptionProduct = this.ppcpConfig?.data_client_id?.has_subscriptions === true; if (isSubscriptionProduct) { return; } @@ -145,13 +146,12 @@ class ApplepayButton { return session; } - - - /** * Add a Apple Pay purchase button */ addButton() { + this.log('addButton', this.context); + const wrapper = (this.context === 'mini-cart') ? this.buttonConfig.button.mini_cart_wrapper @@ -160,7 +160,7 @@ class ApplepayButton { (this.context === 'mini-cart') ? this.ppcpConfig.button.mini_cart_style.shape : this.ppcpConfig.button.style.shape; - const appleContainer = this.context === 'mini-cart' ? document.getElementById("applepay-container-minicart") : document.getElementById("applepay-container"); + const appleContainer = document.getElementById(wrapper); const type = this.buttonConfig.button.type; const language = this.buttonConfig.button.lang; const color = this.buttonConfig.button.color; @@ -195,7 +195,7 @@ class ApplepayButton { try { const formData = new FormData(document.querySelector(checkoutFormSelector)); this.form_saved = Object.fromEntries(formData.entries()); - // This line should be reviewed, the paypal.Applepay().confirmOrder fails if we add it. + // This line should be reviewed, the widgetBuilder.paypal.Applepay().confirmOrder fails if we add it. //this.update_request_data_with_form(paymentDataRequest); } catch (error) { console.error(error); @@ -274,7 +274,7 @@ class ApplepayButton { return (applePayValidateMerchantEvent) => { this.log('onvalidatemerchant call'); - paypal.Applepay().validateMerchant({ + widgetBuilder.paypal.Applepay().validateMerchant({ validationUrl: applePayValidateMerchantEvent.validationURL }) .then(validateResult => { @@ -501,7 +501,7 @@ class ApplepayButton { this.log('onpaymentauthorized paypal order ID', id, event.payment.token, event.payment.billingContact); try { - const confirmOrderResponse = await paypal.Applepay().confirmOrder({ + const confirmOrderResponse = await widgetBuilder.paypal.Applepay().confirmOrder({ orderId: id, token: event.payment.token, billingContact: event.payment.billingContact, diff --git a/modules/ppcp-applepay/resources/js/Context/ContextHandlerFactory.js b/modules/ppcp-applepay/resources/js/Context/ContextHandlerFactory.js index 72ee4f5fa..d94833daa 100644 --- a/modules/ppcp-applepay/resources/js/Context/ContextHandlerFactory.js +++ b/modules/ppcp-applepay/resources/js/Context/ContextHandlerFactory.js @@ -4,6 +4,7 @@ import CheckoutHandler from "./CheckoutHandler"; import CartBlockHandler from "./CartBlockHandler"; import CheckoutBlockHandler from "./CheckoutBlockHandler"; import MiniCartHandler from "./MiniCartHandler"; +import PreviewHandler from "./PreviewHandler"; class ContextHandlerFactory { @@ -22,6 +23,8 @@ class ContextHandlerFactory { return new CartBlockHandler(buttonConfig, ppcpConfig); case 'checkout-block': return new CheckoutBlockHandler(buttonConfig, ppcpConfig); + case 'preview': + return new PreviewHandler(buttonConfig, ppcpConfig); } } } diff --git a/modules/ppcp-applepay/resources/js/Context/PreviewHandler.js b/modules/ppcp-applepay/resources/js/Context/PreviewHandler.js new file mode 100644 index 000000000..6e0da8852 --- /dev/null +++ b/modules/ppcp-applepay/resources/js/Context/PreviewHandler.js @@ -0,0 +1,37 @@ +import BaseHandler from "./BaseHandler"; + +class PreviewHandler extends BaseHandler { + + constructor(buttonConfig, ppcpConfig, externalHandler) { + super(buttonConfig, ppcpConfig, externalHandler); + } + + transactionInfo() { + // We need to return something as ApplePay button initialization expects valid data. + return { + countryCode: "US", + currencyCode: "USD", + totalPrice: "10.00", + totalPriceStatus: "FINAL" + } + } + + createOrder() { + throw new Error('Create order fail. This is just a preview.'); + } + + approveOrder(data, actions) { + throw new Error('Approve order fail. This is just a preview.'); + } + + actionHandler() { + throw new Error('Action handler fail. This is just a preview.'); + } + + errorHandler() { + throw new Error('Error handler fail. This is just a preview.'); + } + +} + +export default PreviewHandler; diff --git a/modules/ppcp-applepay/resources/js/boot-admin.js b/modules/ppcp-applepay/resources/js/boot-admin.js new file mode 100644 index 000000000..c2fa7796a --- /dev/null +++ b/modules/ppcp-applepay/resources/js/boot-admin.js @@ -0,0 +1,144 @@ +import {loadCustomScript} from "@paypal/paypal-js"; +import ApplepayButton from "./ApplepayButton"; +import widgetBuilder from "../../../ppcp-button/resources/js/modules/Renderer/WidgetBuilder"; + +(function ({ + buttonConfig, + jQuery +}) { + + let applePayConfig; + let buttonQueue = []; + let activeButtons = {}; + let bootstrapped = false; + + // React to PayPal config changes. + jQuery(document).on('ppcp_paypal_render_preview', (ev, ppcpConfig) => { + if (bootstrapped) { + createButton(ppcpConfig); + } else { + buttonQueue.push({ + ppcpConfig: JSON.parse(JSON.stringify(ppcpConfig)) + }); + } + }); + + // React to ApplePay config changes. + jQuery([ + '#ppcp-applepay_button_enabled', + '#ppcp-applepay_button_type', + '#ppcp-applepay_button_color', + '#ppcp-applepay_button_language' + ].join(',')).on('change', () => { + for (const [selector, ppcpConfig] of Object.entries(activeButtons)) { + createButton(ppcpConfig); + } + }); + + // Maybe we can find a more elegant reload method when transitioning from styling modes. + jQuery([ + '#ppcp-smart_button_enable_styling_per_location' + ].join(',')).on('change', () => { + setTimeout(() => { + for (const [selector, ppcpConfig] of Object.entries(activeButtons)) { + createButton(ppcpConfig); + } + }, 100); + }); + + const applyConfigOptions = function (buttonConfig) { + buttonConfig.button = buttonConfig.button || {}; + buttonConfig.button.type = jQuery('#ppcp-applepay_button_type').val(); + buttonConfig.button.color = jQuery('#ppcp-applepay_button_color').val(); + buttonConfig.button.lang = jQuery('#ppcp-applepay_button_language').val(); + } + + const createButton = function (ppcpConfig) { + const selector = ppcpConfig.button.wrapper + 'ApplePay'; + + if (!jQuery('#ppcp-applepay_button_enabled').is(':checked')) { + jQuery(selector).remove(); + return; + } + + buttonConfig = JSON.parse(JSON.stringify(buttonConfig)); + buttonConfig.button.wrapper = selector.replace('#', ''); + applyConfigOptions(buttonConfig); + + const wrapperElement = `
`; + + if (!jQuery(selector).length) { + jQuery(ppcpConfig.button.wrapper).after(wrapperElement); + } else { + jQuery(selector).replaceWith(wrapperElement); + } + + const button = new ApplepayButton( + 'preview', + null, + buttonConfig, + ppcpConfig, + ); + + button.init(applePayConfig); + + activeButtons[selector] = ppcpConfig; + } + + const bootstrap = async function () { + if (!widgetBuilder.paypal) { + return; + } + + applePayConfig = await widgetBuilder.paypal.Applepay().config(); + + // We need to set bootstrapped here otherwise applePayConfig may not be set. + bootstrapped = true; + + let options; + while (options = buttonQueue.pop()) { + createButton(options.ppcpConfig); + } + }; + + document.addEventListener( + 'DOMContentLoaded', + () => { + + if (typeof (buttonConfig) === 'undefined') { + console.error('PayPal button could not be configured.'); + return; + } + + let paypalLoaded = false; + let applePayLoaded = false; + + const tryToBoot = () => { + if (!bootstrapped && paypalLoaded && applePayLoaded) { + bootstrap(); + } + } + + // Load ApplePay SDK + loadCustomScript({ url: buttonConfig.sdk_url }).then(() => { + applePayLoaded = true; + tryToBoot(); + }); + + // Wait for PayPal to be loaded externally + if (typeof widgetBuilder.paypal !== 'undefined') { + paypalLoaded = true; + tryToBoot(); + } + + jQuery(document).on('ppcp-paypal-loaded', () => { + paypalLoaded = true; + tryToBoot(); + }); + }, + ); + +})({ + buttonConfig: window.wc_ppcp_applepay_admin, + jQuery: window.jQuery +}); diff --git a/modules/ppcp-applepay/src/ApplepayModule.php b/modules/ppcp-applepay/src/ApplepayModule.php index b81329811..1abbf339b 100644 --- a/modules/ppcp-applepay/src/ApplepayModule.php +++ b/modules/ppcp-applepay/src/ApplepayModule.php @@ -89,6 +89,8 @@ class ApplepayModule implements ModuleInterface { $module->render_buttons( $c, $apple_payment_method ); $apple_payment_method->bootstrap_ajax_request(); + + $module->load_admin_assets( $c, $apple_payment_method ); } ); @@ -180,6 +182,43 @@ class ApplepayModule implements ModuleInterface { ); } + /** + * Registers and enqueues the assets. + * + * @param ContainerInterface $c The container. + * @param ApplePayButton $button The button. + * @return void + */ + public function load_admin_assets( ContainerInterface $c, ApplePayButton $button ): void { + // Enqueue backend scripts. + add_action( + 'admin_enqueue_scripts', + static function () use ( $c, $button ) { + if ( ! is_admin() ) { + return; + } + + /** + * Should add this to the ButtonInterface. + * + * @psalm-suppress UndefinedInterfaceMethod + */ + $button->enqueue_admin(); + } + ); + + // Adds ApplePay component to the backend button preview settings. + add_action( + 'woocommerce_paypal_payments_admin_gateway_settings', + function( array $settings ) use ( $c ): array { + if ( is_array( $settings['components'] ) ) { + $settings['components'][] = 'applepay'; + } + return $settings; + } + ); + } + /** * Renders the Apple Pay buttons in the enabled places. * diff --git a/modules/ppcp-applepay/src/Assets/ApplePayButton.php b/modules/ppcp-applepay/src/Assets/ApplePayButton.php index fe7313a85..3f1063684 100644 --- a/modules/ppcp-applepay/src/Assets/ApplePayButton.php +++ b/modules/ppcp-applepay/src/Assets/ApplePayButton.php @@ -942,7 +942,7 @@ class ApplePayButton implements ButtonInterface { } if ( $button_enabled_cart ) { $default_hook_name = 'woocommerce_paypal_payments_cart_button_render'; - $render_placeholder = apply_filters( 'woocommerce_paypal_payments_googlepay_cart_button_render_hook', $default_hook_name ); + $render_placeholder = apply_filters( 'woocommerce_paypal_payments_applepay_cart_button_render_hook', $default_hook_name ); $render_placeholder = is_string( $render_placeholder ) ? $render_placeholder : $default_hook_name; add_action( $render_placeholder, @@ -954,7 +954,7 @@ class ApplePayButton implements ButtonInterface { if ( $button_enabled_checkout ) { $default_hook_name = 'woocommerce_paypal_payments_checkout_button_render'; - $render_placeholder = apply_filters( 'woocommerce_paypal_payments_googlepay_checkout_button_render_hook', $default_hook_name ); + $render_placeholder = apply_filters( 'woocommerce_paypal_payments_applepay_checkout_button_render_hook', $default_hook_name ); $render_placeholder = is_string( $render_placeholder ) ? $render_placeholder : $default_hook_name; add_action( $render_placeholder, @@ -966,7 +966,7 @@ class ApplePayButton implements ButtonInterface { } if ( $button_enabled_payorder ) { $default_hook_name = 'woocommerce_paypal_payments_payorder_button_render'; - $render_placeholder = apply_filters( 'woocommerce_paypal_payments_googlepay_payorder_button_render_hook', $default_hook_name ); + $render_placeholder = apply_filters( 'woocommerce_paypal_payments_applepay_payorder_button_render_hook', $default_hook_name ); $render_placeholder = is_string( $render_placeholder ) ? $render_placeholder : $default_hook_name; add_action( $render_placeholder, @@ -979,7 +979,7 @@ class ApplePayButton implements ButtonInterface { if ( $button_enabled_minicart ) { $default_hook_name = 'woocommerce_paypal_payments_minicart_button_render'; - $render_placeholder = apply_filters( 'woocommerce_paypal_payments_googlepay_minicart_button_render_hook', $default_hook_name ); + $render_placeholder = apply_filters( 'woocommerce_paypal_payments_applepay_minicart_button_render_hook', $default_hook_name ); $render_placeholder = is_string( $render_placeholder ) ? $render_placeholder : $default_hook_name; add_action( $render_placeholder, @@ -1059,6 +1059,34 @@ class ApplePayButton implements ButtonInterface { wp_enqueue_style( 'wc-ppcp-applepay' ); } + /** + * Enqueues scripts/styles for admin. + */ + public function enqueue_admin(): void { + wp_register_style( + 'wc-ppcp-applepay-admin', + untrailingslashit( $this->module_url ) . '/assets/css/styles.css', + array(), + $this->version + ); + wp_enqueue_style( 'wc-ppcp-applepay-admin' ); + + wp_register_script( + 'wc-ppcp-applepay-admin', + untrailingslashit( $this->module_url ) . '/assets/js/boot-admin.js?x=' . time(), + array(), + $this->version, + true + ); + wp_enqueue_script( 'wc-ppcp-applepay-admin' ); + + wp_localize_script( + 'wc-ppcp-applepay-admin', + 'wc_ppcp_applepay_admin', + $this->script_data_for_admin() + ); + } + /** * Returns the script data. * @@ -1068,6 +1096,15 @@ class ApplePayButton implements ButtonInterface { return $this->script_data->apple_pay_script_data(); } + /** + * Returns the admin script data. + * + * @return array + */ + public function script_data_for_admin(): array { + return $this->script_data->apple_pay_script_data_for_admin(); + } + /** * Returns true if the module is enabled. * diff --git a/modules/ppcp-applepay/src/Assets/DataToAppleButtonScripts.php b/modules/ppcp-applepay/src/Assets/DataToAppleButtonScripts.php index 0b15fbe78..a530ba95f 100644 --- a/modules/ppcp-applepay/src/Assets/DataToAppleButtonScripts.php +++ b/modules/ppcp-applepay/src/Assets/DataToAppleButtonScripts.php @@ -69,6 +69,26 @@ class DataToAppleButtonScripts { ); } + + /** + * Returns the appropriate admin data to send to ApplePay script + * + * @return array + * @throws NotFoundException When the setting is not found. + */ + public function apple_pay_script_data_for_admin(): array { + $base_location = wc_get_base_location(); + $shop_country_code = $base_location['country']; + $currency_code = get_woocommerce_currency(); + $total_label = get_bloginfo( 'name' ); + + return $this->data_for_admin_page( + $shop_country_code, + $currency_code, + $total_label + ); + } + /** * Check if the product needs shipping * @@ -197,4 +217,47 @@ class DataToAppleButtonScripts { 'ajax_url' => admin_url( 'admin-ajax.php' ), ); } + + /** + * Prepares the data for the cart page. + * Consider refactoring this method along with data_for_cart_page() and data_for_product_page() methods. + * + * @param string $shop_country_code The shop country code. + * @param string $currency_code The currency code. + * @param string $total_label The label for the total amount. + * + * @return array + */ + protected function data_for_admin_page( + $shop_country_code, + $currency_code, + $total_label + ) { + $type = $this->settings->has( 'applepay_button_type' ) ? $this->settings->get( 'applepay_button_type' ) : ''; + $color = $this->settings->has( 'applepay_button_color' ) ? $this->settings->get( 'applepay_button_color' ) : ''; + $lang = $this->settings->has( 'applepay_button_language' ) ? $this->settings->get( 'applepay_button_language' ) : ''; + $lang = apply_filters( 'woocommerce_paypal_payments_applepay_button_language', $lang ); + + return array( + 'sdk_url' => $this->sdk_url, + 'is_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG ? true : false, + 'button' => array( + 'wrapper' => 'applepay-container', + 'mini_cart_wrapper' => 'applepay-container-minicart', + 'type' => $type, + 'color' => $color, + 'lang' => $lang, + ), + 'product' => array( + 'needShipping' => false, + 'subtotal' => 0, + ), + 'shop' => array( + 'countryCode' => $shop_country_code, + 'currencyCode' => $currency_code, + 'totalLabel' => $total_label, + ), + 'ajax_url' => admin_url( 'admin-ajax.php' ), + ); + } } diff --git a/modules/ppcp-applepay/webpack.config.js b/modules/ppcp-applepay/webpack.config.js index 63834c8a6..94e7bfd8b 100644 --- a/modules/ppcp-applepay/webpack.config.js +++ b/modules/ppcp-applepay/webpack.config.js @@ -11,6 +11,7 @@ module.exports = { entry: { 'boot': path.resolve('./resources/js/boot.js'), 'boot-block': path.resolve('./resources/js/boot-block.js'), + 'boot-admin': path.resolve('./resources/js/boot-admin.js'), "styles": path.resolve('./resources/css/styles.scss') }, output: { diff --git a/modules/ppcp-googlepay/resources/js/Context/PreviewHandler.js b/modules/ppcp-googlepay/resources/js/Context/PreviewHandler.js index a637f078d..f4eeee486 100644 --- a/modules/ppcp-googlepay/resources/js/Context/PreviewHandler.js +++ b/modules/ppcp-googlepay/resources/js/Context/PreviewHandler.js @@ -1,6 +1,6 @@ import BaseHandler from "./BaseHandler"; -class CartHandler extends BaseHandler { +class PreviewHandler extends BaseHandler { constructor(buttonConfig, ppcpConfig, externalHandler) { super(buttonConfig, ppcpConfig, externalHandler); @@ -28,4 +28,4 @@ class CartHandler extends BaseHandler { } -export default CartHandler; +export default PreviewHandler; From d8b5d3120df9f48fae2fb8c0bf0f90adede75d5d Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Fri, 3 Nov 2023 10:30:40 +0000 Subject: [PATCH 06/10] Fix lint. --- modules/ppcp-compat/src/Assets/CompatAssets.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ppcp-compat/src/Assets/CompatAssets.php b/modules/ppcp-compat/src/Assets/CompatAssets.php index 85e0bde7b..34b038048 100644 --- a/modules/ppcp-compat/src/Assets/CompatAssets.php +++ b/modules/ppcp-compat/src/Assets/CompatAssets.php @@ -107,8 +107,8 @@ class CompatAssets { 'ppcp-tracking-compat', 'PayPalCommerceGatewayOrderTrackingCompat', array( - 'gzd_sync_enabled' => apply_filters( 'woocommerce_paypal_payments_sync_gzd_tracking', true ) && $this->is_gzd_active, - 'wc_shipment_sync_enabled' => apply_filters( 'woocommerce_paypal_payments_sync_wc_shipment_tracking', true ) && $this->is_wc_shipment_active, + 'gzd_sync_enabled' => apply_filters( 'woocommerce_paypal_payments_sync_gzd_tracking', true ) && $this->is_gzd_active, + 'wc_shipment_sync_enabled' => apply_filters( 'woocommerce_paypal_payments_sync_wc_shipment_tracking', true ) && $this->is_wc_shipment_active, 'wc_shipping_tax_sync_enabled' => apply_filters( 'woocommerce_paypal_payments_sync_wc_shipping_tax', true ) && $this->is_wc_shipping_tax_active, ) ); From 813af819dd9278ef54eeb53ed0c50e484a93ea3e Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Fri, 3 Nov 2023 10:33:43 +0000 Subject: [PATCH 07/10] Remove ApplePay script debug param. --- 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 3f1063684..da909f677 100644 --- a/modules/ppcp-applepay/src/Assets/ApplePayButton.php +++ b/modules/ppcp-applepay/src/Assets/ApplePayButton.php @@ -1073,7 +1073,7 @@ class ApplePayButton implements ButtonInterface { wp_register_script( 'wc-ppcp-applepay-admin', - untrailingslashit( $this->module_url ) . '/assets/js/boot-admin.js?x=' . time(), + untrailingslashit( $this->module_url ) . '/assets/js/boot-admin.js', array(), $this->version, true From 1b87bc3da11f8445575ddadb3403c791b610b977 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Fri, 3 Nov 2023 11:44:06 +0000 Subject: [PATCH 08/10] Add ApplePay preview support on non ios devices Fix clicking on preview ApplePay / GooglePay buttons --- modules/ppcp-applepay/resources/css/styles.scss | 14 +++++++++++++- modules/ppcp-applepay/resources/js/boot-admin.js | 4 ++++ modules/ppcp-googlepay/resources/css/styles.scss | 6 ++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/modules/ppcp-applepay/resources/css/styles.scss b/modules/ppcp-applepay/resources/css/styles.scss index 0abd19451..5eabe5640 100644 --- a/modules/ppcp-applepay/resources/css/styles.scss +++ b/modules/ppcp-applepay/resources/css/styles.scss @@ -52,5 +52,17 @@ } } } - +} + +.wp-admin { + .ppcp-button-applepay { + pointer-events: none; + } + &.ppcp-non-ios-device { + .ppcp-button-applepay { + apple-pay-button { + display: block; + } + } + } } diff --git a/modules/ppcp-applepay/resources/js/boot-admin.js b/modules/ppcp-applepay/resources/js/boot-admin.js index c2fa7796a..30032f56b 100644 --- a/modules/ppcp-applepay/resources/js/boot-admin.js +++ b/modules/ppcp-applepay/resources/js/boot-admin.js @@ -99,6 +99,10 @@ import widgetBuilder from "../../../ppcp-button/resources/js/modules/Renderer/Wi while (options = buttonQueue.pop()) { createButton(options.ppcpConfig); } + + if (!window.ApplePaySession) { + jQuery('body').addClass('ppcp-non-ios-device') + } }; document.addEventListener( diff --git a/modules/ppcp-googlepay/resources/css/styles.scss b/modules/ppcp-googlepay/resources/css/styles.scss index c7f8a80a1..f8233a410 100644 --- a/modules/ppcp-googlepay/resources/css/styles.scss +++ b/modules/ppcp-googlepay/resources/css/styles.scss @@ -44,3 +44,9 @@ } } + +.wp-admin { + .ppcp-button-googlepay { + pointer-events: none; + } +} From 0d3ec6e36195ae6e4f0dde318575f2b05f1fdcdc Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Mon, 6 Nov 2023 09:41:19 +0100 Subject: [PATCH 09/10] Fix phpcs --- modules/ppcp-applepay/src/ApplepayModule.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ppcp-applepay/src/ApplepayModule.php b/modules/ppcp-applepay/src/ApplepayModule.php index 378af1ff5..a02e26884 100644 --- a/modules/ppcp-applepay/src/ApplepayModule.php +++ b/modules/ppcp-applepay/src/ApplepayModule.php @@ -91,8 +91,8 @@ class ApplepayModule implements ModuleInterface { $apple_payment_method->bootstrap_ajax_request(); } - $module->load_admin_assets( $c, $apple_payment_method ); - }, + $module->load_admin_assets( $c, $apple_payment_method ); + }, 1 ); From 440f59a82bf400e898e167ac76575346d60e66ff Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Mon, 6 Nov 2023 11:43:36 +0100 Subject: [PATCH 10/10] Bump 2.4.1 version --- changelog.txt | 20 ++++++++++++++++++++ package.json | 2 +- readme.txt | 22 +++++++++++++++++++++- woocommerce-paypal-payments.php | 4 ++-- 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/changelog.txt b/changelog.txt index a840377a9..52e9534b1 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,25 @@ *** Changelog *** += 2.4.1 - xxxx-xx-xx = +* Fix - Error "PayPal order ID not found in meta" prevents automations from triggering when buying subscription via third-party payment gateway #1822 +* Fix - Card button subscription support declaration #1796 +* Fix - Pay Later messaging disappears when updating shipping option on cart page #1807 +* Fix - Apple Pay payment from single product may fail after changing shipping options in Apple Pay payment sheet #1810 +* Enhancement - Extend list of supported countries for Advanced Card Processing #1808 +* Enhancement - Extend Apple Pay/Google Pay country eligibility to Italy #1811 +* Enhancement - Override language used to display PayPal buttons #600 +* Enhancement - Apple Pay button preview #1824 +* Enhancement - Add Apple Pay & Google Pay logos on the onboarding page #1823 +* Enhancement - Improve Apple Pay compatibility with variable products on single product page #1803 +* Enhancement - Apple Pay domain registration & browser eligibility check #1821 +* Enhancement - Package Tracking compatibility with WooCommerce Shipping & ShipStation for WooCommerce #1813 +* Enhancement - Fill form when continuation in block #1794 +* Enhancement - Display Shop location Pay Later messaging on product category pages #1809 +* Enhancement - Present apple-developer-merchantid-domain-association file only when Apple Pay is enabled #1818 +* Enhancement - Improve Apple Pay compatibility on Pay for Order page #1815 +* Enhancement - Display Pay Later messages before the payment methods on the Pay for Order page #1814 +* Enhancement - Handle undefined array key warnings on PHP 8.1 #1804 + = 2.4.0 - 2023-10-31 = * Fix - Mini-Cart Bug cause of wrong DOM-Structure in v2.3.1 #1735 * Fix - ACDC disappearing after plugin updates #1751 diff --git a/package.json b/package.json index 929473958..a4d6ea019 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "woocommerce-paypal-payments", - "version": "2.4.0", + "version": "2.4.1", "description": "WooCommerce PayPal Payments", "repository": "https://github.com/woocommerce/woocommerce-paypal-payments", "license": "GPL-2.0", diff --git a/readme.txt b/readme.txt index 7df738d23..db1e38b34 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Tags: woocommerce, paypal, payments, ecommerce, checkout, cart, pay later, apple Requires at least: 5.3 Tested up to: 6.3 Requires PHP: 7.2 -Stable tag: 2.4.0 +Stable tag: 2.4.1 License: GPLv2 License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -180,6 +180,26 @@ If you encounter issues with the PayPal buttons not appearing after an update, p == Changelog == += 2.4.1 - xxxx-xx-xx = +* Fix - Error "PayPal order ID not found in meta" prevents automations from triggering when buying subscription via third-party payment gateway #1822 +* Fix - Card button subscription support declaration #1796 +* Fix - Pay Later messaging disappears when updating shipping option on cart page #1807 +* Fix - Apple Pay payment from single product may fail after changing shipping options in Apple Pay payment sheet #1810 +* Enhancement - Extend list of supported countries for Advanced Card Processing #1808 +* Enhancement - Extend Apple Pay/Google Pay country eligibility to Italy #1811 +* Enhancement - Override language used to display PayPal buttons #600 +* Enhancement - Apple Pay button preview #1824 +* Enhancement - Add Apple Pay & Google Pay logos on the onboarding page #1823 +* Enhancement - Improve Apple Pay compatibility with variable products on single product page #1803 +* Enhancement - Apple Pay domain registration & browser eligibility check #1821 +* Enhancement - Package Tracking compatibility with WooCommerce Shipping & ShipStation for WooCommerce #1813 +* Enhancement - Fill form when continuation in block #1794 +* Enhancement - Display Shop location Pay Later messaging on product category pages #1809 +* Enhancement - Present apple-developer-merchantid-domain-association file only when Apple Pay is enabled #1818 +* Enhancement - Improve Apple Pay compatibility on Pay for Order page #1815 +* Enhancement - Display Pay Later messages before the payment methods on the Pay for Order page #1814 +* Enhancement - Handle undefined array key warnings on PHP 8.1 #1804 + = 2.4.0 - 2023-10-31 = * Fix - Mini-Cart Bug cause of wrong DOM-Structure in v2.3.1 #1735 * Fix - ACDC disappearing after plugin updates #1751 diff --git a/woocommerce-paypal-payments.php b/woocommerce-paypal-payments.php index 2092a9cee..5e89cbae4 100644 --- a/woocommerce-paypal-payments.php +++ b/woocommerce-paypal-payments.php @@ -3,7 +3,7 @@ * Plugin Name: WooCommerce PayPal Payments * Plugin URI: https://woocommerce.com/products/woocommerce-paypal-payments/ * Description: PayPal's latest complete payments processing solution. Accept PayPal, Pay Later, credit/debit cards, alternative digital wallets local payment types and bank accounts. Turn on only PayPal options or process a full suite of payment methods. Enable global transaction with extensive currency and country coverage. - * Version: 2.4.0 + * Version: 2.4.1 * Author: WooCommerce * Author URI: https://woocommerce.com/ * License: GPL-2.0 @@ -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-25' ); +define( 'PAYPAL_INTEGRATION_DATE', '2023-11-06' ); ! 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_' );