Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/calm-paws-shave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@godaddy/react": patch
---

fix payload amount precision for godaddy payment express checkout on shipping changes
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ import { filterAndSortShippingMethods } from '@/components/checkout/shipping/uti
import { useGetShippingMethodByAddress } from '@/components/checkout/shipping/utils/use-get-shipping-methods';
import { useGetTaxes } from '@/components/checkout/taxes/utils/use-get-taxes';
import { mapOrderToFormValues } from '@/components/checkout/utils/checkout-transformers';
import { useFormatCurrency } from '@/components/checkout/utils/format-currency';
import {
useConvertMajorToMinorUnits,
useFormatCurrency,
} from '@/components/checkout/utils/format-currency';
import { Skeleton } from '@/components/ui/skeleton';
import { useGoDaddyContext } from '@/godaddy-provider';
import { GraphQLErrorWithCodes } from '@/lib/graphql-with-errors';
Expand All @@ -47,6 +50,7 @@ import {

export function ExpressCheckoutButton() {
const formatCurrency = useFormatCurrency();
const convertMajorToMinorUnits = useConvertMajorToMinorUnits();
const { session, setCheckoutErrors } = useCheckoutContext();
const { isPoyntLoaded } = useLoadPoyntCollect();
const { godaddyPaymentsConfig } = useCheckoutContext();
Expand Down Expand Up @@ -104,7 +108,7 @@ export function ExpressCheckoutButton() {
subtotalPrice: {
currencyCode: currency,
// Wallet APIs provide amounts in major units (e.g., "10.50"), convert to minor units for our API
value: Number(amount) * 100 || 0,
value: convertMajorToMinorUnits(amount || '0', currency),
},
},
],
Expand Down Expand Up @@ -927,7 +931,10 @@ export function ExpressCheckoutButton() {
shipping: {
currencyCode: currencyCode,
// Convert wallet API amount from major to minor units for internal storage
value: Number(shippingAmount) * 100 || 0,
value: convertMajorToMinorUnits(
shippingAmount || '0',
currencyCode
),
},
}));

Expand All @@ -938,7 +945,10 @@ export function ExpressCheckoutButton() {
shippingAddress,
{
// Convert wallet API amount from major to minor units for API request
amountInMinorUnits: Number(shippingAmount) * 100 || 0,
amountInMinorUnits: convertMajorToMinorUnits(
shippingAmount || '0',
currencyCode
),
name: e.shippingMethod?.label || t.totals.shipping,
}
);
Expand Down Expand Up @@ -1036,7 +1046,12 @@ export function ExpressCheckoutButton() {
...updatedOrder,
total: {
label: t.payment.orderTotal,
amount: totalAmount.toString(),
amount: formatCurrency({
amount: totalAmount,
currencyCode: currencyCode,
inputInMinorUnits: false,
returnRaw: true,
}),
},
lineItems: poyntLineItems,
};
Expand Down Expand Up @@ -1220,7 +1235,12 @@ export function ExpressCheckoutButton() {
...poyntExpressRequest,
total: {
label: t.payment.orderTotal,
amount: totalAmount.toString(),
amount: formatCurrency({
amount: totalAmount,
currencyCode: currencyCode,
inputInMinorUnits: false,
returnRaw: true,
}),
},
shippingMethods: methods as ShippingMethod[],
lineItems: poyntLineItems,
Expand Down
34 changes: 34 additions & 0 deletions packages/react/src/components/checkout/utils/format-currency.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,28 @@ export function formatCurrency({
}
}

/**
* Converts a currency amount from major units (dollars) to minor units (cents).
*
* This is the reverse operation of formatCurrency with inputInMinorUnits=true.
* It properly handles different currency precisions:
* - 2 decimals (USD, EUR, etc.): multiply by 100
* - 0 decimals (JPY, KRW, VND, etc.): multiply by 1
* - 3 decimals (KWD, BHD, JOD, OMR): multiply by 1000
*
* @param amount - The amount in major units (e.g., "10.50" or 10.50)
* @param currencyCode - ISO 4217 currency code (e.g., 'USD', 'JPY', 'KWD')
* @returns The amount in minor units (e.g., 1050 for USD, 10 for JPY, 10500 for KWD)
*/
export function convertMajorToMinorUnits(
amount: number | string,
currencyCode: string
): number {
const config = currencyConfigs[currencyCode] || { precision: 2 };
const numAmount = typeof amount === 'string' ? Number(amount) : amount;
return Math.round(numAmount * Math.pow(10, config.precision));
}

/**
* Hook that returns a formatCurrency function using the locale from GoDaddyProvider context.
* The returned function has the same signature as formatCurrency, but uses the context locale as default.
Expand All @@ -119,3 +141,15 @@ export function useFormatCurrency() {
});
};
}

/**
* Hook that returns a convertMajorToMinorUnits function.
* This follows the same pattern as useFormatCurrency for consistency.
* Note: Locale is not used in currency conversion (only in display formatting),
* but we access context to maintain the same hook pattern.
*/
export function useConvertMajorToMinorUnits() {
return (amount: number | string, currencyCode: string) => {
return convertMajorToMinorUnits(amount, currencyCode);
};
}