diff --git a/env.default b/env.default index a2bcc1ddb0..1b6dee8377 100644 --- a/env.default +++ b/env.default @@ -1,4 +1,4 @@ -API_VERSION=v68 +API_VERSION=v69 CHECKOUT_API_KEY= diff --git a/packages/e2e-playwright/package.json b/packages/e2e-playwright/package.json index 125ab1ab50..df0432d9d4 100644 --- a/packages/e2e-playwright/package.json +++ b/packages/e2e-playwright/package.json @@ -25,6 +25,6 @@ "webpack-dev-server": "4.13.3" }, "dependencies": { - "@adyen/adyen-web": "5.50.1" + "@adyen/adyen-web": "5.51.0" } } diff --git a/packages/e2e/package.json b/packages/e2e/package.json index ff4739c7da..45947bc449 100644 --- a/packages/e2e/package.json +++ b/packages/e2e/package.json @@ -41,6 +41,6 @@ "whatwg-fetch": "^3.6.2" }, "dependencies": { - "@adyen/adyen-web": "5.50.1" + "@adyen/adyen-web": "5.51.0" } } diff --git a/packages/lib/CHANGELOG.md b/packages/lib/CHANGELOG.md index 987a99a7a6..e35f5344fc 100644 --- a/packages/lib/CHANGELOG.md +++ b/packages/lib/CHANGELOG.md @@ -1,5 +1,11 @@ # @adyen/adyen-web +## 5.51.0 + +### Minor Changes + +- Add 'redirectFromTopWhenInIframe' config prop to allow top level redirect when Checkout loaded in an iframe ([#2325](https://github.com/Adyen/adyen-web/pull/2325)) + ## 5.50.1 ### Patch Changes diff --git a/packages/lib/package.json b/packages/lib/package.json index 80ba1b7bf8..4d6ba83c09 100644 --- a/packages/lib/package.json +++ b/packages/lib/package.json @@ -24,7 +24,7 @@ "./dist/es/adyen.css": "./dist/es/adyen.css", "./package.json": "./package.json" }, - "version": "5.50.1", + "version": "5.51.0", "license": "MIT", "homepage": "https://docs.adyen.com/checkout", "repository": "github:Adyen/adyen-web", diff --git a/packages/lib/src/components/Redirect/Redirect.test.tsx b/packages/lib/src/components/Redirect/Redirect.test.tsx index d1fd718726..2d65fcb4e9 100644 --- a/packages/lib/src/components/Redirect/Redirect.test.tsx +++ b/packages/lib/src/components/Redirect/Redirect.test.tsx @@ -3,6 +3,12 @@ import { h } from 'preact'; import Redirect from './Redirect'; import RedirectShopper from './components/RedirectShopper'; +jest.mock('../../utils/detectInIframe', () => { + return jest.fn().mockImplementation(() => { + return true; + }); +}); + describe('Redirect', () => { describe('isValid', () => { test('Is always valid', () => { @@ -19,6 +25,17 @@ describe('Redirect', () => { expect(wrapper.find('form')).toHaveLength(1); expect(wrapper.find('form').prop('action')).toBe('http://www.adyen.com'); + expect(wrapper.find('form').prop('target')).toBe(undefined); + setTimeout(() => expect(window.HTMLFormElement.prototype.submit).toHaveBeenCalled(), 0); + }); + + test('Accepts a POST redirect status, setting target to _top, when the config prop tells it to', () => { + window.HTMLFormElement.prototype.submit = jest.fn(); + + const wrapper = mount(); + + expect(wrapper.find('form')).toHaveLength(1); + expect(wrapper.find('form').prop('target')).toBe('_top'); setTimeout(() => expect(window.HTMLFormElement.prototype.submit).toHaveBeenCalled(), 0); }); }); diff --git a/packages/lib/src/components/Redirect/components/RedirectShopper/RedirectShopper.tsx b/packages/lib/src/components/Redirect/components/RedirectShopper/RedirectShopper.tsx index c625c817d0..ac69bd52a8 100644 --- a/packages/lib/src/components/Redirect/components/RedirectShopper/RedirectShopper.tsx +++ b/packages/lib/src/components/Redirect/components/RedirectShopper/RedirectShopper.tsx @@ -1,10 +1,12 @@ import { Component, h } from 'preact'; +import detectInIframe from '../../../../utils/detectInIframe'; interface RedirectShopperProps { beforeRedirect: (resolve, reject, url) => Promise; url: string; method: 'GET' | 'POST'; data?: any; + redirectFromTopWhenInIframe?: boolean; } class RedirectShopper extends Component { @@ -19,7 +21,12 @@ class RedirectShopper extends Component { if (this.postForm) { this.postForm.submit(); } else { - window.location.assign(this.props.url); + if (this.props.redirectFromTopWhenInIframe && detectInIframe()) { + // if in an iframe and the config prop allows it - try to redirect from the top level window + window.top.location.assign?.(this.props.url); + } else { + window.location.assign(this.props.url); + } } }; @@ -44,6 +51,7 @@ class RedirectShopper extends Component { ref={ref => { this.postForm = ref; }} + {...(this.props.redirectFromTopWhenInIframe && detectInIframe() && { target: '_top' })} > {Object.keys(data).map(key => ( diff --git a/packages/lib/src/core/config.ts b/packages/lib/src/core/config.ts index 79c438618b..ef81e05816 100644 --- a/packages/lib/src/core/config.ts +++ b/packages/lib/src/core/config.ts @@ -15,6 +15,7 @@ export const GENERIC_OPTIONS = [ 'session', 'clientKey', 'showPayButton', + 'redirectFromTopWhenInIframe', 'installmentOptions', // Events diff --git a/packages/lib/src/utils/detectInIframe.ts b/packages/lib/src/utils/detectInIframe.ts new file mode 100644 index 0000000000..5307d7028e --- /dev/null +++ b/packages/lib/src/utils/detectInIframe.ts @@ -0,0 +1,2 @@ +// Returns true if the page is being run in an iframe +export default () => window.location !== window.parent.location; diff --git a/packages/playground/package.json b/packages/playground/package.json index 264783d13c..72c468194a 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -41,6 +41,6 @@ "whatwg-fetch": "^3.6.2" }, "dependencies": { - "@adyen/adyen-web": "5.50.1" + "@adyen/adyen-web": "5.51.0" } } diff --git a/packages/playground/src/config/paymentsConfig.js b/packages/playground/src/config/paymentsConfig.js index ac7d553974..e89ba72fb4 100644 --- a/packages/playground/src/config/paymentsConfig.js +++ b/packages/playground/src/config/paymentsConfig.js @@ -9,23 +9,23 @@ const paymentsConfig = { origin, returnUrl, reference: `${identifier}-checkout-components-ref`, - additionalData: { - // Force response code. See https://docs.adyen.com/development-resources/test-cards/result-code-testing/adyen-response-codes - // RequestedTestAcquirerResponseCode: 2, - allow3DS2: true - // To force threeds2InMDFlow: - // comment out "allow3DS2" & comment in the following 2 lines: - // threeDS2InMDFlow: true, - // executeThreeD: true - }, - // Ready for v69 - lose any additionalData 3DS2 related lines e.g. allow3DS2: true - // authenticationData: { - // attemptAuthentication: 'always', - // // To force MDFlow: comment out below, and just keep line above - // threeDSRequestData: { - // nativeThreeDS: 'preferred' - // } + // additionalData: { + // // Force response code. See https://docs.adyen.com/development-resources/test-cards/result-code-testing/adyen-response-codes + // // RequestedTestAcquirerResponseCode: 2, + // allow3DS2: true + // // To force threeds2InMDFlow: + // // comment out "allow3DS2" & comment in the following 2 lines: + // // threeDS2InMDFlow: true, + // // executeThreeD: true // }, + // Ready for v69+ - lose any additionalData 3DS2 related lines e.g. allow3DS2: true + authenticationData: { + attemptAuthentication: 'always', + // To force MDFlow: comment out below, and just keep line above + threeDSRequestData: { + nativeThreeDS: 'preferred' + } + }, shopperEmail: 'test-shopper@storytel.com', shopperIP: '172.30.0.1', // threeDS2RequestData: {