Skip to content

Commit 924e7ba

Browse files
committed
W-20975340: Display SPM at checkout
1 parent 00a30d4 commit 924e7ba

File tree

3 files changed

+110
-6
lines changed

3 files changed

+110
-6
lines changed

packages/template-retail-react-app/app/hooks/use-current-customer.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,15 @@ import {useCustomer, useCustomerId, useCustomerType} from '@salesforce/commerce-
1414
export const useCurrentCustomer = () => {
1515
const customerId = useCustomerId()
1616
const {isRegistered, isGuest, customerType} = useCustomerType()
17-
const query = useCustomer({parameters: {customerId}}, {enabled: !!customerId && isRegistered})
17+
const query = useCustomer(
18+
{
19+
parameters: {
20+
customerId,
21+
expand: ['paymentmethodreferences']
22+
}
23+
},
24+
{enabled: !!customerId && isRegistered}
25+
)
1826
const value = {
1927
...query,
2028
data: {

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

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import {
4848
buildTheme,
4949
getSFPaymentsInstrument,
5050
createPaymentInstrumentBody,
51+
transformPaymentMethodReferences,
5152
getClientSecret
5253
} from '@salesforce/retail-react-app/app/utils/sf-payments-utils'
5354
import logger from '@salesforce/retail-react-app/app/utils/logger-instance'
@@ -486,27 +487,44 @@ const SFPaymentsSheet = forwardRef((props, ref) => {
486487
confirmPayment
487488
}))
488489

490+
const savedPaymentMethods = useMemo(() => {
491+
if (!customer?.paymentMethodReferences || !paymentConfig?.paymentMethodSetAccounts) {
492+
return []
493+
}
494+
return transformPaymentMethodReferences(
495+
customer.paymentMethodReferences,
496+
paymentConfig.paymentMethodSetAccounts
497+
)
498+
}, [customer?.paymentMethodReferences, paymentConfig?.paymentMethodSetAccounts])
499+
489500
useEffect(() => {
490501
if (sfp && metadata && containerElementRef.current && paymentConfig) {
502+
const paymentMethodSetAccounts = (paymentConfig.paymentMethodSetAccounts || []).map(
503+
(account) => ({
504+
...account,
505+
gatewayId: account.gatewayId || account.accountId
506+
})
507+
)
508+
491509
const paymentMethodSet = {
492510
paymentMethods: paymentConfig.paymentMethods,
493-
paymentMethodSetAccounts: paymentConfig.paymentMethodSetAccounts
511+
paymentMethodSetAccounts: paymentMethodSetAccounts
494512
}
495513

496514
config.current = {
497515
theme: buildTheme(),
498516
actions: {
499517
createIntent: createPaymentInstrument,
500-
onClick: () => {} // No-op: return empty function since its not applicable and SDK proceeds immediately
518+
onClick: () => {}
501519
},
502520
options: {
503521
useManualCapture: !cardCaptureAutomatic,
504522
returnUrl: `${window.location.protocol}//${window.location.host}/checkout/payment-processing`,
505523
showSaveForFutureUsageCheckbox: !!(
506524
customer?.isRegistered && customer?.customerId
507525
),
508-
// Suppress "Make payment method default" checkbox since we don't support default SPM yet
509-
showSaveAsDefaultCheckbox: false
526+
showSaveAsDefaultCheckbox: false,
527+
savedPaymentMethods: savedPaymentMethods
510528
}
511529
}
512530

@@ -549,7 +567,9 @@ const SFPaymentsSheet = forwardRef((props, ref) => {
549567
containerElementRef.current,
550568
paymentConfig,
551569
cardCaptureAutomatic,
552-
customer?.isRegistered
570+
customer?.isRegistered,
571+
customer?.customerId,
572+
savedPaymentMethods
553573
])
554574

555575
useEffect(() => {

packages/template-retail-react-app/app/utils/sf-payments-utils.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,82 @@ export const createPaymentInstrumentBody = ({
278278
}
279279
}
280280

281+
/**
282+
* Transforms payment method references from API format to SF Payments SDK format.
283+
* @param {Array} paymentMethodReferences - Array of payment method references
284+
* @param {Array} paymentMethodSetAccounts - Array of payment method set accounts
285+
* @returns {Array} Transformed payment method references for SF Payments SDK
286+
*/
287+
export const transformPaymentMethodReferences = (
288+
paymentMethodReferences,
289+
paymentMethodSetAccounts = []
290+
) => {
291+
if (!paymentMethodReferences || !Array.isArray(paymentMethodReferences)) {
292+
return []
293+
}
294+
295+
return paymentMethodReferences
296+
.map((pmr) => {
297+
const generateDisplayName = () => {
298+
if (pmr.brand && pmr.last4) {
299+
const brandName = pmr.brand.charAt(0).toUpperCase() + pmr.brand.slice(1)
300+
return `${brandName} •••• ${pmr.last4}`
301+
}
302+
if (pmr.type === 'card' && pmr.last4) {
303+
return `Card •••• ${pmr.last4}`
304+
}
305+
if (pmr.type === 'sepa_debit' && pmr.last4) {
306+
return `Account ending in ${pmr.last4}`
307+
}
308+
return 'Saved Payment Method'
309+
}
310+
311+
// Determine gatewayId for SDK matching
312+
if (
313+
!pmr.accountId ||
314+
!paymentMethodSetAccounts ||
315+
!Array.isArray(paymentMethodSetAccounts)
316+
) {
317+
return null
318+
}
319+
320+
const matchingAccount = paymentMethodSetAccounts.find(
321+
(account) => account.accountId === pmr.accountId
322+
)
323+
if (!matchingAccount) {
324+
return null
325+
}
326+
327+
const gatewayId = matchingAccount.gatewayId || matchingAccount.accountId
328+
329+
if (!gatewayId || typeof gatewayId !== 'string') {
330+
return null
331+
}
332+
333+
return {
334+
accountId: pmr.accountId || null,
335+
name: generateDisplayName(),
336+
status: 'Active',
337+
isDefault: false,
338+
type: pmr.type || null,
339+
accountHolderName: null,
340+
id: pmr.id || null,
341+
gatewayTokenId: pmr.id || null,
342+
usageType: 'OffSession',
343+
gatewayId: gatewayId,
344+
gatewayCustomerId: null,
345+
last4: pmr.last4 || null,
346+
network: pmr.brand || null,
347+
issuer: null,
348+
expiryMonth: null,
349+
expiryYear: null,
350+
bankName: null,
351+
savedByMerchant: false
352+
}
353+
})
354+
.filter((spm) => spm !== null)
355+
}
356+
281357
/**
282358
* Returns a theme object containing CSS information for use with SF Payments components.
283359
* @param {*} options - theme override options

0 commit comments

Comments
 (0)