Skip to content

Commit 568523b

Browse files
authored
Merge pull request #3642 from SalesforceCommerceCloud/rvishwanathbhat/adyen-support-for-spm
@W-21012995, W-21103673: Adyen support for SPM
2 parents 1c145e6 + 1b79ca4 commit 568523b

File tree

4 files changed

+693
-112
lines changed

4 files changed

+693
-112
lines changed

packages/template-retail-react-app/app/pages/checkout/partials/sf-payments-sheet.jsx

Lines changed: 66 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {
2020
Divider
2121
} from '@salesforce/retail-react-app/app/components/shared/ui'
2222
import {useForm} from 'react-hook-form'
23-
import {useShopperBasketsMutation} from '@salesforce/commerce-sdk-react'
23+
import {useShopperBasketsMutation, useCustomerType} from '@salesforce/commerce-sdk-react'
2424
import {useCurrentBasket} from '@salesforce/retail-react-app/app/hooks/use-current-basket'
2525
import {useCurrentCustomer} from '@salesforce/retail-react-app/app/hooks/use-current-customer'
2626
import {useCurrency} from '@salesforce/retail-react-app/app/hooks/use-currency'
@@ -62,7 +62,11 @@ const SFPaymentsSheet = forwardRef((props, ref) => {
6262
const navigate = useNavigation()
6363

6464
const {data: basket} = useCurrentBasket()
65-
const {data: customer} = useCurrentCustomer(['paymentmethodreferences'])
65+
const {isRegistered} = useCustomerType()
66+
const {data: customer, isLoading: customerLoading} = useCurrentCustomer(
67+
isRegistered ? ['paymentmethodreferences'] : undefined
68+
)
69+
const isCustomerDataLoading = isRegistered && customerLoading
6670

6771
const isPickupOnly =
6872
basket?.shipments?.length > 0 &&
@@ -162,7 +166,7 @@ const SFPaymentsSheet = forwardRef((props, ref) => {
162166
savePaymentMethodRef.current = event.detail.savePaymentMethodForFutureUse === true
163167
}
164168
updatedOrder.current = await createAndUpdateOrder(
165-
savePaymentMethodRef.current && customer?.isRegistered
169+
savePaymentMethodRef.current && isRegistered
166170
)
167171
// Clear the ref after successful order creation
168172
currentBasket.current = null
@@ -274,7 +278,7 @@ const SFPaymentsSheet = forwardRef((props, ref) => {
274278
}
275279

276280
// For Stripe and Adyen, update order payment instrument to create payment
277-
const shouldSavePaymentMethod = savePaymentMethodRef.current && customer?.isRegistered
281+
const shouldSavePaymentMethod = savePaymentMethodRef.current && isRegistered
278282
updatedOrder.current = await createAndUpdateOrder(shouldSavePaymentMethod, paymentData)
279283

280284
// Find updated SF Payments payment instrument in updated order
@@ -330,7 +334,7 @@ const SFPaymentsSheet = forwardRef((props, ref) => {
330334
// Find SF Payments payment instrument in created order
331335
const orderPaymentInstrument = getSFPaymentsInstrument(order)
332336

333-
if (gateway.current === PAYMENT_GATEWAYS.ADYEN) {
337+
if (gateway.current === PAYMENT_GATEWAYS.ADYEN && paymentData) {
334338
// Append necessary data to Adyen redirect return URL
335339
paymentData.returnUrl +=
336340
'&orderNo=' +
@@ -525,79 +529,79 @@ const SFPaymentsSheet = forwardRef((props, ref) => {
525529
)
526530

527531
useEffect(() => {
528-
if (sfp && metadata && containerElementRef.current && paymentConfig) {
529-
const paymentMethodSetAccounts = (paymentConfig.paymentMethodSetAccounts || []).map(
530-
(account) => ({
531-
...account,
532-
gatewayId: account.accountId
533-
})
534-
)
532+
// Mount SFP only when all required data and DOM are ready; otherwise skip or wait for a later run.
535533

536-
const paymentMethodSet = {
537-
paymentMethods: paymentConfig.paymentMethods,
538-
paymentMethodSetAccounts: paymentMethodSetAccounts
539-
}
534+
if (isCustomerDataLoading) return // Wait for savedPaymentMethods data to load for registered users
535+
if (checkoutComponent.current) return // Skip if Componenet Already mounted
536+
if (!sfp) return // Skip if SFP SDK not loaded yet
537+
if (!metadata) return // Skip if SFP metadata not available yet
538+
if (!containerElementRef.current) return // Skip if Payment container ref not attached to DOM yet
539+
if (!paymentConfig) return // Skip if Payment config not loaded yet
540540

541-
config.current = {
542-
theme: buildTheme(),
543-
actions: {
544-
createIntent: createIntent,
545-
onClick: () => {} // No-op: return empty function since its not applicable and SDK proceeds immediately
546-
},
547-
options: {
548-
useManualCapture: !cardCaptureAutomatic,
549-
returnUrl: `${window.location.protocol}//${window.location.host}/checkout/payment-processing`,
550-
showSaveForFutureUsageCheckbox: !!(
551-
customer?.isRegistered && customer?.customerId
552-
),
553-
// Suppress "Make payment method default" checkbox since we don't support default SPM yet
554-
showSaveAsDefaultCheckbox: false,
555-
savedPaymentMethods: savedPaymentMethods
556-
}
557-
}
558541

559-
const paymentRequest = {
560-
amount: basket.productTotal,
561-
currency: basket.currency,
562-
country: 'US', // TODO: see W-18812582
563-
locale: intl.locale
564-
}
542+
const paymentMethodSetAccounts = (paymentConfig.paymentMethodSetAccounts || []).map(
543+
(account) => ({
544+
...account,
545+
gatewayId: account.accountId
546+
})
547+
)
565548

566-
// Clear the container and create a new div element
567-
containerElementRef.current.innerHTML = ''
568-
const paymentElement = document.createElement('div')
569-
containerElementRef.current.appendChild(paymentElement)
549+
const paymentMethodSet = {
550+
paymentMethods: paymentConfig.paymentMethods,
551+
paymentMethodSetAccounts: paymentMethodSetAccounts
552+
}
570553

571-
paymentElement.addEventListener(
572-
'sfp:paymentmethodselected',
573-
handlePaymentMethodSelected
574-
)
575-
paymentElement.addEventListener('sfp:paymentapprove', handlePaymentButtonApprove)
576-
paymentElement.addEventListener('sfp:paymentcancel', handlePaymentButtonCancel)
577-
578-
checkoutComponent.current = sfp.checkout(
579-
metadata,
580-
paymentMethodSet,
581-
config.current,
582-
paymentRequest,
583-
paymentElement
584-
)
554+
config.current = {
555+
theme: buildTheme(),
556+
actions: {
557+
createIntent: createIntent,
558+
onClick: () => {} // No-op: return empty function since its not applicable and SDK proceeds immediately
559+
},
560+
options: {
561+
useManualCapture: !cardCaptureAutomatic,
562+
returnUrl: `${window.location.protocol}//${window.location.host}/checkout/payment-processing`,
563+
showSaveForFutureUsageCheckbox: isRegistered,
564+
// Suppress "Make payment method default" checkbox since we don't support default SPM yet
565+
showSaveAsDefaultCheckbox: false,
566+
savedPaymentMethods: savedPaymentMethods
567+
}
585568
}
586569

587-
// Cleanup on unmount
570+
const paymentRequest = {
571+
amount: basket.productTotal,
572+
currency: basket.currency,
573+
country: 'US', // TODO: see W-18812582
574+
locale: intl.locale
575+
}
576+
577+
// Clear the container and create a new div element
578+
containerElementRef.current.innerHTML = ''
579+
const paymentElement = document.createElement('div')
580+
containerElementRef.current.appendChild(paymentElement)
581+
582+
paymentElement.addEventListener('sfp:paymentmethodselected', handlePaymentMethodSelected)
583+
paymentElement.addEventListener('sfp:paymentapprove', handlePaymentButtonApprove)
584+
paymentElement.addEventListener('sfp:paymentcancel', handlePaymentButtonCancel)
585+
586+
checkoutComponent.current = sfp.checkout(
587+
metadata,
588+
paymentMethodSet,
589+
config.current,
590+
paymentRequest,
591+
paymentElement
592+
)
593+
588594
return () => {
589595
checkoutComponent.current?.destroy()
590596
checkoutComponent.current = null
591597
}
592598
}, [
599+
isCustomerDataLoading,
593600
sfp,
594601
metadata,
595602
containerElementRef.current,
596603
paymentConfig,
597-
cardCaptureAutomatic,
598-
customer?.isRegistered,
599-
customer?.customerId,
600-
savedPaymentMethods
604+
cardCaptureAutomatic
601605
])
602606

603607
useEffect(() => {

0 commit comments

Comments
 (0)