diff --git a/.eslintignore b/.eslintignore
index 590187b9d5e..e558812a35a 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -10,3 +10,7 @@ vendor/*
release/*
tests/e2e/docker*
tests/e2e/deps*
+
+# We'll delete the directory and its contents as part of https://github.com/Automattic/woocommerce-payments/issues/9722 .
+# ignoring it because we're temporariily cleaning it up.
+client/tokenized-payment-request
diff --git a/.github/workflows/e2e-pull-request.yml b/.github/workflows/e2e-pull-request.yml
index aa4748b37d0..4ed61a3882b 100644
--- a/.github/workflows/e2e-pull-request.yml
+++ b/.github/workflows/e2e-pull-request.yml
@@ -18,23 +18,23 @@ on:
description: "Branch to be used for running tests"
env:
- E2E_GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
- WCP_DEV_TOOLS_REPO: ${{ secrets.WCP_DEV_TOOLS_REPO }}
- WCP_DEV_TOOLS_BRANCH: 'trunk'
- WCP_SERVER_REPO: ${{ secrets.WCP_SERVER_REPO }}
- WC_SUBSCRIPTIONS_REPO: ${{ secrets.WC_SUBSCRIPTIONS_REPO }}
- E2E_BLOG_ID: ${{ secrets.E2E_BLOG_ID }}
- E2E_BLOG_TOKEN: ${{ secrets.E2E_BLOG_TOKEN }}
- E2E_USER_TOKEN: ${{ secrets.E2E_USER_TOKEN }}
- WC_E2E_SCREENSHOTS: 1
- E2E_SLACK_CHANNEL: ${{ secrets.E2E_SLACK_CHANNEL }}
- E2E_SLACK_TOKEN: ${{ secrets.E2E_SLACK_TOKEN }}
- E2E_USE_LOCAL_SERVER: false
- E2E_RESULT_FILEPATH: 'tests/e2e/results.json'
- WCPAY_USE_BUILD_ARTIFACT: ${{ inputs.wcpay-use-build-artifact }}
- WCPAY_ARTIFACT_DIRECTORY: 'zipfile'
- NODE_ENV: 'test'
- FORCE_E2E_DEPS_SETUP: true
+ E2E_GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
+ WCP_DEV_TOOLS_REPO: ${{ secrets.WCP_DEV_TOOLS_REPO }}
+ WCP_DEV_TOOLS_BRANCH: 'trunk'
+ TRANSACT_PLATFORM_SERVER_REPO: ${{ secrets.TRANSACT_PLATFORM_SERVER_REPO }}
+ WC_SUBSCRIPTIONS_REPO: ${{ secrets.WC_SUBSCRIPTIONS_REPO }}
+ E2E_BLOG_ID: ${{ secrets.E2E_BLOG_ID }}
+ E2E_BLOG_TOKEN: ${{ secrets.E2E_BLOG_TOKEN }}
+ E2E_USER_TOKEN: ${{ secrets.E2E_USER_TOKEN }}
+ WC_E2E_SCREENSHOTS: 1
+ E2E_SLACK_CHANNEL: ${{ secrets.E2E_SLACK_CHANNEL }}
+ E2E_SLACK_TOKEN: ${{ secrets.E2E_SLACK_TOKEN }}
+ E2E_USE_LOCAL_SERVER: false
+ E2E_RESULT_FILEPATH: 'tests/e2e/results.json'
+ WCPAY_USE_BUILD_ARTIFACT: ${{ inputs.wcpay-use-build-artifact }}
+ WCPAY_ARTIFACT_DIRECTORY: 'zipfile'
+ NODE_ENV: 'test'
+ FORCE_E2E_DEPS_SETUP: true
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
diff --git a/.github/workflows/e2e-pw-pull-request.yml b/.github/workflows/e2e-pw-pull-request.yml
index 0cc22f767c2..da6765fb51b 100644
--- a/.github/workflows/e2e-pw-pull-request.yml
+++ b/.github/workflows/e2e-pw-pull-request.yml
@@ -21,7 +21,7 @@ env:
E2E_GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
WCP_DEV_TOOLS_REPO: ${{ secrets.WCP_DEV_TOOLS_REPO }}
WCP_DEV_TOOLS_BRANCH: 'trunk'
- WCP_SERVER_REPO: ${{ secrets.WCP_SERVER_REPO }}
+ TRANSACT_PLATFORM_SERVER_REPO: ${{ secrets.TRANSACT_PLATFORM_SERVER_REPO }}
WC_SUBSCRIPTIONS_REPO: ${{ secrets.WC_SUBSCRIPTIONS_REPO }}
E2E_BLOG_ID: ${{ secrets.E2E_BLOG_ID }}
E2E_BLOG_TOKEN: ${{ secrets.E2E_BLOG_TOKEN }}
diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml
index 04e85183f3e..1d1f0b1bd71 100644
--- a/.github/workflows/e2e-test.yml
+++ b/.github/workflows/e2e-test.yml
@@ -10,22 +10,22 @@ on:
workflow_dispatch:
env:
- E2E_GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
- WCP_DEV_TOOLS_REPO: ${{ secrets.WCP_DEV_TOOLS_REPO }}
- WCP_DEV_TOOLS_BRANCH: 'trunk'
- WCP_SERVER_REPO: ${{ secrets.WCP_SERVER_REPO }}
- WC_SUBSCRIPTIONS_REPO: ${{ secrets.WC_SUBSCRIPTIONS_REPO }}
- E2E_BLOG_ID: ${{ secrets.E2E_BLOG_ID }}
- E2E_BLOG_TOKEN: ${{ secrets.E2E_BLOG_TOKEN }}
- E2E_USER_TOKEN: ${{ secrets.E2E_USER_TOKEN }}
- WC_E2E_SCREENSHOTS: 1
- E2E_SLACK_CHANNEL: ${{ secrets.E2E_SLACK_CHANNEL }}
- E2E_SLACK_TOKEN: ${{ secrets.E2E_SLACK_TOKEN }}
- E2E_USE_LOCAL_SERVER: false
- E2E_RESULT_FILEPATH: 'tests/e2e/results.json'
- WC_MIN_SUPPORTED_VERSION: '7.6.0'
- NODE_ENV: 'test'
- FORCE_E2E_DEPS_SETUP: true
+ E2E_GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
+ WCP_DEV_TOOLS_REPO: ${{ secrets.WCP_DEV_TOOLS_REPO }}
+ WCP_DEV_TOOLS_BRANCH: 'trunk'
+ TRANSACT_PLATFORM_SERVER_REPO: ${{ secrets.TRANSACT_PLATFORM_SERVER_REPO }}
+ WC_SUBSCRIPTIONS_REPO: ${{ secrets.WC_SUBSCRIPTIONS_REPO }}
+ E2E_BLOG_ID: ${{ secrets.E2E_BLOG_ID }}
+ E2E_BLOG_TOKEN: ${{ secrets.E2E_BLOG_TOKEN }}
+ E2E_USER_TOKEN: ${{ secrets.E2E_USER_TOKEN }}
+ WC_E2E_SCREENSHOTS: 1
+ E2E_SLACK_CHANNEL: ${{ secrets.E2E_SLACK_CHANNEL }}
+ E2E_SLACK_TOKEN: ${{ secrets.E2E_SLACK_TOKEN }}
+ E2E_USE_LOCAL_SERVER: false
+ E2E_RESULT_FILEPATH: 'tests/e2e/results.json'
+ WC_MIN_SUPPORTED_VERSION: '7.6.0'
+ NODE_ENV: 'test'
+ FORCE_E2E_DEPS_SETUP: true
jobs:
generate-matrix:
diff --git a/.github/workflows/php-compatibility.yml b/.github/workflows/php-compatibility.yml
index 5d018dabc37..41d87e5b1db 100644
--- a/.github/workflows/php-compatibility.yml
+++ b/.github/workflows/php-compatibility.yml
@@ -1,7 +1,8 @@
name: PHP Compatibility
on:
- pull_request
+ #pull_request # Workflow disabled temporarily until PHP Compatibility fixes are in place
+ workflow_dispatch
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
diff --git a/assets/images/illustrations/setup.svg b/assets/images/illustrations/setup.svg
new file mode 100644
index 00000000000..b5c8abde96d
--- /dev/null
+++ b/assets/images/illustrations/setup.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/changelog.txt b/changelog.txt
index 745c2fe24be..d97e8e7ba85 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,5 +1,8 @@
*** WooPayments Changelog ***
+= 8.5.1 - 2024-11-25 =
+* Fix - fix: remove "test mode" badge from shortcode checkout.
+
= 8.5.0 - 2024-11-13 =
* Add - Add country-specific test card numbers for credit card testing
* Add - Add risk level information to the fraud and risk box on the order details page.
diff --git a/changelog/add-5316-payout-trace-id b/changelog/add-5316-payout-trace-id
new file mode 100644
index 00000000000..a5e90413a86
--- /dev/null
+++ b/changelog/add-5316-payout-trace-id
@@ -0,0 +1,4 @@
+Significance: minor
+Type: add
+
+Add Bank reference key column in Payout reports. This will help reconcile WooPayments Payouts with bank statements.
diff --git a/changelog/add-9556-set-support-phone-mandatory b/changelog/add-9556-set-support-phone-mandatory
new file mode 100644
index 00000000000..e777eaae4a6
--- /dev/null
+++ b/changelog/add-9556-set-support-phone-mandatory
@@ -0,0 +1,4 @@
+Significance: minor
+Type: fix
+
+Set the support phone field as mandatory in the settings page.
diff --git a/changelog/as-fix-ece-tax-based-billing-address b/changelog/as-fix-ece-tax-based-billing-address
new file mode 100644
index 00000000000..ab6fc7be8fd
--- /dev/null
+++ b/changelog/as-fix-ece-tax-based-billing-address
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Ensure ECE is displayed correctly taking into account the tax settings.
\ No newline at end of file
diff --git a/changelog/chore-ece-states-class-constants b/changelog/chore-ece-states-class-constants
new file mode 100644
index 00000000000..5ff6dfd3ab8
--- /dev/null
+++ b/changelog/chore-ece-states-class-constants
@@ -0,0 +1,5 @@
+Significance: patch
+Type: dev
+Comment: chore: rename Payment_Request_Button_States to Express_Checkout_Element_States to reflect its usage
+
+
diff --git a/changelog/chore-remove-redundant-init-for-payfororder b/changelog/chore-remove-redundant-init-for-payfororder
new file mode 100644
index 00000000000..3ca1a909911
--- /dev/null
+++ b/changelog/chore-remove-redundant-init-for-payfororder
@@ -0,0 +1,4 @@
+Significance: minor
+Type: update
+
+Avoid getting the appearance for pay for order page with the wrong appearance key.
diff --git a/changelog/dev-4293-address-additional-union-types b/changelog/dev-4293-address-additional-union-types
new file mode 100644
index 00000000000..361b062f85f
--- /dev/null
+++ b/changelog/dev-4293-address-additional-union-types
@@ -0,0 +1,4 @@
+Significance: patch
+Type: dev
+
+Fix return types
diff --git a/changelog/dev-4293-enforce-proper-return-types-for-methodsfunctions-get_order_from_event_body_intent_id b/changelog/dev-4293-enforce-proper-return-types-for-methodsfunctions-get_order_from_event_body_intent_id
new file mode 100644
index 00000000000..c31e1d66df8
--- /dev/null
+++ b/changelog/dev-4293-enforce-proper-return-types-for-methodsfunctions-get_order_from_event_body_intent_id
@@ -0,0 +1,4 @@
+Significance: patch
+Type: dev
+
+Ensure proper return types in the webhook processing service.
diff --git a/changelog/dev-allow-redirect-to-settings-page-from-wcpay-connect b/changelog/dev-allow-redirect-to-settings-page-from-wcpay-connect
new file mode 100644
index 00000000000..3fca0c1ff3e
--- /dev/null
+++ b/changelog/dev-allow-redirect-to-settings-page-from-wcpay-connect
@@ -0,0 +1,4 @@
+Significance: patch
+Type: dev
+
+Allow redirect to the settings page from WCPay connect
diff --git a/changelog/fix-7399 b/changelog/fix-7399
new file mode 100644
index 00000000000..91b8aed706d
--- /dev/null
+++ b/changelog/fix-7399
@@ -0,0 +1,5 @@
+Significance: patch
+Type: dev
+Comment: Ensure dispute urls in order notes are urlencoded
+
+
diff --git a/changelog/fix-9709-load-stripe-asynchronously b/changelog/fix-9709-load-stripe-asynchronously
new file mode 100644
index 00000000000..0e95dac6d8d
--- /dev/null
+++ b/changelog/fix-9709-load-stripe-asynchronously
@@ -0,0 +1,4 @@
+Significance: minor
+Type: fix
+
+Add support to load stripe js asynchronously when it is not immediately available in the global scope.
diff --git a/changelog/fix-9784-ece-tracks-events b/changelog/fix-9784-ece-tracks-events
new file mode 100644
index 00000000000..4c9ab158fa3
--- /dev/null
+++ b/changelog/fix-9784-ece-tracks-events
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Fix ECE Tracks events not triggering when WooPay is disabled.
diff --git a/changelog/fix-no-bnpl-subscriptions b/changelog/fix-no-bnpl-subscriptions
new file mode 100644
index 00000000000..7c9035f8736
--- /dev/null
+++ b/changelog/fix-no-bnpl-subscriptions
@@ -0,0 +1,5 @@
+Significance: patch
+Type: fix
+Comment: Small fix for BNPL messaging element.
+
+
diff --git a/changelog/fix-pmme-appearance-blocks b/changelog/fix-pmme-appearance-blocks
new file mode 100644
index 00000000000..bfde3b89bdd
--- /dev/null
+++ b/changelog/fix-pmme-appearance-blocks
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Use paragraph selector instead of label for pmme appearance
diff --git a/changelog/fix-remove-shortcode-test-mode-badge-from-label b/changelog/fix-remove-shortcode-test-mode-badge-from-label
new file mode 100644
index 00000000000..80d0813d077
--- /dev/null
+++ b/changelog/fix-remove-shortcode-test-mode-badge-from-label
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+fix: remove "test mode" badge from shortcode checkout.
diff --git a/changelog/fix-woopay-component-spacing b/changelog/fix-woopay-component-spacing
new file mode 100644
index 00000000000..0939c834ad9
--- /dev/null
+++ b/changelog/fix-woopay-component-spacing
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Fix WooPay component spacing.
diff --git a/changelog/fix-woopay-trial-subscriptions b/changelog/fix-woopay-trial-subscriptions
new file mode 100644
index 00000000000..58c43b05c16
--- /dev/null
+++ b/changelog/fix-woopay-trial-subscriptions
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Fix WooPay trial subscriptions purchases.
diff --git a/changelog/refactor-tokenized-ece-base-implementation b/changelog/refactor-tokenized-ece-base-implementation
new file mode 100644
index 00000000000..8402a60a94f
--- /dev/null
+++ b/changelog/refactor-tokenized-ece-base-implementation
@@ -0,0 +1,5 @@
+Significance: patch
+Type: update
+Comment: feat: tokenized cart ECE shortcode base implementation.
+
+
diff --git a/changelog/update-phpcompatibility-latest b/changelog/update-phpcompatibility-latest
new file mode 100644
index 00000000000..5765c8249d8
--- /dev/null
+++ b/changelog/update-phpcompatibility-latest
@@ -0,0 +1,5 @@
+Significance: patch
+Type: dev
+Comment: Update phpcompatibility to develop version to get sniffs for PHP 8. No need to include it in the changelog since it is a dev task that doesn't impact WooPayments.
+
+
diff --git a/changelog/update-server-container-name b/changelog/update-server-container-name
new file mode 100644
index 00000000000..cb9580f8a22
--- /dev/null
+++ b/changelog/update-server-container-name
@@ -0,0 +1,5 @@
+Significance: patch
+Type: dev
+Comment: Updates server container name used by E2E tests
+
+
diff --git a/client/cart/blocks/product-details.js b/client/cart/blocks/product-details.js
index 87e807d354e..f52d4270aa6 100644
--- a/client/cart/blocks/product-details.js
+++ b/client/cart/blocks/product-details.js
@@ -11,6 +11,7 @@ import { select } from '@wordpress/data';
* Internal dependencies
*/
import { getAppearance, getFontRulesFromPage } from 'wcpay/checkout/upe-styles';
+import { useStripeAsync } from 'wcpay/hooks/use-stripe-async';
import { getUPEConfig } from 'utils/checkout';
import WCPayAPI from '../../checkout/api';
import request from '../../checkout/utils/request';
@@ -47,6 +48,8 @@ const ProductDetail = ( { cart, context } ) => {
const [ fontRules ] = useState( getFontRulesFromPage() );
+ const stripe = useStripeAsync( api );
+
useEffect( () => {
async function generateUPEAppearance() {
// Generate UPE input styles.
@@ -63,6 +66,10 @@ const ProductDetail = ( { cart, context } ) => {
}
}, [ appearance ] );
+ if ( ! stripe ) {
+ return null;
+ }
+
if ( Object.keys( appearance ).length === 0 ) {
return null;
}
@@ -91,8 +98,6 @@ const ProductDetail = ( { cart, context } ) => {
countryCode: country, // Customer's country or base country of the store.
};
- const stripe = api.getStripe();
-
return (
+ setTimeout( resolve, waitInterval )
+ );
+ currentWaitTime += waitInterval;
+ if ( currentWaitTime > maxWaitTime ) {
+ throw new Error( 'Stripe object not found' );
+ }
+ }
+ return this.__getStripe( forceAccountRequest );
+ }
+
/**
* Generates a new instance of Stripe.
*
* @param {boolean} forceAccountRequest True to instantiate the Stripe object with the merchant's account key.
* @return {Object} The Stripe Object.
*/
- getStripe( forceAccountRequest = false ) {
+ __getStripe( forceAccountRequest = false ) {
const {
publishableKey,
accountId,
@@ -105,17 +121,15 @@ export default class WCPayAPI {
*
* @return {Promise} Promise with the Stripe object or an error.
*/
- loadStripeForExpressCheckout() {
- return new Promise( ( resolve ) => {
- try {
- // Force Stripe to be loadded with the connected account.
- resolve( this.getStripe( true ) );
- } catch ( error ) {
- // In order to avoid showing console error publicly to users,
- // we resolve instead of rejecting when there is an error.
- resolve( { error } );
- }
- } );
+ async loadStripeForExpressCheckout() {
+ // Force Stripe to be loadded with the connected account.
+ try {
+ return this.getStripe( true );
+ } catch ( error ) {
+ // In order to avoid showing console error publicly to users,
+ // we resolve instead of rejecting when there is an error.
+ return { error };
+ }
}
/**
@@ -160,7 +174,7 @@ export default class WCPayAPI {
orderId = orderIdPartials[ 0 ];
}
- const confirmPaymentOrSetup = () => {
+ const confirmPaymentOrSetup = async () => {
const { locale, publishableKey } = this.options;
const accountIdForIntentConfirmation = getConfig(
'accountIdForIntentConfirmation'
@@ -168,8 +182,9 @@ export default class WCPayAPI {
// If this is a setup intent we're not processing a woopay payment so we can
// use the regular getStripe function.
+ const stripe = await this.getStripe();
if ( isSetupIntent ) {
- return this.getStripe().handleNextAction( {
+ return stripe.handleNextAction( {
clientSecret: clientSecret,
} );
}
@@ -186,7 +201,8 @@ export default class WCPayAPI {
// When not dealing with a setup intent or woopay we need to force an account
// specific request in Stripe.
- return this.getStripe( true ).handleNextAction( {
+ const stripeWithForcedAccountRequest = await this.getStripe( true );
+ return stripeWithForcedAccountRequest.handleNextAction( {
clientSecret: clientSecret,
} );
};
@@ -251,32 +267,34 @@ export default class WCPayAPI {
* @param {string} paymentMethodId The ID of the payment method.
* @return {Promise} The final promise for the request to the server.
*/
- setupIntent( paymentMethodId ) {
- return this.request( getConfig( 'ajaxUrl' ), {
+ async setupIntent( paymentMethodId ) {
+ const response = await this.request( getConfig( 'ajaxUrl' ), {
action: 'create_setup_intent',
'wcpay-payment-method': paymentMethodId,
_ajax_nonce: getConfig( 'createSetupIntentNonce' ),
- } ).then( ( response ) => {
- if ( ! response.success ) {
- throw response.data.error;
- }
+ } );
- if ( response.data.status === 'succeeded' ) {
- // No need for further authentication.
- return response.data;
- }
+ if ( ! response.success ) {
+ throw response.data.error;
+ }
- return this.getStripe()
- .confirmCardSetup( response.data.client_secret )
- .then( ( confirmedSetupIntent ) => {
- const { setupIntent, error } = confirmedSetupIntent;
- if ( error ) {
- throw error;
- }
+ if ( response.data.status === 'succeeded' ) {
+ // No need for further authentication.
+ return response.data;
+ }
- return setupIntent;
- } );
- } );
+ const stripe = await this.getStripe();
+
+ const confirmedSetupIntent = await stripe.confirmCardSetup(
+ response.data.client_secret
+ );
+
+ const { setupIntent, error } = confirmedSetupIntent;
+ if ( error ) {
+ throw error;
+ }
+
+ return setupIntent;
}
/**
diff --git a/client/checkout/api/test/index.test.js b/client/checkout/api/test/index.test.js
index 06fbf00765b..8ec819ea4c0 100644
--- a/client/checkout/api/test/index.test.js
+++ b/client/checkout/api/test/index.test.js
@@ -55,6 +55,45 @@ const mockAppearance = {
};
describe( 'WCPayAPI', () => {
+ describe( 'getStripe', () => {
+ afterEach( () => {
+ jest.useRealTimers();
+ window.Stripe = undefined;
+ } );
+
+ test( 'waits for Stripe to be available in the global scope', async () => {
+ jest.useFakeTimers();
+ const api = new WCPayAPI( {}, request );
+ let stripeInstance = null;
+
+ api.getStripe().then( ( result ) => {
+ stripeInstance = result;
+ } );
+
+ jest.runOnlyPendingTimers();
+ await Promise.resolve();
+
+ expect( stripeInstance ).toBeNull();
+
+ window.Stripe = function Stripe() {};
+
+ jest.runOnlyPendingTimers();
+ await Promise.resolve();
+
+ jest.runOnlyPendingTimers();
+ await Promise.resolve();
+
+ expect( stripeInstance ).toBeInstanceOf( window.Stripe );
+ } );
+
+ test( 'resolves immediately if Stripe is already available', async () => {
+ const api = new WCPayAPI( {}, request );
+ window.Stripe = function Stripe() {};
+ const stripeInstance = await api.getStripe();
+ expect( stripeInstance ).toBeInstanceOf( window.Stripe );
+ } );
+ } );
+
test( 'does not initialize woopay if already requesting', async () => {
buildAjaxURL.mockReturnValue( 'https://example.org/' );
getConfig.mockImplementation( ( key ) => {
diff --git a/client/checkout/blocks/index.js b/client/checkout/blocks/index.js
index 8376d0b3e8a..cdb3d105861 100644
--- a/client/checkout/blocks/index.js
+++ b/client/checkout/blocks/index.js
@@ -103,9 +103,8 @@ Object.entries( enabledPaymentMethodsConfig )
const isAvailableInTheCountry =
! isRestrictedInAnyCountry ||
upeConfig.countries.includes( billingCountry );
- return (
- isAvailableInTheCountry && !! api.getStripeForUPE( upeName )
- );
+ // We used to check if stripe was loaded with `getStripeForUPE`, but we can't guarantee it will be loaded synchronously.
+ return isAvailableInTheCountry;
},
paymentMethodId: upeMethods[ upeName ],
// see .wc-block-checkout__payment-method styles in blocks/style.scss
diff --git a/client/checkout/blocks/payment-elements.js b/client/checkout/blocks/payment-elements.js
index bedbf4777cc..f782ba13545 100644
--- a/client/checkout/blocks/payment-elements.js
+++ b/client/checkout/blocks/payment-elements.js
@@ -11,6 +11,7 @@ import { StoreNotice } from '@woocommerce/blocks-checkout';
*/
import './style.scss';
import { getAppearance, getFontRulesFromPage } from 'wcpay/checkout/upe-styles';
+import { useStripeForUPE } from 'wcpay/hooks/use-stripe-async';
import { getUPEConfig } from 'wcpay/utils/checkout';
import { useFingerprint } from './hooks';
import { LoadableBlock } from 'wcpay/components/loadable';
@@ -18,7 +19,8 @@ import PaymentProcessor from './payment-processor';
import { getPaymentMethodTypes } from 'wcpay/checkout/utils/upe';
const PaymentElements = ( { api, ...props } ) => {
- const stripe = api.getStripeForUPE( props.paymentMethodId );
+ const stripeForUPE = useStripeForUPE( api, props.paymentMethodId );
+
const [ errorMessage, setErrorMessage ] = useState( null );
const [
paymentProcessorLoadErrorMessage,
@@ -59,10 +61,14 @@ const PaymentElements = ( { api, ...props } ) => {
props.paymentMethodId,
] );
+ if ( ! stripeForUPE ) {
+ return ;
+ }
+
return (
@@ -117,7 +124,7 @@ export default ( {
appearance={ appearance }
>
{
.fn()
.mockResolvedValue( { paymentMethod: {} } );
mockApi = {
- getStripeForUPE: () => ( {
- createPaymentMethod: mockCreatePaymentMethod,
- } ),
+ getStripeForUPE: () =>
+ Promise.resolve( {
+ createPaymentMethod: mockCreatePaymentMethod,
+ } ),
};
} );
diff --git a/client/checkout/classic/event-handlers.js b/client/checkout/classic/event-handlers.js
index 0bcfc06f8d1..fe53b9b2a88 100644
--- a/client/checkout/classic/event-handlers.js
+++ b/client/checkout/classic/event-handlers.js
@@ -122,7 +122,7 @@ jQuery( function ( $ ) {
}
} );
- if ( $addPaymentMethodForm.length || $payForOrderForm.length ) {
+ if ( $addPaymentMethodForm.length ) {
maybeMountStripePaymentElement( 'add_payment_method' );
}
@@ -169,43 +169,55 @@ jQuery( function ( $ ) {
async function injectStripePMMEContainers() {
const bnplMethods = [ 'affirm', 'afterpay_clearpay', 'klarna' ];
+ const labelBase = 'payment_method_woocommerce_payments_';
const paymentMethods = getUPEConfig( 'paymentMethodsConfig' );
const paymentMethodsKeys = Object.keys( paymentMethods );
const cartData = await api.pmmeGetCartData();
for ( const method of paymentMethodsKeys ) {
if ( bnplMethods.includes( method ) ) {
+ const targetLabel = document.querySelector(
+ `label[for="${ labelBase }${ method }"]`
+ );
const containerID = `stripe-pmme-container-${ method }`;
- const container = document.getElementById( containerID );
- if ( ! container ) {
- continue;
+ if ( document.getElementById( containerID ) ) {
+ document.getElementById( containerID ).innerHTML = '';
}
- container.innerHTML = '';
- container.dataset.paymentMethodType = method;
-
- const currentCountry =
- cartData?.billing_address?.country ||
- getUPEConfig( 'storeCountry' );
- if (
- paymentMethods[ method ]?.countries.length === 0 ||
- paymentMethods[ method ]?.countries?.includes(
- currentCountry
- )
- ) {
- await mountStripePaymentMethodMessagingElement(
- api,
- container,
- {
- amount: cartData?.totals?.total_price,
- currency: cartData?.totals?.currency_code,
- decimalPlaces:
- cartData?.totals?.currency_minor_unit,
- country: currentCountry,
- },
- 'shortcode_checkout'
- );
+ if ( targetLabel ) {
+ let container = document.getElementById( containerID );
+ if ( ! container ) {
+ container = document.createElement( 'span' );
+ container.id = containerID;
+ container.dataset.paymentMethodType = method;
+ container.classList.add( 'stripe-pmme-container' );
+ targetLabel.appendChild( container );
+ }
+
+ const currentCountry =
+ cartData?.billing_address?.country ||
+ getUPEConfig( 'storeCountry' );
+
+ if (
+ paymentMethods[ method ]?.countries.length === 0 ||
+ paymentMethods[ method ]?.countries?.includes(
+ currentCountry
+ )
+ ) {
+ await mountStripePaymentMethodMessagingElement(
+ api,
+ container,
+ {
+ amount: cartData?.totals?.total_price,
+ currency: cartData?.totals?.currency_code,
+ decimalPlaces:
+ cartData?.totals?.currency_minor_unit,
+ country: currentCountry,
+ },
+ 'shortcode_checkout'
+ );
+ }
}
}
}
diff --git a/client/checkout/classic/payment-processing.js b/client/checkout/classic/payment-processing.js
index 839e53a2ca7..56595bebf93 100644
--- a/client/checkout/classic/payment-processing.js
+++ b/client/checkout/classic/payment-processing.js
@@ -166,7 +166,7 @@ function isMissingRequiredAddressFieldsForBNPL( params, paymentMethodType ) {
* @param {string} paymentMethodType The type of Stripe payment method to create.
* @return {Promise