From 893fa63e56c1b6c83ff85145a2755e5add719b79 Mon Sep 17 00:00:00 2001
From: Shani <31096696+shanikantsingh@users.noreply.github.com>
Date: Fri, 27 Oct 2023 17:06:35 +0200
Subject: [PATCH] feature: update billing address before sendPayments (#31)
---
adyen/components/AdyenCheckout.js | 12 +--
adyen/components/helpers/baseConfig.js | 86 ++++++++++---------
.../components/paymentMethodsConfiguration.js | 2 +-
adyen/context/adyen-checkout-context.js | 64 ++++++++++----
adyen/controllers/payments.js | 18 +---
adyen/utils/executeCallbacks.js | 13 +++
.../app/pages/checkout/partials/payment.jsx | 6 +-
.../static/translations/compiled/en-US.json | 18 ----
translations/en-US.json | 9 --
9 files changed, 119 insertions(+), 109 deletions(-)
create mode 100644 adyen/utils/executeCallbacks.js
diff --git a/adyen/components/AdyenCheckout.js b/adyen/components/AdyenCheckout.js
index 6f1bd76..f4b82f1 100644
--- a/adyen/components/AdyenCheckout.js
+++ b/adyen/components/AdyenCheckout.js
@@ -1,21 +1,23 @@
-import React, {useRef, useEffect} from 'react'
+import React, {useEffect, useRef} from 'react'
import AdyenCheckout from '@adyen/adyen-web'
import '@adyen/adyen-web/dist/adyen.css'
import {useAdyenCheckout} from '../context/adyen-checkout-context'
-const AdyenCheckoutComponent = () => {
- const {adyenPaymentMethods, adyenPaymentMethodsConfig, setAdyenStateData} = useAdyenCheckout()
+const AdyenCheckoutComponent = (props) => {
+ const {adyenPaymentMethods, getPaymentMethodsConfiguration, setAdyenStateData} =
+ useAdyenCheckout()
const paymentContainer = useRef(null)
useEffect(() => {
const createCheckout = async () => {
+ const paymentMethodsConfiguration = await getPaymentMethodsConfiguration(props)
const checkout = await AdyenCheckout({
environment: adyenPaymentMethods.ADYEN_ENVIRONMENT,
clientKey: adyenPaymentMethods.ADYEN_CLIENT_KEY,
paymentMethodsResponse: adyenPaymentMethods,
- paymentMethodsConfiguration: adyenPaymentMethodsConfig,
+ paymentMethodsConfiguration: paymentMethodsConfiguration,
onAdditionalDetails(state, element) {
- adyenPaymentMethodsConfig.card.onAdditionalDetails(state, element)
+ paymentMethodsConfiguration.card.onAdditionalDetails(state, element)
},
onChange: (state) => {
if (state.isValid) {
diff --git a/adyen/components/helpers/baseConfig.js b/adyen/components/helpers/baseConfig.js
index 438cbe2..2d1d787 100644
--- a/adyen/components/helpers/baseConfig.js
+++ b/adyen/components/helpers/baseConfig.js
@@ -1,50 +1,54 @@
import {AdyenPaymentsService} from '../../services/payments'
import {AdyenPaymentsDetailsService} from '../../services/payments-details'
-export const baseConfig = (props) => {
- const onSubmit = async (state, component) => {
- try {
- if (!state.isValid) {
- throw new Error('invalid state')
- }
- const adyenPaymentService = new AdyenPaymentsService(props?.token)
- const paymentsResponse = await adyenPaymentService.submitPayment(
- state.data,
- props.basketId,
- props?.customerId
- )
- if (paymentsResponse?.isSuccessful) {
- props?.successHandler(paymentsResponse.merchantReference)
- } else if (paymentsResponse?.action) {
- await component.handleAction(paymentsResponse.action)
- } else {
- // handle error
- }
- } catch (error) {
- props?.errorHandler(error)
- }
+import {executeCallbacks} from '../../utils/executeCallbacks'
+
+export const baseConfig = ({
+ beforeSubmit = [],
+ afterSubmit = [],
+ beforeAdditionalDetails = [],
+ afterAdditionalDetails = [],
+ onError = (error) => {
+ console.log(JSON.stringify(error))
+ },
+ ...props
+}) => {
+ return {
+ onSubmit: executeCallbacks([...beforeSubmit, onSubmit, ...afterSubmit], props, onError),
+ onAdditionalDetails: executeCallbacks(
+ [...beforeAdditionalDetails, onAdditionalDetails, ...afterAdditionalDetails],
+ props,
+ onError
+ )
}
+}
- const onAdditionalDetails = async (state, component) => {
- try {
- const adyenPaymentsDetailsService = new AdyenPaymentsDetailsService(props?.token)
- const paymentsDetailsResponse = await adyenPaymentsDetailsService.submitPaymentsDetails(
- state.data,
- props?.customerId
- )
- if (paymentsDetailsResponse?.isSuccessful) {
- props?.successHandler(paymentsDetailsResponse.merchantReference)
- } else if (paymentsDetailsResponse?.action) {
- await component.handleAction(paymentsDetailsResponse.action)
- } else {
- // handle error
- }
- } catch (error) {
- props?.errorHandler(error)
+export const onSubmit = async (state, component, props) => {
+ try {
+ if (!state.isValid) {
+ throw new Error('invalid state')
}
+ // await props.submitBilling()
+ const adyenPaymentService = new AdyenPaymentsService(props?.token)
+ const paymentsResponse = await adyenPaymentService.submitPayment(
+ state.data,
+ props.basketId,
+ props?.customerId
+ )
+ return {paymentsResponse: paymentsResponse}
+ } catch (error) {
+ return new Error(error)
}
+}
- return {
- onSubmit: onSubmit,
- onAdditionalDetails: onAdditionalDetails
+export const onAdditionalDetails = async (state, component, props) => {
+ try {
+ const adyenPaymentsDetailsService = new AdyenPaymentsDetailsService(props?.token)
+ const paymentsDetailsResponse = await adyenPaymentsDetailsService.submitPaymentsDetails(
+ state.data,
+ props?.customerId
+ )
+ return {paymentsDetailsResponse: paymentsDetailsResponse}
+ } catch (error) {
+ return new Error(error)
}
}
diff --git a/adyen/components/paymentMethodsConfiguration.js b/adyen/components/paymentMethodsConfiguration.js
index b01c383..f7b39cb 100644
--- a/adyen/components/paymentMethodsConfiguration.js
+++ b/adyen/components/paymentMethodsConfiguration.js
@@ -4,7 +4,7 @@ import {cardConfig} from './card/config'
import {paypalConfig} from './paypal/config'
import {applePayConfig} from './applepay/config'
-export const paymentMethodsConfiguration = ({paymentMethods, ...props}) => {
+export const paymentMethodsConfiguration = ({paymentMethods = [], ...props}) => {
const defaultConfig = baseConfig(props)
const paymentMethodsConfig = {
card: cardConfig(props),
diff --git a/adyen/context/adyen-checkout-context.js b/adyen/context/adyen-checkout-context.js
index c3ee498..dfb80f7 100644
--- a/adyen/context/adyen-checkout-context.js
+++ b/adyen/context/adyen-checkout-context.js
@@ -1,11 +1,10 @@
import React, {useEffect, useState} from 'react'
import {useLocation} from 'react-router-dom'
import PropTypes from 'prop-types'
-import {useAccessToken, useCustomerId} from '@salesforce/commerce-sdk-react'
+import {useAccessToken, useCustomerId, useCustomerType} from '@salesforce/commerce-sdk-react'
import {useCurrentBasket} from '@salesforce/retail-react-app/app/hooks/use-current-basket'
import {resolveLocaleFromUrl} from '@salesforce/retail-react-app/app/utils/site-utils'
import useNavigation from '@salesforce/retail-react-app/app/hooks/use-navigation'
-import {useCustomerType} from '@salesforce/commerce-sdk-react'
import {AdyenPaymentMethodsService} from '../services/payment-methods'
import {paymentMethodsConfiguration} from '../components/paymentMethodsConfiguration'
@@ -24,7 +23,6 @@ export const AdyenCheckoutProvider = ({children}) => {
const [adyenPaymentMethods, setAdyenPaymentMethods] = useState()
const [adyenStateData, setAdyenStateData] = useState()
const [paymentConfig, setPaymentConfig] = useState()
- const [adyenPaymentMethodsConfig, setAdyenPaymentMethodsConfig] = useState()
useEffect(() => {
const fetchPaymentMethods = async () => {
@@ -37,18 +35,6 @@ export const AdyenCheckoutProvider = ({children}) => {
locale
)
setAdyenPaymentMethods(data ? data : {error: true})
- setAdyenPaymentMethodsConfig(
- paymentMethodsConfiguration({
- paymentMethods: data.paymentMethods,
- customerType,
- token,
- basketId: basket.basketId,
- customerId,
- successHandler: (merchantReference) =>
- navigate(`/checkout/confirmation/${merchantReference}`),
- errorHandler: (error) => console.log(error)
- })
- )
setFetching(false)
} catch (error) {
setAdyenPaymentMethods({error})
@@ -61,14 +47,56 @@ export const AdyenCheckoutProvider = ({children}) => {
}
}, [basket?.basketId])
+ const getPaymentMethodsConfiguration = async ({
+ beforeSubmit = [],
+ afterSubmit = [],
+ beforeAdditionalDetails = [],
+ afterAdditionalDetails = [],
+ onError
+ }) => {
+ const token = await getTokenWhenReady()
+ return paymentMethodsConfiguration({
+ paymentMethods: adyenPaymentMethods?.paymentMethods,
+ customerType,
+ token,
+ basketId: basket.basketId,
+ customerId,
+ onError: onError,
+ afterSubmit: [...afterSubmit, onPaymentsSuccess],
+ beforeSubmit: beforeSubmit,
+ afterAdditionalDetails: [...afterAdditionalDetails, onPaymentsDetailsSuccess],
+ beforeAdditionalDetails: beforeAdditionalDetails
+ })
+ }
+
+ const onPaymentsSuccess = async (state, component, props, responses) => {
+ if (responses?.paymentsResponse?.isSuccessful) {
+ navigate(`/checkout/confirmation/${responses?.paymentsResponse?.merchantReference}`)
+ } else if (responses?.paymentsResponse?.action) {
+ await component.handleAction(responses?.paymentsResponse?.action)
+ } else {
+ return new Error(responses?.paymentsResponse)
+ }
+ }
+
+ const onPaymentsDetailsSuccess = async (state, component, props, responses) => {
+ if (responses?.paymentsDetailsResponse?.isSuccessful) {
+ navigate(
+ `/checkout/confirmation/${responses?.paymentsDetailsResponse?.merchantReference}`
+ )
+ } else if (responses?.paymentsDetailsResponse?.action) {
+ await component.handleAction(responses?.paymentsDetailsResponse?.action)
+ } else {
+ return new Error(responses?.paymentsDetailsResponse)
+ }
+ }
+
const value = {
adyenPaymentMethods,
adyenStateData,
paymentConfig,
- adyenPaymentMethodsConfig,
setAdyenStateData: (data) => setAdyenStateData(data),
- setPaymentConfig: (data) => setPaymentConfig(data),
- setAdyenPaymentMethodsConfig: (data) => setAdyenPaymentMethodsConfig(data)
+ getPaymentMethodsConfiguration
}
return {children}
diff --git a/adyen/controllers/payments.js b/adyen/controllers/payments.js
index 93d5242..bed212d 100644
--- a/adyen/controllers/payments.js
+++ b/adyen/controllers/payments.js
@@ -2,15 +2,14 @@ import {formatAddressInAdyenFormat} from '../utils/formatAddress.mjs'
import {getCurrencyValueForApi} from '../utils/parsers.mjs'
import {
APPLICATION_VERSION,
- SHOPPER_INTERACTIONS,
+ PAYMENT_METHODS,
RECURRING_PROCESSING_MODEL,
- PAYMENT_METHODS
+ SHOPPER_INTERACTIONS
} from '../utils/constants.mjs'
import {createCheckoutResponse} from '../utils/createCheckoutResponse.mjs'
-import {Checkout} from 'commerce-sdk'
-import {ShopperOrders, ShopperBaskets} from 'commerce-sdk-isomorphic'
+import {ShopperBaskets, ShopperOrders} from 'commerce-sdk-isomorphic'
import {getConfig} from '@salesforce/pwa-kit-runtime/utils/ssr-config'
-import AdyenCheckoutConfig from './checkout-config';
+import AdyenCheckoutConfig from './checkout-config'
const errorMessages = {
AMOUNT_NOT_CORRECT: 'amount not correct',
@@ -62,15 +61,6 @@ async function sendPayments(req, res) {
})
}
- if (!basket.billingAddress) {
- await shopperBaskets.updateBillingAddressForBasket({
- body: basket.shipments[0].shippingAddress,
- parameters: {
- basketId: req.headers.basketid
- }
- })
- }
-
const shopperOrders = new ShopperOrders({
...appConfig.commerceAPI,
headers: {authorization: req.headers.authorization}
diff --git a/adyen/utils/executeCallbacks.js b/adyen/utils/executeCallbacks.js
new file mode 100644
index 0000000..b0c4fe9
--- /dev/null
+++ b/adyen/utils/executeCallbacks.js
@@ -0,0 +1,13 @@
+export const executeCallbacks = (callbacks, props, onError) => {
+ return async (...params) => {
+ callbacks.reduce(async (data, func, index, arr) => {
+ const next = await data
+ const response = await func(...params, props, next)
+ if (response instanceof Error) {
+ onError(response)
+ arr.splice(index)
+ }
+ return {...next, ...response}
+ }, {})
+ }
+}
diff --git a/overrides/app/pages/checkout/partials/payment.jsx b/overrides/app/pages/checkout/partials/payment.jsx
index c4bd6a4..ed8ef99 100644
--- a/overrides/app/pages/checkout/partials/payment.jsx
+++ b/overrides/app/pages/checkout/partials/payment.jsx
@@ -7,7 +7,7 @@
import React, {useState} from 'react'
import PropTypes from 'prop-types'
import {FormattedMessage, useIntl} from 'react-intl'
-import {Box, Button, Checkbox, Container, Heading, Stack, Text, Divider} from '@chakra-ui/react'
+import {Box, Checkbox, Divider, Heading, Stack, Text} from '@chakra-ui/react'
import {useForm} from 'react-hook-form'
import {useToast} from '@salesforce/retail-react-app/app/hooks/use-toast'
import {useShopperBasketsMutation} from '@salesforce/commerce-sdk-react'
@@ -93,7 +93,7 @@ const Payment = () => {
// Using destructuring to remove properties from the object...
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const {addressId, creationDate, lastModified, preferred, ...address} = billingAddress
- return updateBillingAddressForBasket({
+ return await updateBillingAddressForBasket({
body: address,
parameters: {basketId: basket.basketId, shipmentId: 'me'}
})
@@ -146,7 +146,7 @@ const Payment = () => {
-
+
diff --git a/overrides/app/static/translations/compiled/en-US.json b/overrides/app/static/translations/compiled/en-US.json
index b51e690..89ef442 100644
--- a/overrides/app/static/translations/compiled/en-US.json
+++ b/overrides/app/static/translations/compiled/en-US.json
@@ -533,18 +533,6 @@
"value": "Add New Card"
}
],
- "checkout.button.place_order": [
- {
- "type": 0,
- "value": "Place Order"
- }
- ],
- "checkout.message.generic_error": [
- {
- "type": 0,
- "value": "An unexpected error occurred during checkout."
- }
- ],
"checkout_confirmation.button.create_account": [
{
"type": 0,
@@ -767,12 +755,6 @@
"value": "Back to cart"
}
],
- "checkout_payment.button.review_order": [
- {
- "type": 0,
- "value": "Review Order"
- }
- ],
"checkout_payment.heading.billing_address": [
{
"type": 0,
diff --git a/translations/en-US.json b/translations/en-US.json
index 536594a..d75f762 100644
--- a/translations/en-US.json
+++ b/translations/en-US.json
@@ -201,12 +201,6 @@
"cc_radio_group.button.add_new_card": {
"defaultMessage": "Add New Card"
},
- "checkout.button.place_order": {
- "defaultMessage": "Place Order"
- },
- "checkout.message.generic_error": {
- "defaultMessage": "An unexpected error occurred during checkout."
- },
"checkout_confirmation.button.create_account": {
"defaultMessage": "Create Account"
},
@@ -295,9 +289,6 @@
"checkout_header.link.cart": {
"defaultMessage": "Back to cart"
},
- "checkout_payment.button.review_order": {
- "defaultMessage": "Review Order"
- },
"checkout_payment.heading.billing_address": {
"defaultMessage": "Billing Address"
},