From bbebcd260d3e25c7cfb04848f214c0fce85054f2 Mon Sep 17 00:00:00 2001 From: Francesco Date: Mon, 24 Jun 2024 09:00:37 +0200 Subject: [PATCH] fix: pricing decimal formatting for tokenized cart (#8992) --- changelog/fix-tokenized-cart-decimals-price | 4 +++ .../frontend-utils.js | 14 +++++++-- .../payment-request.js | 31 +++++++++++++------ .../transformers/wc-to-stripe.js | 28 ++++++++++++++--- 4 files changed, 60 insertions(+), 17 deletions(-) create mode 100644 changelog/fix-tokenized-cart-decimals-price diff --git a/changelog/fix-tokenized-cart-decimals-price b/changelog/fix-tokenized-cart-decimals-price new file mode 100644 index 00000000000..ba840696aff --- /dev/null +++ b/changelog/fix-tokenized-cart-decimals-price @@ -0,0 +1,4 @@ +Significance: patch +Type: fix + +fix: pricing decimal formatting for tokenized cart diff --git a/client/tokenized-payment-request/frontend-utils.js b/client/tokenized-payment-request/frontend-utils.js index a52abf6df8a..4c7344fc888 100644 --- a/client/tokenized-payment-request/frontend-utils.js +++ b/client/tokenized-payment-request/frontend-utils.js @@ -7,7 +7,10 @@ import { doingAction } from '@wordpress/hooks'; /** * Internal dependencies */ -import { transformCartDataForDisplayItems } from './transformers/wc-to-stripe'; +import { + transformCartDataForDisplayItems, + transformPrice, +} from './transformers/wc-to-stripe'; /** * Retrieves payment request data from global variable. @@ -61,9 +64,14 @@ export const getPaymentRequest = ( { stripe, cartData, productData } ) => { currency: cartData.totals.currency_code.toLowerCase(), total: { label: getPaymentRequestData( 'total_label' ), - amount: + amount: transformPrice( parseInt( cartData.totals.total_price, 10 ) - - parseInt( cartData.totals.total_refund || 0, 10 ), + parseInt( + cartData.totals.total_refund || 0, + 10 + ), + cartData.totals + ), }, requestShipping: getPaymentRequestData( 'button_context' ) === diff --git a/client/tokenized-payment-request/payment-request.js b/client/tokenized-payment-request/payment-request.js index 445168cf5cb..93381769892 100644 --- a/client/tokenized-payment-request/payment-request.js +++ b/client/tokenized-payment-request/payment-request.js @@ -25,6 +25,7 @@ import { import { transformCartDataForDisplayItems, transformCartDataForShippingOptions, + transformPrice, } from './transformers/wc-to-stripe'; import paymentRequestButtonUi from './button-ui'; import { @@ -177,12 +178,14 @@ export default class WooPaymentsPaymentRequest { paymentRequest.update( { total: { label: getPaymentRequestData( 'total_label' ), - amount: + amount: transformPrice( parseInt( newCartData.totals.total_price, 10 ) - - parseInt( - newCartData.totals.total_refund || 0, - 10 - ), + parseInt( + newCartData.totals.total_refund || 0, + 10 + ), + newCartData.totals + ), }, displayItems: transformCartDataForDisplayItems( newCartData @@ -266,9 +269,14 @@ export default class WooPaymentsPaymentRequest { ), total: { label: getPaymentRequestData( 'total_label' ), - amount: + amount: transformPrice( parseInt( cartData.totals.total_price, 10 ) - - parseInt( cartData.totals.total_refund || 0, 10 ), + parseInt( + cartData.totals.total_refund || 0, + 10 + ), + cartData.totals + ), }, displayItems: transformCartDataForDisplayItems( cartData ), } ); @@ -292,9 +300,14 @@ export default class WooPaymentsPaymentRequest { status: 'success', total: { label: getPaymentRequestData( 'total_label' ), - amount: + amount: transformPrice( parseInt( cartData.totals.total_price, 10 ) - - parseInt( cartData.totals.total_refund || 0, 10 ), + parseInt( + cartData.totals.total_refund || 0, + 10 + ), + cartData.totals + ), }, displayItems: transformCartDataForDisplayItems( cartData ), } ); diff --git a/client/tokenized-payment-request/transformers/wc-to-stripe.js b/client/tokenized-payment-request/transformers/wc-to-stripe.js index ae175bf9338..1f932b47602 100644 --- a/client/tokenized-payment-request/transformers/wc-to-stripe.js +++ b/client/tokenized-payment-request/transformers/wc-to-stripe.js @@ -3,6 +3,21 @@ */ import { __ } from '@wordpress/i18n'; +/** + * GooglePay/ApplePay expect the prices to be formatted in cents. + * But WooCommerce has a setting to define the number of decimals for amounts. + * Using this function to ensure the prices provided to GooglePay/ApplePay + * are always provided accurately, regardless of the number of decimals. + * + * @param {number} price the price to format. + * @param {{currency_minor_unit: {number}}} priceObject the price object returned by the Store API + * + * @return {number} the price amount for GooglePay/ApplePay, always expressed in cents. + */ +export const transformPrice = ( price, priceObject ) => + // making sure the decimals are always correctly represented for GooglePay/ApplePay, since they don't allow us to specify the decimals. + price * 10 ** ( 2 - priceObject.currency_minor_unit ); + /** * Transforms the data from the Store API Cart response to `displayItems` for the Stripe PRB. * See https://docs.stripe.com/js/appendix/payment_item_object for the data structure @@ -12,7 +27,10 @@ import { __ } from '@wordpress/i18n'; */ export const transformCartDataForDisplayItems = ( cartData ) => { const displayItems = cartData.items.map( ( item ) => ( { - amount: parseInt( item.prices.price, 10 ), + amount: transformPrice( + parseInt( item.prices.price, 10 ), + item.prices + ), label: [ item.name, item.quantity > 1 && `(x${ item.quantity })`, @@ -31,7 +49,7 @@ export const transformCartDataForDisplayItems = ( cartData ) => { const taxAmount = parseInt( cartData.totals.total_tax || '0', 10 ); if ( taxAmount ) { displayItems.push( { - amount: taxAmount, + amount: transformPrice( taxAmount, cartData.totals ), label: __( 'Tax', 'woocommerce-payments' ), } ); } @@ -42,7 +60,7 @@ export const transformCartDataForDisplayItems = ( cartData ) => { ); if ( shippingAmount ) { displayItems.push( { - amount: shippingAmount, + amount: transformPrice( shippingAmount, cartData.totals ), label: __( 'Shipping', 'woocommerce-payments' ), } ); } @@ -50,7 +68,7 @@ export const transformCartDataForDisplayItems = ( cartData ) => { const refundAmount = parseInt( cartData.totals.total_refund || '0', 10 ); if ( refundAmount ) { displayItems.push( { - amount: -refundAmount, + amount: -transformPrice( refundAmount, cartData.totals ), label: __( 'Refund', 'woocommerce-payments' ), } ); } @@ -68,6 +86,6 @@ export const transformCartDataForShippingOptions = ( cartData ) => cartData.shipping_rates[ 0 ].shipping_rates.map( ( rate ) => ( { id: rate.rate_id, label: rate.name, - amount: parseInt( rate.price, 10 ), + amount: transformPrice( parseInt( rate.price, 10 ), rate ), detail: '', } ) );