From 452e72aea07ddcdc4984e6f8f64d162482e00fb6 Mon Sep 17 00:00:00 2001 From: Ricardo Metring Date: Fri, 19 Mar 2021 12:24:18 -0300 Subject: [PATCH] Enable the Payment Request feature by default for new merchants only (#1404) * Do not display error notice when account is not live, even if cached setting has `'apple_pay_domain_set' => 'no'` * Remove redundant check now that the notice is only visible from WCPay settings * Remove gateway from Apple Pay registration class * Enable by default for new merchants and refactor default settings * Refactor leftover code and change hook initialization * Remove redundant getters since default values are always set in the array * Add return before Apple Pay hooks if feature is disabled * Remove now unnecessary is_enabled checks * Remove default settings function and replace gateway_settings with get_option * Restore is_enabled checks --- includes/class-wc-payment-gateway-wcpay.php | 16 +- ...ass-wc-payments-apple-pay-registration.php | 91 ++++----- ...ayments-payment-request-button-handler.php | 174 +++++------------- includes/class-wc-payments.php | 2 +- ...ass-wc-payments-apple-pay-registration.php | 13 +- 5 files changed, 103 insertions(+), 193 deletions(-) diff --git a/includes/class-wc-payment-gateway-wcpay.php b/includes/class-wc-payment-gateway-wcpay.php index 33065d290f0..4d1f13d2481 100644 --- a/includes/class-wc-payment-gateway-wcpay.php +++ b/includes/class-wc-payment-gateway-wcpay.php @@ -171,9 +171,7 @@ public function __construct( // TODO: Remove this check and inject contents of `$payment_request_fields` into `$this->form_fields` // after `saved_cards` ahead of Apple Pay release. if ( 'yes' === get_option( '_wcpay_feature_payment_request' ) ) { - // Default values for Payment Request. - $payment_request_default_settings = WC_Payments_Payment_Request_Button_Handler::get_default_settings(); - $payment_request_fields = [ + $payment_request_fields = [ 'payment_request' => [ 'title' => __( 'Payment Request Button', 'woocommerce-payments' ), 'label' => sprintf( @@ -185,7 +183,7 @@ public function __construct( ), 'type' => 'checkbox', 'description' => __( 'If enabled, users will be able to pay using Apple Pay or Chrome Payment Request if supported by the browser.', 'woocommerce-payments' ), - 'default' => $payment_request_default_settings['payment_request'], + 'default' => empty( get_option( 'woocommerce_woocommerce_payments_settings' ) ) ? 'yes' : 'no', // Enable by default for new installations only. 'desc_tip' => true, ], 'payment_request_button_type' => [ @@ -193,7 +191,7 @@ public function __construct( 'label' => __( 'Button Type', 'woocommerce-payments' ), 'type' => 'select', 'description' => __( 'Select the button type you would like to show.', 'woocommerce-payments' ), - 'default' => $payment_request_default_settings['payment_request_button_type'], + 'default' => 'buy', 'desc_tip' => true, 'options' => [ 'default' => __( 'Default', 'woocommerce-payments' ), @@ -208,7 +206,7 @@ public function __construct( 'label' => __( 'Button Theme', 'woocommerce-payments' ), 'type' => 'select', 'description' => __( 'Select the button theme you would like to show.', 'woocommerce-payments' ), - 'default' => $payment_request_default_settings['payment_request_button_theme'], + 'default' => 'dark', 'desc_tip' => true, 'options' => [ 'dark' => __( 'Dark', 'woocommerce-payments' ), @@ -221,7 +219,7 @@ public function __construct( 'label' => __( 'Button Height', 'woocommerce-payments' ), 'type' => 'text', 'description' => __( 'Enter the height you would like the button to be in pixels. Width will always be 100%.', 'woocommerce-payments' ), - 'default' => $payment_request_default_settings['payment_request_button_height'], + 'default' => '44', 'desc_tip' => true, ], 'payment_request_button_label' => [ @@ -229,7 +227,7 @@ public function __construct( 'label' => __( 'Button Label', 'woocommerce-payments' ), 'type' => 'text', 'description' => __( 'Enter the custom text you would like the button to have.', 'woocommerce-payments' ), - 'default' => $payment_request_default_settings['payment_request_button_label'], + 'default' => __( 'Buy now', 'woocommerce-payments' ), 'desc_tip' => true, ], 'payment_request_button_branded_type' => [ @@ -237,7 +235,7 @@ public function __construct( 'label' => __( 'Branded Button Label Format', 'woocommerce-payments' ), 'type' => 'select', 'description' => __( 'Select the branded button label format.', 'woocommerce-payments' ), - 'default' => $payment_request_default_settings['payment_request_button_branded_type'], + 'default' => 'long', 'desc_tip' => true, 'options' => [ 'short' => __( 'Logo only', 'woocommerce-payments' ), diff --git a/includes/class-wc-payments-apple-pay-registration.php b/includes/class-wc-payments-apple-pay-registration.php index 6c1c11239e1..60072c3e6f9 100644 --- a/includes/class-wc-payments-apple-pay-registration.php +++ b/includes/class-wc-payments-apple-pay-registration.php @@ -30,13 +30,6 @@ class WC_Payments_Apple_Pay_Registration { */ private $payments_api_client; - /** - * The WCPay gateway object. - * - * @var WC_Payment_Gateway_WCPay - */ - private $gateway; - /** * The WCPay account object. * @@ -45,11 +38,11 @@ class WC_Payments_Apple_Pay_Registration { private $account; /** - * Gateway settings. + * WC_Payment_Gateway_WCPay instance. * - * @var array + * @var WC_Payment_Gateway_WCPay */ - private $gateway_settings; + private $gateway; /** * Current domain name. @@ -68,12 +61,27 @@ class WC_Payments_Apple_Pay_Registration { /** * Initialize class actions. * - * @param WC_Payments_API_Client $payments_api_client WooCommerce Payments API client. - * @param WC_Payment_Gateway_WCPay $gateway WooCommerce Payments gateway. - * @param WC_Payments_Account $account WooCommerce Payments account. + * @param WC_Payments_API_Client $payments_api_client WooCommerce Payments API client. + * @param WC_Payments_Account $account WooCommerce Payments account. */ - public function __construct( WC_Payments_API_Client $payments_api_client, WC_Payment_Gateway_WCPay $gateway, WC_Payments_Account $account ) { - add_action( 'init', [ $this, 'add_domain_association_rewrite_rule' ] ); + public function __construct( WC_Payments_API_Client $payments_api_client, WC_Payments_Account $account ) { + $this->domain_name = $_SERVER['HTTP_HOST'] ?? str_replace( [ 'https://', 'http://' ], '', get_site_url() ); // @codingStandardsIgnoreLine + $this->apple_pay_verify_notice = ''; + $this->payments_api_client = $payments_api_client; + $this->account = $account; + + add_action( 'init', [ $this, 'init' ] ); + } + + /** + * Initialize hooks. + * + * @return void + */ + public function init() { + $this->gateway = WC_Payments::get_gateway(); + $this->add_domain_association_rewrite_rule(); + add_action( 'admin_init', [ $this, 'verify_domain_on_domain_name_change' ] ); add_filter( 'query_vars', [ $this, 'whitelist_domain_association_query_param' ], 10, 1 ); add_action( 'parse_request', [ $this, 'parse_domain_association_request' ], 10, 1 ); @@ -83,30 +91,27 @@ public function __construct( WC_Payments_API_Client $payments_api_client, WC_Pay add_action( 'woocommerce_woocommerce_payments_updated', [ $this, 'verify_domain_if_configured' ] ); 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 ); - - // Add default settings in case the payment request options are missing. - $this->gateway_settings = array_merge( WC_Payments_Payment_Request_Button_Handler::get_default_settings(), get_option( 'woocommerce_woocommerce_payments_settings', [] ) ); - $this->domain_name = $_SERVER['HTTP_HOST'] ?? str_replace( [ 'https://', 'http://' ], '', get_site_url() ); // @codingStandardsIgnoreLine - $this->apple_pay_verify_notice = ''; - $this->payments_api_client = $payments_api_client; - $this->gateway = $gateway; - $this->account = $account; } /** * Whether the gateway and Payment Request Button (prerequisites for Apple Pay) are enabled. * - * @param array|null $settings Gateway settings. - * - * @return string Whether Apple Pay required settings are enabled. + * @return bool Whether Apple Pay required settings are enabled. */ - private function is_enabled( $settings = null ) { - // Use given settings array or use default cached settings. - $settings = $settings ?? $this->gateway_settings; - - $gateway_enabled = 'yes' === ( $settings['enabled'] ?? 'no' ); - $payment_request_enabled = 'yes' === ( $settings['payment_request'] ?? 'yes' ); + private function is_enabled() { + return $this->gateway->is_enabled() && 'yes' === $this->gateway->get_option( 'payment_request' ); + } + /** + * Whether the gateway and Payment Request Button were enabled in previous settings. + * + * @param array|null $prev_settings Gateway settings. + * + * @return bool Whether Apple Pay required settings are 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; } @@ -114,7 +119,7 @@ private function is_enabled( $settings = null ) { * Trigger Apple Pay registration upon domain name change. */ public function verify_domain_on_domain_name_change() { - $verified_domain = $this->gateway_settings['apple_pay_verified_domain'] ?? ''; + $verified_domain = $this->gateway->get_option( 'apple_pay_verified_domain' ); if ( $this->domain_name !== $verified_domain ) { $this->verify_domain_if_configured(); } @@ -248,9 +253,8 @@ public function register_domain_with_apple() { $registration_response = $this->payments_api_client->register_domain_with_apple( $this->domain_name ); if ( isset( $registration_response['id'] ) ) { - $this->gateway_settings['apple_pay_verified_domain'] = $this->domain_name; - $this->gateway_settings['apple_pay_domain_set'] = 'yes'; - update_option( 'woocommerce_woocommerce_payments_settings', $this->gateway_settings ); + $this->gateway->update_option( 'apple_pay_verified_domain', $this->domain_name ); + $this->gateway->update_option( 'apple_pay_domain_set', 'yes' ); Logger::log( __( 'Your domain has been verified with Apple Pay!', 'woocommerce-payments' ) ); Tracker::track_admin( @@ -272,9 +276,8 @@ public function register_domain_with_apple() { // Display error message in notice. $this->apple_pay_verify_notice = $error; - $this->gateway_settings['apple_pay_verified_domain'] = $this->domain_name; - $this->gateway_settings['apple_pay_domain_set'] = 'no'; - update_option( 'woocommerce_woocommerce_payments_settings', $this->gateway_settings ); + $this->gateway->update_option( 'apple_pay_verified_domain', $this->domain_name ); + $this->gateway->update_option( 'apple_pay_domain_set', 'no' ); Logger::log( 'Error registering domain with Apple: ' . $error ); Tracker::track_admin( @@ -325,10 +328,8 @@ 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 ) { - $this->gateway_settings = $settings; - - // If Gateway or Payment Request Button wasn't enabled, then might need to verify now. - if ( ! $this->is_enabled( $prev_settings ) ) { + // If Gateway or Payment Request Button weren't enabled, then might need to verify now. + if ( ! $this->was_enabled( $prev_settings ) ) { $this->verify_domain_if_configured(); } } @@ -355,12 +356,12 @@ public function display_live_account_notice() { * Display Apple Pay registration errors. */ public function display_error_notice() { - if ( ! $this->is_enabled() || ! current_user_can( 'manage_woocommerce' ) ) { + if ( ! $this->is_enabled() || ! $this->account->get_is_live() ) { return; } $empty_notice = empty( $this->apple_pay_verify_notice ); - $domain_set = $this->gateway_settings['apple_pay_domain_set'] ?? ''; + $domain_set = $this->gateway->get_option( 'apple_pay_domain_set' ); // 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 ) { diff --git a/includes/class-wc-payments-payment-request-button-handler.php b/includes/class-wc-payments-payment-request-button-handler.php index 32b0e19048a..2a98341f678 100644 --- a/includes/class-wc-payments-payment-request-button-handler.php +++ b/includes/class-wc-payments-payment-request-button-handler.php @@ -20,53 +20,45 @@ */ class WC_Payments_Payment_Request_Button_Handler { /** - * Gateway settings. + * WC_Payments_Account instance to get information about the account * - * @var array + * @var WC_Payments_Account */ - public $gateway_settings; + private $account; /** - * Is test mode active? + * WC_Payment_Gateway_WCPay instance. * - * @var bool + * @var WC_Payment_Gateway_WCPay */ - public $testmode; + private $gateway; /** - * This Instance. + * Initialize class actions. * - * @var WC_Payments_Payment_Request_Button_Handler + * @param WC_Payments_Account $account Account information. */ - private static $instance; + public function __construct( WC_Payments_Account $account ) { + $this->account = $account; - /** - * WC_Payments_Account instance to get information about the account - * - * @var WC_Payments_Account - */ - private $account; + add_action( 'init', [ $this, 'init' ] ); + } /** - * Initialize class actions. + * Initialize hooks. * - * @param WC_Payments_Account $account Account information. + * @return void */ - public function __construct( WC_Payments_Account $account ) { - self::$instance = $this; - - // Add default settings in case the payment request options are missing. - $this->gateway_settings = array_merge( self::get_default_settings(), get_option( 'woocommerce_woocommerce_payments_settings', [] ) ); - $this->account = $account; - $this->testmode = ( ! empty( $this->gateway_settings['test_mode'] ) && 'yes' === $this->gateway_settings['test_mode'] ) ? true : false; + public function init() { + $this->gateway = WC_Payments::get_gateway(); - // Checks if Stripe Gateway is enabled. - if ( empty( $this->gateway_settings ) || ( isset( $this->gateway_settings['enabled'] ) && 'yes' !== $this->gateway_settings['enabled'] ) ) { + // Checks if WCPay is enabled. + if ( ! $this->gateway->is_enabled() ) { return; } // Checks if Payment Request is enabled. - if ( ! isset( $this->gateway_settings['payment_request'] ) || 'yes' !== $this->gateway_settings['payment_request'] ) { + if ( 'yes' !== $this->gateway->get_option( 'payment_request' ) ) { return; } @@ -76,65 +68,6 @@ public function __construct( WC_Payments_Account $account ) { } add_action( 'template_redirect', [ $this, 'set_session' ] ); - $this->init(); - } - - /** - * Payment request default settings. - * - * @return array Default settings. - */ - public static function get_default_settings() { - return [ - 'payment_request' => 'no', - 'payment_request_button_type' => 'buy', - 'payment_request_button_theme' => 'dark', - 'payment_request_button_height' => '44', - 'payment_request_button_label' => __( 'Buy now', 'woocommerce-payments' ), - 'payment_request_button_branded_type' => 'long', - ]; - } - - /** - * Get this instance. - * - * @return class - */ - public static function instance() { - return self::$instance; - } - - /** - * Get total label. - * - * @return string - */ - public function get_total_label() { - // Get statement descriptor from API/cached account data. - $statement_descriptor = $this->account->get_statement_descriptor(); - return str_replace( "'", '', $statement_descriptor ) . apply_filters( 'wcpay_payment_request_total_label_suffix', ' (via WooCommerce)' ); - } - - /** - * Sets the WC customer session if one is not set. - * This is needed so nonces can be verified by AJAX Request. - * - * @return void - */ - public function set_session() { - if ( ! is_product() || ( isset( WC()->session ) && WC()->session->has_session() ) ) { - return; - } - - WC()->session->set_customer_session_cookie( true ); - } - - /** - * Initialize hooks. - * - * @return void - */ - public function init() { add_action( 'wp_enqueue_scripts', [ $this, 'scripts' ] ); add_action( 'woocommerce_after_add_to_cart_quantity', [ $this, 'display_payment_request_button_html' ], 1 ); @@ -162,30 +95,37 @@ public function init() { } /** - * Gets the button type. + * Gets total label. * - * @return string + * @return string */ - public function get_button_type() { - return isset( $this->gateway_settings['payment_request_button_type'] ) ? $this->gateway_settings['payment_request_button_type'] : 'default'; + public function get_total_label() { + // Get statement descriptor from API/cached account data. + $statement_descriptor = $this->account->get_statement_descriptor(); + return str_replace( "'", '', $statement_descriptor ) . apply_filters( 'wcpay_payment_request_total_label_suffix', ' (via WooCommerce)' ); } /** - * Gets the button theme. + * Sets the WC customer session if one is not set. + * This is needed so nonces can be verified by AJAX Request. * - * @return string + * @return void */ - public function get_button_theme() { - return isset( $this->gateway_settings['payment_request_button_theme'] ) ? $this->gateway_settings['payment_request_button_theme'] : 'dark'; + public function set_session() { + if ( ! is_product() || ( isset( WC()->session ) && WC()->session->has_session() ) ) { + return; + } + + WC()->session->set_customer_session_cookie( true ); } /** * Gets the button height. * - * @return string + * @return string */ public function get_button_height() { - return isset( $this->gateway_settings['payment_request_button_height'] ) ? str_replace( 'px', '', $this->gateway_settings['payment_request_button_height'] ) : '64'; + return str_replace( 'px', '', $this->gateway->get_option( 'payment_request_button_height' ) ); } /** @@ -194,49 +134,31 @@ public function get_button_height() { * @return boolean */ public function is_branded_button() { - return 'branded' === $this->get_button_type(); - } - - /** - * Gets the branded button type. - * - * @return string - */ - public function get_button_branded_type() { - return isset( $this->gateway_settings['payment_request_button_branded_type'] ) ? $this->gateway_settings['payment_request_button_branded_type'] : 'default'; + return 'branded' === $this->gateway->get_option( 'payment_request_button_type' ); } /** * Checks if the button is custom. * - * @return boolean + * @return boolean */ public function is_custom_button() { - return 'custom' === $this->get_button_type(); + return 'custom' === $this->gateway->get_option( 'payment_request_button_type' ); } /** * Returns custom button css selector. * - * @return string + * @return string */ public function custom_button_selector() { return $this->is_custom_button() ? '#wcpay-custom-button' : ''; } - /** - * Gets the custom button label. - * - * @return string - */ - public function get_button_label() { - return isset( $this->gateway_settings['payment_request_button_label'] ) ? $this->gateway_settings['payment_request_button_label'] : 'Buy now'; - } - /** * Gets the product data for the currently viewed page * - * @return mixed Returns false if not on a product page, the product information otherwise. + * @return mixed Returns false if not on a product page, the product information otherwise. */ public function get_product_data() { if ( ! is_product() ) { @@ -452,7 +374,7 @@ public function scripts() { } // If no SSL bail. - if ( ! $this->testmode && ! is_ssl() ) { + if ( ! $this->gateway->is_in_test_mode() && ! is_ssl() ) { Logger::log( 'Stripe Payment Request live mode requires SSL.' ); return; } @@ -468,7 +390,7 @@ public function scripts() { $stripe_params = [ 'ajax_url' => WC_AJAX::get_endpoint( '%%endpoint%%' ), 'stripe' => [ - 'publishableKey' => $this->account->get_publishable_key( WC_Payments::get_gateway()->is_in_test_mode() ), + 'publishableKey' => $this->account->get_publishable_key( $this->gateway->is_in_test_mode() ), 'accountId' => $this->account->get_stripe_account_id(), 'allow_prepaid_card' => apply_filters( 'wcpay_allow_prepaid_card', true ) ? 'yes' : 'no', ], @@ -496,14 +418,14 @@ public function scripts() { 'needs_payer_phone' => 'required' === get_option( 'woocommerce_checkout_phone_field', 'required' ), ], 'button' => [ - 'type' => $this->get_button_type(), - 'theme' => $this->get_button_theme(), + 'type' => $this->gateway->get_option( 'payment_request_button_type' ), + 'theme' => $this->gateway->get_option( 'payment_request_button_theme' ), 'height' => $this->get_button_height(), 'locale' => apply_filters( 'wcpay_payment_request_button_locale', substr( get_locale(), 0, 2 ) ), // Default format is en_US. 'is_custom' => $this->is_custom_button(), 'is_branded' => $this->is_branded_button(), 'css_selector' => $this->custom_button_selector(), - 'branded_type' => $this->get_button_branded_type(), + 'branded_type' => $this->gateway->get_option( 'payment_request_button_branded_type' ), ], 'is_product_page' => is_product(), 'product' => $this->get_product_data(), @@ -554,8 +476,8 @@ public function display_payment_request_button_html() {
is_custom_button() ) { - $label = esc_html( $this->get_button_label() ); - $class_name = esc_attr( 'button ' . $this->get_button_theme() ); + $label = esc_html( $this->gateway->get_option( 'payment_request_button_label' ) ); + $class_name = esc_attr( 'button ' . $this->gateway->get_option( 'payment_request_button_theme' ) ); $style = esc_attr( 'height:' . $this->get_button_height() . 'px;' ); echo ''; } diff --git a/includes/class-wc-payments.php b/includes/class-wc-payments.php index 9a0bedd93e6..ec8a371b12b 100644 --- a/includes/class-wc-payments.php +++ b/includes/class-wc-payments.php @@ -171,7 +171,7 @@ public static function init() { // TODO: Remove this check ahead of Apple Pay release. if ( 'yes' === get_option( '_wcpay_feature_payment_request' ) ) { self::$payment_request_button_handler = new WC_Payments_Payment_Request_Button_Handler( self::$account ); - self::$apple_pay_registration = new WC_Payments_Apple_Pay_Registration( self::$api_client, self::$gateway, self::$account ); + self::$apple_pay_registration = new WC_Payments_Apple_Pay_Registration( self::$api_client, self::$account ); } add_filter( 'woocommerce_payment_gateways', [ __CLASS__, 'register_gateway' ] ); 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 e72b1406f87..e509f4652a7 100644 --- a/tests/unit/test-class-wc-payments-apple-pay-registration.php +++ b/tests/unit/test-class-wc-payments-apple-pay-registration.php @@ -24,13 +24,6 @@ class WC_Payments_Apple_Pay_Registration_Test extends WP_UnitTestCase { */ private $mock_api_client; - /** - * Mock WC_Payment_Gateway_WCPay. - * - * @var WC_Payment_Gateway_WCPay|PHPUnit_Framework_MockObject_MockObject - */ - private $mock_gateway; - /** * Mock WC_Payments_Account. * @@ -62,15 +55,11 @@ public function setUp() { ->disableOriginalConstructor() ->getMock(); - $this->mock_gateway = $this->getMockBuilder( 'WC_Payment_Gateway_WCPay' ) - ->disableOriginalConstructor() - ->getMock(); - $this->mock_account = $this->getMockBuilder( 'WC_Payments_Account' ) ->disableOriginalConstructor() ->getMock(); - $this->wc_apple_pay_registration = new WC_Payments_Apple_Pay_Registration( $this->mock_api_client, $this->mock_gateway, $this->mock_account ); + $this->wc_apple_pay_registration = new WC_Payments_Apple_Pay_Registration( $this->mock_api_client, $this->mock_account ); $this->file_name = 'apple-developer-merchantid-domain-association'; $this->initial_file_contents = file_get_contents( WCPAY_ABSPATH . '/' . $this->file_name ); // @codingStandardsIgnoreLine