diff --git a/.changeset/quiet-masks-agree.md b/.changeset/quiet-masks-agree.md deleted file mode 100644 index 932a7e3803..0000000000 --- a/.changeset/quiet-masks-agree.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@adyen/adyen-web': patch ---- - -Small optimisation to only call document.querySelector once, rather than three times diff --git a/.changeset/rotten-camels-think.md b/.changeset/rotten-camels-think.md deleted file mode 100644 index 6381324056..0000000000 --- a/.changeset/rotten-camels-think.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@adyen/adyen-web': patch ---- - -Added optional chaining operator to postMessage handler function. Fixes issue where 'get-process-message.handler.js' caused exceptions due to stray postMessages without properly formed events diff --git a/examples/angular/package-lock.json b/examples/angular/package-lock.json index 158626dab3..8fe183fab9 100644 --- a/examples/angular/package-lock.json +++ b/examples/angular/package-lock.json @@ -19,7 +19,7 @@ "@angular/platform-server": "^18.0.0", "@angular/router": "^18.0.0", "@angular/ssr": "^18.0.7", - "express": "^4.20.0", + "express": "^4.21.1", "rxjs": "~7.8.0", "tslib": "^2.3.0", "zone.js": "~0.14.3" @@ -4939,20 +4939,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "node_modules/body-parser/node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/bonjour-service": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", @@ -5541,9 +5527,9 @@ "dev": true }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "engines": { "node": ">= 0.6" } @@ -6378,23 +6364,23 @@ "dev": true }, "node_modules/express": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.20.0.tgz", - "integrity": "sha512-pLdae7I6QqShF5PnNTCVn4hI91Dx0Grkn2+IAsMTgMIKuQVte2dN9PeGSSAME2FR8anOhVA62QDIUaWVfEXVLw==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", "merge-descriptors": "1.0.3", @@ -6403,11 +6389,11 @@ "parseurl": "~1.3.3", "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "0.19.0", - "serve-static": "1.16.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -6545,12 +6531,12 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -6569,6 +6555,14 @@ "ms": "2.0.0" } }, + "node_modules/finalhandler/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -9882,11 +9876,11 @@ } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -10583,58 +10577,25 @@ } }, "node_modules/serve-static": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.0.tgz", - "integrity": "sha512-pDLK8zwl2eKaYrs8mrPZBJua4hMplRWJ1tIFksVC3FtBEBnl8dxgeHtsaMS8DhS9i4fLObaon6ABoc4/hQGdPA==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" } }, - "node_modules/serve-static/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/serve-static/node_modules/debug/node_modules/ms": { + "node_modules/serve-static/node_modules/encodeurl": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/serve-static/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/serve-static/node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "engines": { - "node": ">= 0.8.0" + "node": ">= 0.8" } }, "node_modules/set-function-length": { diff --git a/examples/angular/package.json b/examples/angular/package.json index 62fa03aad4..9afc7d1f6a 100644 --- a/examples/angular/package.json +++ b/examples/angular/package.json @@ -23,7 +23,7 @@ "@angular/platform-server": "^18.0.0", "@angular/router": "^18.0.0", "@angular/ssr": "^18.0.7", - "express": "^4.20.0", + "express": "^4.21.1", "rxjs": "~7.8.0", "tslib": "^2.3.0", "zone.js": "~0.14.3" diff --git a/packages/e2e-playwright/package.json b/packages/e2e-playwright/package.json index 768128d5f3..749b48958f 100644 --- a/packages/e2e-playwright/package.json +++ b/packages/e2e-playwright/package.json @@ -26,6 +26,6 @@ "webpack-dev-server": "4.15.1" }, "dependencies": { - "@adyen/adyen-web": "6.3.0" + "@adyen/adyen-web": "6.4.0" } } diff --git a/packages/e2e/package.json b/packages/e2e/package.json index 288c113b6a..661c86127c 100644 --- a/packages/e2e/package.json +++ b/packages/e2e/package.json @@ -41,6 +41,6 @@ "whatwg-fetch": "^3.6.2" }, "dependencies": { - "@adyen/adyen-web": "6.3.0" + "@adyen/adyen-web": "6.4.0" } } diff --git a/packages/lib/.storybook/main.ts b/packages/lib/.storybook/main.ts index 219da2f1af..551616d520 100644 --- a/packages/lib/.storybook/main.ts +++ b/packages/lib/.storybook/main.ts @@ -49,7 +49,7 @@ const config: StorybookConfig = { } }, plugins: [ - stylelint() + stylelint({ emitErrorAsWarning: true }) // TODO: Enable this once @rollup/plugin-eslint supports ESLINT 9 // { // ...eslint({ diff --git a/packages/lib/CHANGELOG.md b/packages/lib/CHANGELOG.md index 34138ce486..13dafe2da3 100644 --- a/packages/lib/CHANGELOG.md +++ b/packages/lib/CHANGELOG.md @@ -1,5 +1,23 @@ # @adyen/adyen-web +## 6.4.0 + +### Minor Changes + +- All actions lead to a call to the onActionHandled callback. With the exception of 3DS2 actions this callback is always passed the original action object. ([#2892](https://github.com/Adyen/adyen-web/pull/2892)) + +- Adds selector for savings and checking accounts on ACH component ([#2898](https://github.com/Adyen/adyen-web/pull/2898)) + +- Export CustomTranslations type ([#2905](https://github.com/Adyen/adyen-web/pull/2905)) + +### Patch Changes + +- Calling actions.reject() in the beforeSubmit callback should leave the UI in the current state. Fixes situation where it leads to a call to handleFailedResult which ultimately leads to a call to the onPaymentFailed callback and sets the UI to an error state ([#2901](https://github.com/Adyen/adyen-web/pull/2901)) + +- Small optimisation to only call document.querySelector once, rather than three times ([#2895](https://github.com/Adyen/adyen-web/pull/2895)) + +- Added optional chaining operator to postMessage handler function. Fixes issue where 'get-process-message.handler.js' caused exceptions due to stray postMessages without properly formed events ([#2894](https://github.com/Adyen/adyen-web/pull/2894)) + ## 6.3.0 ### Minor Changes diff --git a/packages/lib/package.json b/packages/lib/package.json index b092cb0a74..0167af17c5 100644 --- a/packages/lib/package.json +++ b/packages/lib/package.json @@ -1,6 +1,6 @@ { "name": "@adyen/adyen-web", - "version": "6.3.0", + "version": "6.4.0", "license": "MIT", "homepage": "https://docs.adyen.com/checkout", "type": "module", diff --git a/packages/lib/src/components/ANCV/ANCV.tsx b/packages/lib/src/components/ANCV/ANCV.tsx index 6be67bf0fe..7f2c5e74d5 100644 --- a/packages/lib/src/components/ANCV/ANCV.tsx +++ b/packages/lib/src/components/ANCV/ANCV.tsx @@ -107,7 +107,7 @@ export class ANCVElement extends UIElement { showCountdownTimer={config.showCountdownTimer} throttleTime={config.THROTTLE_TIME} throttleInterval={config.THROTTLE_INTERVAL} - onActionHandled={this.props.onActionHandled} + onActionHandled={this.onActionHandled} /> diff --git a/packages/lib/src/components/Ach/Ach.tsx b/packages/lib/src/components/Ach/Ach.tsx index 9db10d62db..58847f481a 100644 --- a/packages/lib/src/components/Ach/Ach.tsx +++ b/packages/lib/src/components/Ach/Ach.tsx @@ -38,7 +38,6 @@ export class AchElement extends UIElement { return { paymentMethod, - ...(this.state.billingAddress && { billingAddress: this.state.billingAddress }), ...(this.state.storePaymentMethod && { storePaymentMethod: this.state.storePaymentMethod }) }; } diff --git a/packages/lib/src/components/Ach/components/AchInput/AchInput.scss b/packages/lib/src/components/Ach/components/AchInput/AchInput.scss index e27c0f4155..cb3bb4f99a 100644 --- a/packages/lib/src/components/Ach/components/AchInput/AchInput.scss +++ b/packages/lib/src/components/Ach/components/AchInput/AchInput.scss @@ -31,3 +31,4 @@ position: relative; } } + diff --git a/packages/lib/src/components/Ach/components/AchInput/AchInput.test.tsx b/packages/lib/src/components/Ach/components/AchInput/AchInput.test.tsx index e0f05a2c7c..d6fe6ca4f1 100644 --- a/packages/lib/src/components/Ach/components/AchInput/AchInput.test.tsx +++ b/packages/lib/src/components/Ach/components/AchInput/AchInput.test.tsx @@ -20,11 +20,6 @@ describe('AchInput', () => { expect(await screen.findByText(/aba routing number/i)).toBeTruthy(); }); - test('should render Address by default', async () => { - withCoreProvider(); - expect(await screen.findByText(/billing address/i)).toBeTruthy(); - }); - test('should render FormInstruction by default', async () => { withCoreProvider(); expect(await screen.findByText(/all fields are required unless marked otherwise./i)).toBeTruthy(); @@ -41,4 +36,9 @@ describe('AchInput', () => { ); expect(await screen.findByText(/test pay button/i)).toBeTruthy(); }); + + test('should show checking and savings selector', async () => { + withCoreProvider(); + expect(await screen.findByText(/Checking/i)).toBeTruthy(); + }); }); diff --git a/packages/lib/src/components/Ach/components/AchInput/AchInput.tsx b/packages/lib/src/components/Ach/components/AchInput/AchInput.tsx index 06761b6cdc..8454915d85 100644 --- a/packages/lib/src/components/Ach/components/AchInput/AchInput.tsx +++ b/packages/lib/src/components/Ach/components/AchInput/AchInput.tsx @@ -3,7 +3,6 @@ import { useState, useEffect, useRef } from 'preact/hooks'; import classNames from 'classnames'; import AchSecuredFields from './components/AchSecuredFields'; import SecuredFieldsProvider from '../../../internal/SecuredFields/SFP/SecuredFieldsProvider'; -import Address from '../../../internal/Address'; import Field from '../../../internal/FormFields/Field'; import LoadingWrapper from '../../../internal/LoadingWrapper/LoadingWrapper'; import defaultProps from './defaultProps'; @@ -15,6 +14,7 @@ import StoreDetails from '../../../internal/StoreDetails'; import InputText from '../../../internal/FormFields/InputText'; import FormInstruction from '../../../internal/FormInstruction'; import { ComponentMethodsRef } from '../../../internal/UIElement/types'; +import RadioGroup from '../../../internal/FormFields/RadioGroup'; function validateHolderName(holderName, holderNameRequired = false) { if (holderNameRequired) { @@ -32,11 +32,12 @@ function AchInput(props: ACHInputProps) { const [valid, setValid] = useState({ ...(props.holderNameRequired && { holderName: holderNameIsValid }) }); + const [data, setData] = useState({ + bankAccountType: 'checking', ...(props.hasHolderName && { holderName: props.holderName || props.data.holderName }) }); - const [billingAddress, setBillingAddress] = useState(props.billingAddressRequired ? props.data.billingAddress : null); const [isSfpValid, setIsSfpValid] = useState(false); const [focusedElement, setFocusedElement] = useState(''); const [storePaymentMethod, setStorePaymentMethod] = useState(false); @@ -53,11 +54,6 @@ function AchInput(props: ACHInputProps) { } }; - const handleAddress = address => { - setBillingAddress({ ...billingAddress, ...address.data }); - setValid({ ...valid, billingAddress: address.isValid }); - }; - const handleHolderName = e => { const holderName = e.target.value; @@ -66,6 +62,12 @@ function AchInput(props: ACHInputProps) { setValid({ ...valid, holderName: props.holderNameRequired ? validateHolderName(holderName, props.holderNameRequired) : true }); }; + const handleBankAccountType = e => { + const bankAccountType = e.target.value; + + setData({ ...data, bankAccountType }); + }; + const handleSecuredFieldsChange = newState => { const sfState = newState; @@ -84,10 +86,6 @@ function AchInput(props: ACHInputProps) { // Refs const sfp = useRef(null); - const billingAddressRef = useRef(null); - const setAddressRef = ref => { - billingAddressRef.current = ref; - }; const [status, setStatus] = useState('ready'); @@ -106,9 +104,6 @@ function AchInput(props: ACHInputProps) { if (props.holderNameRequired && !valid.holderName) { setErrors({ ...errors, holderName: true }); } - - // Validate Address - if (billingAddressRef.current) billingAddressRef.current.showValidation(); }; achRef.current.setStatus = setStatus; @@ -124,14 +119,13 @@ function AchInput(props: ACHInputProps) { // Run when state.data, -errors or -valid change useEffect(() => { - // Validate whole component i.e holderName + securedFields + address + // Validate whole component i.e holderName + securedFields const holderNameValid = validateHolderName(data.holderName, props.holderNameRequired); const sfpValid = isSfpValid; - const billingAddressValid = props.billingAddressRequired ? Boolean(valid.billingAddress) : true; - const isValid = sfpValid && holderNameValid && billingAddressValid; + const isValid = sfpValid && holderNameValid; - props.onChange({ data, isValid, billingAddress, storePaymentMethod }); + props.onChange({ data, isValid, storePaymentMethod }); }, [data, valid, errors, storePaymentMethod]); return ( @@ -150,6 +144,20 @@ function AchInput(props: ACHInputProps) {
{
{i18n.get('ach.bankAccount')}
} + + + + {props.hasHolderName && (
- {props.billingAddressRequired && ( -
- )} - {props.enableStoreDetails && } diff --git a/packages/lib/src/components/Ach/components/AchInput/types.ts b/packages/lib/src/components/Ach/components/AchInput/types.ts index 7682ef68bb..431fe82a4e 100644 --- a/packages/lib/src/components/Ach/components/AchInput/types.ts +++ b/packages/lib/src/components/Ach/components/AchInput/types.ts @@ -5,21 +5,19 @@ import { Resources } from '../../../../core/Context/Resources'; export interface ACHInputStateValid { holderName?: boolean; - billingAddress?: boolean; encryptedBankAccountNumber?: boolean; encryptedBankLocationId?: boolean; } export interface ACHInputStateError { holderName?: boolean; - billingAddress?: boolean; encryptedBankAccountNumber?: boolean; encryptedBankLocationId?: boolean; } export interface ACHInputDataState { + bankAccountType?: 'savings' | 'checking'; holderName?: string; - billingAddress?: object; } type PlaceholderKeys = 'holderName' | 'bankAccountNumber' | 'bankLocationId'; @@ -28,9 +26,6 @@ export type Placeholders = Partial>; export interface ACHInputProps { autoFocus?: boolean; - billingAddressAllowedCountries?: string[]; - billingAddressRequired?: boolean; - billingAddressRequiredFields?: string[]; clientKey?: string; data?: ACHInputDataState; enableStoreDetails: boolean; diff --git a/packages/lib/src/components/Ach/types.ts b/packages/lib/src/components/Ach/types.ts index 2842758003..6ffbd71b02 100644 --- a/packages/lib/src/components/Ach/types.ts +++ b/packages/lib/src/components/Ach/types.ts @@ -1,6 +1,5 @@ import { Placeholders } from './components/AchInput/types'; import { UIElementProps } from '../internal/UIElement/types'; -import { AddressData } from '../../types/global-types'; export interface AchConfiguration extends UIElementProps { storedPaymentMethodId?: string; @@ -15,6 +14,5 @@ export interface AchConfiguration extends UIElementProps { */ data?: { holderName?: string; - billingAddress?: Partial; }; } diff --git a/packages/lib/src/components/BacsDD/BacsDD.tsx b/packages/lib/src/components/BacsDD/BacsDD.tsx index 799160f46d..8ba7ad28df 100644 --- a/packages/lib/src/components/BacsDD/BacsDD.tsx +++ b/packages/lib/src/components/BacsDD/BacsDD.tsx @@ -42,6 +42,8 @@ class BacsElement extends UIElement { icon={this.icon} url={this.props.url} paymentMethodType={this.props.paymentMethodType} + onActionHandled={this.onActionHandled} + // originalAction={this.props.originalAction} /> ) : ( { const { i18n } = useCoreContext(); const getImage = useImage(); - const { url, paymentMethodType } = props; return ( ); diff --git a/packages/lib/src/components/BankTransfer/BankTransfer.tsx b/packages/lib/src/components/BankTransfer/BankTransfer.tsx index 5d94c49001..8f4458cca2 100644 --- a/packages/lib/src/components/BankTransfer/BankTransfer.tsx +++ b/packages/lib/src/components/BankTransfer/BankTransfer.tsx @@ -46,7 +46,7 @@ export class BankTransferElement extends UIElement { if (this.props.reference) { return ( - + ); } diff --git a/packages/lib/src/components/BankTransfer/components/BankTransferResult/BankTransferResult.tsx b/packages/lib/src/components/BankTransfer/components/BankTransferResult/BankTransferResult.tsx index 93606273d7..6f8a124f71 100644 --- a/packages/lib/src/components/BankTransfer/components/BankTransferResult/BankTransferResult.tsx +++ b/packages/lib/src/components/BankTransfer/components/BankTransferResult/BankTransferResult.tsx @@ -3,18 +3,17 @@ import Voucher from '../../../internal/Voucher'; import { useCoreContext } from '../../../../core/Context/CoreProvider'; import useImage from '../../../../core/Context/useImage'; +import { extractCommonPropsForVoucher } from '../../../internal/Voucher/utils'; export default function BankTransferResult(props) { - const { reference, totalAmount, paymentMethodType } = props; + const { reference } = props; const { i18n } = useCoreContext(); const getImage = useImage(); return ( { countdownTime={config.COUNTDOWN_MINUTES} throttleTime={config.THROTTLE_TIME} throttleInterval={config.THROTTLE_INTERVAL} - onActionHandled={this.props.onActionHandled} + onActionHandled={this.onActionHandled} /> diff --git a/packages/lib/src/components/Boleto/Boleto.tsx b/packages/lib/src/components/Boleto/Boleto.tsx index 9a53306c14..08a1f07be7 100644 --- a/packages/lib/src/components/Boleto/Boleto.tsx +++ b/packages/lib/src/components/Boleto/Boleto.tsx @@ -47,7 +47,7 @@ export class BoletoElement extends UIElement { return ( {this.props.reference ? ( - + ) : ( { const { i18n, loadingContext } = useCoreContext(); const getImage = useImage(); - const { reference, expiresAt, totalAmount, paymentMethodType, downloadUrl } = props; + const { reference, expiresAt, downloadUrl } = props; const barcodeReference = reference.replace(/[^\d]/g, '').replace(/^(\d{4})(\d{5})\d{1}(\d{10})\d{1}(\d{10})\d{1}(\d{15})$/, '$1$5$2$3$4'); const barcodeUrl = `${loadingContext}barcode.shtml?data=${barcodeReference}&barcodeType=BT_Int2of5A&fileType=png`; + const paymentMethodType = 'boletobancario'; // overwrite the bank specific type of boleto, e.g. 'boletobancario_santander', to a more generic form + return ( { this.componentRef = ref; }} {...this.props} + onActionHandled={this.onActionHandled} /> ) : ( { - const { reference, expiresAt, instructionsUrl, shopperName, merchantName, totalAmount, paymentMethodType } = props; + const { expiresAt, instructionsUrl, shopperName, merchantName } = props; const { i18n } = useCoreContext(); const getImage = useImage(); return ( void; } diff --git a/packages/lib/src/components/Dragonpay/Dragonpay.tsx b/packages/lib/src/components/Dragonpay/Dragonpay.tsx index ffa7e82856..0d127d9614 100644 --- a/packages/lib/src/components/Dragonpay/Dragonpay.tsx +++ b/packages/lib/src/components/Dragonpay/Dragonpay.tsx @@ -53,6 +53,7 @@ export class DragonpayElement extends UIElement { }} icon={this.icon} {...this.props} + onActionHandled={this.onActionHandled} /> ) : ( void; } diff --git a/packages/lib/src/components/Econtext/Econtext.tsx b/packages/lib/src/components/Econtext/Econtext.tsx index 9b6ee04d41..15153b3c22 100644 --- a/packages/lib/src/components/Econtext/Econtext.tsx +++ b/packages/lib/src/components/Econtext/Econtext.tsx @@ -48,6 +48,7 @@ export class EcontextElement extends UIElement { this.componentRef = ref; }} {...this.props} + onActionHandled={this.onActionHandled} /> ) : ( { - const { reference, totalAmount, expiresAt, paymentMethodType, maskedTelephoneNumber, instructionsUrl, collectionInstitutionNumber } = props; + const { expiresAt, maskedTelephoneNumber, instructionsUrl, collectionInstitutionNumber } = props; const { i18n } = useCoreContext(); const getImage = useImage(); return ( void; } export interface EcontextInputSchema { diff --git a/packages/lib/src/components/Klarna/KlarnaPayments.tsx b/packages/lib/src/components/Klarna/KlarnaPayments.tsx index 7969260806..d692a08299 100644 --- a/packages/lib/src/components/Klarna/KlarnaPayments.tsx +++ b/packages/lib/src/components/Klarna/KlarnaPayments.tsx @@ -64,6 +64,7 @@ class KlarnaPayments extends UIElement { onError={this.props.onError} payButton={this.payButton} onLoaded={this.onLoaded} + onActionHandled={this.onActionHandled} /> ); diff --git a/packages/lib/src/components/Klarna/components/KlarnaContainer/KlarnaContainer.tsx b/packages/lib/src/components/Klarna/components/KlarnaContainer/KlarnaContainer.tsx index 99b0b12bfc..19cdd04089 100644 --- a/packages/lib/src/components/Klarna/components/KlarnaContainer/KlarnaContainer.tsx +++ b/packages/lib/src/components/Klarna/components/KlarnaContainer/KlarnaContainer.tsx @@ -22,7 +22,10 @@ export function KlarnaContainer(props) { payButton={props.payButton} onComplete={props.onComplete} onError={props.onError} - onLoaded={props.onLoaded} + onLoaded={() => { + props.onActionHandled?.({ componentType: props.type, actionDescription: 'sdk-loaded', originalAction: action }); + props.onLoaded(); + }} /> ); } diff --git a/packages/lib/src/components/MBWay/MBWay.tsx b/packages/lib/src/components/MBWay/MBWay.tsx index 3a8b8c25a8..3575aeea5a 100644 --- a/packages/lib/src/components/MBWay/MBWay.tsx +++ b/packages/lib/src/components/MBWay/MBWay.tsx @@ -68,7 +68,7 @@ export class MBWayElement extends UIElement { countdownTime={config.COUNTDOWN_MINUTES} throttleTime={config.THROTTLE_TIME} throttleInterval={config.THROTTLE_INTERVAL} - onActionHandled={this.props.onActionHandled} + onActionHandled={this.onActionHandled} /> diff --git a/packages/lib/src/components/Multibanco/Multibanco.tsx b/packages/lib/src/components/Multibanco/Multibanco.tsx index 6952f9342e..f99b85b56b 100644 --- a/packages/lib/src/components/Multibanco/Multibanco.tsx +++ b/packages/lib/src/components/Multibanco/Multibanco.tsx @@ -39,7 +39,7 @@ export class MultibancoElement extends UIElement { if (this.props.reference) { return ( - + ); } diff --git a/packages/lib/src/components/Multibanco/components/MultibancoVoucherResult/MultibancoVoucherResult.tsx b/packages/lib/src/components/Multibanco/components/MultibancoVoucherResult/MultibancoVoucherResult.tsx index 8fb0d4f773..f02a5e5df0 100644 --- a/packages/lib/src/components/Multibanco/components/MultibancoVoucherResult/MultibancoVoucherResult.tsx +++ b/packages/lib/src/components/Multibanco/components/MultibancoVoucherResult/MultibancoVoucherResult.tsx @@ -5,11 +5,12 @@ import { useCoreContext } from '../../../../core/Context/CoreProvider'; import { MultibancoVoucherResultProps } from '../../types'; import { VoucherDetail } from '../../../internal/Voucher/types'; import useImage from '../../../../core/Context/useImage'; +import { extractCommonPropsForVoucher } from '../../../internal/Voucher/utils'; const MultibancoVoucherResult = (props: MultibancoVoucherResultProps) => { const { i18n } = useCoreContext(); const getImage = useImage(); - const { entity, reference, expiresAt, merchantReference, totalAmount, paymentMethodType, downloadUrl } = props; + const { entity, expiresAt, merchantReference, downloadUrl } = props; const voucherDetails: VoucherDetail[] = [ ...(entity ? [{ label: i18n.get('voucher.entity'), value: entity }] : []), @@ -19,14 +20,10 @@ const MultibancoVoucherResult = (props: MultibancoVoucherResultProps) => { return ( ); diff --git a/packages/lib/src/components/Multibanco/types.ts b/packages/lib/src/components/Multibanco/types.ts index 3c94e266d1..3202c05c18 100644 --- a/packages/lib/src/components/Multibanco/types.ts +++ b/packages/lib/src/components/Multibanco/types.ts @@ -1,4 +1,4 @@ -import { PaymentAmount } from '../../types/global-types'; +import { ActionHandledReturnObject, PaymentAmount } from '../../types/global-types'; export interface MultibancoVoucherResultProps { entity?: string; @@ -9,4 +9,5 @@ export interface MultibancoVoucherResultProps { paymentMethodType?: string; downloadUrl?: string; ref?: any; + onActionHandled?: (rtnObj: ActionHandledReturnObject) => void; } diff --git a/packages/lib/src/components/Oxxo/Oxxo.tsx b/packages/lib/src/components/Oxxo/Oxxo.tsx index 8664c96348..5bcb04405f 100644 --- a/packages/lib/src/components/Oxxo/Oxxo.tsx +++ b/packages/lib/src/components/Oxxo/Oxxo.tsx @@ -32,7 +32,7 @@ export class OxxoElement extends UIElement { return ( {this.props.reference ? ( - + ) : ( this.props.showPayButton && this.payButton({ diff --git a/packages/lib/src/components/Oxxo/components/OxxoVoucherResult/OxxoVoucherResult.tsx b/packages/lib/src/components/Oxxo/components/OxxoVoucherResult/OxxoVoucherResult.tsx index c47db73004..122ee33ecc 100644 --- a/packages/lib/src/components/Oxxo/components/OxxoVoucherResult/OxxoVoucherResult.tsx +++ b/packages/lib/src/components/Oxxo/components/OxxoVoucherResult/OxxoVoucherResult.tsx @@ -6,11 +6,12 @@ import { useCoreContext } from '../../../../core/Context/CoreProvider'; import { OxxoVoucherResultProps } from '../../types'; import './OxxoVoucherResult.scss'; import useImage from '../../../../core/Context/useImage'; +import { extractCommonPropsForVoucher } from '../../../internal/Voucher/utils'; const OxxoVoucherResult = (props: OxxoVoucherResultProps) => { const { i18n, loadingContext } = useCoreContext(); const getImage = useImage(); - const { alternativeReference, reference, expiresAt, merchantReference, totalAmount, paymentMethodType, downloadUrl } = props; + const { alternativeReference, reference, expiresAt, merchantReference, downloadUrl } = props; const barcodeUrl = `${loadingContext}barcode.shtml?data=${reference}&barcodeType=BT_Code128C&fileType=png`; const voucherDetails: VoucherDetail[] = [ @@ -42,14 +43,10 @@ const OxxoVoucherResult = (props: OxxoVoucherResultProps) => { return ( ); diff --git a/packages/lib/src/components/Oxxo/types.ts b/packages/lib/src/components/Oxxo/types.ts index f8ed50eaac..5fa8daa487 100644 --- a/packages/lib/src/components/Oxxo/types.ts +++ b/packages/lib/src/components/Oxxo/types.ts @@ -1,4 +1,4 @@ -import { PaymentAmount } from '../../types/global-types'; +import { ActionHandledReturnObject, PaymentAmount } from '../../types/global-types'; export interface OxxoVoucherResultProps { alternativeReference?: string; @@ -9,4 +9,5 @@ export interface OxxoVoucherResultProps { paymentMethodType?: string; downloadUrl?: string; ref?: any; + onActionHandled?: (rtnObj: ActionHandledReturnObject) => void; } diff --git a/packages/lib/src/components/PayPal/Paypal.tsx b/packages/lib/src/components/PayPal/Paypal.tsx index 496723f801..6718ac8112 100644 --- a/packages/lib/src/components/PayPal/Paypal.tsx +++ b/packages/lib/src/components/PayPal/Paypal.tsx @@ -98,6 +98,7 @@ class PaypalElement extends UIElement { } if (action.sdkData && action.sdkData.token) { + this.onActionHandled({ componentType: this.type, actionDescription: 'sdk-loaded', originalAction: action }); this.handleResolve(action.sdkData.token); } else { this.handleReject(ERRORS.NO_TOKEN_PROVIDED); diff --git a/packages/lib/src/components/Redirect/Redirect.tsx b/packages/lib/src/components/Redirect/Redirect.tsx index daab945a65..8abe8425b6 100644 --- a/packages/lib/src/components/Redirect/Redirect.tsx +++ b/packages/lib/src/components/Redirect/Redirect.tsx @@ -33,7 +33,7 @@ class RedirectElement extends UIElement { render() { if (this.props.url && this.props.method) { - return ; + return ; } if (this.props.showPayButton) { diff --git a/packages/lib/src/components/Redirect/components/RedirectShopper/RedirectShopper.tsx b/packages/lib/src/components/Redirect/components/RedirectShopper/RedirectShopper.tsx index c9c0643a09..b01693e8ce 100644 --- a/packages/lib/src/components/Redirect/components/RedirectShopper/RedirectShopper.tsx +++ b/packages/lib/src/components/Redirect/components/RedirectShopper/RedirectShopper.tsx @@ -1,5 +1,6 @@ import { Component, h } from 'preact'; import detectInIframeInSameOrigin from '../../../../utils/detectInIframeInSameOrigin'; +import { ActionHandledReturnObject } from '../../../../types/global-types'; interface RedirectShopperProps { beforeRedirect: (resolve, reject, url) => Promise; @@ -7,6 +8,8 @@ interface RedirectShopperProps { method: 'GET' | 'POST'; data?: any; redirectFromTopWhenInIframe?: boolean; + paymentMethodType?: string; + onActionHandled?: (rtnObj: ActionHandledReturnObject) => void; } class RedirectShopper extends Component { @@ -18,6 +21,13 @@ class RedirectShopper extends Component { componentDidMount() { const doRedirect = () => { + // call callback + this.props.onActionHandled?.({ + componentType: this.props.paymentMethodType, + actionDescription: 'performing-redirect' + }); + + // perform redirect if (this.postForm) { this.postForm.submit(); } else { diff --git a/packages/lib/src/components/ThreeDS2/ThreeDS2Challenge.tsx b/packages/lib/src/components/ThreeDS2/ThreeDS2Challenge.tsx index ed90c00b77..c336c299c3 100644 --- a/packages/lib/src/components/ThreeDS2/ThreeDS2Challenge.tsx +++ b/packages/lib/src/components/ThreeDS2/ThreeDS2Challenge.tsx @@ -1,15 +1,16 @@ import { h } from 'preact'; import UIElement from '../internal/UIElement/UIElement'; import PrepareChallenge from './components/Challenge'; -import { DEFAULT_CHALLENGE_WINDOW_SIZE, THREEDS2_CHALLENGE, THREEDS2_CHALLENGE_ERROR, THREEDS2_ERROR } from './constants'; +import { DEFAULT_CHALLENGE_WINDOW_SIZE, THREEDS2_CHALLENGE, THREEDS2_CHALLENGE_ERROR, THREEDS2_ERROR, THREEDS2_FULL } from './constants'; import { existy } from '../../utils/commonUtils'; import { hasOwnProperty } from '../../utils/hasOwnProperty'; import { TxVariants } from '../tx-variants'; import { ThreeDS2ChallengeConfiguration } from './types'; import AdyenCheckoutError, { API_ERROR } from '../../core/Errors/AdyenCheckoutError'; -import { ANALYTICS_API_ERROR, Analytics3DS2Errors, ANALYTICS_RENDERED_STR } from '../../core/Analytics/constants'; +import { ANALYTICS_API_ERROR, Analytics3DS2Errors, ANALYTICS_RENDERED_STR, Analytics3DS2Events } from '../../core/Analytics/constants'; import { SendAnalyticsObject } from '../../core/Analytics/types'; import { CoreProvider } from '../../core/Context/CoreProvider'; +import { ActionHandledReturnObject } from '../../types/global-types'; class ThreeDS2Challenge extends UIElement { public static type = TxVariants.threeDS2Challenge; @@ -26,6 +27,16 @@ class ThreeDS2Challenge extends UIElement { super.submitAnalytics(aObj); }; + protected onActionHandled = (rtnObj: ActionHandledReturnObject) => { + this.submitAnalytics({ + type: THREEDS2_FULL, + message: rtnObj.actionDescription, + subtype: Analytics3DS2Events.CHALLENGE_IFRAME_LOADED + }); + + super.onActionHandled(rtnObj); + }; + onComplete(state) { /** * Equals a call to onAdditionalDetails (as set in actionTypes.ts) for the regular, "native" flow. @@ -64,6 +75,7 @@ class ThreeDS2Challenge extends UIElement { onComplete={this.onComplete} onSubmitAnalytics={this.submitAnalytics} isMDFlow={this.props.paymentData.length < 15} + onActionHandled={this.onActionHandled} /> ); diff --git a/packages/lib/src/components/ThreeDS2/ThreeDS2DeviceFingerprint.tsx b/packages/lib/src/components/ThreeDS2/ThreeDS2DeviceFingerprint.tsx index 52d8eb1b4d..cc42630db7 100644 --- a/packages/lib/src/components/ThreeDS2/ThreeDS2DeviceFingerprint.tsx +++ b/packages/lib/src/components/ThreeDS2/ThreeDS2DeviceFingerprint.tsx @@ -6,9 +6,10 @@ import { existy } from '../../utils/commonUtils'; import { TxVariants } from '../tx-variants'; import { ThreeDS2DeviceFingerprintConfiguration } from './types'; import AdyenCheckoutError, { API_ERROR } from '../../core/Errors/AdyenCheckoutError'; -import { ANALYTICS_API_ERROR, Analytics3DS2Errors, ANALYTICS_RENDERED_STR } from '../../core/Analytics/constants'; +import { ANALYTICS_API_ERROR, Analytics3DS2Errors, ANALYTICS_RENDERED_STR, Analytics3DS2Events } from '../../core/Analytics/constants'; import { SendAnalyticsObject } from '../../core/Analytics/types'; -import { THREEDS2_ERROR, THREEDS2_FINGERPRINT, THREEDS2_FINGERPRINT_ERROR } from './constants'; +import { THREEDS2_ERROR, THREEDS2_FINGERPRINT, THREEDS2_FINGERPRINT_ERROR, THREEDS2_FULL } from './constants'; +import { ActionHandledReturnObject } from '../../types/global-types'; class ThreeDS2DeviceFingerprint extends UIElement { public static type = TxVariants.threeDS2Fingerprint; @@ -26,6 +27,15 @@ class ThreeDS2DeviceFingerprint extends UIElement { + this.submitAnalytics({ + type: THREEDS2_FULL, + message: rtnObj.actionDescription, + subtype: Analytics3DS2Events.FINGERPRINT_IFRAME_LOADED + }); + super.onActionHandled(rtnObj); + }; + onComplete(state) { super.onComplete(state); this.unmount(); // re. fixing issue around back to back fingerprinting calls @@ -60,6 +70,7 @@ class ThreeDS2DeviceFingerprint extends UIElement ); } diff --git a/packages/lib/src/components/ThreeDS2/components/Challenge/DoChallenge3DS2.tsx b/packages/lib/src/components/ThreeDS2/components/Challenge/DoChallenge3DS2.tsx index 48893a6ce6..e913e3c273 100644 --- a/packages/lib/src/components/ThreeDS2/components/Challenge/DoChallenge3DS2.tsx +++ b/packages/lib/src/components/ThreeDS2/components/Challenge/DoChallenge3DS2.tsx @@ -32,7 +32,7 @@ class DoChallenge3DS2 extends Component {}, onError: () => {}, - onActionHandled: () => {}, isMDFlow: false }; @@ -52,16 +50,6 @@ class PrepareChallenge3DS2 extends Component { - this.props.onSubmitAnalytics({ - type: THREEDS2_FULL, - message: rtnObj.actionDescription, - subtype: Analytics3DS2Events.CHALLENGE_IFRAME_LOADED - }); - - this.props.onActionHandled(rtnObj); - }; - public onFormSubmit = (msg: string) => { this.props.onSubmitAnalytics({ type: THREEDS2_FULL, @@ -356,7 +344,7 @@ class PrepareChallenge3DS2 extends Component ); diff --git a/packages/lib/src/components/ThreeDS2/components/DeviceFingerprint/DoFingerprint3DS2.tsx b/packages/lib/src/components/ThreeDS2/components/DeviceFingerprint/DoFingerprint3DS2.tsx index 48dc0d6d96..0d9c1e816b 100644 --- a/packages/lib/src/components/ThreeDS2/components/DeviceFingerprint/DoFingerprint3DS2.tsx +++ b/packages/lib/src/components/ThreeDS2/components/DeviceFingerprint/DoFingerprint3DS2.tsx @@ -49,7 +49,6 @@ class DoFingerprint3DS2 extends Component { - onActionHandled({ componentType: '3DS2Fingerprint', actionDescription: `${THREEDS2_NUM} fingerprint iframe loaded` }); + onActionHandled?.({ componentType: '3DS2Fingerprint', actionDescription: `${THREEDS2_NUM} fingerprint iframe loaded` }); }} /> {}, paymentData: '', showSpinner: true, - onActionHandled: () => {}, isMDFlow: false }; @@ -50,15 +48,6 @@ class PrepareFingerprint3DS2 extends Component { - this.props.onSubmitAnalytics({ - type: THREEDS2_FULL, - message: rtnObj.actionDescription, - subtype: Analytics3DS2Events.FINGERPRINT_IFRAME_LOADED - }); - this.props.onActionHandled(rtnObj); - }; - public onFormSubmit = (msg: string) => { this.props.onSubmitAnalytics({ type: THREEDS2_FULL, @@ -262,7 +251,7 @@ class PrepareFingerprint3DS2 extends Component ); diff --git a/packages/lib/src/components/ThreeDS2/types.ts b/packages/lib/src/components/ThreeDS2/types.ts index 2e92514695..87b752ab25 100644 --- a/packages/lib/src/components/ThreeDS2/types.ts +++ b/packages/lib/src/components/ThreeDS2/types.ts @@ -12,7 +12,7 @@ interface ThreeDS2Configuration extends UIElementProps { loadingContext?: string; modules?: { analytics: AnalyticsModule }; notificationURL?: string; - onActionHandled: (rtnObj: ActionHandledReturnObject) => void; + onActionHandled?: (rtnObj: ActionHandledReturnObject) => void; onError?: (error: AdyenCheckoutError, element?: UIElement) => void; paymentData?: string; token?: string; diff --git a/packages/lib/src/components/UPI/UPI.tsx b/packages/lib/src/components/UPI/UPI.tsx index f472686ff1..69901fd2a4 100644 --- a/packages/lib/src/components/UPI/UPI.tsx +++ b/packages/lib/src/components/UPI/UPI.tsx @@ -102,7 +102,7 @@ class UPI extends UIElement { onComplete={this.onComplete} introduction={this.props.i18n.get('upi.qrCodeWaitingMessage')} countdownTime={5} - onActionHandled={this.props.onActionHandled} + onActionHandled={this.onActionHandled} /> ); case 'await': @@ -118,7 +118,7 @@ class UPI extends UIElement { countdownTime={5} clientKey={this.props.clientKey} paymentData={this.props.paymentData} - onActionHandled={this.props.onActionHandled} + onActionHandled={this.onActionHandled} onError={this.props.onError} messageText={this.props.i18n.get('upi.vpaWaitingMessage')} awaitText={this.props.i18n.get('await.waitForConfirmation')} diff --git a/packages/lib/src/components/helpers/QRLoaderContainer/QRLoaderContainer.tsx b/packages/lib/src/components/helpers/QRLoaderContainer/QRLoaderContainer.tsx index 7786bd77bd..9fa7928298 100644 --- a/packages/lib/src/components/helpers/QRLoaderContainer/QRLoaderContainer.tsx +++ b/packages/lib/src/components/helpers/QRLoaderContainer/QRLoaderContainer.tsx @@ -13,8 +13,7 @@ class QRLoaderContainer amount: null, paymentData: null, onError: () => {}, - onComplete: () => {}, - onActionHandled: () => {} + onComplete: () => {} }; formatData() { @@ -46,7 +45,7 @@ class QRLoaderContainer onComplete={this.onComplete} countdownTime={this.props.countdownTime} instructions={this.props.instructions} - onActionHandled={this.props.onActionHandled} + onActionHandled={this.onActionHandled} brandName={this.displayName} onSubmitAnalytics={this.submitAnalytics} /> diff --git a/packages/lib/src/components/internal/Await/Await.tsx b/packages/lib/src/components/internal/Await/Await.tsx index 513a653b04..4379696503 100644 --- a/packages/lib/src/components/internal/Await/Await.tsx +++ b/packages/lib/src/components/internal/Await/Await.tsx @@ -79,7 +79,7 @@ function Await(props: AwaitComponentProps) { const { paymentData, clientKey, throttleInterval } = props; if (!hasCalledActionHandled) { - props.onActionHandled({ componentType: props.type, actionDescription: 'polling-started' }); + props.onActionHandled?.({ componentType: props.type, actionDescription: 'polling-started' }); setHasCalledActionHandled(true); } @@ -228,7 +228,6 @@ Await.defaultProps = { countdownTime: 15, onError: () => {}, onComplete: () => {}, - onActionHandled: () => {}, delay: 2000, throttleTime: 60000, throttleInterval: 10000, diff --git a/packages/lib/src/components/internal/Await/types.ts b/packages/lib/src/components/internal/Await/types.ts index f9fa03e7e0..68390cb1c2 100644 --- a/packages/lib/src/components/internal/Await/types.ts +++ b/packages/lib/src/components/internal/Await/types.ts @@ -30,7 +30,7 @@ export interface AwaitComponentProps { messageText: string; awaitText: string; ref: any; - onActionHandled: (rtnObj: ActionHandledReturnObject) => void; + onActionHandled?: (rtnObj: ActionHandledReturnObject) => void; } export interface AwaitConfiguration extends UIElementProps { diff --git a/packages/lib/src/components/internal/FormFields/Field/Field.scss b/packages/lib/src/components/internal/FormFields/Field/Field.scss index 1d41dbf6e5..d129a78c4c 100644 --- a/packages/lib/src/components/internal/FormFields/Field/Field.scss +++ b/packages/lib/src/components/internal/FormFields/Field/Field.scss @@ -9,6 +9,27 @@ display: block; margin-bottom: token(spacer-070); width: 100%; + + &--no-borders { + .adyen-checkout__input-wrapper { + box-shadow: none; + border: none; + background-color: transparent; + + &:active, + &:active:hover, + &:focus-within, + &:focus-within:hover { + box-shadow: none; + border: none; + } + + &:hover { + box-shadow: none; + border: none; + } + } + } } .adyen-checkout__input-wrapper { @@ -85,7 +106,7 @@ top: 0; } -.adyen-checkout__label__text{ +.adyen-checkout__label__text { display: block; font-size: token(text-body-font-size); margin-bottom: token(spacer-020); diff --git a/packages/lib/src/components/internal/FormFields/RadioGroup/RadioGroup.scss b/packages/lib/src/components/internal/FormFields/RadioGroup/RadioGroup.scss index ed9f879d68..8033f69871 100644 --- a/packages/lib/src/components/internal/FormFields/RadioGroup/RadioGroup.scss +++ b/packages/lib/src/components/internal/FormFields/RadioGroup/RadioGroup.scss @@ -90,3 +90,53 @@ .adyen-checkout__radio_group__label.adyen-checkout__radio_group__label--invalid::before { border: token(border-width-s) solid token(color-outline-critical); } + + +.adyen-checkout__radio_group--button { + display: flex; + align-items: flex-start; + flex-wrap: wrap; + gap: token(spacer-070); + align-self: stretch; + width: 100%; + + .adyen-checkout__radio_group__input-wrapper { + display: flex; + flex: 1 0 0; + } + + .adyen-checkout__radio_group__label::after { + position: absolute; + top: calc(50% - token(spacer-030) / 2); + left: calc(token(spacer-060) + 5px); + } + + .adyen-checkout__radio_group__label::before { + position: absolute; + top: calc(50% - token(spacer-070) / 2); + left: calc(token(spacer-060)); + } + + .adyen-checkout__radio_group__label { + padding: token(spacer-060); + padding-left: calc(token(spacer-060) + token(spacer-090)); + width: 100%; + border: token(border-width-s) solid token(color-outline-primary); + border-radius: token(border-radius-m); + background-color: token(color-background-primary); + } + + .adyen-checkout__radio_group__input:checked + .adyen-checkout__radio_group__label { + border-color: token(color-outline-primary-active); + } + + .adyen-checkout__radio_group__input + .adyen-checkout__radio_group__label:hover { + border-color: token(color-outline-primary-active); + } + + .adyen-checkout__radio_group__input:checked:focus + .adyen-checkout__radio_group__label, + .adyen-checkout__radio_group__input:checked:active + .adyen-checkout__radio_group__label { + box-shadow: 0 0 0 0.5px token(color-outline-primary-active); + border-color: token(color-outline-primary-active); + } +} \ No newline at end of file diff --git a/packages/lib/src/components/internal/FormFields/RadioGroup/RadioGroup.tsx b/packages/lib/src/components/internal/FormFields/RadioGroup/RadioGroup.tsx index 9176b3cb54..675c139a5c 100644 --- a/packages/lib/src/components/internal/FormFields/RadioGroup/RadioGroup.tsx +++ b/packages/lib/src/components/internal/FormFields/RadioGroup/RadioGroup.tsx @@ -6,13 +6,17 @@ import { getUniqueId } from '../../../../utils/idGenerator'; import { useCoreContext } from '../../../../core/Context/CoreProvider'; export default function RadioGroup(props: RadioGroupProps) { - const { items, name, onChange, value, isInvalid, uniqueId, ariaLabel } = props; + const { items, name, onChange, value, isInvalid, uniqueId, ariaLabel, style = 'classic' } = props; const { i18n } = useCoreContext(); const uniqueIdBase = uniqueId?.replace(/[0-9]/g, '').substring(0, uniqueId.lastIndexOf('-')); return ( -
+
{items.map(item => { const uniqueId = getUniqueId(uniqueIdBase); return ( diff --git a/packages/lib/src/components/internal/FormFields/RadioGroup/types.ts b/packages/lib/src/components/internal/FormFields/RadioGroup/types.ts index 1db3a02346..47cf7f552d 100644 --- a/packages/lib/src/components/internal/FormFields/RadioGroup/types.ts +++ b/packages/lib/src/components/internal/FormFields/RadioGroup/types.ts @@ -14,4 +14,5 @@ export interface RadioGroupProps extends InputBaseProps { value?: string; uniqueId?: string; ariaLabel?: string; + style?: 'classic' | 'button'; } diff --git a/packages/lib/src/components/internal/QRLoader/QRLoader.tsx b/packages/lib/src/components/internal/QRLoader/QRLoader.tsx index eaf660c187..0a10d5ce92 100644 --- a/packages/lib/src/components/internal/QRLoader/QRLoader.tsx +++ b/packages/lib/src/components/internal/QRLoader/QRLoader.tsx @@ -226,7 +226,10 @@ class QRLoader extends Component { src={qrCodeImage} alt={i18n.get('wechatpay.scanqrcode')} onLoad={() => { - onActionHandled?.({ componentType: this.props.type, actionDescription: 'qr-code-loaded' }); + onActionHandled?.({ + componentType: this.props.type, + actionDescription: 'qr-code-loaded' + }); }} /> diff --git a/packages/lib/src/components/internal/UIElement/UIElement.beforeSubmit.test.tsx b/packages/lib/src/components/internal/UIElement/UIElement.beforeSubmit.test.tsx new file mode 100644 index 0000000000..11b9f840ca --- /dev/null +++ b/packages/lib/src/components/internal/UIElement/UIElement.beforeSubmit.test.tsx @@ -0,0 +1,110 @@ +import { h } from 'preact'; +import UIElement from './UIElement'; + +class MyElement extends UIElement { + public static type = 'myComp'; + + // @ts-ignore it's a test + public elementRef = { + state: { + status: null + }, + setStatus: status => { + this.elementRef.state.status = status; + } + }; + + get isValid() { + return !!this.state.isValid; + } + + render() { + return ''; + } +} + +let onPaymentCompleted; +let onPaymentFailed; + +beforeEach(() => { + onPaymentCompleted = jest.fn(); + onPaymentFailed = jest.fn(); +}); + +describe('Testing beforeSubmit', () => { + test('Because beforeSubmit resolves onPaymentCompleted is called', done => { + const beforeSubmit = jest.fn((data, component, actions) => { + actions.resolve(data); + }); + + const myElement = new MyElement(global.core, { + amount: { value: 0, currency: 'USD' }, + // @ts-ignore it's just a test + session: { configuration: {} }, + beforeSubmit, + onPaymentCompleted + }); + + const paymentResponse = { + resultCode: 'Authorised', + sessionData: 'Ab02b4c0uKS50x...', + sessionResult: 'X3XtfGC9...' + }; + + // @ts-ignore it's a test + myElement.submitUsingSessionsFlow = () => { + return Promise.resolve(paymentResponse); + }; + + myElement.setState({ isValid: true }); + + myElement.submit(); + + // initially submit should lead to UIElement.makePaymentsCall() which sets status to 'loading' + expect(myElement.elementRef.state.status).toEqual('loading'); + + setTimeout(() => { + expect(beforeSubmit).toHaveBeenCalled(); + + // state.status doesn't get reset + expect(myElement.elementRef.state.status).toEqual('loading'); + + expect(onPaymentCompleted).toHaveBeenCalledWith(paymentResponse, myElement.elementRef); + + done(); + }, 0); + }); + + test('Because beforeSubmit rejects the status gets set back to "ready" but onPaymentFailed does not get called', done => { + const beforeSubmit = jest.fn((data, component, actions) => { + actions.reject(); + }); + + const myElement = new MyElement(global.core, { + amount: { value: 0, currency: 'USD' }, + // @ts-ignore it's just a test + session: { configuration: {} }, + beforeSubmit, + onPaymentCompleted, + onPaymentFailed + }); + + myElement.setState({ isValid: true }); + + myElement.submit(); + + // initially submit should lead to UIElement.makePaymentsCall() which sets status to 'loading' + expect(myElement.elementRef.state.status).toEqual('loading'); + + setTimeout(() => { + expect(beforeSubmit).toHaveBeenCalled(); + + expect(myElement.elementRef.state.status).toEqual('ready'); + + expect(onPaymentCompleted).not.toHaveBeenCalled(); + expect(onPaymentFailed).not.toHaveBeenCalled(); + + done(); + }, 0); + }); +}); diff --git a/packages/lib/src/components/internal/UIElement/UIElement.tsx b/packages/lib/src/components/internal/UIElement/UIElement.tsx index fc22abdfa5..7fbdeee913 100644 --- a/packages/lib/src/components/internal/UIElement/UIElement.tsx +++ b/packages/lib/src/components/internal/UIElement/UIElement.tsx @@ -12,6 +12,7 @@ import type { CoreConfiguration, ICore, AdditionalDetailsData } from '../../../c import type { ComponentMethodsRef, PayButtonFunctionProps, UIElementProps, UIElementStatus } from './types'; import type { CheckoutSessionDetailsResponse, CheckoutSessionPaymentResponse } from '../../../core/CheckoutSession/types'; import type { + ActionHandledReturnObject, CheckoutAdvancedFlowResponse, Order, PaymentAction, @@ -23,6 +24,7 @@ import type { } from '../../../types/global-types'; import type { IDropin } from '../../Dropin/types'; import type { NewableComponent } from '../../../core/core.registry'; +import CancelError from '../../../core/Errors/CancelError'; import './UIElement.scss'; @@ -64,6 +66,7 @@ export abstract class UIElement

exten this.storeElementRefOnCore(this.props); this.onEnterKeyPressed = this.onEnterKeyPressed.bind(this); + this.onActionHandled = this.onActionHandled.bind(this); } protected override buildElementProps(componentProps?: P) { @@ -175,7 +178,17 @@ export abstract class UIElement

exten return; } - this.makePaymentsCall().then(sanitizeResponse).then(verifyPaymentDidNotFail).then(this.handleResponse).catch(this.handleFailedResult); + this.makePaymentsCall() + .then(sanitizeResponse) + .then(verifyPaymentDidNotFail) + .then(this.handleResponse) + .catch((e: PaymentResponseData | Error) => { + if (e instanceof CancelError) { + this.setElementStatus('ready'); + return; + } + this.handleFailedResult(e as PaymentResponseData); + }); } protected makePaymentsCall(): Promise { @@ -190,7 +203,7 @@ export abstract class UIElement

exten ? new Promise((resolve, reject) => this.props.beforeSubmit(this.data, this.elementRef, { resolve, - reject + reject: () => reject(new CancelError('beforeSubmitRejected')) }) ) : Promise.resolve(this.data); @@ -324,6 +337,10 @@ export abstract class UIElement

exten return null; } + protected onActionHandled(actionHandledObj: ActionHandledReturnObject) { + this.props?.onActionHandled?.({ originalAction: this.props.originalAction, ...actionHandledObj }); + } + protected handleOrder = (response: PaymentResponseData): void => { const { order } = response; @@ -362,7 +379,7 @@ export abstract class UIElement

exten }; /** - * Handles a session /payments or /payments/details response. + * Handles a /payments or /payments/details response. * The component will handle automatically actions, orders, and final results. * * @param rawResponse - diff --git a/packages/lib/src/components/internal/UIElement/types.ts b/packages/lib/src/components/internal/UIElement/types.ts index 1833a3c844..7f9728759e 100644 --- a/packages/lib/src/components/internal/UIElement/types.ts +++ b/packages/lib/src/components/internal/UIElement/types.ts @@ -101,6 +101,11 @@ export type UIElementProps = BaseElementProps & * @internal */ paymentMethodType?: string; + + /** + * Reference to the action object found in a /payments response. This, in most cases, is passed on to the onActionHandled callback + */ + originalAction?: PaymentAction; }; export type UIElementStatus = 'ready' | 'loading' | 'error' | 'success'; diff --git a/packages/lib/src/components/internal/Voucher/Voucher.test.tsx b/packages/lib/src/components/internal/Voucher/Voucher.test.tsx index 630f87cd1b..55532e03a9 100644 --- a/packages/lib/src/components/internal/Voucher/Voucher.test.tsx +++ b/packages/lib/src/components/internal/Voucher/Voucher.test.tsx @@ -2,13 +2,16 @@ import { mount } from 'enzyme'; import { h } from 'preact'; import Voucher from './Voucher'; import { CoreProvider } from '../../../core/Context/CoreProvider'; +import { PaymentAction } from '../../../types/global-types'; const outputDetails = { paymentMethodType: 'type', introduction: 'Introduction Text', amount: '100', instructionsUrl: 'http://...', - reference: '123456' + reference: '123456', + onActionHandled: jest.fn(() => {}), + originalAction: { type: 'voucher' } as PaymentAction }; describe('Voucher', () => { @@ -22,6 +25,11 @@ describe('Voucher', () => { expect(wrapper.find('.adyen-checkout__voucher-result__amount').text()).toBe('100'); expect(wrapper.find('.adyen-checkout-link--voucher-result-instructions').length).toBe(1); expect(wrapper.find('.adyen-checkout__voucher-result__code > span').text()).toBe('123456'); + + expect(outputDetails.onActionHandled).toBeCalledWith({ + componentType: 'type', + actionDescription: 'voucher-presented' + }); }); test('Render VoucherDetails', () => { diff --git a/packages/lib/src/components/internal/Voucher/Voucher.tsx b/packages/lib/src/components/internal/Voucher/Voucher.tsx index 23ec3e29e1..16ff7bb142 100644 --- a/packages/lib/src/components/internal/Voucher/Voucher.tsx +++ b/packages/lib/src/components/internal/Voucher/Voucher.tsx @@ -13,6 +13,8 @@ export default function Voucher({ voucherDetails = [], className = '', ...props const { i18n } = useCoreContext(); const getImage = useImage(); + props.onActionHandled?.({ componentType: props.paymentMethodType, actionDescription: 'voucher-presented' }); + return (

diff --git a/packages/lib/src/components/internal/Voucher/types.ts b/packages/lib/src/components/internal/Voucher/types.ts index b83e8db32f..dc31951814 100644 --- a/packages/lib/src/components/internal/Voucher/types.ts +++ b/packages/lib/src/components/internal/Voucher/types.ts @@ -1,4 +1,5 @@ import { UIElementProps } from '../UIElement/types'; +import { ActionHandledReturnObject } from '../../../types/global-types'; export interface VoucherDetail { label: string; @@ -47,6 +48,9 @@ export interface VoucherProps { /** Show/Hide a button to copy the payment reference. It will only show if a reference is available. */ copyBtn?: boolean; + + // callback, at Checkout level + onActionHandled?: (rtnObj: ActionHandledReturnObject) => void; } export interface VoucherConfiguration extends UIElementProps { @@ -54,3 +58,5 @@ export interface VoucherConfiguration extends UIElementProps { url?: string; paymentMethodType?: string; } + +export type CommonVoucherProps = Pick; diff --git a/packages/lib/src/components/internal/Voucher/utils.ts b/packages/lib/src/components/internal/Voucher/utils.ts new file mode 100644 index 0000000000..c160f18a11 --- /dev/null +++ b/packages/lib/src/components/internal/Voucher/utils.ts @@ -0,0 +1,17 @@ +import { CommonVoucherProps } from './types'; + +export const extractCommonPropsForVoucher = ({ props, i18n, introKey, getImage }): CommonVoucherProps => { + const { paymentMethodType, onActionHandled, totalAmount, reference } = props; + + return { + // occur in all vouchers + paymentMethodType, + introduction: i18n.get(introKey), + imageUrl: getImage(paymentMethodType), + onActionHandled, + // occurs in 7/8 vouchers + ...(totalAmount ? { amount: i18n.amount(totalAmount.value, totalAmount.currency) } : {}), + // occurs in 6/8 vouchers + ...(reference ? { reference } : {}) + }; +}; diff --git a/packages/lib/src/core/Errors/CancelError.ts b/packages/lib/src/core/Errors/CancelError.ts new file mode 100644 index 0000000000..9caefa5379 --- /dev/null +++ b/packages/lib/src/core/Errors/CancelError.ts @@ -0,0 +1,7 @@ +class CancelError extends Error { + constructor(message?: string) { + super(message); + } +} + +export default CancelError; diff --git a/packages/lib/src/core/ProcessResponse/PaymentAction/actionTypes.ts b/packages/lib/src/core/ProcessResponse/PaymentAction/actionTypes.ts index b6a47231d4..ddb9699266 100644 --- a/packages/lib/src/core/ProcessResponse/PaymentAction/actionTypes.ts +++ b/packages/lib/src/core/ProcessResponse/PaymentAction/actionTypes.ts @@ -22,7 +22,8 @@ const getActionHandler = statusType => { ...action, onComplete: props.onAdditionalDetails, onError: props.onError, - statusType + statusType, + originalAction: action }; return createComponent(core, registry, action.paymentMethodType, config); @@ -34,7 +35,8 @@ const actionTypes = { const config = { ...props, ...action, - statusType: 'redirect' + statusType: 'redirect', + originalAction: action }; return createComponent(core, registry, 'redirect', config); diff --git a/packages/lib/src/types.ts b/packages/lib/src/types.ts index 9ea45e38ae..8b7266626e 100644 --- a/packages/lib/src/types.ts +++ b/packages/lib/src/types.ts @@ -2,6 +2,7 @@ export * from './index'; export * from './components/types'; export * from './core/types'; export * from './types/global-types'; +export { CustomTranslations } from './language/types'; export { default as AdyenCheckoutError } from './core/Errors/AdyenCheckoutError'; export { default as UIElement } from './components/internal/UIElement'; diff --git a/packages/lib/src/types/global-types.ts b/packages/lib/src/types/global-types.ts index da6a680352..5e4f759cb6 100644 --- a/packages/lib/src/types/global-types.ts +++ b/packages/lib/src/types/global-types.ts @@ -352,11 +352,29 @@ export type RawPaymentResponse = PaymentResponseData & [key: string]: any; }; -export type ActionDescriptionType = 'qr-code-loaded' | 'polling-started' | '3DS2 fingerprint iframe loaded' | '3DS2 challenge iframe loaded'; +/** + * onActionHandled is called for all actions: + * - qrcode + * - await + * - threeds2 + * - redirect + * - sdk + * - voucher + * - bankTransfer + */ +export type ActionDescriptionType = + | 'qr-code-loaded' + | 'polling-started' + | '3DS2 fingerprint iframe loaded' + | '3DS2 challenge iframe loaded' + | 'performing-redirect' + | 'voucher-presented' + | 'sdk-loaded'; export interface ActionHandledReturnObject { componentType: string; actionDescription: ActionDescriptionType; + originalAction?: PaymentAction; } export interface AnalyticsModule { diff --git a/packages/playground/package.json b/packages/playground/package.json index 9b420b5bfb..87b58bbc0d 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -41,6 +41,6 @@ "whatwg-fetch": "^3.6.2" }, "dependencies": { - "@adyen/adyen-web": "6.3.0" + "@adyen/adyen-web": "6.4.0" } } diff --git a/packages/playground/src/config/commonConfig.js b/packages/playground/src/config/commonConfig.js index b18ea26e0e..0b0f3712fb 100644 --- a/packages/playground/src/config/commonConfig.js +++ b/packages/playground/src/config/commonConfig.js @@ -9,7 +9,7 @@ const merchantAccount = urlParams.merchantAccount; export const shopperLocale = urlParams.shopperLocale || urlParams.shopperlocale || DEFAULT_LOCALE; export const countryCode = urlParams.countryCode || urlParams.countrycode || DEFAULT_COUNTRY; export const currency = getCurrency(countryCode); -export const amountValue = urlParams.amount ?? 85900; +export const amountValue = urlParams.amount ?? 1999; export const shopperReference = 'newshoppert'; export const amount = { currency, diff --git a/packages/playground/src/pages/Dropin/manual.js b/packages/playground/src/pages/Dropin/manual.js index 1d602e3074..0d95ccf9bb 100644 --- a/packages/playground/src/pages/Dropin/manual.js +++ b/packages/playground/src/pages/Dropin/manual.js @@ -12,7 +12,16 @@ import { AmazonPay, Pix, Klarna, - Bancontact + Bancontact, + SepaDirectDebit, + OnlineBankingCZ, + BacsDirectDebit, + BankTransfer, + CashAppPay, + Twint, + BcmcMobile, + Blik, + UPI } from '@adyen/adyen-web'; import '@adyen/adyen-web/styles/adyen.css'; import { getPaymentMethods, makePayment, checkBalance, createOrder, cancelOrder, makeDetailsCall } from '../../services'; @@ -86,7 +95,7 @@ export async function initManual() { console.info(error.name, error.message, error.stack, component); }, onActionHandled: rtnObj => { - console.log('onActionHandled', rtnObj); + console.log('manual::onActionHandled', rtnObj); }, onPaymentMethodsRequest: async (data, { resolve, reject }) => { console.log('onPaymentMethodsRequest', data); @@ -134,7 +143,29 @@ export async function initManual() { } const dropin = new Dropin(checkout, { - paymentMethodComponents: [Card, ApplePay, GooglePay, PayPal, Ach, Affirm, WeChat, Giftcard, AmazonPay, Pix, Bancontact, Klarna], + paymentMethodComponents: [ + Card, + ApplePay, + GooglePay, + PayPal, + Ach, + Affirm, + WeChat, + Giftcard, + AmazonPay, + Pix, + Bancontact, + Klarna, + SepaDirectDebit, + OnlineBankingCZ, + BacsDirectDebit, + BankTransfer, + CashAppPay, + Twint, + BcmcMobile, + Blik, + UPI + ], instantPaymentTypes: ['googlepay', 'applepay'], paymentMethodsConfiguration: { card: { diff --git a/packages/playground/src/pages/Vouchers/Vouchers.js b/packages/playground/src/pages/Vouchers/Vouchers.js index 7023dd59c1..29a6f43147 100644 --- a/packages/playground/src/pages/Vouchers/Vouchers.js +++ b/packages/playground/src/pages/Vouchers/Vouchers.js @@ -1,7 +1,6 @@ import { AdyenCheckout, BacsDirectDebit, Multibanco, Oxxo, Dragonpay, Boleto, Doku, Econtext } from '@adyen/adyen-web'; import '@adyen/adyen-web/styles/adyen.css'; import { shopperLocale, countryCode } from '../../config/commonConfig'; -import { handleChange } from '../../handlers'; import '../../../config/polyfills'; import '../../style.scss'; import '../../utils'; @@ -12,7 +11,9 @@ import './Vouchers.scss'; countryCode, locale: shopperLocale, environment: process.env.__CLIENT_ENV__, - onChange: handleChange + onActionHandled: obj => { + console.log('### Vouchers::onActionHandled:: obj', obj); + } }); window.bacsdd = new BacsDirectDebit(window.checkout, { @@ -67,7 +68,7 @@ import './Vouchers.scss'; street: 'Fake street', houseNumberOrName: '123', city: 'Sao Paulo', - postalCode: '123456', + postalCode: '12345678', stateOrProvince: 'SP' }, shopperEmail: 'paolo@adyen.nl' diff --git a/packages/server/translations/ar.json b/packages/server/translations/ar.json index 7cb500ce13..c5ee0cf61d 100644 --- a/packages/server/translations/ar.json +++ b/packages/server/translations/ar.json @@ -132,6 +132,8 @@ "ach.accountNumberField.invalid": "رقم حساب غير صحيح", "ach.accountLocationField.invalid": "رقم توجيه ABA غير صحيح", "ach.savedBankAccount": "الحساب البنكي المحفوظ", + "ach.savings": "حساب التوفير", + "ach.checking": "الحساب الجاري", "select.state": "حدد الولاية", "select.stateOrProvince": "حدد الولاية أو المقاطعة", "select.provinceOrTerritory": "حدد المقاطعة أو الإقليم", diff --git a/packages/server/translations/bg-BG.json b/packages/server/translations/bg-BG.json index e1a7c08cac..44ad4a1a98 100644 --- a/packages/server/translations/bg-BG.json +++ b/packages/server/translations/bg-BG.json @@ -133,6 +133,8 @@ "ach.accountNumberField.invalid": "Невалиден номер на сметка", "ach.accountLocationField.invalid": "Невалиден маршрутизиращ номер на ABA", "ach.savedBankAccount": "Запазена банкова сметка", + "ach.savings": "Спестовна сметка", + "ach.checking": "Разплащателна сметка", "select.state": "Изберете щат", "select.stateOrProvince": "Изберете държава или провинция", "select.provinceOrTerritory": "Изберете провинция или територия", diff --git a/packages/server/translations/ca-ES.json b/packages/server/translations/ca-ES.json index d9deb00e67..d5b92271b6 100644 --- a/packages/server/translations/ca-ES.json +++ b/packages/server/translations/ca-ES.json @@ -133,6 +133,8 @@ "ach.accountNumberField.invalid": "El número de compte no és vàlid", "ach.accountLocationField.invalid": "El número d'encaminament ABA no és vàlid", "ach.savedBankAccount": "S'ha desat el compte bancari", + "ach.savings": "Compte d'estalvi", + "ach.checking": "Compte corrent", "select.state": "Seleccioneu l'estat", "select.stateOrProvince": "Seleccioneu l'estat o la província", "select.provinceOrTerritory": "Seleccioneu la província o el territori", diff --git a/packages/server/translations/cs-CZ.json b/packages/server/translations/cs-CZ.json index e253a5dd39..9a44a5b57e 100644 --- a/packages/server/translations/cs-CZ.json +++ b/packages/server/translations/cs-CZ.json @@ -132,6 +132,8 @@ "ach.accountNumberField.invalid": "Neplatné číslo účtu", "ach.accountLocationField.invalid": "Neplatné směrovací tranzitní číslo ABA", "ach.savedBankAccount": "Uložený bankovní účet", + "ach.savings": "Spořicí účet", + "ach.checking": "Běžný účet", "select.state": "Vyberte stát", "select.stateOrProvince": "Vyberte kraj nebo okres", "select.provinceOrTerritory": "Vyberte provincii nebo teritorium", diff --git a/packages/server/translations/da-DK.json b/packages/server/translations/da-DK.json index baef20c8b3..fb5fb9ef80 100644 --- a/packages/server/translations/da-DK.json +++ b/packages/server/translations/da-DK.json @@ -133,6 +133,8 @@ "ach.accountNumberField.invalid": "Ugyldigt kontonummer", "ach.accountLocationField.invalid": "Ugyldigt ABA-registreringsnummer", "ach.savedBankAccount": "Gemt bankkonto", + "ach.savings": "Opsparingskonto", + "ach.checking": "Lønkonto", "select.state": "Vælg stat", "select.stateOrProvince": "Vælg region eller kommune", "select.provinceOrTerritory": "Vælg provins eller territorium", diff --git a/packages/server/translations/de-DE.json b/packages/server/translations/de-DE.json index 653c02bbcc..da042b96a2 100644 --- a/packages/server/translations/de-DE.json +++ b/packages/server/translations/de-DE.json @@ -132,6 +132,8 @@ "ach.accountNumberField.invalid": "Ungültige Kontonummer", "ach.accountLocationField.invalid": "Ungültige ABA-Nummer", "ach.savedBankAccount": "Gespeichertes Bankkonto", + "ach.savings": "Sparkonto", + "ach.checking": "Girokonto", "select.state": "Bundesstaat auswählen", "select.stateOrProvince": "Bundesland oder Provinz/Region auswählen", "select.provinceOrTerritory": "Provinz oder Territorium auswählen", diff --git a/packages/server/translations/el-GR.json b/packages/server/translations/el-GR.json index 56212616c8..bff5068f64 100644 --- a/packages/server/translations/el-GR.json +++ b/packages/server/translations/el-GR.json @@ -132,6 +132,8 @@ "ach.accountNumberField.invalid": "Μη έγκυρος αριθμός λογαριασμού", "ach.accountLocationField.invalid": "Μη έγκυρος αριθμός δρομολόγησης ABA", "ach.savedBankAccount": "Αποθηκευμένος τραπεζικός λογαριασμός", + "ach.savings": "Λογαριασμός ταμιευτηρίου", + "ach.checking": "Τρεχούμενος λογαριασμός", "select.state": "Επιλέξτε πολιτεία", "select.stateOrProvince": "Επιλέξτε πολιτεία ή επαρχία", "select.provinceOrTerritory": "Επιλέξτε επαρχία ή περιφέρεια", diff --git a/packages/server/translations/en-US.json b/packages/server/translations/en-US.json index f747a07234..d61909117a 100644 --- a/packages/server/translations/en-US.json +++ b/packages/server/translations/en-US.json @@ -133,6 +133,8 @@ "ach.accountNumberField.invalid": "Invalid account number", "ach.accountLocationField.invalid": "Invalid ABA routing number", "ach.savedBankAccount": "Saved bank account", + "ach.savings": "Savings account", + "ach.checking": "Checking account", "select.state": "Select state", "select.stateOrProvince": "Select state or province", "select.provinceOrTerritory": "Select province or territory", diff --git a/packages/server/translations/es-ES.json b/packages/server/translations/es-ES.json index f6b472ab5b..53352707e3 100644 --- a/packages/server/translations/es-ES.json +++ b/packages/server/translations/es-ES.json @@ -132,6 +132,8 @@ "ach.accountNumberField.invalid": "Número de cuenta no válido", "ach.accountLocationField.invalid": "El número de ruta ABA no es válido", "ach.savedBankAccount": "Se ha guardado la cuenta bancaria", + "ach.savings": "Cuenta de ahorros", + "ach.checking": "Cuenta corriente", "select.state": "Seleccione el estado", "select.stateOrProvince": "Seleccione el estado o provincia", "select.provinceOrTerritory": "Seleccione la provincia o territorio", diff --git a/packages/server/translations/et-EE.json b/packages/server/translations/et-EE.json index a422756462..b6d8b8873a 100644 --- a/packages/server/translations/et-EE.json +++ b/packages/server/translations/et-EE.json @@ -133,6 +133,8 @@ "ach.accountNumberField.invalid": "Vale kontonumber", "ach.accountLocationField.invalid": "Vale ABA pangakood", "ach.savedBankAccount": "Salvestatud pangakonto", + "ach.savings": "Säästukonto", + "ach.checking": "Arvelduskonto", "select.state": "Valige osariik", "select.stateOrProvince": "Valige osariik või maakond", "select.provinceOrTerritory": "Valige maakond või territoorium", diff --git a/packages/server/translations/fi-FI.json b/packages/server/translations/fi-FI.json index db71ce37c8..8182aec106 100644 --- a/packages/server/translations/fi-FI.json +++ b/packages/server/translations/fi-FI.json @@ -132,6 +132,8 @@ "ach.accountNumberField.invalid": "Väärä tilin numero", "ach.accountLocationField.invalid": "Ei-kelvollinen ABA-reititysnumero", "ach.savedBankAccount": "Tallennettu pankkitili", + "ach.savings": "Säästötili", + "ach.checking": "Käyttötili", "select.state": "Valitse osavaltio", "select.stateOrProvince": "Valitse osavaltio tai lääni", "select.provinceOrTerritory": "Valitse maakunta tai alue", diff --git a/packages/server/translations/fr-FR.json b/packages/server/translations/fr-FR.json index 2f6e8b6dc4..e6d25519ae 100644 --- a/packages/server/translations/fr-FR.json +++ b/packages/server/translations/fr-FR.json @@ -132,6 +132,8 @@ "ach.accountNumberField.invalid": "Numéro du compte incorrect", "ach.accountLocationField.invalid": "Code ABA incorrect", "ach.savedBankAccount": "Compte bancaire enregistré", + "ach.savings": "Compte d’épargne", + "ach.checking": "Compte courant", "select.state": "Sélectionnez l'État", "select.stateOrProvince": "Sélectionnez l'État ou la province", "select.provinceOrTerritory": "Sélectionnez la province ou le territoire", diff --git a/packages/server/translations/hr-HR.json b/packages/server/translations/hr-HR.json index ef0fca7d44..e18030904a 100644 --- a/packages/server/translations/hr-HR.json +++ b/packages/server/translations/hr-HR.json @@ -132,6 +132,8 @@ "ach.accountNumberField.invalid": "Nevažeći broj računa", "ach.accountLocationField.invalid": "Nevažeći ABA identifikacijski broj", "ach.savedBankAccount": "Spremljeni bankovni račun", + "ach.savings": "Štedni račun", + "ach.checking": "Tekući račun", "select.state": "Odaberite saveznu državu", "select.stateOrProvince": "Odaberite državu ili provinciju", "select.provinceOrTerritory": "Odaberite provinciju ili teritorij", diff --git a/packages/server/translations/hu-HU.json b/packages/server/translations/hu-HU.json index 15a191e54d..9715c90ac0 100644 --- a/packages/server/translations/hu-HU.json +++ b/packages/server/translations/hu-HU.json @@ -132,6 +132,8 @@ "ach.accountNumberField.invalid": "Érvénytelen számlaszám", "ach.accountLocationField.invalid": "Érvénytelen ABA-irányítószám", "ach.savedBankAccount": "Mentett bankszámla", + "ach.savings": "Betétszámla", + "ach.checking": "Folyószámla", "select.state": "Állam kiválasztása", "select.stateOrProvince": "Állam vagy tartomány kiválasztása", "select.provinceOrTerritory": "Tartomány vagy terület kiválasztása", diff --git a/packages/server/translations/is-IS.json b/packages/server/translations/is-IS.json index 26f034d2f8..f01b99b0cb 100644 --- a/packages/server/translations/is-IS.json +++ b/packages/server/translations/is-IS.json @@ -133,6 +133,8 @@ "ach.accountNumberField.invalid": "Ógilt reikningsnúmer", "ach.accountLocationField.invalid": "Ógilt ABA-bankanúmer", "ach.savedBankAccount": "Vistaður bankareikningur", + "ach.savings": "Sparireikningur", + "ach.checking": "Tékkareikningur", "select.state": "Veldu fylki", "select.stateOrProvince": "Veldu fylki eða hérað", "select.provinceOrTerritory": "Veldu hérað eða landsvæði", diff --git a/packages/server/translations/it-IT.json b/packages/server/translations/it-IT.json index 6b8b9218ad..e89f0ca172 100644 --- a/packages/server/translations/it-IT.json +++ b/packages/server/translations/it-IT.json @@ -132,6 +132,8 @@ "ach.accountNumberField.invalid": "Numero di conto non valido", "ach.accountLocationField.invalid": "Codice ABA non valido", "ach.savedBankAccount": "Conto corrente salvato", + "ach.savings": "Conto di risparmio", + "ach.checking": "Conto corrente", "select.state": "Seleziona stato", "select.stateOrProvince": "Seleziona stato o provincia", "select.provinceOrTerritory": "Seleziona provincia o territorio", diff --git a/packages/server/translations/ja-JP.json b/packages/server/translations/ja-JP.json index 6b825f6cc4..dde1ea6343 100644 --- a/packages/server/translations/ja-JP.json +++ b/packages/server/translations/ja-JP.json @@ -132,6 +132,8 @@ "ach.accountNumberField.invalid": "口座番号の入力間違い", "ach.accountLocationField.invalid": "無効なABAナンバー", "ach.savedBankAccount": "保存済みの銀行口座", + "ach.savings": "普通預金口座", + "ach.checking": "当座預金口座", "select.state": "都道府県を選択してください", "select.stateOrProvince": "都道府県を選択してください", "select.provinceOrTerritory": "州または準州を選択してください", diff --git a/packages/server/translations/ko-KR.json b/packages/server/translations/ko-KR.json index 9fa0592cd6..2cdbe796d5 100644 --- a/packages/server/translations/ko-KR.json +++ b/packages/server/translations/ko-KR.json @@ -132,6 +132,8 @@ "ach.accountNumberField.invalid": "유효하지 않은 계좌 번호", "ach.accountLocationField.invalid": "유효하지 않은 ABA 라우팅 번호", "ach.savedBankAccount": "저장된 은행 계좌", + "ach.savings": "저축 계좌", + "ach.checking": "당좌 예금 계좌", "select.state": "주 선택", "select.stateOrProvince": "주/도 선택", "select.provinceOrTerritory": "도 선택", diff --git a/packages/server/translations/lt-LT.json b/packages/server/translations/lt-LT.json index 2f5652d82f..a36b770469 100644 --- a/packages/server/translations/lt-LT.json +++ b/packages/server/translations/lt-LT.json @@ -133,6 +133,8 @@ "ach.accountNumberField.invalid": "Netinkamas sąskaitos numeris", "ach.accountLocationField.invalid": "Neteisingas ABA maršruto numeris", "ach.savedBankAccount": "Išsaugota banko sąskaita", + "ach.savings": "Taupomoji sąskaita", + "ach.checking": "Atsiskaitomoji sąskaita", "select.state": "Pasirinkite valstiją", "select.stateOrProvince": "Pasirinkite valstiją arba provinciją", "select.provinceOrTerritory": "Pasirinkite provinciją arba teritoriją", diff --git a/packages/server/translations/lv-LV.json b/packages/server/translations/lv-LV.json index a4736e33cc..b9bfd9ea3f 100644 --- a/packages/server/translations/lv-LV.json +++ b/packages/server/translations/lv-LV.json @@ -133,6 +133,8 @@ "ach.accountNumberField.invalid": "Nederīgs konta numurs", "ach.accountLocationField.invalid": "Nederīgs ABA maršrutēšanas numurs", "ach.savedBankAccount": "Saglabātais bankas konts", + "ach.savings": "Krājkonts", + "ach.checking": "Norēķinu konts", "select.state": "Atlasiet valsti", "select.stateOrProvince": "Atlasiet valsti vai apgabaltu", "select.provinceOrTerritory": "Atlasiet apgabalu vai teritoriju", diff --git a/packages/server/translations/nl-NL.json b/packages/server/translations/nl-NL.json index 3654e4a9b2..b1ad6487e2 100644 --- a/packages/server/translations/nl-NL.json +++ b/packages/server/translations/nl-NL.json @@ -132,6 +132,8 @@ "ach.accountNumberField.invalid": "Ongeldig rekeningnummer", "ach.accountLocationField.invalid": "Ongeldig routingnummer (ABA)", "ach.savedBankAccount": "Opgeslagen bankrekening", + "ach.savings": "Spaarrekening", + "ach.checking": "Betaalrekening", "select.state": "Selecteer staat", "select.stateOrProvince": "Selecteer staat of provincie", "select.provinceOrTerritory": "Selecteer provincie of territorium", diff --git a/packages/server/translations/no-NO.json b/packages/server/translations/no-NO.json index e2431deb66..ffb8ad2def 100644 --- a/packages/server/translations/no-NO.json +++ b/packages/server/translations/no-NO.json @@ -132,6 +132,8 @@ "ach.accountNumberField.invalid": "Ugyldig kontonummer", "ach.accountLocationField.invalid": "Ugyldig ABA-dirigeringsnummer", "ach.savedBankAccount": "Lagret bankkonto", + "ach.savings": "Sparekonto", + "ach.checking": "Sjekkkonto", "select.state": "Velg delstat", "select.stateOrProvince": "Velg delstat eller provins", "select.provinceOrTerritory": "Velg provins eller territorium", diff --git a/packages/server/translations/pl-PL.json b/packages/server/translations/pl-PL.json index 3ed82a0499..4a31d7d4bc 100644 --- a/packages/server/translations/pl-PL.json +++ b/packages/server/translations/pl-PL.json @@ -132,6 +132,8 @@ "ach.accountNumberField.invalid": "Nieprawidłowy numer rachunku", "ach.accountLocationField.invalid": "Nieprawidłowy kod bankowy ABA Routing Number", "ach.savedBankAccount": "Zapisane konto bankowe", + "ach.savings": "Konto oszczędnościowe", + "ach.checking": "Rachunek bieżący", "select.state": "Wybierz stan", "select.stateOrProvince": "Wybierz stan/województwo", "select.provinceOrTerritory": "Wybierz region/terytorium", diff --git a/packages/server/translations/pt-BR.json b/packages/server/translations/pt-BR.json index 10d4ba5ba9..7ce2386a10 100644 --- a/packages/server/translations/pt-BR.json +++ b/packages/server/translations/pt-BR.json @@ -132,6 +132,8 @@ "ach.accountNumberField.invalid": "Número de conta inválido", "ach.accountLocationField.invalid": "Número de roteamento ABA inválido", "ach.savedBankAccount": "Conta bancária cadastrada", + "ach.savings": "Conta poupança", + "ach.checking": "Conta corrente", "select.state": "Selecionar estado", "select.stateOrProvince": "Selecione estado ou província", "select.provinceOrTerritory": "Selecionar província ou território", diff --git a/packages/server/translations/pt-PT.json b/packages/server/translations/pt-PT.json index 4160bd09f3..ab54f80830 100644 --- a/packages/server/translations/pt-PT.json +++ b/packages/server/translations/pt-PT.json @@ -133,6 +133,8 @@ "ach.accountNumberField.invalid": "Número de conta inválido", "ach.accountLocationField.invalid": "Número de encaminhamento ABA inválido", "ach.savedBankAccount": "Conta bancária guardada", + "ach.savings": "Conta poupança", + "ach.checking": "Conta corrente", "select.state": "Selecione estado", "select.stateOrProvince": "Selecione estado ou província", "select.provinceOrTerritory": "Selecionar província ou território", diff --git a/packages/server/translations/ro-RO.json b/packages/server/translations/ro-RO.json index c4daba9626..733266aecd 100644 --- a/packages/server/translations/ro-RO.json +++ b/packages/server/translations/ro-RO.json @@ -132,6 +132,8 @@ "ach.accountNumberField.invalid": "Numărul de cont este incorect", "ach.accountLocationField.invalid": "Număr de direcționare ABA incorect", "ach.savedBankAccount": "Cont bancar salvat", + "ach.savings": "Cont de economii", + "ach.checking": "Cont curent", "select.state": "Selectați statul", "select.stateOrProvince": "Selectați județul sau provincia", "select.provinceOrTerritory": "Selectați provincia sau teritoriul", diff --git a/packages/server/translations/ru-RU.json b/packages/server/translations/ru-RU.json index 3625dfa04b..86b3441e3c 100644 --- a/packages/server/translations/ru-RU.json +++ b/packages/server/translations/ru-RU.json @@ -132,6 +132,8 @@ "ach.accountNumberField.invalid": "Недействительный номер счета", "ach.accountLocationField.invalid": "Недействительный маршрутный номер ABA", "ach.savedBankAccount": "Сохраненный банковский счет", + "ach.savings": "Сберегательный счет", + "ach.checking": "Текущий счет", "select.state": "Выберите штат", "select.stateOrProvince": "Выберите штат или область", "select.provinceOrTerritory": "Выберите провинцию или территорию", diff --git a/packages/server/translations/sk-SK.json b/packages/server/translations/sk-SK.json index 6d6b40614d..a319f80ed4 100644 --- a/packages/server/translations/sk-SK.json +++ b/packages/server/translations/sk-SK.json @@ -132,6 +132,8 @@ "ach.accountNumberField.invalid": "Neplatné číslo účtu", "ach.accountLocationField.invalid": "Neplatné smerovacie číslo ABA", "ach.savedBankAccount": "Uložený bankový účet", + "ach.savings": "Sporiaci účet", + "ach.checking": "Kontrolný účet", "select.state": "Vyberte kraj", "select.stateOrProvince": "Vyberte kraj alebo okres", "select.provinceOrTerritory": "Vyberte okres alebo územie", diff --git a/packages/server/translations/sl-SI.json b/packages/server/translations/sl-SI.json index 1e2a731e6d..6fc565d231 100644 --- a/packages/server/translations/sl-SI.json +++ b/packages/server/translations/sl-SI.json @@ -132,6 +132,8 @@ "ach.accountNumberField.invalid": "Neveljavna številka računa", "ach.accountLocationField.invalid": "Neveljavna koda banke ABA", "ach.savedBankAccount": "Shranjen bančni račun", + "ach.savings": "Varčevalni račun", + "ach.checking": "Tekoči račun", "select.state": "Izberite državo", "select.stateOrProvince": "Izberite državo ali provinco", "select.provinceOrTerritory": "Izberite območje ali ozemlje", diff --git a/packages/server/translations/sv-SE.json b/packages/server/translations/sv-SE.json index 19aaf7555e..795175ca6c 100644 --- a/packages/server/translations/sv-SE.json +++ b/packages/server/translations/sv-SE.json @@ -132,6 +132,8 @@ "ach.accountNumberField.invalid": "Ogiltigt kontonummer", "ach.accountLocationField.invalid": "Ogiltigt ABA-nummer", "ach.savedBankAccount": "Sparat bankkonto", + "ach.savings": "Sparkonto", + "ach.checking": "Checkkonto", "select.state": "Välj delstat", "select.stateOrProvince": "Välj delstat eller provins", "select.provinceOrTerritory": "Välj provins eller territorium", diff --git a/packages/server/translations/zh-CN.json b/packages/server/translations/zh-CN.json index 82cb975a37..1842ffc972 100644 --- a/packages/server/translations/zh-CN.json +++ b/packages/server/translations/zh-CN.json @@ -132,6 +132,8 @@ "ach.accountNumberField.invalid": "无效的账号", "ach.accountLocationField.invalid": "无效的 ABA 路由电汇编码", "ach.savedBankAccount": "已保存的银行账户", + "ach.savings": "储蓄账户", + "ach.checking": "支票账户", "select.state": "选择州", "select.stateOrProvince": "选择州或省", "select.provinceOrTerritory": "选择省或地区", diff --git a/packages/server/translations/zh-TW.json b/packages/server/translations/zh-TW.json index f6f49c4ac4..378159e0ce 100644 --- a/packages/server/translations/zh-TW.json +++ b/packages/server/translations/zh-TW.json @@ -132,6 +132,8 @@ "ach.accountNumberField.invalid": "帳戶號碼無效", "ach.accountLocationField.invalid": "ABA 匯款路徑編號無效", "ach.savedBankAccount": "儲存的銀行帳戶", + "ach.savings": "儲蓄帳戶", + "ach.checking": "支票帳戶", "select.state": "選取州", "select.stateOrProvince": "選擇州或省", "select.provinceOrTerritory": "選取省或地區",