diff --git a/client/checkout/api/index.js b/client/checkout/api/index.js index 6f67546f75a..a809fb53bb8 100644 --- a/client/checkout/api/index.js +++ b/client/checkout/api/index.js @@ -430,7 +430,10 @@ export default class WCPayAPI { paymentCountry ) { return this.request( - buildAjaxURL( getConfig( 'wcAjaxUrl' ), 'update_payment_intent' ), + buildAjaxURL( + getConfig( 'wcAjaxUrl' ), + `update_payment_intent_${ selectedUPEPaymentType }` + ), { wcpay_order_id: orderId, wc_payment_intent_id: paymentIntentId, diff --git a/client/checkout/blocks/fields.js b/client/checkout/blocks/fields.js index 08a0f08a808..8e4b0884f7a 100644 --- a/client/checkout/blocks/fields.js +++ b/client/checkout/blocks/fields.js @@ -7,6 +7,7 @@ import { CardElement, } from '@stripe/react-stripe-js'; import { useEffect, useState } from '@wordpress/element'; +import { getConfig } from 'utils/checkout'; /** * Internal dependencies @@ -30,6 +31,17 @@ const WCPayFields = ( { shouldSavePayment, } ) => { const [ errorMessage, setErrorMessage ] = useState( null ); + const isTestMode = getConfig( 'testMode' ); + const testingInstructions = ( +

+ Test mode: use the test VISA card 4242424242424242 + with any expiry date and CVC, or any test card numbers listed{ ' ' } + + here + + . +

+ ); // When it's time to process the payment, generate a Stripe payment method object. useEffect( @@ -86,12 +98,15 @@ const WCPayFields = ( { }; return ( -
- -
+ <> + { isTestMode ? testingInstructions : '' } +
+ +
+ ); }; diff --git a/client/checkout/blocks/upe-fields.js b/client/checkout/blocks/upe-fields.js index 3d9aec6a299..6e36d6b98de 100644 --- a/client/checkout/blocks/upe-fields.js +++ b/client/checkout/blocks/upe-fields.js @@ -20,9 +20,13 @@ import { useEffect, useState } from '@wordpress/element'; */ import './style.scss'; import confirmUPEPayment from './confirm-upe-payment.js'; -import { getConfig } from 'utils/checkout'; -import { getTerms } from '../utils/upe'; -import { PAYMENT_METHOD_NAME_CARD, WC_STORE_CART } from '../constants.js'; +import { getConfig, getUPEConfig } from 'utils/checkout'; +import { + getTerms, + getPaymentIntentFromSession, + getCookieValue, +} from '../utils/upe'; +import { WC_STORE_CART } from '../constants.js'; import enableStripeLinkPaymentMethod from 'wcpay/checkout/stripe-link'; import { useDispatch, useSelect } from '@wordpress/data'; import { getAppearance, getFontRulesFromPage } from '../upe-styles'; @@ -57,12 +61,14 @@ const useCustomerData = () => { const WCPayUPEFields = ( { api, activePaymentMethod, + testingInstructions, billing: { billingData }, eventRegistration: { onPaymentProcessing, onCheckoutAfterProcessingWithSuccess, }, emitResponse, + paymentMethodId, paymentIntentId, paymentIntentSecret, errorMessage, @@ -78,15 +84,11 @@ const WCPayUPEFields = ( { const [ paymentCountry, setPaymentCountry ] = useState( null ); const paymentMethodsConfig = getConfig( 'paymentMethodsConfig' ); - const testMode = getConfig( 'testMode' ); - const testCopy = ( -

- Test mode: use the test VISA card 4242424242424242 - with any expiry date and CVC. -

- ); - - const gatewayConfig = getPaymentMethods()[ PAYMENT_METHOD_NAME_CARD ]; + const isTestMode = getConfig( 'testMode' ); + const testingInstructionsIfAppropriate = isTestMode + ? testingInstructions + : ''; + const gatewayConfig = getPaymentMethods()[ paymentMethodId ]; const customerData = useCustomerData(); useEffect( () => { @@ -200,7 +202,7 @@ const WCPayUPEFields = ( { useEffect( () => onPaymentProcessing( () => { - if ( PAYMENT_METHOD_NAME_CARD !== activePaymentMethod ) { + if ( paymentMethodId !== activePaymentMethod ) { return; } @@ -234,7 +236,7 @@ const WCPayUPEFields = ( { type: 'success', meta: { paymentMethodData: { - paymentMethod: PAYMENT_METHOD_NAME_CARD, + paymentMethod: paymentMethodId, wc_payment_intent_id: paymentIntentId, wcpay_selected_upe_payment_type: selectedUPEPaymentType, }, @@ -338,7 +340,12 @@ const WCPayUPEFields = ( { return ( <> - { testMode ? testCopy : '' } +

{ getConfig( 'wcBlocksUPEAppearance' ) ); const [ fontRules ] = useState( getFontRulesFromPage() ); + const paymentMethodsConfig = getUPEConfig( 'paymentMethodsConfig' ); useEffect( () => { async function generateUPEAppearance() { @@ -381,10 +389,20 @@ const ConsumableWCPayFields = ( { api, ...props } ) => { if ( paymentIntentId || hasRequestedIntent ) { return; } - - async function createIntent() { + async function createIntent( paymentMethodId ) { try { - const response = await api.createIntent(); + const response = await api.createIntent( paymentMethodId ); + const cartHash = getCookieValue( 'woocommerce_cart_hash' ); + if ( cartHash ) { + paymentMethodsConfig[ + paymentMethodId + ].upePaymentIntentData = + cartHash + + '-' + + response.id + + '-' + + response.client_secret; + } setPaymentIntentId( response.id ); setClientSecret( response.client_secret ); } catch ( error ) { @@ -395,9 +413,34 @@ const ConsumableWCPayFields = ( { api, ...props } ) => { ); } } + + function getOrCreateIntent( paymentMethodId ) { + const { + intentId, + clientSecret: paymentClientSecret, + } = getPaymentIntentFromSession( + paymentMethodsConfig, + paymentMethodId + ); + if ( ! intentId ) { + createIntent( paymentMethodId ); + } else { + setPaymentIntentId( intentId ); + setClientSecret( paymentClientSecret ); + } + } + setHasRequestedIntent( true ); - createIntent(); - }, [ paymentIntentId, hasRequestedIntent, api, errorMessage, appearance ] ); + getOrCreateIntent( props.paymentMethodId ); + }, [ + props.paymentMethodId, + paymentIntentId, + paymentMethodsConfig, + hasRequestedIntent, + api, + errorMessage, + appearance, + ] ); if ( ! clientSecret ) { if ( errorMessage ) { diff --git a/client/checkout/blocks/upe.js b/client/checkout/blocks/upe.js index e78a1be4cce..79d3aa618b0 100644 --- a/client/checkout/blocks/upe.js +++ b/client/checkout/blocks/upe.js @@ -13,53 +13,89 @@ import { /** * Internal dependencies */ -import { PAYMENT_METHOD_NAME_CARD } from '../constants.js'; -import { getConfig } from 'utils/checkout'; +import { getUPEConfig } from 'utils/checkout'; import WCPayAPI from './../api'; import WCPayUPEFields from './upe-fields.js'; import { SavedTokenHandler } from './saved-token-handler'; import request from '../utils/request'; import enqueueFraudScripts from 'fraud-scripts'; import paymentRequestPaymentMethod from '../../payment-request/blocks'; +import { + PAYMENT_METHOD_NAME_CARD, + PAYMENT_METHOD_NAME_BANCONTACT, + PAYMENT_METHOD_NAME_BECS, + PAYMENT_METHOD_NAME_EPS, + PAYMENT_METHOD_NAME_GIROPAY, + PAYMENT_METHOD_NAME_IDEAL, + PAYMENT_METHOD_NAME_P24, + PAYMENT_METHOD_NAME_SEPA, + PAYMENT_METHOD_NAME_SOFORT, +} from '../constants.js'; + +const upeMethods = { + card: PAYMENT_METHOD_NAME_CARD, + bancontact: PAYMENT_METHOD_NAME_BANCONTACT, + au_becs_debit: PAYMENT_METHOD_NAME_BECS, + eps: PAYMENT_METHOD_NAME_EPS, + giropay: PAYMENT_METHOD_NAME_GIROPAY, + ideal: PAYMENT_METHOD_NAME_IDEAL, + p24: PAYMENT_METHOD_NAME_P24, + sepa_debit: PAYMENT_METHOD_NAME_SEPA, + sofort: PAYMENT_METHOD_NAME_SOFORT, +}; -const paymentMethodsConfig = getConfig( 'paymentMethodsConfig' ); +const enabledPaymentMethodsConfig = getUPEConfig( 'paymentMethodsConfig' ); const isStripeLinkEnabled = - paymentMethodsConfig.link !== undefined && - paymentMethodsConfig.card !== undefined; + enabledPaymentMethodsConfig.link !== undefined && + enabledPaymentMethodsConfig.card !== undefined; // Create an API object, which will be used throughout the checkout. const api = new WCPayAPI( { - publishableKey: getConfig( 'publishableKey' ), - accountId: getConfig( 'accountId' ), - forceNetworkSavedCards: getConfig( 'forceNetworkSavedCards' ), - locale: getConfig( 'locale' ), - isUPEEnabled: getConfig( 'isUPEEnabled' ), + publishableKey: getUPEConfig( 'publishableKey' ), + accountId: getUPEConfig( 'accountId' ), + forceNetworkSavedCards: getUPEConfig( 'forceNetworkSavedCards' ), + locale: getUPEConfig( 'locale' ), + isUPEEnabled: getUPEConfig( 'isUPEEnabled' ), isStripeLinkEnabled, }, request ); -registerPaymentMethod( { - name: PAYMENT_METHOD_NAME_CARD, - content: , - edit: , - savedTokenComponent: , - canMakePayment: () => !! api.getStripe(), - paymentMethodId: PAYMENT_METHOD_NAME_CARD, - label: getConfig( 'checkoutTitle' ), - ariaLabel: __( 'WooCommerce Payments', 'woocommerce-payments' ), - supports: { - showSavedCards: getConfig( 'isSavedCardsEnabled' ) ?? false, - showSaveOption: - ( getConfig( 'isSavedCardsEnabled' ) && - ! getConfig( 'cartContainsSubscription' ) ) ?? - false, - features: getConfig( 'features' ), - }, -} ); +Object.entries( enabledPaymentMethodsConfig ).map( ( [ upeName, upeConfig ] ) => + registerPaymentMethod( { + name: upeName, + content: ( + + ), + edit: ( + + ), + savedTokenComponent: , + canMakePayment: () => !! api.getStripe(), + paymentMethodId: upeMethods[ upeName ], + label: upeConfig.title, + ariaLabel: __( 'WooCommerce Payments', 'woocommerce-payments' ), + supports: { + showSavedCards: getUPEConfig( 'isSavedCardsEnabled' ) ?? false, + showSaveOption: + ( getUPEConfig( 'isSavedCardsEnabled' ) && + ! getUPEConfig( 'cartContainsSubscription' ) ) ?? + false, + features: getUPEConfig( 'features' ), + }, + } ) +); registerExpressPaymentMethod( paymentRequestPaymentMethod( api ) ); window.addEventListener( 'load', () => { - enqueueFraudScripts( getConfig( 'fraudServices' ) ); + enqueueFraudScripts( getUPEConfig( 'fraudServices' ) ); } ); diff --git a/client/checkout/classic/upe.js b/client/checkout/classic/upe.js index 351bf2eac91..90dbab2ed65 100644 --- a/client/checkout/classic/upe.js +++ b/client/checkout/classic/upe.js @@ -18,7 +18,11 @@ import { getUPEConfig } from 'utils/checkout'; import WCPayAPI from '../api'; import enqueueFraudScripts from 'fraud-scripts'; import { getFontRulesFromPage, getAppearance } from '../upe-styles'; -import { getTerms, getCookieValue, isWCPayChosen } from '../utils/upe'; +import { + getTerms, + isWCPayChosen, + getPaymentIntentFromSession, +} from '../utils/upe'; import enableStripeLinkPaymentMethod from '../stripe-link'; import apiRequest from '../utils/request'; import showErrorCheckout from '../utils/show-error-checkout'; @@ -230,7 +234,10 @@ jQuery( function ( $ ) { let { intentId, clientSecret } = isSetupIntent ? getSetupIntentFromSession( paymentMethodType ) - : getPaymentIntentFromSession( paymentMethodType ); + : getPaymentIntentFromSession( + paymentMethodsConfig, + paymentMethodType + ); const $upeContainer = $( upeDOMElement ); blockUI( $upeContainer ); @@ -667,30 +674,6 @@ jQuery( function ( $ ) { ); } - /** - * Returns the cached payment intent for the current cart state. - * - * @param {string} paymentMethodType Stripe payment method type ID. - * @return {Object} The intent id and client secret required for mounting the UPE element. - */ - function getPaymentIntentFromSession( paymentMethodType ) { - const cartHash = getCookieValue( 'woocommerce_cart_hash' ); - const upePaymentIntentData = - paymentMethodsConfig[ paymentMethodType ].upePaymentIntentData; - - if ( - cartHash && - upePaymentIntentData && - upePaymentIntentData.startsWith( cartHash ) - ) { - const intentId = upePaymentIntentData.split( '-' )[ 1 ]; - const clientSecret = upePaymentIntentData.split( '-' )[ 2 ]; - return { intentId, clientSecret }; - } - - return {}; - } - /** * Returns the cached setup intent. * @@ -721,6 +704,7 @@ jQuery( function ( $ ) { return upeComponents.paymentIntentClientSecret; } const { clientSecret } = getPaymentIntentFromSession( + paymentMethodsConfig, paymentMethodType ); return clientSecret ? clientSecret : null; diff --git a/client/checkout/constants.js b/client/checkout/constants.js index 6e10ac456ad..d9a71f96861 100644 --- a/client/checkout/constants.js +++ b/client/checkout/constants.js @@ -7,7 +7,6 @@ export const PAYMENT_METHOD_NAME_IDEAL = 'woocommerce_payments_ideal'; export const PAYMENT_METHOD_NAME_P24 = 'woocommerce_payments_p24'; export const PAYMENT_METHOD_NAME_SEPA = 'woocommerce_payments_sepa_debit'; export const PAYMENT_METHOD_NAME_SOFORT = 'woocommerce_payments_sofort'; -export const PAYMENT_METHOD_NAME_UPE = 'woocommerce_payments_upe'; export const PAYMENT_METHOD_NAME_PAYMENT_REQUEST = 'woocommerce_payments_payment_request'; export const WC_STORE_CART = 'wc/store/cart'; diff --git a/client/checkout/utils/upe.js b/client/checkout/utils/upe.js index 8dabb9500b4..e5cba6529ab 100644 --- a/client/checkout/utils/upe.js +++ b/client/checkout/utils/upe.js @@ -36,3 +36,31 @@ export const isWCPayChosen = function () { return document.getElementById( 'payment_method_woocommerce_payments' ) .checked; }; + +/** + * Returns the cached payment intent for the current cart state. + * + * @param {Object} paymentMethodsConfig Array of configs for payment methods. + * @param {string} paymentMethodType Type of the payment method. + * @return {Object} The intent id and client secret required for mounting the UPE element. + */ +export const getPaymentIntentFromSession = ( + paymentMethodsConfig, + paymentMethodType +) => { + const cartHash = getCookieValue( 'woocommerce_cart_hash' ); + const upePaymentIntentData = + paymentMethodsConfig[ paymentMethodType ].upePaymentIntentData; + + if ( + cartHash && + upePaymentIntentData && + upePaymentIntentData.startsWith( cartHash ) + ) { + const intentId = upePaymentIntentData.split( '-' )[ 1 ]; + const clientSecret = upePaymentIntentData.split( '-' )[ 2 ]; + return { intentId, clientSecret }; + } + + return {}; +}; diff --git a/includes/class-payment-information.php b/includes/class-payment-information.php index 25d1c3fa84b..44558fc7704 100644 --- a/includes/class-payment-information.php +++ b/includes/class-payment-information.php @@ -227,7 +227,6 @@ public static function from_payment_request( $order->add_meta_data( 'is_woopay', true, true ); $order->save_meta_data(); } - return new Payment_Information( $payment_method, $order, $payment_type, $token, $payment_initiated_by, $manual_capture, $cvc_confirmation ); } diff --git a/includes/class-wc-payment-gateway-wcpay.php b/includes/class-wc-payment-gateway-wcpay.php index 55c18f57c7f..709ee4ef10b 100644 --- a/includes/class-wc-payment-gateway-wcpay.php +++ b/includes/class-wc-payment-gateway-wcpay.php @@ -1276,7 +1276,6 @@ public function process_payment_for_order( $cart, $payment_information, $additio $intent = $this->payments_api_client->get_intent( $platform_checkout_intent_id ); $intent_meta_order_id_raw = $intent->get_metadata()['order_id'] ?? ''; $intent_meta_order_id = is_numeric( $intent_meta_order_id_raw ) ? intval( $intent_meta_order_id_raw ) : 0; - if ( $intent_meta_order_id !== $order_id ) { throw new Intent_Authentication_Exception( __( "We're not able to process this payment. Please try again later.", 'woocommerce-payments' ), diff --git a/includes/class-wc-payments-upe-blocks-payment-method.php b/includes/class-wc-payments-upe-blocks-payment-method.php index 0a5ebcbd4c0..f65be6b9ff1 100644 --- a/includes/class-wc-payments-upe-blocks-payment-method.php +++ b/includes/class-wc-payments-upe-blocks-payment-method.php @@ -15,30 +15,17 @@ class WC_Payments_UPE_Blocks_Payment_Method extends WC_Payments_Blocks_Payment_M * @return string[] A list of script handles. */ public function get_payment_method_script_handles() { - wp_enqueue_style( - 'wc-blocks-checkout-style', - plugins_url( 'dist/upe-blocks-checkout.css', WCPAY_PLUGIN_FILE ), - [], - '1.0' - ); - - wp_register_script( - 'stripe', - 'https://js.stripe.com/v3/', - [], - '3.0', - true - ); + $classic_blocks_scripts = parent::get_payment_method_script_handles(); wp_register_script( - 'WCPAY_BLOCKS_CHECKOUT', + 'WCPAY_BLOCKS_UPE_CHECKOUT', plugins_url( 'dist/upe-blocks-checkout.js', WCPAY_PLUGIN_FILE ), [ 'stripe' ], '1.0.1', true ); - wp_set_script_translations( 'WCPAY_BLOCKS_CHECKOUT', 'woocommerce-payments' ); + wp_set_script_translations( 'WCPAY_BLOCKS_UPE_CHECKOUT', 'woocommerce-payments' ); - return [ 'WCPAY_BLOCKS_CHECKOUT' ]; + return array_merge( $classic_blocks_scripts, [ 'WCPAY_BLOCKS_UPE_CHECKOUT' ] ); } } diff --git a/includes/payment-methods/class-bancontact-payment-method.php b/includes/payment-methods/class-bancontact-payment-method.php index 269dd3611fc..aa936112f2a 100644 --- a/includes/payment-methods/class-bancontact-payment-method.php +++ b/includes/payment-methods/class-bancontact-payment-method.php @@ -33,10 +33,10 @@ public function __construct( $token_service ) { /** * Returns testing credentials to be printed at checkout in test mode. * - * @return string|bool + * @return string */ public function get_testing_instructions() { - return false; + return ''; } } diff --git a/includes/payment-methods/class-becs-payment-method.php b/includes/payment-methods/class-becs-payment-method.php index 61eef6b91a6..305537643f1 100644 --- a/includes/payment-methods/class-becs-payment-method.php +++ b/includes/payment-methods/class-becs-payment-method.php @@ -33,7 +33,7 @@ public function __construct( $token_service ) { /** * Returns testing credentials to be printed at checkout in test mode. * - * @return string|bool + * @return string */ public function get_testing_instructions() { return __( 'Test mode: use the test account number 000123456. Other payment methods may redirect to a Stripe test page to authorize payment. More test card numbers are listed here.', 'woocommerce-payments' ); diff --git a/includes/payment-methods/class-cc-payment-method.php b/includes/payment-methods/class-cc-payment-method.php index c8ac9d682e0..8511d1453d1 100644 --- a/includes/payment-methods/class-cc-payment-method.php +++ b/includes/payment-methods/class-cc-payment-method.php @@ -63,7 +63,7 @@ public function get_title( $payment_details = false ) { /** * Returns testing credentials to be printed at checkout in test mode. * - * @return string|bool + * @return string */ public function get_testing_instructions() { return __( 'Test mode: use the test VISA card 4242424242424242 with any expiry date and CVC. Other payment methods may redirect to a Stripe test page to authorize payment. More test card numbers are listed here.', 'woocommerce-payments' ); diff --git a/includes/payment-methods/class-eps-payment-method.php b/includes/payment-methods/class-eps-payment-method.php index 64da91bfde7..f4edea97f1c 100644 --- a/includes/payment-methods/class-eps-payment-method.php +++ b/includes/payment-methods/class-eps-payment-method.php @@ -33,9 +33,9 @@ public function __construct( $token_service ) { /** * Returns testing credentials to be printed at checkout in test mode. * - * @return string|bool + * @return string */ public function get_testing_instructions() { - return false; + return ''; } } diff --git a/includes/payment-methods/class-giropay-payment-method.php b/includes/payment-methods/class-giropay-payment-method.php index 97f24399fc0..1dfce93aa4a 100644 --- a/includes/payment-methods/class-giropay-payment-method.php +++ b/includes/payment-methods/class-giropay-payment-method.php @@ -33,9 +33,9 @@ public function __construct( $token_service ) { /** * Returns testing credentials to be printed at checkout in test mode. * - * @return string|bool + * @return string */ public function get_testing_instructions() { - return false; + return ''; } } diff --git a/includes/payment-methods/class-ideal-payment-method.php b/includes/payment-methods/class-ideal-payment-method.php index b562202ea77..1a642e612aa 100644 --- a/includes/payment-methods/class-ideal-payment-method.php +++ b/includes/payment-methods/class-ideal-payment-method.php @@ -33,9 +33,9 @@ public function __construct( $token_service ) { /** * Returns testing credentials to be printed at checkout in test mode. * - * @return string|bool + * @return string */ public function get_testing_instructions() { - return false; + return ''; } } diff --git a/includes/payment-methods/class-link-payment-method.php b/includes/payment-methods/class-link-payment-method.php index 4c02af48e7e..23943f16309 100644 --- a/includes/payment-methods/class-link-payment-method.php +++ b/includes/payment-methods/class-link-payment-method.php @@ -33,9 +33,9 @@ public function __construct( $token_service ) { /** * Returns testing credentials to be printed at checkout in test mode. * - * @return string|bool + * @return string */ public function get_testing_instructions() { - return false; + return ''; } } diff --git a/includes/payment-methods/class-p24-payment-method.php b/includes/payment-methods/class-p24-payment-method.php index 8e95225307e..abb51b47e71 100644 --- a/includes/payment-methods/class-p24-payment-method.php +++ b/includes/payment-methods/class-p24-payment-method.php @@ -33,9 +33,9 @@ public function __construct( $token_service ) { /** * Returns testing credentials to be printed at checkout in test mode. * - * @return string|bool + * @return string */ public function get_testing_instructions() { - return false; + return ''; } } diff --git a/includes/payment-methods/class-sepa-payment-method.php b/includes/payment-methods/class-sepa-payment-method.php index 0b3fb6a9a25..eef834296ed 100644 --- a/includes/payment-methods/class-sepa-payment-method.php +++ b/includes/payment-methods/class-sepa-payment-method.php @@ -33,7 +33,7 @@ public function __construct( $token_service ) { /** * Returns testing credentials to be printed at checkout in test mode. * - * @return string|bool + * @return string */ public function get_testing_instructions() { return __( 'Test mode: use the test account number AT611904300234573201. Other payment methods may redirect to a Stripe test page to authorize payment. More test card numbers are listed here.', 'woocommerce-payments' ); diff --git a/includes/payment-methods/class-sofort-payment-method.php b/includes/payment-methods/class-sofort-payment-method.php index 2d9b9c2f617..a9d254d107f 100644 --- a/includes/payment-methods/class-sofort-payment-method.php +++ b/includes/payment-methods/class-sofort-payment-method.php @@ -34,9 +34,9 @@ public function __construct( $token_service ) { /** * Returns testing credentials to be printed at checkout in test mode. * - * @return string|bool + * @return string */ public function get_testing_instructions() { - return false; + return ''; } } diff --git a/includes/payment-methods/class-upe-payment-gateway.php b/includes/payment-methods/class-upe-payment-gateway.php index f611f95ad84..7fc60180be3 100644 --- a/includes/payment-methods/class-upe-payment-gateway.php +++ b/includes/payment-methods/class-upe-payment-gateway.php @@ -99,24 +99,47 @@ public function __construct( $this->icon = $payment_method->get_icon(); add_action( "wc_ajax_wcpay_create_payment_intent_$this->stripe_id", [ $this, 'create_payment_intent_ajax' ] ); - add_action( "wc_ajax_wcpay_update_payment_inten_ $this->stripe_id", [ $this, 'update_payment_intent_ajax' ] ); + add_action( "wc_ajax_wcpay_update_payment_intent_$this->stripe_id", [ $this, 'update_payment_intent_ajax' ] ); add_action( "wc_ajax_wcpay_init_setup_intent_$this->stripe_id", [ $this, 'init_setup_intent_ajax' ] ); if ( 'card' !== $this->stripe_id ) { $this->id = self::GATEWAY_ID . '_' . $this->stripe_id; $this->method_title = "WooCommerce Payments ($this->title)"; - } else { - // Only add these filters once. + } + + if ( ! has_action( 'wc_ajax_wcpay_log_payment_error', [ $this, 'log_payment_error_ajax' ] ) ) { add_action( 'wc_ajax_wcpay_log_payment_error', [ $this, 'log_payment_error_ajax' ] ); + } + + if ( ! has_action( 'wp_ajax_save_upe_appearance', [ $this, 'save_upe_appearance_ajax' ] ) ) { add_action( 'wp_ajax_save_upe_appearance', [ $this, 'save_upe_appearance_ajax' ] ); + } + + if ( ! has_action( 'wp_ajax_nopriv_save_upe_appearance', [ $this, 'save_upe_appearance_ajax' ] ) ) { add_action( 'wp_ajax_nopriv_save_upe_appearance', [ $this, 'save_upe_appearance_ajax' ] ); + } + + if ( ! has_action( 'switch_theme', [ $this, 'clear_upe_appearance_transient' ] ) ) { add_action( 'switch_theme', [ $this, 'clear_upe_appearance_transient' ] ); + } + + if ( ! has_action( 'woocommerce_woocommerce_payments_updated', [ $this, 'clear_upe_appearance_transient' ] ) ) { add_action( 'woocommerce_woocommerce_payments_updated', [ $this, 'clear_upe_appearance_transient' ] ); + } + if ( ! has_action( 'wp', [ $this, 'maybe_process_upe_redirect' ] ) ) { add_action( 'wp', [ $this, 'maybe_process_upe_redirect' ] ); + } + if ( ! has_action( 'woocommerce_order_payment_status_changed', [ __CLASS__, 'remove_upe_payment_intent_from_session' ] ) ) { add_action( 'woocommerce_order_payment_status_changed', [ __CLASS__, 'remove_upe_payment_intent_from_session' ], 10, 0 ); + } + + if ( ! has_action( 'woocommerce_after_account_payment_methods', [ $this, 'remove_upe_setup_intent_from_session' ] ) ) { add_action( 'woocommerce_after_account_payment_methods', [ $this, 'remove_upe_setup_intent_from_session' ], 10, 0 ); + } + + if ( ! has_action( 'woocommerce_subscription_payment_method_updated', [ $this, 'remove_upe_setup_intent_from_session' ] ) ) { add_action( 'woocommerce_subscription_payment_method_updated', [ $this, 'remove_upe_setup_intent_from_session' ], 10, 0 ); } } @@ -1069,12 +1092,23 @@ private function get_enabled_payment_method_config() { $enabled_payment_methods = $this->get_payment_method_ids_enabled_at_checkout(); foreach ( $enabled_payment_methods as $payment_method_id ) { + if ( 'card' === $payment_method_id ) { + continue; + } $payment_method = $this->wc_payments_get_payment_method_by_id( $payment_method_id ); $settings[ $payment_method_id ] = [ 'isReusable' => $payment_method->is_reusable(), 'title' => $payment_method->get_title(), 'upePaymentIntentData' => $this->get_payment_intent_data_from_session( $payment_method_id ), 'upeSetupIntentData' => $this->get_setup_intent_data_from_session( $payment_method_id ), + 'testingInstructions' => WC_Payments_Utils::esc_interpolated_html( + /* translators: link to Stripe testing page */ + $payment_method->get_testing_instructions(), + [ + 'strong' => '', + 'a' => '', + ] + ), ]; } diff --git a/includes/payment-methods/class-upe-payment-method.php b/includes/payment-methods/class-upe-payment-method.php index 556da212f01..583a405567a 100644 --- a/includes/payment-methods/class-upe-payment-method.php +++ b/includes/payment-methods/class-upe-payment-method.php @@ -151,7 +151,7 @@ public function get_payment_token_for_user( $user, $payment_method_id ) { /** * Returns testing credentials to be printed at checkout in test mode. * - * @return string|bool + * @return string */ abstract public function get_testing_instructions(); diff --git a/includes/wc-payment-api/class-wc-payments-api-client.php b/includes/wc-payment-api/class-wc-payments-api-client.php index 0a5a4d38fb3..7f6c2cd060c 100644 --- a/includes/wc-payment-api/class-wc-payments-api-client.php +++ b/includes/wc-payment-api/class-wc-payments-api-client.php @@ -246,7 +246,6 @@ public function create_and_confirm_intention( if ( ! empty( $cvc_confirmation ) ) { $request['cvc_confirmation'] = $cvc_confirmation; } - $response_array = $this->request_with_level3_data( $request, self::INTENTIONS_API, self::POST ); return $this->deserialize_intention_object_from_array( $response_array ); diff --git a/tests/unit/payment-methods/test-class-upe-payment-gateway.php b/tests/unit/payment-methods/test-class-upe-payment-gateway.php index 70329321087..93588150657 100644 --- a/tests/unit/payment-methods/test-class-upe-payment-gateway.php +++ b/tests/unit/payment-methods/test-class-upe-payment-gateway.php @@ -1551,17 +1551,12 @@ public function test_link_payment_method_if_card_enabled() { $this->assertSame( $mock_upe_gateway->get_payment_fields_js_config()['paymentMethodsConfig'], [ - 'card' => [ - 'isReusable' => true, - 'title' => 'Credit card / debit card', - 'upePaymentIntentData' => null, - 'upeSetupIntentData' => null, - ], 'link' => [ 'isReusable' => true, 'title' => 'Link', 'upePaymentIntentData' => null, 'upeSetupIntentData' => null, + 'testingInstructions' => '', ], ] );