diff --git a/client/classic/upe/payment-processing.js b/client/classic/upe/payment-processing.js index 389d075820..fdb5f1bda6 100644 --- a/client/classic/upe/payment-processing.js +++ b/client/classic/upe/payment-processing.js @@ -85,15 +85,6 @@ function createStripePaymentElement( api, paymentMethodType = null ) { }, } ); - // To be removed with Split PE. - if ( paymentMethodType === null ) { - paymentMethodType = 'stripe'; - gatewayUPEComponents.stripe = { - elements: null, - upeElement: null, - }; - } - gatewayUPEComponents[ paymentMethodType ].elements = elements; gatewayUPEComponents[ paymentMethodType @@ -172,8 +163,6 @@ function createStripePaymentMethod( * Mounts the existing Stripe Payment Element to the DOM element. * Creates the Stripe Payment Element instance if it doesn't exist and mounts it to the DOM element. * - * @todo Make it only Split when implemented. - * * @param {Object} api The API object. * @param {string} domElement The selector of the DOM element of particular payment method to mount the UPE element to. **/ @@ -190,31 +179,19 @@ export async function mountStripePaymentElement( api, domElement ) { const event = new Event( 'wc-credit-card-form-init' ); document.body.dispatchEvent( event ); - const paymentMethodType = domElement.dataset.paymentMethodType; - let upeElement; + let paymentMethodType = domElement.dataset.paymentMethodType; - // Non-split PE. To be removed. if ( typeof paymentMethodType === 'undefined' ) { - upeElement = await createStripePaymentElement( api ); - - upeElement.on( 'change', ( e ) => { - const selectedUPEPaymentType = e.value.type; - const isPaymentMethodReusable = - paymentMethodsConfig[ selectedUPEPaymentType ].isReusable; - showNewPaymentMethodCheckbox( isPaymentMethodReusable ); - setSelectedUPEPaymentType( selectedUPEPaymentType ); - } ); - } else { - // Split PE. - if ( ! gatewayUPEComponents[ paymentMethodType ] ) { - return; - } + paymentMethodType = 'card'; + } - upeElement = - gatewayUPEComponents[ paymentMethodType ].upeElement || - ( await createStripePaymentElement( api, paymentMethodType ) ); + if ( ! gatewayUPEComponents[ paymentMethodType ] ) { + return; } + const upeElement = + gatewayUPEComponents[ paymentMethodType ].upeElement || + ( await createStripePaymentElement( api, paymentMethodType ) ); upeElement.mount( domElement ); } @@ -225,26 +202,6 @@ function setSelectedUPEPaymentType( paymentType ) { ).value = paymentType; } -// Show or hide save payment information checkbox -function showNewPaymentMethodCheckbox( show = true ) { - const saveCardElement = document.querySelector( - '.woocommerce-SavedPaymentMethods-saveNew' - ); - - if ( saveCardElement ) { - saveCardElement.style.visibility = show ? 'visible' : 'hidden'; - } - - const stripeSaveCardCheckbox = document.querySelector( - 'input#wc-stripe-new-payment-method' - ); - - if ( ! show && stripeSaveCardCheckbox ) { - stripeSaveCardCheckbox.setAttribute( 'checked', false ); - stripeSaveCardCheckbox.dispatchEvent( new Event( 'change' ) ); - } -} - /** * Handles the checkout process for the provided jQuery form and Stripe payment method type. The function blocks the * form UI to prevent duplicate submission and validates the Stripe elements. It then creates a Stripe payment method @@ -270,11 +227,6 @@ export const processPayment = ( blockUI( jQueryForm ); - // Non split. To be removed. - if ( paymentMethodType === null ) { - paymentMethodType = 'stripe'; - } - const elements = gatewayUPEComponents[ paymentMethodType ].elements; ( async () => { @@ -286,6 +238,7 @@ export const processPayment = ( jQueryForm, paymentMethodType ); + setSelectedUPEPaymentType( paymentMethodType ); appendIsUsingDeferredIntentToForm( jQueryForm ); appendPaymentMethodIdToForm( jQueryForm, diff --git a/client/stripe-utils/constants.js b/client/stripe-utils/constants.js index 7257f91cca..390ecbb7a0 100644 --- a/client/stripe-utils/constants.js +++ b/client/stripe-utils/constants.js @@ -1,3 +1,29 @@ +export const PAYMENT_METHOD_NAME_CARD = 'stripe'; +export const PAYMENT_METHOD_NAME_GIROPAY = 'stripe_giropay'; +export const PAYMENT_METHOD_NAME_EPS = 'stripe_eps'; +export const PAYMENT_METHOD_NAME_IDEAL = 'stripe_ideal'; +export const PAYMENT_METHOD_NAME_P24 = 'stripe_p24'; +export const PAYMENT_METHOD_NAME_SEPA = 'stripe_sepa_debit'; +export const PAYMENT_METHOD_NAME_SOFORT = 'stripe_sofort'; +export const PAYMENT_METHOD_NAME_BOLETO = 'stripe_boleto'; +export const PAYMENT_METHOD_NAME_OXXO = 'stripe_oxxo'; +export const PAYMENT_METHOD_NAME_BANCONTACT = 'stripe_bancontact'; + +export function getPaymentMethodsConstants() { + return { + card: PAYMENT_METHOD_NAME_CARD, + giropay: PAYMENT_METHOD_NAME_GIROPAY, + eps: PAYMENT_METHOD_NAME_EPS, + ideal: PAYMENT_METHOD_NAME_IDEAL, + p24: PAYMENT_METHOD_NAME_P24, + sepa: PAYMENT_METHOD_NAME_SEPA, + sofort: PAYMENT_METHOD_NAME_SOFORT, + boleto: PAYMENT_METHOD_NAME_BOLETO, + oxxo: PAYMENT_METHOD_NAME_OXXO, + bancontact: PAYMENT_METHOD_NAME_BANCONTACT, + }; +} + export const errorTypes = { INVALID_EMAIL: 'email_invalid', INVALID_REQUEST: 'invalid_request_error', diff --git a/client/stripe-utils/utils.js b/client/stripe-utils/utils.js index b7fc4f09a2..e7d3ffaf7d 100644 --- a/client/stripe-utils/utils.js +++ b/client/stripe-utils/utils.js @@ -2,7 +2,11 @@ import { __ } from '@wordpress/i18n'; import { getAppearance } from '../styles/upe'; -import { errorTypes, errorCodes } from './constants'; +import { + errorTypes, + errorCodes, + getPaymentMethodsConstants, +} from './constants'; /** * @typedef {import('./type-defs').StripeServerData} StripeServerData @@ -262,10 +266,14 @@ function shouldIncludeTerms() { return false; } +/** + * Returns a string of event names to be used for registering checkout submission handlers. + * For example: "checkout_place_order_stripe checkout_place_order_stripe_ideal ...checkout_place_order_{paymentMethod}" + * + * @return {string} String of event names. + */ export const generateCheckoutEventNames = () => { - const paymentMethods = [ 'stripe' ]; - - return paymentMethods + return Object.values( getPaymentMethodsConstants() ) .map( ( method ) => `checkout_place_order_${ method }` ) .join( ' ' ); }; @@ -292,13 +300,17 @@ export const appendSetupIntentToForm = ( form, setupIntent ) => { /** * Checks if the customer is using a saved payment method. * + * @param {string} paymentMethodType The payment method type ('card', 'ideal', etc.). + * * @return {boolean} Boolean indicating whether or not a saved payment method is being used. */ -export const isUsingSavedPaymentMethod = () => { +export const isUsingSavedPaymentMethod = ( paymentMethodType ) => { + const paymentMethod = getPaymentMethodName( paymentMethodType ); return ( - document.querySelector( '#wc-stripe-new-payment-method' )?.length && + document.querySelector( `#wc-${ paymentMethod }-new-payment-method` ) + ?.length && ! document - .querySelector( '#wc-stripe-new-payment-method' ) + .querySelector( `#wc-${ paymentMethod }-new-payment-method` ) .is( ':checked' ) ); }; @@ -466,3 +478,17 @@ export const initializeUPEAppearance = () => { return appearance; }; + +/** + * Gets the payment method name from the given payment method type. + * For example, when passed 'card' returns 'stripe' and for 'ideal' returns 'stripe_ideal'. + * + * Defaults to 'stripe' if the given payment method type is not found in the list of payment methods constants. + * + * @param {string} paymentMethodType The payment method type ('card', 'ideal', etc.). + * + * @return {string} The payment method name. + */ +export const getPaymentMethodName = ( paymentMethodType ) => { + return getPaymentMethodsConstants()[ paymentMethodType ] || 'stripe'; +}; diff --git a/includes/payment-methods/class-wc-stripe-upe-payment-gateway.php b/includes/payment-methods/class-wc-stripe-upe-payment-gateway.php index c93c16f2ad..1b4c99d7d6 100644 --- a/includes/payment-methods/class-wc-stripe-upe-payment-gateway.php +++ b/includes/payment-methods/class-wc-stripe-upe-payment-gateway.php @@ -299,6 +299,7 @@ public function javascript_params() { $is_change_payment_method = $this->is_changing_payment_method_for_subscription(); $stripe_params = [ + 'gatewayId' => self::ID, 'title' => $this->title, 'isUPEEnabled' => true, 'key' => $this->publishable_key, diff --git a/includes/payment-methods/class-wc-stripe-upe-payment-method.php b/includes/payment-methods/class-wc-stripe-upe-payment-method.php index d99e6be0d8..97adb3775a 100644 --- a/includes/payment-methods/class-wc-stripe-upe-payment-method.php +++ b/includes/payment-methods/class-wc-stripe-upe-payment-method.php @@ -87,14 +87,9 @@ abstract class WC_Stripe_UPE_Payment_Method extends WC_Payment_Gateway { public function __construct() { $main_settings = get_option( 'woocommerce_stripe_settings' ); - if ( isset( $main_settings['upe_checkout_experience_accepted_payments'] ) ) { - $enabled_upe_methods = $main_settings['upe_checkout_experience_accepted_payments']; - } else { - $enabled_upe_methods = [ WC_Stripe_UPE_Payment_Method_CC::STRIPE_ID ]; - } - - $this->enabled = in_array( static::STRIPE_ID, $enabled_upe_methods, true ); - $this->id = WC_Gateway_Stripe::ID . '_' . static::STRIPE_ID; + $this->enabled = in_array( static::STRIPE_ID, $this->get_option( 'upe_checkout_experience_accepted_payments', [ 'card' ] ), true ) ? 'yes' : 'no'; + $this->id = WC_Gateway_Stripe::ID . '_' . static::STRIPE_ID; + $this->testmode = ! empty( $main_settings['testmode'] ) && 'yes' === $main_settings['testmode']; } /** @@ -112,7 +107,7 @@ public function get_id() { * @return bool */ public function is_enabled() { - return $this->enabled; + return 'yes' === $this->enabled; } /** @@ -121,7 +116,11 @@ public function is_enabled() { * @return bool */ public function is_available() { - return $this->is_enabled_at_checkout(); + if ( is_add_payment_method_page() && ! $this->is_reusable() ) { + return false; + } + + return $this->is_enabled_at_checkout() && parent::is_available(); } /** @@ -374,4 +373,75 @@ public function process_payment( $order_id ) { public function is_available_for_account_country() { return true; } + + /** + * Returns the UPE Payment Method settings option. + * + * Overrides @see WC:Settings_API::get_option_key() to use the same option key as the main Stripe gateway. + * + * @return string + */ + public function get_option_key() { + return 'woocommerce_stripe_settings'; + } + + /** + * Renders the UPE payment fields. + */ + public function payment_fields() { + try { + $display_tokenization = $this->is_reusable() && is_checkout(); + + if ( $this->testmode && ! empty( $this->get_testing_instructions() ) ) : ?> +
get_testing_instructions() ); ?>
+ + + is_saved_cards_enabled() && $this->is_reusable() ) { + $force_save_payment = ( $display_tokenization && ! apply_filters( 'wc_stripe_display_save_payment_method_checkbox', $display_tokenization ) ) || is_add_payment_method_page(); + if ( is_user_logged_in() ) { + $this->save_payment_method_checkbox( $force_save_payment ); + } + } + } catch ( Exception $e ) { + // Output the error message. + WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() ); + ?> +