Skip to content

Commit

Permalink
feature: update billing address before sendPayments (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
shanikantsingh authored Oct 27, 2023
1 parent ad12319 commit 893fa63
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 109 deletions.
12 changes: 7 additions & 5 deletions adyen/components/AdyenCheckout.js
Original file line number Diff line number Diff line change
@@ -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) {
Expand Down
86 changes: 45 additions & 41 deletions adyen/components/helpers/baseConfig.js
Original file line number Diff line number Diff line change
@@ -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)
}
}
2 changes: 1 addition & 1 deletion adyen/components/paymentMethodsConfiguration.js
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
64 changes: 46 additions & 18 deletions adyen/context/adyen-checkout-context.js
Original file line number Diff line number Diff line change
@@ -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'

Expand All @@ -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 () => {
Expand All @@ -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})
Expand All @@ -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 <AdyenCheckoutContext.Provider value={value}>{children}</AdyenCheckoutContext.Provider>
Expand Down
18 changes: 4 additions & 14 deletions adyen/controllers/payments.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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}
Expand Down
13 changes: 13 additions & 0 deletions adyen/utils/executeCallbacks.js
Original file line number Diff line number Diff line change
@@ -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}
}, {})
}
}
6 changes: 3 additions & 3 deletions overrides/app/pages/checkout/partials/payment.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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'}
})
Expand Down Expand Up @@ -146,7 +146,7 @@ const Payment = () => {
</Box>

<Stack spacing={6}>
<AdyenCheckout />
<AdyenCheckout beforeSubmit={[onBillingSubmit]} />

<Divider borderColor="gray.100" />

Expand Down
18 changes: 0 additions & 18 deletions overrides/app/static/translations/compiled/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
9 changes: 0 additions & 9 deletions translations/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down Expand Up @@ -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"
},
Expand Down

0 comments on commit 893fa63

Please sign in to comment.