diff --git a/changelog/fix-tokenized-ece-applepay-delay b/changelog/fix-tokenized-ece-applepay-delay new file mode 100644 index 00000000000..30409da99e8 --- /dev/null +++ b/changelog/fix-tokenized-ece-applepay-delay @@ -0,0 +1,5 @@ +Significance: patch +Type: fix +Comment: fix: ensure the "add to cart" ECE call is completed before other calls are made. + + diff --git a/client/express-checkout/index.js b/client/express-checkout/index.js index 4cbb279b1c7..f1cbdc5ebb0 100644 --- a/client/express-checkout/index.js +++ b/client/express-checkout/index.js @@ -235,6 +235,7 @@ jQuery( ( $ ) => { return; } + let addToCartPromise = Promise.resolve(); const stripe = await api.getStripe(); const elements = stripe.elements( { @@ -301,7 +302,14 @@ jQuery( ( $ ) => { } // Add products to the cart if everything is right. - wcpayECE.addToCart(); + // we are storing the promise to ensure that the "add to cart" call is completed, + // before the `shippingaddresschange` is triggered when the dialog is opened. + // Otherwise, it might happen that the `shippingaddresschange` is triggered before the "add to cart" call is done, + // which can cause errors. + addToCartPromise = wcpayECE.addToCart(); + addToCartPromise.finally( () => { + addToCartPromise = Promise.resolve(); + } ); } const clickOptions = { @@ -319,9 +327,10 @@ jQuery( ( $ ) => { event.resolve( clickOptions ); } ); - eceButton.on( 'shippingaddresschange', async ( event ) => - shippingAddressChangeHandler( api, event, elements ) - ); + eceButton.on( 'shippingaddresschange', async ( event ) => { + await addToCartPromise; + return shippingAddressChangeHandler( api, event, elements ); + } ); eceButton.on( 'shippingratechange', async ( event ) => shippingRateChangeHandler( api, event, elements ) diff --git a/client/tokenized-express-checkout/index.js b/client/tokenized-express-checkout/index.js index 0ab1ea230f6..924fdc79482 100644 --- a/client/tokenized-express-checkout/index.js +++ b/client/tokenized-express-checkout/index.js @@ -187,6 +187,7 @@ jQuery( ( $ ) => { * @param {Object} options ECE options. */ startExpressCheckoutElement: async ( options ) => { + let addToCartPromise = Promise.resolve(); const stripe = await api.getStripe(); const elements = stripe.elements( { mode: 'payment', @@ -247,7 +248,14 @@ jQuery( ( $ ) => { } // Add products to the cart if everything is right. - getCartApiHandler().addProductToCart(); + // we are storing the promise to ensure that the "add to cart" call is completed, + // before the `shippingaddresschange` is triggered when the dialog is opened. + // Otherwise, it might happen that the `shippingaddresschange` is triggered before the "add to cart" call is done, + // which can cause errors. + addToCartPromise = getCartApiHandler().addProductToCart(); + addToCartPromise.finally( () => { + addToCartPromise = Promise.resolve(); + } ); } const clickOptions = { @@ -270,9 +278,10 @@ jQuery( ( $ ) => { event.resolve( clickOptions ); } ); - eceButton.on( 'shippingaddresschange', async ( event ) => - shippingAddressChangeHandler( event, elements ) - ); + eceButton.on( 'shippingaddresschange', async ( event ) => { + await addToCartPromise; + return shippingAddressChangeHandler( event, elements ); + } ); eceButton.on( 'shippingratechange', async ( event ) => shippingRateChangeHandler( event, elements )