From 4dbf584a55bf703149002000dc7601b3a024dcc6 Mon Sep 17 00:00:00 2001 From: frosso Date: Thu, 4 Dec 2025 18:07:28 +0100 Subject: [PATCH 01/16] refactor: ECE buttons and settings consistency --- ...ctor-google-pay-apple-pay-settings-storage | 4 + ...s-wc-rest-payments-settings-controller.php | 40 ++- .../class-duplicates-detection-service.php | 5 +- includes/class-wc-payment-gateway-wcpay.php | 15 +- includes/class-wc-payments-account.php | 2 +- ...ass-wc-payments-apple-pay-registration.php | 96 ++++---- ...lass-wc-payments-blocks-payment-method.php | 1 - .../class-wc-payments-onboarding-service.php | 20 +- includes/class-wc-payments-status.php | 2 +- includes/class-wc-payments.php | 2 + ...xpress-checkout-button-display-handler.php | 2 +- ...yments-express-checkout-button-handler.php | 4 +- ...nt-request-to-express-checkout-enabled.php | 62 +++++ ...s-wc-rest-payments-settings-controller.php | 121 ++++++++- .../class-test-gateway.php | 16 ++ ...est-class-duplicates-detection-service.php | 6 +- ...nt-request-to-express-checkout-enabled.php | 224 +++++++++++++++++ .../test-class-wc-payment-gateway-wcpay.php | 123 ++++++++++ tests/unit/test-class-wc-payments-account.php | 3 +- ...ass-wc-payments-apple-pay-registration.php | 229 ++++++++++++++---- 20 files changed, 861 insertions(+), 116 deletions(-) create mode 100644 changelog/refactor-google-pay-apple-pay-settings-storage create mode 100644 includes/migrations/class-migrate-payment-request-to-express-checkout-enabled.php create mode 100644 tests/unit/migrations/test-class-migrate-payment-request-to-express-checkout-enabled.php diff --git a/changelog/refactor-google-pay-apple-pay-settings-storage b/changelog/refactor-google-pay-apple-pay-settings-storage new file mode 100644 index 00000000000..8b614f78813 --- /dev/null +++ b/changelog/refactor-google-pay-apple-pay-settings-storage @@ -0,0 +1,4 @@ +Significance: patch +Type: update + +refactor: Google Pay/Apple Pay settings storage consistency diff --git a/includes/admin/class-wc-rest-payments-settings-controller.php b/includes/admin/class-wc-rest-payments-settings-controller.php index d70c08f29d5..4bea3ad0923 100644 --- a/includes/admin/class-wc-rest-payments-settings-controller.php +++ b/includes/admin/class-wc-rest-payments-settings-controller.php @@ -499,7 +499,7 @@ public function get_settings(): WP_REST_Response { 'account_branding_primary_color' => $this->wcpay_gateway->get_option( 'account_branding_primary_color' ), 'account_branding_secondary_color' => $this->wcpay_gateway->get_option( 'account_branding_secondary_color' ), 'account_domestic_currency' => $this->wcpay_gateway->get_option( 'account_domestic_currency' ), - 'is_payment_request_enabled' => 'yes' === $this->wcpay_gateway->get_option( 'payment_request' ), + 'is_payment_request_enabled' => $this->get_is_payment_request_enabled(), 'is_apple_google_pay_in_payment_methods_options_enabled' => 'yes' === $this->wcpay_gateway->get_option( 'apple_google_pay_in_payment_methods_options' ), 'is_debug_log_enabled' => 'yes' === $this->wcpay_gateway->get_option( 'enable_logging' ), 'payment_request_enabled_locations' => $this->wcpay_gateway->get_option( 'payment_request_button_locations' ), @@ -842,6 +842,25 @@ private function update_account( WP_REST_Request $request ) { return $this->wcpay_gateway->update_account_settings( $updated_fields ); } + /** + * Gets the payment request enabled status. + * + * @return bool + */ + private function get_is_payment_request_enabled() { + $google_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'google_pay' ); + if ( $google_pay_gateway ) { + return $google_pay_gateway->is_enabled(); + } + + $apple_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'apple_pay' ); + if ( $apple_pay_gateway ) { + return $apple_pay_gateway->is_enabled(); + } + + return false; + } + /** * Updates the "payment request" enable/disable settings. * @@ -854,7 +873,24 @@ private function update_is_payment_request_enabled( WP_REST_Request $request ) { $is_payment_request_enabled = $request->get_param( 'is_payment_request_enabled' ); - $this->wcpay_gateway->update_option( 'payment_request', $is_payment_request_enabled ? 'yes' : 'no' ); + // Update Google Pay and Apple Pay enabled settings to keep them in sync. + $google_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'google_pay' ); + if ( $google_pay_gateway ) { + if ( $is_payment_request_enabled ) { + $google_pay_gateway->enable(); + } else { + $google_pay_gateway->disable(); + } + } + + $apple_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'apple_pay' ); + if ( $apple_pay_gateway ) { + if ( $is_payment_request_enabled ) { + $apple_pay_gateway->enable(); + } else { + $apple_pay_gateway->disable(); + } + } } /** diff --git a/includes/class-duplicates-detection-service.php b/includes/class-duplicates-detection-service.php index e2fbf78bebb..30628037b41 100644 --- a/includes/class-duplicates-detection-service.php +++ b/includes/class-duplicates-detection-service.php @@ -144,7 +144,10 @@ private function search_for_payment_request_buttons() { if ( strpos( $gateway->id, $keyword ) !== false ) { $this->gateways_qualified_by_duplicates_detector[ $prb_payment_method ][] = $gateway->id; break; - } elseif ( 'yes' === $gateway->get_option( 'payment_request' ) && in_array( $gateway->id, [ 'woocommerce_payments', 'stripe' ], true ) ) { + } elseif ( 'woocommerce_payments' === $gateway->id && method_exists( $gateway, 'is_payment_request_enabled' ) && $gateway->is_payment_request_enabled() ) { + $this->gateways_qualified_by_duplicates_detector[ $prb_payment_method ][] = $gateway->id; + break; + } elseif ( 'stripe' === $gateway->id && 'yes' === $gateway->get_option( 'payment_request' ) ) { $this->gateways_qualified_by_duplicates_detector[ $prb_payment_method ][] = $gateway->id; break; } elseif ( 'yes' === $gateway->get_option( 'express_checkout_enabled' ) ) { diff --git a/includes/class-wc-payment-gateway-wcpay.php b/includes/class-wc-payment-gateway-wcpay.php index c34a66c73c5..791efbf2bbb 100644 --- a/includes/class-wc-payment-gateway-wcpay.php +++ b/includes/class-wc-payment-gateway-wcpay.php @@ -920,7 +920,7 @@ public function is_available() { } // Disable the gateway if it should not be displayed on the checkout page. - $is_gateway_enabled = in_array( $this->stripe_id, $this->get_payment_method_ids_enabled_at_checkout(), true ) ? true : false; + $is_gateway_enabled = in_array( $this->stripe_id, $this->get_payment_method_ids_enabled_at_checkout(), true ) ? true : false; if ( ! $is_gateway_enabled ) { return false; } @@ -957,7 +957,18 @@ public function is_saved_cards_enabled() { * @return bool Whether the setting to show the payment request buttons is enabled or not. */ public function is_payment_request_enabled() { - return 'yes' === $this->get_option( 'payment_request' ); + $google_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'google_pay' ); + if ( $google_pay_gateway && $google_pay_gateway->is_enabled() ) { + return true; + } + + // fallback, just in case. + $apple_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'apple_pay' ); + if ( $apple_pay_gateway && $apple_pay_gateway->is_enabled() ) { + return true; + } + + return false; } /** diff --git a/includes/class-wc-payments-account.php b/includes/class-wc-payments-account.php index af62d5e7f26..56c129a771f 100644 --- a/includes/class-wc-payments-account.php +++ b/includes/class-wc-payments-account.php @@ -2726,7 +2726,7 @@ private function get_store_setup_details(): array { 'debug_log_enabled' => 'yes' === $gateway->get_option( 'enable_logging' ), 'payment_request' => [ - 'enabled' => 'yes' === $gateway->get_option( 'payment_request' ), + 'enabled' => $gateway->is_payment_request_enabled(), 'enabled_locations' => $gateway->get_option( 'payment_request_button_locations' ), 'button_type' => $gateway->get_option( 'payment_request_button_type' ), 'button_size' => $gateway->get_option( 'payment_request_button_size' ), diff --git a/includes/class-wc-payments-apple-pay-registration.php b/includes/class-wc-payments-apple-pay-registration.php index 07ae5385881..542deb6432c 100644 --- a/includes/class-wc-payments-apple-pay-registration.php +++ b/includes/class-wc-payments-apple-pay-registration.php @@ -49,11 +49,11 @@ class WC_Payments_Apple_Pay_Registration { private $domain_name; /** - * Stores Apple Pay domain verification issues. + * Option name for storing Apple Pay domain verification errors. * * @var string */ - private $apple_pay_verify_notice; + const APPLE_PAY_DOMAIN_ERROR_OPTION = 'wcpay_apple_pay_domain_error'; /** * Initialize class actions. @@ -63,11 +63,10 @@ class WC_Payments_Apple_Pay_Registration { * @param WC_Payment_Gateway_WCPay $gateway WooCommerce Payments gateway. */ public function __construct( WC_Payments_API_Client $payments_api_client, WC_Payments_Account $account, WC_Payment_Gateway_WCPay $gateway ) { - $this->domain_name = wp_parse_url( get_site_url(), PHP_URL_HOST ); - $this->apple_pay_verify_notice = ''; - $this->payments_api_client = $payments_api_client; - $this->account = $account; - $this->gateway = $gateway; + $this->domain_name = wp_parse_url( get_site_url(), PHP_URL_HOST ); + $this->payments_api_client = $payments_api_client; + $this->account = $account; + $this->gateway = $gateway; } /** @@ -88,30 +87,44 @@ public function init() { add_action( 'admin_init', [ $this, 'verify_domain_on_domain_name_change' ] ); add_action( 'woocommerce_woocommerce_payments_admin_notices', [ $this, 'display_error_notice' ] ); - add_action( 'add_option_woocommerce_woocommerce_payments_settings', [ $this, 'verify_domain_on_new_settings' ], 10, 2 ); - add_action( 'update_option_woocommerce_woocommerce_payments_settings', [ $this, 'verify_domain_on_updated_settings' ], 10, 2 ); + + // Listen to Apple Pay gateway settings changes for domain verification. + add_action( 'add_option_woocommerce_woocommerce_payments_apple_pay_settings', [ $this, 'verify_domain_on_new_settings' ], 10, 2 ); + add_action( 'update_option_woocommerce_woocommerce_payments_apple_pay_settings', [ $this, 'verify_domain_on_updated_settings' ], 10, 2 ); } /** - * Whether the gateway and Express Checkout Buttons (prerequisites for Apple Pay) are enabled. + * Whether Apple Pay is enabled. + * + * Checks both the main gateway and the Apple Pay gateway are enabled. * - * @return bool Whether Apple Pay required settings are enabled. + * @return bool Whether Apple Pay is enabled. */ private function is_enabled() { - return $this->gateway->is_enabled() && 'yes' === $this->gateway->get_option( 'payment_request' ); + // Check if the main gateway is enabled. + if ( ! $this->gateway->is_enabled() ) { + return false; + } + + // Check if the Apple Pay gateway is enabled. + $apple_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'apple_pay' ); + + if ( ! $apple_pay_gateway ) { + return false; + } + + return $apple_pay_gateway->is_enabled(); } /** - * Whether the gateway and Express Checkout Buttons were enabled in previous settings. + * Whether Apple Pay was enabled in previous settings. * - * @param array|null $prev_settings Gateway settings. + * @param array|null $prev_settings Apple Pay gateway settings. * - * @return bool Whether Apple Pay required settings are enabled. + * @return bool Whether Apple Pay was enabled. */ private function was_enabled( $prev_settings ) { - $gateway_enabled = 'yes' === ( $prev_settings['enabled'] ?? 'no' ); - $payment_request_enabled = 'yes' === ( $prev_settings['payment_request'] ?? 'no' ); - return $gateway_enabled && $payment_request_enabled; + return 'yes' === ( $prev_settings['enabled'] ?? 'no' ); } /** @@ -153,6 +166,7 @@ public function register_domain() { if ( isset( $registration_response['id'] ) && ( isset( $registration_response['apple_pay']['status'] ) && 'active' === $registration_response['apple_pay']['status'] ) ) { $this->gateway->update_option( 'apple_pay_verified_domain', $this->domain_name ); $this->gateway->update_option( 'apple_pay_domain_set', 'yes' ); + delete_option( self::APPLE_PAY_DOMAIN_ERROR_OPTION ); Logger::log( __( 'Your domain has been verified with Apple Pay!', 'woocommerce-payments' ) ); Tracker::track_admin( @@ -170,11 +184,10 @@ public function register_domain() { } catch ( API_Exception $e ) { $error = $e->getMessage(); } - // Display error message in notice. - $this->apple_pay_verify_notice = $error; $this->gateway->update_option( 'apple_pay_verified_domain', $this->domain_name ); $this->gateway->update_option( 'apple_pay_domain_set', 'no' ); + update_option( self::APPLE_PAY_DOMAIN_ERROR_OPTION, $error ); Logger::log( 'Error registering domain with Apple: ' . $error ); Tracker::track_admin( @@ -192,7 +205,7 @@ public function register_domain() { */ public function verify_domain_if_configured() { // If Express Checkout Buttons are not enabled, - // do not attempt to register domain. + // do not attempt to register the domain. if ( ! $this->is_enabled() ) { return; } @@ -232,29 +245,36 @@ public function display_error_notice() { return; } - $empty_notice = empty( $this->apple_pay_verify_notice ); $domain_set = $this->gateway->get_option( 'apple_pay_domain_set' ); + $error_notice = get_option( self::APPLE_PAY_DOMAIN_ERROR_OPTION, '' ); + $empty_notice = empty( $error_notice ); + // Don't display error notice if verification notice is empty and // apple_pay_domain_set option equals to '' or 'yes'. if ( $empty_notice && 'no' !== $domain_set ) { return; } + // Clear the error after retrieving it so it only displays once. + if ( ! $empty_notice ) { + delete_option( self::APPLE_PAY_DOMAIN_ERROR_OPTION ); + } + /** * Apple pay is enabled by default and domain verification initializes * when setting screen is displayed. So if domain verification is not set, * something went wrong so lets notify user. */ - $allowed_html = [ + $allowed_html = [ 'a' => [ 'href' => [], 'title' => [], ], ]; - $payment_request_button_text = __( 'Express checkouts:', 'woocommerce-payments' ); - $verification_failed_without_error = __( 'Apple Pay domain verification failed.', 'woocommerce-payments' ); - $verification_failed_with_error = __( 'Apple Pay domain verification failed with the following error:', 'woocommerce-payments' ); - $check_log_text = WC_Payments_Utils::esc_interpolated_html( + $verification_failed = $empty_notice + ? __( 'Apple Pay domain verification failed.', 'woocommerce-payments' ) + : __( 'Apple Pay domain verification failed with the following error:', 'woocommerce-payments' ); + $check_log_text = WC_Payments_Utils::esc_interpolated_html( /* translators: a: Link to the logs page */ __( 'Please check the logs for more details on this issue. Debug log must be enabled under Advanced settings to see recorded logs.', 'woocommerce-payments' ), [ @@ -271,20 +291,14 @@ public function display_error_notice() { ?>
- -

- - - -

- -

- - - -

-

apple_pay_verify_notice ) ), $allowed_html ); ?>

- +

+ + + +

+ +

+

update_is_woopay_enabled( false ); } - // Update gateway option with the Apple/Google Pay capability. - if ( ! empty( $capabilities['apple_google'] ) || ( ! empty( $capabilities['apple_pay'] ) || ! empty( $capabilities['google_pay'] ) ) ) { - $gateway->update_option( 'payment_request', 'yes' ); + // Update Apple/Google Pay gateway enabled state. + $apple_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'apple_pay' ); + $google_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'google_pay' ); + if ( ! empty( $capabilities['apple_google'] ) || ! empty( $capabilities['apple_pay'] ) ) { + if ( $apple_pay_gateway ) { + $apple_pay_gateway->enable(); + } + if ( $google_pay_gateway ) { + $google_pay_gateway->enable(); + } } else { - $gateway->update_option( 'payment_request', 'no' ); + if ( $apple_pay_gateway ) { + $apple_pay_gateway->update_option( 'enabled', 'no' ); + } + if ( $google_pay_gateway ) { + $google_pay_gateway->update_option( 'enabled', 'no' ); + } } } diff --git a/includes/class-wc-payments-status.php b/includes/class-wc-payments-status.php index b9b7d5222f0..027ccfb055c 100644 --- a/includes/class-wc-payments-status.php +++ b/includes/class-wc-payments-status.php @@ -255,7 +255,7 @@ public function render_status_report_section() { gateway->get_option( 'payment_request' ); + $payment_request_enabled = $this->gateway->is_payment_request_enabled(); $payment_request_enabled_locations = $this->gateway->get_option( 'payment_request_button_locations', [] ); $payment_request_enabled_locations = empty( $payment_request_enabled_locations ) ? 'no locations enabled' : implode( ',', $payment_request_enabled_locations ); echo esc_html( $payment_request_enabled ? __( 'Enabled', 'woocommerce-payments' ) . ' (' . $payment_request_enabled_locations . ')' : __( 'Disabled', 'woocommerce-payments' ) ); diff --git a/includes/class-wc-payments.php b/includes/class-wc-payments.php index aefbf32c0a1..a147bd290b8 100644 --- a/includes/class-wc-payments.php +++ b/includes/class-wc-payments.php @@ -693,6 +693,7 @@ function () { require_once __DIR__ . '/migrations/class-erase-bnpl-announcement-meta.php'; require_once __DIR__ . '/migrations/class-erase-deprecated-flags-and-options.php'; require_once __DIR__ . '/migrations/class-manual-capture-payment-method-settings-update.php'; + require_once __DIR__ . '/migrations/class-migrate-payment-request-to-express-checkout-enabled.php'; add_action( 'woocommerce_woocommerce_payments_updated', [ new Allowed_Payment_Request_Button_Types_Update( self::get_gateway() ), 'maybe_migrate' ] ); add_action( 'woocommerce_woocommerce_payments_updated', [ new \WCPay\Migrations\Allowed_Payment_Request_Button_Sizes_Update( self::get_gateway() ), 'maybe_migrate' ] ); add_action( 'woocommerce_woocommerce_payments_updated', [ new \WCPay\Migrations\Update_Service_Data_From_Server( self::get_account_service() ), 'maybe_migrate' ] ); @@ -705,6 +706,7 @@ function () { add_action( 'woocommerce_woocommerce_payments_updated', [ new \WCPay\Migrations\Erase_Bnpl_Announcement_Meta(), 'maybe_migrate' ] ); add_action( 'woocommerce_woocommerce_payments_updated', [ new \WCPay\Migrations\Erase_Deprecated_Flags_And_Options(), 'maybe_migrate' ] ); add_action( 'woocommerce_woocommerce_payments_updated', [ new \WCPay\Migrations\Manual_Capture_Payment_Method_Settings_Update( self::get_gateway(), self::get_payment_gateway_map() ), 'maybe_migrate' ] ); + add_action( 'woocommerce_woocommerce_payments_updated', [ new \WCPay\Migrations\Migrate_Payment_Request_To_Express_Checkout_Enabled(), 'maybe_migrate' ] ); include_once WCPAY_ABSPATH . '/includes/class-wc-payments-explicit-price-formatter.php'; WC_Payments_Explicit_Price_Formatter::init(); diff --git a/includes/express-checkout/class-wc-payments-express-checkout-button-display-handler.php b/includes/express-checkout/class-wc-payments-express-checkout-button-display-handler.php index fce76ee008d..aab7cdba567 100644 --- a/includes/express-checkout/class-wc-payments-express-checkout-button-display-handler.php +++ b/includes/express-checkout/class-wc-payments-express-checkout-button-display-handler.php @@ -82,7 +82,7 @@ public function init() { $this->express_checkout_button_handler->init(); $is_woopay_enabled = WC_Payments_Features::is_woopay_enabled(); - $is_payment_request_enabled = 'yes' === $this->gateway->get_option( 'payment_request' ); + $is_payment_request_enabled = $this->gateway->is_payment_request_enabled(); if ( $is_woopay_enabled ) { add_action( 'wc_ajax_wcpay_add_to_cart', [ $this->express_checkout_ajax_handler, 'ajax_add_to_cart' ] ); diff --git a/includes/express-checkout/class-wc-payments-express-checkout-button-handler.php b/includes/express-checkout/class-wc-payments-express-checkout-button-handler.php index 2004e5e6261..6fba3ec6883 100644 --- a/includes/express-checkout/class-wc-payments-express-checkout-button-handler.php +++ b/includes/express-checkout/class-wc-payments-express-checkout-button-handler.php @@ -76,8 +76,8 @@ public function init() { return; } - // Checks if Payment Request is enabled. - if ( 'yes' !== $this->gateway->get_option( 'payment_request' ) ) { + // Checks if Google Pay or Apple Pay are enabled. + if ( ! $this->gateway->is_payment_request_enabled() ) { return; } diff --git a/includes/migrations/class-migrate-payment-request-to-express-checkout-enabled.php b/includes/migrations/class-migrate-payment-request-to-express-checkout-enabled.php new file mode 100644 index 00000000000..fced0dc7222 --- /dev/null +++ b/includes/migrations/class-migrate-payment-request-to-express-checkout-enabled.php @@ -0,0 +1,62 @@ +migrate(); + } + + /** + * Does the actual migration as described in the class docblock. + */ + private function migrate() { + // Get card gateway's settings. + $card_settings = get_option( 'woocommerce_woocommerce_payments_settings', [] ); + $payment_request_enabled = ( $card_settings['payment_request'] ?? 'no' ) === 'yes' ? 'yes' : 'no'; + + // Update Google Pay enabled setting. + $google_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'google_pay' ); + if ( $google_pay_gateway ) { + $google_pay_gateway->update_option( 'enabled', $payment_request_enabled ); + } + + // Update Apple Pay enabled setting. + $apple_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'apple_pay' ); + if ( $apple_pay_gateway ) { + $apple_pay_gateway->update_option( 'enabled', $payment_request_enabled ); + } + + // Delete the payment_request setting from card gateway. + unset( $card_settings['payment_request'] ); + update_option( 'woocommerce_woocommerce_payments_settings', $card_settings ); + } +} diff --git a/tests/unit/admin/test-class-wc-rest-payments-settings-controller.php b/tests/unit/admin/test-class-wc-rest-payments-settings-controller.php index 0dacc70c509..c78577f7955 100644 --- a/tests/unit/admin/test-class-wc-rest-payments-settings-controller.php +++ b/tests/unit/admin/test-class-wc-rest-payments-settings-controller.php @@ -108,21 +108,28 @@ class WC_REST_Payments_Settings_Controller_Test extends WCPAY_UnitTestCase { */ private $domestic_currency = 'usd'; + /** + * Backup of the original payment_gateway_map + * + * @var array + */ + private $original_payment_gateway_map; + /** * Pre-test setup */ public function set_up() { parent::set_up(); + $this->original_payment_gateway_map = $this->get_payment_gateway_map(); + self::$settings_route = '/wc/v3/' . ( $this->is_wpcom() ? 'sites/3/' : '' ) . 'payments/settings'; require_once __DIR__ . '/../helpers/class-wc-blocks-rest-api-registration-preventer.php'; WC_Blocks_REST_API_Registration_Preventer::prevent(); - // Set the user so that we can pass the authentication. wp_set_current_user( 1 ); - // Mock the main class's cache service. $this->_cache = WC_Payments::get_database_cache(); $this->mock_cache = $this->createMock( Database_Cache::class ); WC_Payments::set_database_cache( $this->mock_cache ); @@ -246,10 +253,9 @@ public function set_up() { public function tear_down() { parent::tear_down(); WC_Blocks_REST_API_Registration_Preventer::stop_preventing(); - // Restore the cache service in the main class. WC_Payments::set_database_cache( $this->_cache ); + $this->set_payment_gateway_map( $this->original_payment_gateway_map ); - // resetting to prevent test pollution. $reflection = new \ReflectionClass( PaymentMethodDefinitionRegistry::class ); $instance_property = $reflection->getProperty( 'instance' ); $instance_property->setAccessible( true ); @@ -1056,4 +1062,111 @@ public function account_business_support_phone_validation_provider() { ], ]; } + + public function test_update_is_payment_request_enabled_updates_google_pay_and_apple_pay() { + $google_pay_gateway = $this->createMock( WC_Payment_Gateway_WCPay::class ); + $google_pay_gateway->expects( $this->once() )->method( 'enable' ); + + $apple_pay_gateway = $this->createMock( WC_Payment_Gateway_WCPay::class ); + $apple_pay_gateway->expects( $this->once() )->method( 'enable' ); + + $this->set_payment_gateway_map( + [ + 'google_pay' => $google_pay_gateway, + 'apple_pay' => $apple_pay_gateway, + ] + ); + + $request = new WP_REST_Request(); + $request->set_param( 'is_payment_request_enabled', true ); + + $this->controller->update_settings( $request ); + } + + public function test_update_is_payment_request_disabled_updates_google_pay_and_apple_pay() { + $google_pay_gateway = $this->createMock( WC_Payment_Gateway_WCPay::class ); + $google_pay_gateway->expects( $this->once() )->method( 'disable' ); + + $apple_pay_gateway = $this->createMock( WC_Payment_Gateway_WCPay::class ); + $apple_pay_gateway->expects( $this->once() )->method( 'disable' ); + + $this->set_payment_gateway_map( + [ + 'google_pay' => $google_pay_gateway, + 'apple_pay' => $apple_pay_gateway, + ] + ); + + $request = new WP_REST_Request(); + $request->set_param( 'is_payment_request_enabled', false ); + + $this->controller->update_settings( $request ); + } + + public function test_get_is_payment_request_enabled_reads_from_google_pay() { + $google_pay_gateway = $this->createMock( WC_Payment_Gateway_WCPay::class ); + $google_pay_gateway->expects( $this->once() ) + ->method( 'is_enabled' ) + ->willReturn( true ); + + $this->set_payment_gateway_map( [ 'google_pay' => $google_pay_gateway ] ); + + $request = new WP_REST_Request(); + $response = $this->controller->get_settings( $request ); + $data = $response->get_data(); + + $this->assertTrue( $data['is_payment_request_enabled'] ); + } + + public function test_get_is_payment_request_enabled_falls_back_to_apple_pay() { + $apple_pay_gateway = $this->createMock( WC_Payment_Gateway_WCPay::class ); + $apple_pay_gateway->expects( $this->once() ) + ->method( 'is_enabled' ) + ->willReturn( true ); + + $this->set_payment_gateway_map( [ 'apple_pay' => $apple_pay_gateway ] ); + + $request = new WP_REST_Request(); + $response = $this->controller->get_settings( $request ); + $data = $response->get_data(); + + $this->assertTrue( $data['is_payment_request_enabled'] ); + } + + public function test_get_is_payment_request_enabled_returns_false_when_both_unavailable() { + $this->set_payment_gateway_map( [] ); + + $request = new WP_REST_Request(); + $response = $this->controller->get_settings( $request ); + $data = $response->get_data(); + + $this->assertFalse( $data['is_payment_request_enabled'] ); + } + + /** + * Helper to get the current payment_gateway_map for backup purposes. + * + * @return array The current payment_gateway_map. + */ + private function get_payment_gateway_map() { + $reflection = new \ReflectionClass( WC_Payments::class ); + $property = $reflection->getProperty( 'payment_gateway_map' ); + $property->setAccessible( true ); + $value = $property->getValue( null ); + $property->setAccessible( false ); + return $value; + } + + /** + * Helper to set up mock gateways in the payment_gateway_map for testing. + * + * @param array $gateway_map Associative array of gateway_id => gateway_instance. + */ + private function set_payment_gateway_map( $gateway_map ) { + $reflection = new \ReflectionClass( WC_Payments::class ); + $property = $reflection->getProperty( 'payment_gateway_map' ); + $property->setAccessible( true ); + $property->setValue( null, $gateway_map ); + $property->setAccessible( false ); + } } diff --git a/tests/unit/duplicate-detection/class-test-gateway.php b/tests/unit/duplicate-detection/class-test-gateway.php index 99735fb8a7a..4f4818fe6e8 100644 --- a/tests/unit/duplicate-detection/class-test-gateway.php +++ b/tests/unit/duplicate-detection/class-test-gateway.php @@ -17,6 +17,13 @@ class Test_Gateway extends WC_Payment_Gateway { */ public $enabled = 'no'; + /** + * Value returned by is_payment_request_enabled(). + * + * @var bool + */ + public $is_payment_request_enabled_value = false; + public function __construct() { $this->form_fields = [ 'payment_request' => [ @@ -24,4 +31,13 @@ public function __construct() { ], ]; } + + /** + * Returns whether payment request is enabled. + * + * @return bool + */ + public function is_payment_request_enabled() { + return $this->is_payment_request_enabled_value; + } } diff --git a/tests/unit/duplicate-detection/test-class-duplicates-detection-service.php b/tests/unit/duplicate-detection/test-class-duplicates-detection-service.php index 50454ae8560..4f0ee2ad4e9 100644 --- a/tests/unit/duplicate-detection/test-class-duplicates-detection-service.php +++ b/tests/unit/duplicate-detection/test-class-duplicates-detection-service.php @@ -108,9 +108,9 @@ public function test_two_bnpls_enabled() { public function test_two_prbs_enabled() { $this->set_duplicates( CC_Payment_Method::PAYMENT_METHOD_STRIPE_ID, 'yes', 'yes' ); - $this->woopayments_gateway->update_option( 'payment_request', 'yes' ); - $this->woopayments_gateway->enabled = 'yes'; - $this->gateway_from_another_plugin->id = 'apple_pay'; + $this->woopayments_gateway->is_payment_request_enabled_value = true; + $this->woopayments_gateway->enabled = 'yes'; + $this->gateway_from_another_plugin->id = 'apple_pay'; $result = $this->service->find_duplicates(); diff --git a/tests/unit/migrations/test-class-migrate-payment-request-to-express-checkout-enabled.php b/tests/unit/migrations/test-class-migrate-payment-request-to-express-checkout-enabled.php new file mode 100644 index 00000000000..6197a23d059 --- /dev/null +++ b/tests/unit/migrations/test-class-migrate-payment-request-to-express-checkout-enabled.php @@ -0,0 +1,224 @@ +original_payment_gateway_map = $this->get_payment_gateway_map(); + + $this->google_pay_gateway_mock = $this->getMockBuilder( WC_Payment_Gateway_WCPay::class ) + ->disableOriginalConstructor() + ->getMock(); + + $this->apple_pay_gateway_mock = $this->getMockBuilder( WC_Payment_Gateway_WCPay::class ) + ->disableOriginalConstructor() + ->getMock(); + + $this->migration = new Migrate_Payment_Request_To_Express_Checkout_Enabled(); + } + + public function tear_down() { + $this->set_payment_gateway_map( $this->original_payment_gateway_map ); + parent::tear_down(); + } + + public function test_it_does_nothing_if_payment_request_setting_does_not_exist() { + update_option( 'woocommerce_woocommerce_payments_settings', [] ); + $this->set_payment_gateway_map( [] ); + + $this->migration->maybe_migrate(); + + $settings = get_option( 'woocommerce_woocommerce_payments_settings', [] ); + $this->assertArrayNotHasKey( 'payment_request', $settings ); + } + + public function test_it_migrates_payment_request_enabled_to_google_pay_and_apple_pay() { + update_option( 'woocommerce_woocommerce_payments_settings', [ 'payment_request' => 'yes' ] ); + $this->mock_get_payment_gateway_by_id(); + + $this->google_pay_gateway_mock->expects( $this->once() ) + ->method( 'update_option' ) + ->with( 'enabled', 'yes' ); + + $this->apple_pay_gateway_mock->expects( $this->once() ) + ->method( 'update_option' ) + ->with( 'enabled', 'yes' ); + + $this->migration->maybe_migrate(); + + $settings = get_option( 'woocommerce_woocommerce_payments_settings', [] ); + $this->assertArrayNotHasKey( 'payment_request', $settings ); + } + + public function test_it_migrates_payment_request_disabled_to_google_pay_and_apple_pay() { + update_option( 'woocommerce_woocommerce_payments_settings', [ 'payment_request' => 'no' ] ); + $this->mock_get_payment_gateway_by_id(); + + $this->google_pay_gateway_mock->expects( $this->once() ) + ->method( 'update_option' ) + ->with( 'enabled', 'no' ); + + $this->apple_pay_gateway_mock->expects( $this->once() ) + ->method( 'update_option' ) + ->with( 'enabled', 'no' ); + + $this->migration->maybe_migrate(); + + $settings = get_option( 'woocommerce_woocommerce_payments_settings', [] ); + $this->assertArrayNotHasKey( 'payment_request', $settings ); + } + + public function test_it_handles_missing_payment_request_value_as_disabled() { + update_option( 'woocommerce_woocommerce_payments_settings', [ 'payment_request' => '' ] ); + $this->mock_get_payment_gateway_by_id(); + + $this->google_pay_gateway_mock->expects( $this->once() ) + ->method( 'update_option' ) + ->with( 'enabled', 'no' ); + + $this->apple_pay_gateway_mock->expects( $this->once() ) + ->method( 'update_option' ) + ->with( 'enabled', 'no' ); + + $this->migration->maybe_migrate(); + } + + public function test_it_handles_missing_google_pay_gateway() { + update_option( 'woocommerce_woocommerce_payments_settings', [ 'payment_request' => 'yes' ] ); + $this->mock_get_payment_gateway_by_id( false, true ); + + $this->google_pay_gateway_mock->expects( $this->never() )->method( 'update_option' ); + + $this->apple_pay_gateway_mock->expects( $this->once() ) + ->method( 'update_option' ) + ->with( 'enabled', 'yes' ); + + $this->migration->maybe_migrate(); + } + + public function test_it_handles_missing_apple_pay_gateway() { + update_option( 'woocommerce_woocommerce_payments_settings', [ 'payment_request' => 'yes' ] ); + $this->mock_get_payment_gateway_by_id( true, false ); + + $this->google_pay_gateway_mock->expects( $this->once() ) + ->method( 'update_option' ) + ->with( 'enabled', 'yes' ); + + $this->apple_pay_gateway_mock->expects( $this->never() )->method( 'update_option' ); + + $this->migration->maybe_migrate(); + } + + public function test_it_preserves_other_settings_in_card_gateway() { + update_option( + 'woocommerce_woocommerce_payments_settings', + [ + 'payment_request' => 'yes', + 'enabled' => 'yes', + 'test_mode' => 'no', + 'other_setting' => 'some_value', + ] + ); + $this->mock_get_payment_gateway_by_id(); + + $this->google_pay_gateway_mock->method( 'update_option' ); + $this->apple_pay_gateway_mock->method( 'update_option' ); + + $this->migration->maybe_migrate(); + + $settings = get_option( 'woocommerce_woocommerce_payments_settings', [] ); + $this->assertArrayNotHasKey( 'payment_request', $settings ); + $this->assertEquals( 'yes', $settings['enabled'] ); + $this->assertEquals( 'no', $settings['test_mode'] ); + $this->assertEquals( 'some_value', $settings['other_setting'] ); + } + + /** + * Mock WC_Payments::get_payment_gateway_by_id to return gateway mocks. + * + * @param bool $has_google_pay Whether Google Pay gateway should be available. + * @param bool $has_apple_pay Whether Apple Pay gateway should be available. + */ + private function mock_get_payment_gateway_by_id( $has_google_pay = true, $has_apple_pay = true ) { + $gateway_map = []; + + if ( $has_google_pay ) { + $gateway_map['google_pay'] = $this->google_pay_gateway_mock; + } + + if ( $has_apple_pay ) { + $gateway_map['apple_pay'] = $this->apple_pay_gateway_mock; + } + + $this->set_payment_gateway_map( $gateway_map ); + } + + /** + * Helper to get the current payment_gateway_map for backup purposes. + * + * @return array The current payment_gateway_map. + */ + private function get_payment_gateway_map() { + $reflection = new \ReflectionClass( WC_Payments::class ); + $property = $reflection->getProperty( 'payment_gateway_map' ); + $property->setAccessible( true ); + $value = $property->getValue( null ); + $property->setAccessible( false ); + return $value; + } + + /** + * Helper to set up mock gateways in the payment_gateway_map for testing. + * + * @param array $gateway_map Associative array of gateway_id => gateway_instance. + */ + private function set_payment_gateway_map( $gateway_map ) { + $reflection = new \ReflectionClass( WC_Payments::class ); + $property = $reflection->getProperty( 'payment_gateway_map' ); + $property->setAccessible( true ); + $property->setValue( null, $gateway_map ); + $property->setAccessible( false ); + } +} diff --git a/tests/unit/test-class-wc-payment-gateway-wcpay.php b/tests/unit/test-class-wc-payment-gateway-wcpay.php index f7b2133e1e9..ceb975a1877 100644 --- a/tests/unit/test-class-wc-payment-gateway-wcpay.php +++ b/tests/unit/test-class-wc-payment-gateway-wcpay.php @@ -202,12 +202,21 @@ class WC_Payment_Gateway_WCPay_Test extends WCPAY_UnitTestCase { */ private $wp_query_query_vars_backup; + /** + * Backup of the original payment_gateway_map + * + * @var array + */ + private $original_payment_gateway_map; + /** * Pre-test setup */ public function set_up() { parent::set_up(); + $this->original_payment_gateway_map = $this->get_payment_gateway_map(); + $this->mock_api_client = $this ->getMockBuilder( 'WC_Payments_API_Client' ) ->disableOriginalConstructor() @@ -303,6 +312,9 @@ public function tear_down() { // Restore the gateway in the main class. WC_Payments::set_gateway( $this->_gateway ); + // Restore the original payment gateway map to prevent test pollution. + $this->set_payment_gateway_map( $this->original_payment_gateway_map ); + // Fall back to an US store. update_option( 'woocommerce_store_postcode', '94110' ); $this->card_gateway->update_option( 'saved_cards', 'yes' ); @@ -4235,4 +4247,115 @@ function ( $gateway ) use ( $payment_method_id ) { ) ) )[0] ?? null; } + + public function test_is_payment_request_enabled_returns_true_when_google_pay_enabled() { + // Mock Google Pay gateway as enabled. + $google_pay_gateway = $this->createMock( WC_Payment_Gateway_WCPay::class ); + $google_pay_gateway->method( 'is_enabled' ) + ->willReturn( true ); + + // Mock WC_Payments::get_payment_gateway_by_id. + $this->set_payment_gateway_map( + [ + 'google_pay' => $google_pay_gateway, + ] + ); + + $this->assertTrue( $this->card_gateway->is_payment_request_enabled() ); + } + + public function test_is_payment_request_enabled_returns_true_when_apple_pay_enabled() { + // Mock Google Pay gateway as unavailable. + // Mock Apple Pay gateway as enabled. + $apple_pay_gateway = $this->createMock( WC_Payment_Gateway_WCPay::class ); + $apple_pay_gateway->method( 'is_enabled' ) + ->willReturn( true ); + + // Mock WC_Payments::get_payment_gateway_by_id. + $this->set_payment_gateway_map( + [ + 'apple_pay' => $apple_pay_gateway, + ] + ); + + $this->assertTrue( $this->card_gateway->is_payment_request_enabled() ); + } + + public function test_is_payment_request_enabled_returns_false_when_both_disabled() { + // Mock both gateways as disabled. + $google_pay_gateway = $this->createMock( WC_Payment_Gateway_WCPay::class ); + $google_pay_gateway->method( 'is_enabled' ) + ->willReturn( false ); + + $apple_pay_gateway = $this->createMock( WC_Payment_Gateway_WCPay::class ); + $apple_pay_gateway->method( 'is_enabled' ) + ->willReturn( false ); + + // Mock WC_Payments::get_payment_gateway_by_id. + $this->set_payment_gateway_map( + [ + 'google_pay' => $google_pay_gateway, + 'apple_pay' => $apple_pay_gateway, + ] + ); + + $this->assertFalse( $this->card_gateway->is_payment_request_enabled() ); + } + + public function test_is_payment_request_enabled_returns_false_when_both_unavailable() { + // Mock both gateways as unavailable by setting empty map. + $this->set_payment_gateway_map( [] ); + + $this->assertFalse( $this->card_gateway->is_payment_request_enabled() ); + } + + public function test_is_payment_request_enabled_prioritizes_google_pay() { + // Mock both gateways as enabled. + $google_pay_gateway = $this->createMock( WC_Payment_Gateway_WCPay::class ); + $google_pay_gateway->expects( $this->once() ) + ->method( 'is_enabled' ) + ->willReturn( true ); + + $apple_pay_gateway = $this->createMock( WC_Payment_Gateway_WCPay::class ); + // Apple Pay should not be checked since Google Pay returns true. + $apple_pay_gateway->expects( $this->never() ) + ->method( 'is_enabled' ); + + // Mock WC_Payments::get_payment_gateway_by_id. + $this->set_payment_gateway_map( + [ + 'google_pay' => $google_pay_gateway, + 'apple_pay' => $apple_pay_gateway, + ] + ); + + $this->assertTrue( $this->card_gateway->is_payment_request_enabled() ); + } + + /** + * Gets the current payment_gateway_map using reflection. + * + * @return array The current payment gateway map. + */ + private function get_payment_gateway_map() { + $reflection = new \ReflectionClass( WC_Payments::class ); + $property = $reflection->getProperty( 'payment_gateway_map' ); + $property->setAccessible( true ); + $value = $property->getValue( null ); + $property->setAccessible( false ); + return $value; + } + + /** + * Helper to set up mock gateways in the payment_gateway_map for testing. + * + * @param array $gateway_map Associative array of gateway_id => gateway_instance. + */ + private function set_payment_gateway_map( $gateway_map ) { + $reflection = new \ReflectionClass( WC_Payments::class ); + $property = $reflection->getProperty( 'payment_gateway_map' ); + $property->setAccessible( true ); + $property->setValue( null, $gateway_map ); + $property->setAccessible( false ); + } } diff --git a/tests/unit/test-class-wc-payments-account.php b/tests/unit/test-class-wc-payments-account.php index 8223fbf311e..8f1b79067b9 100644 --- a/tests/unit/test-class-wc-payments-account.php +++ b/tests/unit/test-class-wc-payments-account.php @@ -3649,7 +3649,6 @@ function ( $key, $default = null ) { 'apple_google_pay_in_payment_methods_options' => 'yes', 'manual_capture' => 'no', 'enable_logging' => 'no', - 'payment_request' => 'yes', 'payment_request_button_locations' => [ 'product', 'cart' ], 'payment_request_button_type' => 'default', 'payment_request_button_size' => 'default', @@ -3663,6 +3662,7 @@ function ( $key, $default = null ) { } ); $mock_gateway->method( 'is_saved_cards_enabled' )->willReturn( true ); + $mock_gateway->method( 'is_payment_request_enabled' )->willReturn( true ); // Replace the real gateway with the mock. WC_Payments::set_gateway( $mock_gateway ); @@ -3699,7 +3699,6 @@ function ( $data ) use ( &$captured_data ) { $this->assertArrayHasKey( 'saved_cards_enabled', $captured_data ); $this->assertArrayHasKey( 'manual_capture_enabled', $captured_data ); $this->assertArrayHasKey( 'debug_log_enabled', $captured_data ); - $this->assertArrayHasKey( 'payment_request', $captured_data ); $this->assertArrayHasKey( 'woopay', $captured_data ); $this->assertArrayHasKey( 'multi_currency_enabled', $captured_data ); $this->assertArrayHasKey( 'stripe_billing_enabled', $captured_data ); diff --git a/tests/unit/test-class-wc-payments-apple-pay-registration.php b/tests/unit/test-class-wc-payments-apple-pay-registration.php index 46a375f88c1..6ff58167647 100644 --- a/tests/unit/test-class-wc-payments-apple-pay-registration.php +++ b/tests/unit/test-class-wc-payments-apple-pay-registration.php @@ -35,12 +35,19 @@ class WC_Payments_Apple_Pay_Registration_Test extends WCPAY_UnitTestCase { private $mock_account; /** - * Mock Gateway. + * Mock Gateway (card gateway, passed to constructor). * * @var WC_Payment_Gateway_WCPay|PHPUnit_Framework_MockObject_MockObject */ private $mock_gateway; + /** + * Mock Apple Pay Gateway. + * + * @var WC_Payment_Gateway_WCPay|PHPUnit_Framework_MockObject_MockObject + */ + private $mock_apple_pay_gateway; + /** * Expected domain name for testing. * @@ -48,6 +55,13 @@ class WC_Payments_Apple_Pay_Registration_Test extends WCPAY_UnitTestCase { */ private $expected_domain; + /** + * Original payment_gateway_map. + * + * @var array + */ + private $original_payment_gateway_map; + /** * Pre-test setup */ @@ -68,17 +82,29 @@ public function set_up() { ->disableOriginalConstructor() ->getMock(); + $this->mock_apple_pay_gateway = $this->getMockBuilder( WC_Payment_Gateway_WCPay::class ) + ->disableOriginalConstructor() + ->getMock(); + + $this->original_payment_gateway_map = $this->get_payment_gateway_map(); + $this->wc_apple_pay_registration = new WC_Payments_Apple_Pay_Registration( $this->mock_api_client, $this->mock_account, $this->mock_gateway ); $this->wc_apple_pay_registration->init_hooks(); } - public function test_verify_domain_on_new_settings_when_enabled() { - $this->mock_gateway->method( 'is_enabled' ) - ->willReturn( true ); + /** + * Tear down test. + */ + public function tear_down() { + $this->set_payment_gateway_map( $this->original_payment_gateway_map ); + delete_option( WC_Payments_Apple_Pay_Registration::APPLE_PAY_DOMAIN_ERROR_OPTION ); + parent::tear_down(); + } - $this->mock_gateway->method( 'get_option' ) - ->with( 'payment_request' ) - ->willReturn( 'yes' ); + public function test_verify_domain_on_new_settings_when_enabled() { + $this->mock_gateway->method( 'is_enabled' )->willReturn( true ); + $this->mock_apple_pay_gateway->method( 'is_enabled' )->willReturn( true ); + $this->set_payment_gateway_map( [ 'apple_pay' => $this->mock_apple_pay_gateway ] ); $this->mock_api_client->expects( $this->once() ) ->method( 'register_domain' ) @@ -99,61 +125,40 @@ public function test_verify_domain_on_new_settings_when_enabled() { $this->wc_apple_pay_registration->verify_domain_on_new_settings( 'option_name', - [ - 'enabled' => 'yes', - 'payment_request' => 'yes', - ] + [ 'enabled' => 'yes' ] ); } public function test_verify_domain_on_new_settings_when_not_enabled() { - $this->mock_gateway->method( 'is_enabled' ) - ->willReturn( false ); - - $this->mock_api_client->expects( $this->never() ) - ->method( 'register_domain' ); + $this->mock_apple_pay_gateway->method( 'is_enabled' )->willReturn( false ); + $this->set_payment_gateway_map( [ 'apple_pay' => $this->mock_apple_pay_gateway ] ); - $this->mock_gateway->expects( $this->never() ) - ->method( 'update_option' ); + $this->mock_api_client->expects( $this->never() )->method( 'register_domain' ); + $this->mock_gateway->expects( $this->never() )->method( 'update_option' ); $this->wc_apple_pay_registration->verify_domain_on_new_settings( 'option_name', - [ - 'enabled' => 'no', - 'payment_request' => 'yes', - ] + [ 'enabled' => 'no' ] ); } public function test_verify_domain_on_updated_settings_when_not_enabled() { - $this->mock_gateway->method( 'is_enabled' ) - ->willReturn( false ); + $this->mock_apple_pay_gateway->method( 'is_enabled' )->willReturn( false ); + $this->set_payment_gateway_map( [ 'apple_pay' => $this->mock_apple_pay_gateway ] ); - $this->mock_api_client->expects( $this->never() ) - ->method( 'register_domain' ); - - $this->mock_gateway->expects( $this->never() ) - ->method( 'update_option' ); + $this->mock_api_client->expects( $this->never() )->method( 'register_domain' ); + $this->mock_gateway->expects( $this->never() )->method( 'update_option' ); $this->wc_apple_pay_registration->verify_domain_on_updated_settings( - [ - 'enabled' => 'no', - 'payment_request' => 'yes', - ], - [ - 'enabled' => 'no', - 'payment_request' => 'yes', - ] + [ 'enabled' => 'no' ], + [ 'enabled' => 'no' ] ); } public function test_verify_domain_on_updated_settings_when_enabled() { - $this->mock_gateway->method( 'is_enabled' ) - ->willReturn( true ); - - $this->mock_gateway->method( 'get_option' ) - ->with( 'payment_request' ) - ->willReturn( 'yes' ); + $this->mock_gateway->method( 'is_enabled' )->willReturn( true ); + $this->mock_apple_pay_gateway->method( 'is_enabled' )->willReturn( true ); + $this->set_payment_gateway_map( [ 'apple_pay' => $this->mock_apple_pay_gateway ] ); $this->mock_api_client->expects( $this->once() ) ->method( 'register_domain' ) @@ -173,14 +178,136 @@ public function test_verify_domain_on_updated_settings_when_enabled() { ); $this->wc_apple_pay_registration->verify_domain_on_updated_settings( - [ - 'enabled' => 'no', - 'payment_request' => 'no', - ], - [ - 'enabled' => 'yes', - 'payment_request' => 'yes', - ] + [ 'enabled' => 'no' ], + [ 'enabled' => 'yes' ] ); } + + public function test_verify_domain_on_updated_settings_when_already_enabled() { + $this->mock_apple_pay_gateway->method( 'is_enabled' )->willReturn( true ); + $this->set_payment_gateway_map( [ 'apple_pay' => $this->mock_apple_pay_gateway ] ); + + $this->mock_api_client->expects( $this->never() )->method( 'register_domain' ); + $this->mock_gateway->expects( $this->never() )->method( 'update_option' ); + + $this->wc_apple_pay_registration->verify_domain_on_updated_settings( + [ 'enabled' => 'yes' ], + [ 'enabled' => 'yes' ] + ); + } + + public function test_register_domain_stores_error_on_failure() { + $this->mock_gateway->method( 'is_enabled' )->willReturn( true ); + $this->mock_apple_pay_gateway->method( 'is_enabled' )->willReturn( true ); + $this->set_payment_gateway_map( [ 'apple_pay' => $this->mock_apple_pay_gateway ] ); + + $error_message = 'Domain verification failed: invalid domain'; + + $this->mock_api_client->expects( $this->once() ) + ->method( 'register_domain' ) + ->with( $this->expected_domain ) + ->willReturn( + [ + 'id' => 'domain_123', + 'apple_pay' => [ + 'status' => 'failed', + 'status_details' => [ 'error_message' => $error_message ], + ], + ] + ); + + $this->wc_apple_pay_registration->verify_domain_on_new_settings( + 'option_name', + [ 'enabled' => 'yes' ] + ); + + $this->assertEquals( $error_message, get_option( WC_Payments_Apple_Pay_Registration::APPLE_PAY_DOMAIN_ERROR_OPTION ) ); + } + + public function test_register_domain_clears_error_on_success() { + $this->mock_gateway->method( 'is_enabled' )->willReturn( true ); + $this->mock_apple_pay_gateway->method( 'is_enabled' )->willReturn( true ); + $this->set_payment_gateway_map( [ 'apple_pay' => $this->mock_apple_pay_gateway ] ); + + update_option( WC_Payments_Apple_Pay_Registration::APPLE_PAY_DOMAIN_ERROR_OPTION, 'Previous error' ); + + $this->mock_api_client->expects( $this->once() ) + ->method( 'register_domain' ) + ->with( $this->expected_domain ) + ->willReturn( + [ + 'id' => 'domain_123', + 'apple_pay' => [ 'status' => 'active' ], + ] + ); + + $this->wc_apple_pay_registration->verify_domain_on_new_settings( + 'option_name', + [ 'enabled' => 'yes' ] + ); + + $this->assertFalse( get_option( WC_Payments_Apple_Pay_Registration::APPLE_PAY_DOMAIN_ERROR_OPTION ) ); + } + + public function test_display_error_notice_clears_error_after_display() { + $this->mock_gateway->method( 'is_enabled' )->willReturn( true ); + $this->mock_apple_pay_gateway->method( 'is_enabled' )->willReturn( true ); + $this->set_payment_gateway_map( [ 'apple_pay' => $this->mock_apple_pay_gateway ] ); + $this->mock_account->method( 'get_is_live' )->willReturn( true ); + $this->mock_gateway->method( 'get_option' ) + ->with( 'apple_pay_domain_set' ) + ->willReturn( 'no' ); + + update_option( WC_Payments_Apple_Pay_Registration::APPLE_PAY_DOMAIN_ERROR_OPTION, 'Test error message' ); + + ob_start(); + $this->wc_apple_pay_registration->display_error_notice(); + $output = ob_get_clean(); + + $this->assertStringContainsString( 'Test error message', $output ); + $this->assertFalse( get_option( WC_Payments_Apple_Pay_Registration::APPLE_PAY_DOMAIN_ERROR_OPTION ) ); + } + + public function test_display_error_notice_shows_generic_message_when_no_error_stored() { + $this->mock_gateway->method( 'is_enabled' )->willReturn( true ); + $this->mock_apple_pay_gateway->method( 'is_enabled' )->willReturn( true ); + $this->set_payment_gateway_map( [ 'apple_pay' => $this->mock_apple_pay_gateway ] ); + $this->mock_account->method( 'get_is_live' )->willReturn( true ); + $this->mock_gateway->method( 'get_option' ) + ->with( 'apple_pay_domain_set' ) + ->willReturn( 'no' ); + + ob_start(); + $this->wc_apple_pay_registration->display_error_notice(); + $output = ob_get_clean(); + + $this->assertStringContainsString( 'Apple Pay domain verification failed.', $output ); + } + + /** + * Helper to get the current payment_gateway_map. + * + * @return array The current payment_gateway_map. + */ + private function get_payment_gateway_map() { + $reflection = new \ReflectionClass( WC_Payments::class ); + $property = $reflection->getProperty( 'payment_gateway_map' ); + $property->setAccessible( true ); + $value = $property->getValue( null ); + $property->setAccessible( false ); + return $value; + } + + /** + * Helper to set up mock gateways in the payment_gateway_map. + * + * @param array $gateway_map Associative array of gateway_id => gateway_instance. + */ + private function set_payment_gateway_map( $gateway_map ) { + $reflection = new \ReflectionClass( WC_Payments::class ); + $property = $reflection->getProperty( 'payment_gateway_map' ); + $property->setAccessible( true ); + $property->setValue( null, $gateway_map ); + $property->setAccessible( false ); + } } From 99d7397845238632bc4da003d65b04d52d685031 Mon Sep 17 00:00:00 2001 From: Francesco Date: Thu, 4 Dec 2025 18:24:15 +0100 Subject: [PATCH 02/16] Update includes/class-wc-payment-gateway-wcpay.php Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- includes/class-wc-payment-gateway-wcpay.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-wc-payment-gateway-wcpay.php b/includes/class-wc-payment-gateway-wcpay.php index 791efbf2bbb..62d5a02bffe 100644 --- a/includes/class-wc-payment-gateway-wcpay.php +++ b/includes/class-wc-payment-gateway-wcpay.php @@ -920,7 +920,7 @@ public function is_available() { } // Disable the gateway if it should not be displayed on the checkout page. - $is_gateway_enabled = in_array( $this->stripe_id, $this->get_payment_method_ids_enabled_at_checkout(), true ) ? true : false; + $is_gateway_enabled = in_array( $this->stripe_id, $this->get_payment_method_ids_enabled_at_checkout(), true ) ? true : false; if ( ! $is_gateway_enabled ) { return false; } From 4b8f8632e15f7f2f8ba102c6752d61c1d2f6e557 Mon Sep 17 00:00:00 2001 From: Francesco Date: Thu, 4 Dec 2025 18:24:59 +0100 Subject: [PATCH 03/16] Update includes/class-wc-payment-gateway-wcpay.php Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- includes/class-wc-payment-gateway-wcpay.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-wc-payment-gateway-wcpay.php b/includes/class-wc-payment-gateway-wcpay.php index 62d5a02bffe..e24cb95f74b 100644 --- a/includes/class-wc-payment-gateway-wcpay.php +++ b/includes/class-wc-payment-gateway-wcpay.php @@ -962,7 +962,7 @@ public function is_payment_request_enabled() { return true; } - // fallback, just in case. + // Fallback, just in case. $apple_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'apple_pay' ); if ( $apple_pay_gateway && $apple_pay_gateway->is_enabled() ) { return true; From 7488f8aa115f6bb11a4508d42e3f283b52b0a8e6 Mon Sep 17 00:00:00 2001 From: frosso Date: Thu, 4 Dec 2025 18:27:00 +0100 Subject: [PATCH 04/16] WIP --- .../class-wc-rest-payments-settings-controller.php | 12 +----------- includes/class-wc-payments-onboarding-service.php | 4 ++-- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/includes/admin/class-wc-rest-payments-settings-controller.php b/includes/admin/class-wc-rest-payments-settings-controller.php index 4bea3ad0923..fee068d124a 100644 --- a/includes/admin/class-wc-rest-payments-settings-controller.php +++ b/includes/admin/class-wc-rest-payments-settings-controller.php @@ -848,17 +848,7 @@ private function update_account( WP_REST_Request $request ) { * @return bool */ private function get_is_payment_request_enabled() { - $google_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'google_pay' ); - if ( $google_pay_gateway ) { - return $google_pay_gateway->is_enabled(); - } - - $apple_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'apple_pay' ); - if ( $apple_pay_gateway ) { - return $apple_pay_gateway->is_enabled(); - } - - return false; + return $this->wcpay_gateway->is_payment_request_enabled(); } /** diff --git a/includes/class-wc-payments-onboarding-service.php b/includes/class-wc-payments-onboarding-service.php index adb79d16c2e..0ac010c19f6 100644 --- a/includes/class-wc-payments-onboarding-service.php +++ b/includes/class-wc-payments-onboarding-service.php @@ -1451,10 +1451,10 @@ public function update_enabled_payment_methods_ids( $gateway, $capabilities = [] } } else { if ( $apple_pay_gateway ) { - $apple_pay_gateway->update_option( 'enabled', 'no' ); + $apple_pay_gateway->disable(); } if ( $google_pay_gateway ) { - $google_pay_gateway->update_option( 'enabled', 'no' ); + $google_pay_gateway->disable(); } } } From fd0ca7f4c94fa2532b50bfe19850474c55016e54 Mon Sep 17 00:00:00 2001 From: frosso Date: Thu, 4 Dec 2025 18:32:00 +0100 Subject: [PATCH 05/16] WIP --- tests/WCPAY_UnitTestCase.php | 27 ++++++++++++++++++ ...s-wc-rest-payments-settings-controller.php | 27 ------------------ ...nt-request-to-express-checkout-enabled.php | 27 ------------------ .../test-class-wc-payment-gateway-wcpay.php | 28 ------------------- ...ass-wc-payments-apple-pay-registration.php | 27 ------------------ 5 files changed, 27 insertions(+), 109 deletions(-) diff --git a/tests/WCPAY_UnitTestCase.php b/tests/WCPAY_UnitTestCase.php index d7f38e3b5d0..7ad81e522f7 100644 --- a/tests/WCPAY_UnitTestCase.php +++ b/tests/WCPAY_UnitTestCase.php @@ -173,4 +173,31 @@ function ( $argument ) use ( $request_class, $request ) { return $request; } + + /** + * Gets the current payment_gateway_map from WC_Payments. + * + * @return array|null The current payment_gateway_map. + */ + protected function get_payment_gateway_map() { + $reflection = new \ReflectionClass( WC_Payments::class ); + $property = $reflection->getProperty( 'payment_gateway_map' ); + $property->setAccessible( true ); + $value = $property->getValue( null ); + $property->setAccessible( false ); + return $value; + } + + /** + * Sets the payment_gateway_map in WC_Payments. + * + * @param array $gateway_map Associative array of gateway_id => gateway_instance. + */ + protected function set_payment_gateway_map( $gateway_map ) { + $reflection = new \ReflectionClass( WC_Payments::class ); + $property = $reflection->getProperty( 'payment_gateway_map' ); + $property->setAccessible( true ); + $property->setValue( null, $gateway_map ); + $property->setAccessible( false ); + } } diff --git a/tests/unit/admin/test-class-wc-rest-payments-settings-controller.php b/tests/unit/admin/test-class-wc-rest-payments-settings-controller.php index c78577f7955..29b88cb8b35 100644 --- a/tests/unit/admin/test-class-wc-rest-payments-settings-controller.php +++ b/tests/unit/admin/test-class-wc-rest-payments-settings-controller.php @@ -1142,31 +1142,4 @@ public function test_get_is_payment_request_enabled_returns_false_when_both_unav $this->assertFalse( $data['is_payment_request_enabled'] ); } - - /** - * Helper to get the current payment_gateway_map for backup purposes. - * - * @return array The current payment_gateway_map. - */ - private function get_payment_gateway_map() { - $reflection = new \ReflectionClass( WC_Payments::class ); - $property = $reflection->getProperty( 'payment_gateway_map' ); - $property->setAccessible( true ); - $value = $property->getValue( null ); - $property->setAccessible( false ); - return $value; - } - - /** - * Helper to set up mock gateways in the payment_gateway_map for testing. - * - * @param array $gateway_map Associative array of gateway_id => gateway_instance. - */ - private function set_payment_gateway_map( $gateway_map ) { - $reflection = new \ReflectionClass( WC_Payments::class ); - $property = $reflection->getProperty( 'payment_gateway_map' ); - $property->setAccessible( true ); - $property->setValue( null, $gateway_map ); - $property->setAccessible( false ); - } } diff --git a/tests/unit/migrations/test-class-migrate-payment-request-to-express-checkout-enabled.php b/tests/unit/migrations/test-class-migrate-payment-request-to-express-checkout-enabled.php index 6197a23d059..e68a572855d 100644 --- a/tests/unit/migrations/test-class-migrate-payment-request-to-express-checkout-enabled.php +++ b/tests/unit/migrations/test-class-migrate-payment-request-to-express-checkout-enabled.php @@ -194,31 +194,4 @@ private function mock_get_payment_gateway_by_id( $has_google_pay = true, $has_ap $this->set_payment_gateway_map( $gateway_map ); } - - /** - * Helper to get the current payment_gateway_map for backup purposes. - * - * @return array The current payment_gateway_map. - */ - private function get_payment_gateway_map() { - $reflection = new \ReflectionClass( WC_Payments::class ); - $property = $reflection->getProperty( 'payment_gateway_map' ); - $property->setAccessible( true ); - $value = $property->getValue( null ); - $property->setAccessible( false ); - return $value; - } - - /** - * Helper to set up mock gateways in the payment_gateway_map for testing. - * - * @param array $gateway_map Associative array of gateway_id => gateway_instance. - */ - private function set_payment_gateway_map( $gateway_map ) { - $reflection = new \ReflectionClass( WC_Payments::class ); - $property = $reflection->getProperty( 'payment_gateway_map' ); - $property->setAccessible( true ); - $property->setValue( null, $gateway_map ); - $property->setAccessible( false ); - } } diff --git a/tests/unit/test-class-wc-payment-gateway-wcpay.php b/tests/unit/test-class-wc-payment-gateway-wcpay.php index ceb975a1877..58d4b13a00d 100644 --- a/tests/unit/test-class-wc-payment-gateway-wcpay.php +++ b/tests/unit/test-class-wc-payment-gateway-wcpay.php @@ -39,7 +39,6 @@ use WCPay\WooPay\WooPay_Utilities; use WCPay\Session_Rate_Limiter; use WCPay\PaymentMethods\Configs\Registry\PaymentMethodDefinitionRegistry; -use WC_Subscriptions; // Need to use WC_Mock_Data_Store. require_once __DIR__ . '/helpers/class-wc-mock-wc-data-store.php'; @@ -4331,31 +4330,4 @@ public function test_is_payment_request_enabled_prioritizes_google_pay() { $this->assertTrue( $this->card_gateway->is_payment_request_enabled() ); } - - /** - * Gets the current payment_gateway_map using reflection. - * - * @return array The current payment gateway map. - */ - private function get_payment_gateway_map() { - $reflection = new \ReflectionClass( WC_Payments::class ); - $property = $reflection->getProperty( 'payment_gateway_map' ); - $property->setAccessible( true ); - $value = $property->getValue( null ); - $property->setAccessible( false ); - return $value; - } - - /** - * Helper to set up mock gateways in the payment_gateway_map for testing. - * - * @param array $gateway_map Associative array of gateway_id => gateway_instance. - */ - private function set_payment_gateway_map( $gateway_map ) { - $reflection = new \ReflectionClass( WC_Payments::class ); - $property = $reflection->getProperty( 'payment_gateway_map' ); - $property->setAccessible( true ); - $property->setValue( null, $gateway_map ); - $property->setAccessible( false ); - } } diff --git a/tests/unit/test-class-wc-payments-apple-pay-registration.php b/tests/unit/test-class-wc-payments-apple-pay-registration.php index 6ff58167647..6dce97454f4 100644 --- a/tests/unit/test-class-wc-payments-apple-pay-registration.php +++ b/tests/unit/test-class-wc-payments-apple-pay-registration.php @@ -283,31 +283,4 @@ public function test_display_error_notice_shows_generic_message_when_no_error_st $this->assertStringContainsString( 'Apple Pay domain verification failed.', $output ); } - - /** - * Helper to get the current payment_gateway_map. - * - * @return array The current payment_gateway_map. - */ - private function get_payment_gateway_map() { - $reflection = new \ReflectionClass( WC_Payments::class ); - $property = $reflection->getProperty( 'payment_gateway_map' ); - $property->setAccessible( true ); - $value = $property->getValue( null ); - $property->setAccessible( false ); - return $value; - } - - /** - * Helper to set up mock gateways in the payment_gateway_map. - * - * @param array $gateway_map Associative array of gateway_id => gateway_instance. - */ - private function set_payment_gateway_map( $gateway_map ) { - $reflection = new \ReflectionClass( WC_Payments::class ); - $property = $reflection->getProperty( 'payment_gateway_map' ); - $property->setAccessible( true ); - $property->setValue( null, $gateway_map ); - $property->setAccessible( false ); - } } From 5759d104584032a324d5c59caab43ca29e4f42a0 Mon Sep 17 00:00:00 2001 From: frosso Date: Thu, 4 Dec 2025 18:38:25 +0100 Subject: [PATCH 06/16] WIP --- includes/class-wc-payment-gateway-wcpay.php | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/includes/class-wc-payment-gateway-wcpay.php b/includes/class-wc-payment-gateway-wcpay.php index e24cb95f74b..587d45df316 100644 --- a/includes/class-wc-payment-gateway-wcpay.php +++ b/includes/class-wc-payment-gateway-wcpay.php @@ -442,20 +442,6 @@ public function get_form_fields() { 'type' => 'title', 'description' => '', ], - 'payment_request' => [ - 'title' => __( 'Enable/disable', 'woocommerce-payments' ), - 'label' => sprintf( - /* translators: 1) br tag 2) Stripe anchor tag 3) Apple anchor tag */ - __( 'Enable payment request buttons (Apple Pay, Google Pay, and more). %1$sBy using Apple Pay, you agree to %2$s and %3$s\'s Terms of Service.', 'woocommerce-payments' ), - '
', - 'Stripe', - 'Apple' - ), - 'type' => 'checkbox', - 'description' => __( 'If enabled, users will be able to pay using Apple Pay, Google Pay or the Payment Request API if supported by the browser.', 'woocommerce-payments' ), - 'default' => empty( get_option( 'woocommerce_woocommerce_payments_settings' ) ) ? 'yes' : 'no', // Enable by default for new installations only. - 'desc_tip' => true, - ], 'payment_request_button_type' => [ 'title' => __( 'Button type', 'woocommerce-payments' ), 'type' => 'select', From 1e28c156b93a5612834f871f066ec5d13d892077 Mon Sep 17 00:00:00 2001 From: frosso Date: Fri, 5 Dec 2025 09:08:45 +0100 Subject: [PATCH 07/16] WIP --- ...lass-migrate-payment-request-to-express-checkout-enabled.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/migrations/class-migrate-payment-request-to-express-checkout-enabled.php b/includes/migrations/class-migrate-payment-request-to-express-checkout-enabled.php index fced0dc7222..a6ece174525 100644 --- a/includes/migrations/class-migrate-payment-request-to-express-checkout-enabled.php +++ b/includes/migrations/class-migrate-payment-request-to-express-checkout-enabled.php @@ -16,7 +16,7 @@ * * Migrates the payment_request setting to Google Pay and Apple Pay enabled settings. * - * @since 10.3.0 + * @since 10.4.0 */ class Migrate_Payment_Request_To_Express_Checkout_Enabled { From 7f8b80d57e1574c0a8dbe5fe0c10f9744187d8d5 Mon Sep 17 00:00:00 2001 From: frosso Date: Fri, 5 Dec 2025 09:24:18 +0100 Subject: [PATCH 08/16] WIP --- ...nt-request-to-express-checkout-enabled.php | 38 +++++++++++++------ ...nt-request-to-express-checkout-enabled.php | 19 +++++++++- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/includes/migrations/class-migrate-payment-request-to-express-checkout-enabled.php b/includes/migrations/class-migrate-payment-request-to-express-checkout-enabled.php index a6ece174525..f394bcf9d68 100644 --- a/includes/migrations/class-migrate-payment-request-to-express-checkout-enabled.php +++ b/includes/migrations/class-migrate-payment-request-to-express-checkout-enabled.php @@ -14,48 +14,62 @@ /** * Class Migrate_Payment_Request_To_Express_Checkout_Enabled * - * Migrates the payment_request setting to Google Pay and Apple Pay enabled settings. + * In PR #11144, Google Pay and Apple Pay were split into individual payment gateways. + * In PR #11182, the `payment_request` setting on the card gateway was replaced with + * individual `enabled` settings on each of the new gateways. * + * This migration transfers the old `payment_request` value to the new gateway settings + * and removes it from the card gateway. + * + * @see https://github.com/Automattic/woocommerce-payments/pull/11144 + * @see https://github.com/Automattic/woocommerce-payments/pull/11182 * @since 10.4.0 */ class Migrate_Payment_Request_To_Express_Checkout_Enabled { /** - * Execute the migration if the payment_request setting exists. + * Version in which this migration was introduced. + * + * @var string + */ + const VERSION_SINCE = '10.4.0'; + + /** + * Execute the migration if upgrading from a version before 10.4.0 + * and the payment_request setting exists. */ public function maybe_migrate() { - // Get card gateway's settings. - $card_settings = get_option( 'woocommerce_woocommerce_payments_settings', [] ); + $previous_version = get_option( 'woocommerce_woocommerce_payments_version' ); + if ( version_compare( self::VERSION_SINCE, $previous_version, '<=' ) ) { + return; + } - // Check if payment_request setting exists (indicates migration not yet done). + $card_settings = get_option( 'woocommerce_woocommerce_payments_settings', [] ); if ( ! isset( $card_settings['payment_request'] ) ) { return; } - $this->migrate(); + $this->migrate( $card_settings ); } /** * Does the actual migration as described in the class docblock. + * + * @param array $card_settings The card gateway settings. */ - private function migrate() { - // Get card gateway's settings. - $card_settings = get_option( 'woocommerce_woocommerce_payments_settings', [] ); + private function migrate( $card_settings ) { $payment_request_enabled = ( $card_settings['payment_request'] ?? 'no' ) === 'yes' ? 'yes' : 'no'; - // Update Google Pay enabled setting. $google_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'google_pay' ); if ( $google_pay_gateway ) { $google_pay_gateway->update_option( 'enabled', $payment_request_enabled ); } - // Update Apple Pay enabled setting. $apple_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'apple_pay' ); if ( $apple_pay_gateway ) { $apple_pay_gateway->update_option( 'enabled', $payment_request_enabled ); } - // Delete the payment_request setting from card gateway. unset( $card_settings['payment_request'] ); update_option( 'woocommerce_woocommerce_payments_settings', $card_settings ); } diff --git a/tests/unit/migrations/test-class-migrate-payment-request-to-express-checkout-enabled.php b/tests/unit/migrations/test-class-migrate-payment-request-to-express-checkout-enabled.php index e68a572855d..5a63d0b1348 100644 --- a/tests/unit/migrations/test-class-migrate-payment-request-to-express-checkout-enabled.php +++ b/tests/unit/migrations/test-class-migrate-payment-request-to-express-checkout-enabled.php @@ -57,13 +57,30 @@ public function set_up() { ->getMock(); $this->migration = new Migrate_Payment_Request_To_Express_Checkout_Enabled(); + + update_option( 'woocommerce_woocommerce_payments_version', '10.3.0' ); } public function tear_down() { $this->set_payment_gateway_map( $this->original_payment_gateway_map ); + delete_option( 'woocommerce_woocommerce_payments_version' ); parent::tear_down(); } + public function test_it_does_nothing_if_version_is_10_4_0_or_higher() { + update_option( 'woocommerce_woocommerce_payments_version', '10.4.0' ); + update_option( 'woocommerce_woocommerce_payments_settings', [ 'payment_request' => 'yes' ] ); + $this->mock_get_payment_gateway_by_id(); + + $this->google_pay_gateway_mock->expects( $this->never() )->method( 'update_option' ); + $this->apple_pay_gateway_mock->expects( $this->never() )->method( 'update_option' ); + + $this->migration->maybe_migrate(); + + $settings = get_option( 'woocommerce_woocommerce_payments_settings', [] ); + $this->assertArrayHasKey( 'payment_request', $settings ); + } + public function test_it_does_nothing_if_payment_request_setting_does_not_exist() { update_option( 'woocommerce_woocommerce_payments_settings', [] ); $this->set_payment_gateway_map( [] ); @@ -176,8 +193,6 @@ public function test_it_preserves_other_settings_in_card_gateway() { } /** - * Mock WC_Payments::get_payment_gateway_by_id to return gateway mocks. - * * @param bool $has_google_pay Whether Google Pay gateway should be available. * @param bool $has_apple_pay Whether Apple Pay gateway should be available. */ From fd4be115f83d216b75c02e9e5e5f1773978b772a Mon Sep 17 00:00:00 2001 From: frosso Date: Fri, 5 Dec 2025 09:30:34 +0100 Subject: [PATCH 09/16] WIP --- ...yment-request-to-express-checkout-enabled.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/unit/migrations/test-class-migrate-payment-request-to-express-checkout-enabled.php b/tests/unit/migrations/test-class-migrate-payment-request-to-express-checkout-enabled.php index 5a63d0b1348..d9728012251 100644 --- a/tests/unit/migrations/test-class-migrate-payment-request-to-express-checkout-enabled.php +++ b/tests/unit/migrations/test-class-migrate-payment-request-to-express-checkout-enabled.php @@ -67,8 +67,11 @@ public function tear_down() { parent::tear_down(); } - public function test_it_does_nothing_if_version_is_10_4_0_or_higher() { - update_option( 'woocommerce_woocommerce_payments_version', '10.4.0' ); + /** + * @dataProvider versions_that_should_skip_migration_provider + */ + public function test_it_does_nothing_if_version_is_10_4_0_or_higher( string $stored_version ) { + update_option( 'woocommerce_woocommerce_payments_version', $stored_version ); update_option( 'woocommerce_woocommerce_payments_settings', [ 'payment_request' => 'yes' ] ); $this->mock_get_payment_gateway_by_id(); @@ -81,6 +84,15 @@ public function test_it_does_nothing_if_version_is_10_4_0_or_higher() { $this->assertArrayHasKey( 'payment_request', $settings ); } + public function versions_that_should_skip_migration_provider(): array { + return [ + 'same version' => [ '10.4.0' ], + 'newer patch version' => [ '10.4.1' ], + 'newer minor version' => [ '10.5.0' ], + 'newer major version' => [ '11.0.0' ], + ]; + } + public function test_it_does_nothing_if_payment_request_setting_does_not_exist() { update_option( 'woocommerce_woocommerce_payments_settings', [] ); $this->set_payment_gateway_map( [] ); From d4d1780bb79e946ce0e496612c78f05eda77bf30 Mon Sep 17 00:00:00 2001 From: frosso Date: Fri, 5 Dec 2025 11:21:44 +0100 Subject: [PATCH 10/16] WIP --- ...s-wc-rest-payments-settings-controller.php | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/includes/admin/class-wc-rest-payments-settings-controller.php b/includes/admin/class-wc-rest-payments-settings-controller.php index fee068d124a..8ac9860cdae 100644 --- a/includes/admin/class-wc-rest-payments-settings-controller.php +++ b/includes/admin/class-wc-rest-payments-settings-controller.php @@ -44,7 +44,7 @@ class WC_REST_Payments_Settings_Controller extends WC_Payments_REST_Controller { * * @param WC_Payments_API_Client $api_client WC_Payments_API_Client instance. * @param WC_Payment_Gateway_WCPay $wcpay_gateway WC_Payment_Gateway_WCPay instance. - * @param WC_Payments_Account $account Account class instance. + * @param WC_Payments_Account $account Account class instance. */ public function __construct( WC_Payments_API_Client $api_client, @@ -82,7 +82,7 @@ public function register_routes() { 'args' => [ 'is_wcpay_enabled' => [ 'description' => sprintf( - /* translators: %s: WooPayments */ + /* translators: %s: WooPayments */ __( 'If %s should be enabled.', 'woocommerce-payments' ), 'WooPayments' ), @@ -109,7 +109,7 @@ public function register_routes() { ], 'is_saved_cards_enabled' => [ 'description' => sprintf( - /* translators: %s: WooPayments */ + /* translators: %s: WooPayments */ __( 'If %s "Saved cards" should be enabled.', 'woocommerce-payments' ), 'WooPayments' ), @@ -118,7 +118,7 @@ public function register_routes() { ], 'is_test_mode_enabled' => [ 'description' => sprintf( - /* translators: %s: WooPayments */ + /* translators: %s: WooPayments */ __( '%s test mode setting.', 'woocommerce-payments' ), 'WooPayments' ), @@ -127,7 +127,7 @@ public function register_routes() { ], 'is_multi_currency_enabled' => [ 'description' => sprintf( - /* translators: %s: WooPayments */ + /* translators: %s: WooPayments */ __( '%s Multi-Currency feature flag setting.', 'woocommerce-payments' ), 'WooPayments' ), @@ -136,7 +136,7 @@ public function register_routes() { ], 'is_wcpay_subscriptions_enabled' => [ 'description' => sprintf( - /* translators: %s: WooPayments */ + /* translators: %s: WooPayments */ __( '%s Subscriptions feature flag setting.', 'woocommerce-payments' ), 'WooPayments' ), @@ -145,7 +145,7 @@ public function register_routes() { ], 'account_statement_descriptor' => [ 'description' => sprintf( - /* translators: %s: WooPayments */ + /* translators: %s: WooPayments */ __( '%s bank account descriptor to be displayed in customers\' bank accounts.', 'woocommerce-payments' ), 'WooPayments' ), @@ -205,7 +205,7 @@ public function register_routes() { ], 'is_payment_request_enabled' => [ 'description' => sprintf( - /* translators: %s: WooPayments */ + /* translators: %s: WooPayments */ __( 'If %s express checkouts should be enabled.', 'woocommerce-payments' ), 'WooPayments' ), @@ -704,7 +704,7 @@ function ( $payment_method ) use ( $available_payment_methods ) { /** * Requests the capabilities of unrequested payment methods * - * @param array $payment_method_ids_to_enable Enabled Payment method ID's. + * @param array $payment_method_ids_to_enable Enabled Payment method ID's. * * @return void */ @@ -824,7 +824,7 @@ private function update_is_wcpay_subscriptions_enabled( WP_REST_Request $request private function update_account( WP_REST_Request $request ) { $updated_fields_callback = function ( $value, string $key ) { return array_key_exists( $key, WC_Payment_Gateway_WCPay::ACCOUNT_SETTINGS_MAPPING ) && - $this->wcpay_gateway->get_option( $key ) !== $value; + $this->wcpay_gateway->get_option( $key ) !== $value; }; // Filter out fields that are unchanged or not in the list of fields to update. $updated_fields = array_filter( $request->get_params(), $updated_fields_callback, ARRAY_FILTER_USE_BOTH ); @@ -865,19 +865,19 @@ private function update_is_payment_request_enabled( WP_REST_Request $request ) { // Update Google Pay and Apple Pay enabled settings to keep them in sync. $google_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'google_pay' ); - if ( $google_pay_gateway ) { - if ( $is_payment_request_enabled ) { + $apple_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'apple_pay' ); + if ( $is_payment_request_enabled ) { + if ( $google_pay_gateway ) { $google_pay_gateway->enable(); - } else { - $google_pay_gateway->disable(); } - } - - $apple_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'apple_pay' ); - if ( $apple_pay_gateway ) { - if ( $is_payment_request_enabled ) { + if ( $apple_pay_gateway ) { $apple_pay_gateway->enable(); - } else { + } + } else { + if ( $google_pay_gateway ) { + $google_pay_gateway->disable(); + } + if ( $apple_pay_gateway ) { $apple_pay_gateway->disable(); } } @@ -1142,7 +1142,7 @@ private function get_avs_check_enabled( array $ruleset_config ) { * * @todo This is a duplicate of the one in the WC_Payments_Account and WC_Payments_Onboarding_Service classes. * - * @param string $name The event name. + * @param string $name The event name. * @param array $properties Optional. The event custom properties. * * @return void From fb4d1712ee79bebf50eaef939bbb06ff2fd251be Mon Sep 17 00:00:00 2001 From: frosso Date: Fri, 5 Dec 2025 11:24:35 +0100 Subject: [PATCH 11/16] WIP --- ...s-wc-rest-payments-settings-controller.php | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/includes/admin/class-wc-rest-payments-settings-controller.php b/includes/admin/class-wc-rest-payments-settings-controller.php index 8faea3dfb51..5db9130f5a3 100644 --- a/includes/admin/class-wc-rest-payments-settings-controller.php +++ b/includes/admin/class-wc-rest-payments-settings-controller.php @@ -92,7 +92,7 @@ public function register_routes() { 'args' => [ 'is_wcpay_enabled' => [ 'description' => sprintf( - /* translators: %s: WooPayments */ + /* translators: %s: WooPayments */ __( 'If %s should be enabled.', 'woocommerce-payments' ), 'WooPayments' ), @@ -119,7 +119,7 @@ public function register_routes() { ], 'is_saved_cards_enabled' => [ 'description' => sprintf( - /* translators: %s: WooPayments */ + /* translators: %s: WooPayments */ __( 'If %s "Saved cards" should be enabled.', 'woocommerce-payments' ), 'WooPayments' ), @@ -128,7 +128,7 @@ public function register_routes() { ], 'is_test_mode_enabled' => [ 'description' => sprintf( - /* translators: %s: WooPayments */ + /* translators: %s: WooPayments */ __( '%s test mode setting.', 'woocommerce-payments' ), 'WooPayments' ), @@ -137,7 +137,7 @@ public function register_routes() { ], 'is_multi_currency_enabled' => [ 'description' => sprintf( - /* translators: %s: WooPayments */ + /* translators: %s: WooPayments */ __( '%s Multi-Currency feature flag setting.', 'woocommerce-payments' ), 'WooPayments' ), @@ -146,7 +146,7 @@ public function register_routes() { ], 'is_wcpay_subscriptions_enabled' => [ 'description' => sprintf( - /* translators: %s: WooPayments */ + /* translators: %s: WooPayments */ __( '%s Subscriptions feature flag setting.', 'woocommerce-payments' ), 'WooPayments' ), @@ -155,7 +155,7 @@ public function register_routes() { ], 'account_statement_descriptor' => [ 'description' => sprintf( - /* translators: %s: WooPayments */ + /* translators: %s: WooPayments */ __( '%s bank account descriptor to be displayed in customers\' bank accounts.', 'woocommerce-payments' ), 'WooPayments' ), @@ -215,7 +215,7 @@ public function register_routes() { ], 'is_payment_request_enabled' => [ 'description' => sprintf( - /* translators: %s: WooPayments */ + /* translators: %s: WooPayments */ __( 'If %s express checkouts should be enabled.', 'woocommerce-payments' ), 'WooPayments' ), @@ -720,7 +720,7 @@ function ( $payment_method ) use ( $available_payment_methods ) { /** * Requests the capabilities of unrequested payment methods * - * @param array $payment_method_ids_to_enable Enabled Payment method ID's. + * @param array $payment_method_ids_to_enable Enabled Payment method ID's. * * @return void */ @@ -840,7 +840,7 @@ private function update_is_wcpay_subscriptions_enabled( WP_REST_Request $request private function update_account( WP_REST_Request $request ) { $updated_fields_callback = function ( $value, string $key ) { return array_key_exists( $key, WC_Payment_Gateway_WCPay::ACCOUNT_SETTINGS_MAPPING ) && - $this->wcpay_gateway->get_option( $key ) !== $value; + $this->wcpay_gateway->get_option( $key ) !== $value; }; // Filter out fields that are unchanged or not in the list of fields to update. $updated_fields = array_filter( $request->get_params(), $updated_fields_callback, ARRAY_FILTER_USE_BOTH ); @@ -1158,7 +1158,7 @@ private function get_avs_check_enabled( array $ruleset_config ) { * * @todo This is a duplicate of the one in the WC_Payments_Account and WC_Payments_Onboarding_Service classes. * - * @param string $name The event name. + * @param string $name The event name. * @param array $properties Optional. The event custom properties. * * @return void From f405a88dcc529413b71b5692f3d41f991683924b Mon Sep 17 00:00:00 2001 From: frosso Date: Fri, 5 Dec 2025 11:25:21 +0100 Subject: [PATCH 12/16] WIP --- .../class-wc-rest-payments-settings-controller.php | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/includes/admin/class-wc-rest-payments-settings-controller.php b/includes/admin/class-wc-rest-payments-settings-controller.php index 5db9130f5a3..cd1a04b9f3f 100644 --- a/includes/admin/class-wc-rest-payments-settings-controller.php +++ b/includes/admin/class-wc-rest-payments-settings-controller.php @@ -509,7 +509,7 @@ public function get_settings(): WP_REST_Response { 'account_branding_primary_color' => $this->wcpay_gateway->get_option( 'account_branding_primary_color' ), 'account_branding_secondary_color' => $this->wcpay_gateway->get_option( 'account_branding_secondary_color' ), 'account_domestic_currency' => $this->wcpay_gateway->get_option( 'account_domestic_currency' ), - 'is_payment_request_enabled' => $this->get_is_payment_request_enabled(), + 'is_payment_request_enabled' => $this->wcpay_gateway->is_payment_request_enabled(), 'is_apple_google_pay_in_payment_methods_options_enabled' => 'yes' === $this->wcpay_gateway->get_option( 'apple_google_pay_in_payment_methods_options' ), 'is_debug_log_enabled' => 'yes' === $this->wcpay_gateway->get_option( 'enable_logging' ), 'payment_request_enabled_locations' => $this->wcpay_gateway->get_option( 'payment_request_button_locations' ), @@ -858,15 +858,6 @@ private function update_account( WP_REST_Request $request ) { return $this->wcpay_gateway->update_account_settings( $updated_fields ); } - /** - * Gets the payment request enabled status. - * - * @return bool - */ - private function get_is_payment_request_enabled() { - return $this->wcpay_gateway->is_payment_request_enabled(); - } - /** * Updates the "payment request" enable/disable settings. * From b40c8e7464fd38fb679a2499a8bf2d780da4933c Mon Sep 17 00:00:00 2001 From: frosso Date: Fri, 5 Dec 2025 11:40:32 +0100 Subject: [PATCH 13/16] better migration --- ...s-wc-rest-payments-settings-controller.php | 4 +- includes/class-wc-payment-gateway-wcpay.php | 4 +- .../class-wc-payments-onboarding-service.php | 4 +- ...nt-request-to-express-checkout-enabled.php | 11 +- ...nt-request-to-express-checkout-enabled.php | 167 +++++------------- 5 files changed, 50 insertions(+), 140 deletions(-) diff --git a/includes/admin/class-wc-rest-payments-settings-controller.php b/includes/admin/class-wc-rest-payments-settings-controller.php index cd1a04b9f3f..2dbcf5b9164 100644 --- a/includes/admin/class-wc-rest-payments-settings-controller.php +++ b/includes/admin/class-wc-rest-payments-settings-controller.php @@ -871,8 +871,8 @@ private function update_is_payment_request_enabled( WP_REST_Request $request ) { $is_payment_request_enabled = $request->get_param( 'is_payment_request_enabled' ); // Update Google Pay and Apple Pay enabled settings to keep them in sync. - $google_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'google_pay' ); - $apple_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'apple_pay' ); + $google_pay_gateway = WC_Payments::get_payment_gateway_by_id( \WCPay\PaymentMethods\Configs\Definitions\GooglePayDefinition::get_id() ); + $apple_pay_gateway = WC_Payments::get_payment_gateway_by_id( \WCPay\PaymentMethods\Configs\Definitions\ApplePayDefinition::get_id() ); if ( $is_payment_request_enabled ) { if ( $google_pay_gateway ) { $google_pay_gateway->enable(); diff --git a/includes/class-wc-payment-gateway-wcpay.php b/includes/class-wc-payment-gateway-wcpay.php index 587d45df316..e796273ba1d 100644 --- a/includes/class-wc-payment-gateway-wcpay.php +++ b/includes/class-wc-payment-gateway-wcpay.php @@ -943,13 +943,13 @@ public function is_saved_cards_enabled() { * @return bool Whether the setting to show the payment request buttons is enabled or not. */ public function is_payment_request_enabled() { - $google_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'google_pay' ); + $google_pay_gateway = WC_Payments::get_payment_gateway_by_id( \WCPay\PaymentMethods\Configs\Definitions\GooglePayDefinition::get_id() ); if ( $google_pay_gateway && $google_pay_gateway->is_enabled() ) { return true; } // Fallback, just in case. - $apple_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'apple_pay' ); + $apple_pay_gateway = WC_Payments::get_payment_gateway_by_id( \WCPay\PaymentMethods\Configs\Definitions\ApplePayDefinition::get_id() ); if ( $apple_pay_gateway && $apple_pay_gateway->is_enabled() ) { return true; } diff --git a/includes/class-wc-payments-onboarding-service.php b/includes/class-wc-payments-onboarding-service.php index 0ac010c19f6..5e98d7020bd 100644 --- a/includes/class-wc-payments-onboarding-service.php +++ b/includes/class-wc-payments-onboarding-service.php @@ -1440,8 +1440,8 @@ public function update_enabled_payment_methods_ids( $gateway, $capabilities = [] } // Update Apple/Google Pay gateway enabled state. - $apple_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'apple_pay' ); - $google_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'google_pay' ); + $google_pay_gateway = WC_Payments::get_payment_gateway_by_id( \WCPay\PaymentMethods\Configs\Definitions\GooglePayDefinition::get_id() ); + $apple_pay_gateway = WC_Payments::get_payment_gateway_by_id( \WCPay\PaymentMethods\Configs\Definitions\ApplePayDefinition::get_id() ); if ( ! empty( $capabilities['apple_google'] ) || ! empty( $capabilities['apple_pay'] ) ) { if ( $apple_pay_gateway ) { $apple_pay_gateway->enable(); diff --git a/includes/migrations/class-migrate-payment-request-to-express-checkout-enabled.php b/includes/migrations/class-migrate-payment-request-to-express-checkout-enabled.php index f394bcf9d68..fbaf1970654 100644 --- a/includes/migrations/class-migrate-payment-request-to-express-checkout-enabled.php +++ b/includes/migrations/class-migrate-payment-request-to-express-checkout-enabled.php @@ -60,15 +60,8 @@ public function maybe_migrate() { private function migrate( $card_settings ) { $payment_request_enabled = ( $card_settings['payment_request'] ?? 'no' ) === 'yes' ? 'yes' : 'no'; - $google_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'google_pay' ); - if ( $google_pay_gateway ) { - $google_pay_gateway->update_option( 'enabled', $payment_request_enabled ); - } - - $apple_pay_gateway = WC_Payments::get_payment_gateway_by_id( 'apple_pay' ); - if ( $apple_pay_gateway ) { - $apple_pay_gateway->update_option( 'enabled', $payment_request_enabled ); - } + update_option( 'woocommerce_woocommerce_payments_apple_pay_settings', [ 'enabled' => $payment_request_enabled ], true ); + update_option( 'woocommerce_woocommerce_payments_google_pay_settings', [ 'enabled' => $payment_request_enabled ], true ); unset( $card_settings['payment_request'] ); update_option( 'woocommerce_woocommerce_payments_settings', $card_settings ); diff --git a/tests/unit/migrations/test-class-migrate-payment-request-to-express-checkout-enabled.php b/tests/unit/migrations/test-class-migrate-payment-request-to-express-checkout-enabled.php index d9728012251..f851b1862c5 100644 --- a/tests/unit/migrations/test-class-migrate-payment-request-to-express-checkout-enabled.php +++ b/tests/unit/migrations/test-class-migrate-payment-request-to-express-checkout-enabled.php @@ -5,11 +5,9 @@ * @package WooCommerce\Payments\Tests */ -namespace WCPay\Migrations; +namespace unit\migrations; -use PHPUnit\Framework\MockObject\MockObject; -use WC_Payment_Gateway_WCPay; -use WC_Payments; +use WCPay\Migrations\Migrate_Payment_Request_To_Express_Checkout_Enabled; use WCPAY_UnitTestCase; /** @@ -17,53 +15,31 @@ */ class Migrate_Payment_Request_To_Express_Checkout_Enabled_Test extends WCPAY_UnitTestCase { - /** - * Google Pay gateway mock. - * - * @var MockObject|WC_Payment_Gateway_WCPay - */ - private $google_pay_gateway_mock; - - /** - * Apple Pay gateway mock. - * - * @var MockObject|WC_Payment_Gateway_WCPay - */ - private $apple_pay_gateway_mock; + const CARD_SETTINGS_OPTION_KEY = 'woocommerce_woocommerce_payments_settings'; + const GOOGLE_PAY_OPTION_KEY = 'woocommerce_woocommerce_payments_google_pay_settings'; + const APPLE_PAY_OPTION_KEY = 'woocommerce_woocommerce_payments_apple_pay_settings'; /** * @var Migrate_Payment_Request_To_Express_Checkout_Enabled */ private $migration; - /** - * Backup of the original payment_gateway_map - * - * @var array - */ - private $original_payment_gateway_map; - public function set_up() { parent::set_up(); - $this->original_payment_gateway_map = $this->get_payment_gateway_map(); - - $this->google_pay_gateway_mock = $this->getMockBuilder( WC_Payment_Gateway_WCPay::class ) - ->disableOriginalConstructor() - ->getMock(); - - $this->apple_pay_gateway_mock = $this->getMockBuilder( WC_Payment_Gateway_WCPay::class ) - ->disableOriginalConstructor() - ->getMock(); - $this->migration = new Migrate_Payment_Request_To_Express_Checkout_Enabled(); + delete_option( self::GOOGLE_PAY_OPTION_KEY ); + delete_option( self::APPLE_PAY_OPTION_KEY ); update_option( 'woocommerce_woocommerce_payments_version', '10.3.0' ); } public function tear_down() { - $this->set_payment_gateway_map( $this->original_payment_gateway_map ); delete_option( 'woocommerce_woocommerce_payments_version' ); + delete_option( self::CARD_SETTINGS_OPTION_KEY ); + delete_option( self::GOOGLE_PAY_OPTION_KEY ); + delete_option( self::APPLE_PAY_OPTION_KEY ); + parent::tear_down(); } @@ -72,16 +48,15 @@ public function tear_down() { */ public function test_it_does_nothing_if_version_is_10_4_0_or_higher( string $stored_version ) { update_option( 'woocommerce_woocommerce_payments_version', $stored_version ); - update_option( 'woocommerce_woocommerce_payments_settings', [ 'payment_request' => 'yes' ] ); - $this->mock_get_payment_gateway_by_id(); - - $this->google_pay_gateway_mock->expects( $this->never() )->method( 'update_option' ); - $this->apple_pay_gateway_mock->expects( $this->never() )->method( 'update_option' ); + update_option( self::CARD_SETTINGS_OPTION_KEY, [ 'payment_request' => 'yes' ] ); $this->migration->maybe_migrate(); - $settings = get_option( 'woocommerce_woocommerce_payments_settings', [] ); + $settings = get_option( self::CARD_SETTINGS_OPTION_KEY, [] ); $this->assertArrayHasKey( 'payment_request', $settings ); + + $this->assertFalse( get_option( self::GOOGLE_PAY_OPTION_KEY ) ); + $this->assertFalse( get_option( self::APPLE_PAY_OPTION_KEY ) ); } public function versions_that_should_skip_migration_provider(): array { @@ -94,95 +69,59 @@ public function versions_that_should_skip_migration_provider(): array { } public function test_it_does_nothing_if_payment_request_setting_does_not_exist() { - update_option( 'woocommerce_woocommerce_payments_settings', [] ); - $this->set_payment_gateway_map( [] ); + update_option( self::CARD_SETTINGS_OPTION_KEY, [] ); $this->migration->maybe_migrate(); - $settings = get_option( 'woocommerce_woocommerce_payments_settings', [] ); + $settings = get_option( self::CARD_SETTINGS_OPTION_KEY, [] ); $this->assertArrayNotHasKey( 'payment_request', $settings ); + + $this->assertFalse( get_option( self::GOOGLE_PAY_OPTION_KEY ) ); + $this->assertFalse( get_option( self::APPLE_PAY_OPTION_KEY ) ); } public function test_it_migrates_payment_request_enabled_to_google_pay_and_apple_pay() { - update_option( 'woocommerce_woocommerce_payments_settings', [ 'payment_request' => 'yes' ] ); - $this->mock_get_payment_gateway_by_id(); - - $this->google_pay_gateway_mock->expects( $this->once() ) - ->method( 'update_option' ) - ->with( 'enabled', 'yes' ); - - $this->apple_pay_gateway_mock->expects( $this->once() ) - ->method( 'update_option' ) - ->with( 'enabled', 'yes' ); + update_option( self::CARD_SETTINGS_OPTION_KEY, [ 'payment_request' => 'yes' ] ); $this->migration->maybe_migrate(); - $settings = get_option( 'woocommerce_woocommerce_payments_settings', [] ); + $settings = get_option( self::CARD_SETTINGS_OPTION_KEY, [] ); $this->assertArrayNotHasKey( 'payment_request', $settings ); + + $google_pay_settings = get_option( self::GOOGLE_PAY_OPTION_KEY, [] ); + $apple_pay_settings = get_option( self::APPLE_PAY_OPTION_KEY, [] ); + $this->assertEquals( 'yes', $google_pay_settings['enabled'] ); + $this->assertEquals( 'yes', $apple_pay_settings['enabled'] ); } public function test_it_migrates_payment_request_disabled_to_google_pay_and_apple_pay() { - update_option( 'woocommerce_woocommerce_payments_settings', [ 'payment_request' => 'no' ] ); - $this->mock_get_payment_gateway_by_id(); - - $this->google_pay_gateway_mock->expects( $this->once() ) - ->method( 'update_option' ) - ->with( 'enabled', 'no' ); - - $this->apple_pay_gateway_mock->expects( $this->once() ) - ->method( 'update_option' ) - ->with( 'enabled', 'no' ); + update_option( self::CARD_SETTINGS_OPTION_KEY, [ 'payment_request' => 'no' ] ); $this->migration->maybe_migrate(); - $settings = get_option( 'woocommerce_woocommerce_payments_settings', [] ); + $settings = get_option( self::CARD_SETTINGS_OPTION_KEY, [] ); $this->assertArrayNotHasKey( 'payment_request', $settings ); - } - public function test_it_handles_missing_payment_request_value_as_disabled() { - update_option( 'woocommerce_woocommerce_payments_settings', [ 'payment_request' => '' ] ); - $this->mock_get_payment_gateway_by_id(); - - $this->google_pay_gateway_mock->expects( $this->once() ) - ->method( 'update_option' ) - ->with( 'enabled', 'no' ); - - $this->apple_pay_gateway_mock->expects( $this->once() ) - ->method( 'update_option' ) - ->with( 'enabled', 'no' ); - - $this->migration->maybe_migrate(); + $google_pay_settings = get_option( self::GOOGLE_PAY_OPTION_KEY, [] ); + $apple_pay_settings = get_option( self::APPLE_PAY_OPTION_KEY, [] ); + $this->assertEquals( 'no', $google_pay_settings['enabled'] ); + $this->assertEquals( 'no', $apple_pay_settings['enabled'] ); } - public function test_it_handles_missing_google_pay_gateway() { - update_option( 'woocommerce_woocommerce_payments_settings', [ 'payment_request' => 'yes' ] ); - $this->mock_get_payment_gateway_by_id( false, true ); - - $this->google_pay_gateway_mock->expects( $this->never() )->method( 'update_option' ); - - $this->apple_pay_gateway_mock->expects( $this->once() ) - ->method( 'update_option' ) - ->with( 'enabled', 'yes' ); + public function test_it_handles_missing_payment_request_value_as_disabled() { + update_option( self::CARD_SETTINGS_OPTION_KEY, [ 'payment_request' => '' ] ); $this->migration->maybe_migrate(); - } - - public function test_it_handles_missing_apple_pay_gateway() { - update_option( 'woocommerce_woocommerce_payments_settings', [ 'payment_request' => 'yes' ] ); - $this->mock_get_payment_gateway_by_id( true, false ); - - $this->google_pay_gateway_mock->expects( $this->once() ) - ->method( 'update_option' ) - ->with( 'enabled', 'yes' ); - $this->apple_pay_gateway_mock->expects( $this->never() )->method( 'update_option' ); - - $this->migration->maybe_migrate(); + $google_pay_settings = get_option( self::GOOGLE_PAY_OPTION_KEY, [] ); + $apple_pay_settings = get_option( self::APPLE_PAY_OPTION_KEY, [] ); + $this->assertEquals( 'no', $google_pay_settings['enabled'] ); + $this->assertEquals( 'no', $apple_pay_settings['enabled'] ); } public function test_it_preserves_other_settings_in_card_gateway() { update_option( - 'woocommerce_woocommerce_payments_settings', + self::CARD_SETTINGS_OPTION_KEY, [ 'payment_request' => 'yes', 'enabled' => 'yes', @@ -190,35 +129,13 @@ public function test_it_preserves_other_settings_in_card_gateway() { 'other_setting' => 'some_value', ] ); - $this->mock_get_payment_gateway_by_id(); - - $this->google_pay_gateway_mock->method( 'update_option' ); - $this->apple_pay_gateway_mock->method( 'update_option' ); $this->migration->maybe_migrate(); - $settings = get_option( 'woocommerce_woocommerce_payments_settings', [] ); + $settings = get_option( self::CARD_SETTINGS_OPTION_KEY, [] ); $this->assertArrayNotHasKey( 'payment_request', $settings ); $this->assertEquals( 'yes', $settings['enabled'] ); $this->assertEquals( 'no', $settings['test_mode'] ); $this->assertEquals( 'some_value', $settings['other_setting'] ); } - - /** - * @param bool $has_google_pay Whether Google Pay gateway should be available. - * @param bool $has_apple_pay Whether Apple Pay gateway should be available. - */ - private function mock_get_payment_gateway_by_id( $has_google_pay = true, $has_apple_pay = true ) { - $gateway_map = []; - - if ( $has_google_pay ) { - $gateway_map['google_pay'] = $this->google_pay_gateway_mock; - } - - if ( $has_apple_pay ) { - $gateway_map['apple_pay'] = $this->apple_pay_gateway_mock; - } - - $this->set_payment_gateway_map( $gateway_map ); - } } From 54d4f9d50deb48d8586f6cb1507bdfbd79799024 Mon Sep 17 00:00:00 2001 From: frosso Date: Fri, 5 Dec 2025 12:23:06 +0100 Subject: [PATCH 14/16] more accurate apple pay domain verification logic --- ...ass-wc-payments-apple-pay-registration.php | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/includes/class-wc-payments-apple-pay-registration.php b/includes/class-wc-payments-apple-pay-registration.php index 542deb6432c..3c8376b3f61 100644 --- a/includes/class-wc-payments-apple-pay-registration.php +++ b/includes/class-wc-payments-apple-pay-registration.php @@ -91,6 +91,9 @@ public function init() { // Listen to Apple Pay gateway settings changes for domain verification. add_action( 'add_option_woocommerce_woocommerce_payments_apple_pay_settings', [ $this, 'verify_domain_on_new_settings' ], 10, 2 ); add_action( 'update_option_woocommerce_woocommerce_payments_apple_pay_settings', [ $this, 'verify_domain_on_updated_settings' ], 10, 2 ); + + // Also listen to main gateway settings changes, since it's a prerequisite for Apple Pay. + add_action( 'update_option_woocommerce_woocommerce_payments_settings', [ $this, 'verify_domain_on_updated_main_gateway_settings' ], 10, 2 ); } /** @@ -231,12 +234,27 @@ public function verify_domain_on_new_settings( $option, $settings ) { * @param array $settings Settings after update. */ public function verify_domain_on_updated_settings( $prev_settings, $settings ) { - // If Gateway or Express Checkout Buttons weren't enabled, then might need to verify now. + // If Apple Pay wasn't enabled, then might need to verify now. if ( ! $this->was_enabled( $prev_settings ) ) { $this->verify_domain_if_configured(); } } + /** + * Conditionally process the Apple Pay domain verification after main gateway settings are updated. + * + * @param array $prev_settings Settings before update. + * @param array $settings Settings after update. + */ + public function verify_domain_on_updated_main_gateway_settings( $prev_settings, $settings ) { + $was_main_gateway_enabled = 'yes' === ( $prev_settings['enabled'] ?? 'no' ); + + // If main gateway wasn't enabled before, might need to verify now. + if ( ! $was_main_gateway_enabled ) { + $this->verify_domain_if_configured(); + } + } + /** * Display Apple Pay registration errors. */ From 71470085d8b32e55e75366f333bfe4f8f19d4c67 Mon Sep 17 00:00:00 2001 From: frosso Date: Fri, 5 Dec 2025 12:24:27 +0100 Subject: [PATCH 15/16] WIP --- includes/class-wc-payments-onboarding-service.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-wc-payments-onboarding-service.php b/includes/class-wc-payments-onboarding-service.php index 5e98d7020bd..40a285eebca 100644 --- a/includes/class-wc-payments-onboarding-service.php +++ b/includes/class-wc-payments-onboarding-service.php @@ -1442,7 +1442,7 @@ public function update_enabled_payment_methods_ids( $gateway, $capabilities = [] // Update Apple/Google Pay gateway enabled state. $google_pay_gateway = WC_Payments::get_payment_gateway_by_id( \WCPay\PaymentMethods\Configs\Definitions\GooglePayDefinition::get_id() ); $apple_pay_gateway = WC_Payments::get_payment_gateway_by_id( \WCPay\PaymentMethods\Configs\Definitions\ApplePayDefinition::get_id() ); - if ( ! empty( $capabilities['apple_google'] ) || ! empty( $capabilities['apple_pay'] ) ) { + if ( ! empty( $capabilities['apple_google'] ) || ( ! empty( $capabilities['apple_pay'] ) || ! empty( $capabilities['google_pay'] ) ) ) { if ( $apple_pay_gateway ) { $apple_pay_gateway->enable(); } From 61940e5248287627fe7563e960f596bfeda1c451 Mon Sep 17 00:00:00 2001 From: Francesco Date: Fri, 5 Dec 2025 12:25:34 +0100 Subject: [PATCH 16/16] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- tests/unit/test-class-wc-payment-gateway-wcpay.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit/test-class-wc-payment-gateway-wcpay.php b/tests/unit/test-class-wc-payment-gateway-wcpay.php index 58d4b13a00d..405006d6bbf 100644 --- a/tests/unit/test-class-wc-payment-gateway-wcpay.php +++ b/tests/unit/test-class-wc-payment-gateway-wcpay.php @@ -39,6 +39,7 @@ use WCPay\WooPay\WooPay_Utilities; use WCPay\Session_Rate_Limiter; use WCPay\PaymentMethods\Configs\Registry\PaymentMethodDefinitionRegistry; +use WC_Subscriptions; // Need to use WC_Mock_Data_Store. require_once __DIR__ . '/helpers/class-wc-mock-wc-data-store.php';