Skip to content

Commit

Permalink
feat(PAYMENTS-18338): add apple-pay redirect integration
Browse files Browse the repository at this point in the history
  • Loading branch information
Aleksey-Kornienko-xsolla committed Mar 7, 2024
1 parent dfd1c70 commit 40b7330
Show file tree
Hide file tree
Showing 21 changed files with 587 additions and 26 deletions.
92 changes: 92 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
/>
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
<script src="dist/main.js"></script>
</head>
<body>
<h1>Partner</h1>
<!--<psdk-text></psdk-text>-->
<psdk-text name="zip"></psdk-text>
<!--<psdk-text name='zip'></psdk-text>-->
<!--<psdk-text name='email'></psdk-text>-->
<!--<psdk-payment-methods country="RU"></psdk-payment-methods>-->
<psdk-payment-form-messages></psdk-payment-form-messages>
<!--<psdk-apple-pay></psdk-apple-pay>-->
<psdk-submit-button></psdk-submit-button>
<psdk-legal></psdk-legal>
<!--<psdk-payment-methods></psdk-payment-methods>-->
<!--<div>-->
<!-- <psdk-card-number name='card_number'</psdk-card-number>-->
<!--</div>-->
<!--<psdk-payment-form></psdk-payment-form>-->
<!--<psdk-finance-details></psdk-finance-details>-->
<!--<psdk-submit-button text="buy"></psdk-submit-button>-->
<!--<psdk-phone showflags="true"></psdk-phone>-->
<!--<hr>-->
<!--<div>-->
<!-- <h4>Balance</h4>-->
<!-- <psdk-user-balance no-balance="no balance"></psdk-user-balance>-->
<!--</div>-->
<!--<hr>-->
<!--<psdk-text-component name='email'></psdk-text-component>-->
<script type="module">
// import { EventName } from './src/core/event-name.enum';
// import * as PayStationSdk from './src';
init();
async function init() {
console.log(PayStationSdk.headlessCheckout);
const paymentsSdk = PayStationSdk.headlessCheckout;
console.log('await paymentsSdk.init');
await paymentsSdk.init({
isWebView: false,
sandbox: false,
country: 'RU',
});
console.log('after paymentsSdk.init');
await paymentsSdk.setToken('f8q1o1xPYeIjt02sByOHx7FR5VnxgAaA_lc_en');
const form = await paymentsSdk.form.init({
// paymentMethodId: 1738,
paymentMethodId: 3175,
returnUrl:
'https://headless-checkout-app.web.app/return?token=oeptqWDZXW9nU0uKdvQp30vlXW8qaugW_lc_en',
});

console.log('form', form);
const naCallback = (na) => console.log('nextAction', na);
paymentsSdk.form.onNextAction(naCallback);

// then(() => {
// console.log('setToken')
// return paymentsSdk.setToken('f8q1zY9MC9QaPfGGLd6dnaJ6EqMWsWRs_lc_en');
// })

// .then(() => {
// return paymentsSdk.form.init({
// // paymentMethodId: 1738,
// paymentMethodId: 3175,
// returnUrl: 'https://headless-checkout-app.web.app/return?token=oeptqWDZXW9nU0uKdvQp30vlXW8qaugW_lc_en',
// });
// })

// .then((form) => {
// console.log('test', paymentsSdk)
//
// console.log('form', form);
// const naCallback = (na) => console.log('nextAction', na);
// paymentsSdk.form.onNextAction(naCallback);
// })
}
// await paymentsSdk.setToken('8sogaw0qcZbijxvfq1A8Ir6YMKykd5aJ_lc_en');
// await paymentsSdk.setToken('8sogJarHSKGCrbgCbcy24Gk2FPv86ODg_lc_en');
// await paymentsSdk.setToken('8sogPLisB328Snf9M9aChSwkZn4IzOzf_lc_en'); // sandbox
// await paymentsSdk.setToken('q4plmluaBWwtfzReIo5k9vYHDIEwPKRS_bg_201308_tb_FFFAD6');
</script>
</body>
</html>
37 changes: 37 additions & 0 deletions legal-component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
/>
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
<script src="dist/main.js"></script>
<style>
:root {
--color-icon: red;
}
psdk-payment-methods a {
text-decoration: none;
}
psdk-payment-methods a:focus {
text-decoration: underline;
}
</style>
</head>
<body>
<h1>Partner</h1>
<div id="container"></div>
<script type="module">
const paymentsSdk = PayStationSdk.headlessCheckout;
const result = await paymentsSdk.init({
isWebView: false,
sandbox: false,
});
await paymentsSdk.setToken('8sogVHs3ugUZLXKD4kObyCpkbgIRjl2g_lc_en');
</script>
<psdk-legal></psdk-legal>
</body>
</html>
112 changes: 112 additions & 0 deletions partner.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
/>
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
<script src="dist/main.js"></script>
</head>
<body>
<h1>Partner</h1>
<!--<psdk-text></psdk-text>-->
<psdk-text name="zip"></psdk-text>
<!--<psdk-text name='zip'></psdk-text>-->
<!--<psdk-text name='email'></psdk-text>-->
<!--<psdk-payment-methods country="RU"></psdk-payment-methods>-->
<psdk-payment-form-messages></psdk-payment-form-messages>
<psdk-apple-pay></psdk-apple-pay>
<psdk-legal></psdk-legal>
<!--<psdk-payment-methods></psdk-payment-methods>-->
<!--<div>-->
<!-- <psdk-card-number name='card_number'</psdk-card-number>-->
<!--</div>-->
<!--<psdk-payment-form></psdk-payment-form>-->
<!--<psdk-finance-details></psdk-finance-details>-->
<!--<psdk-submit-button text="buy"></psdk-submit-button>-->
<!--<psdk-phone showflags="true"></psdk-phone>-->
<!--<hr>-->
<!--<div>-->
<!-- <h4>Balance</h4>-->
<!-- <psdk-user-balance no-balance="no balance"></psdk-user-balance>-->
<!--</div>-->
<!--<hr>-->
<!--<psdk-text-component name='email'></psdk-text-component>-->
<script type="module">
// import { EventName } from './src/core/event-name.enum';
// import * as PayStationSdk from './src';
init();
async function init() {
console.log(PayStationSdk.headlessCheckout);
const paymentsSdk = PayStationSdk.headlessCheckout;
await paymentsSdk.init({
isWebView: false,
sandbox: false,
country: 'US',
});

setTimeout(() => {
paymentsSdk.setToken('f8q1o1xPYeIjt02sByOHx7FR5VnxgAaA_lc_en');
// paymentsSdk.setToken('f8q1eO5MF7PRXH9R5PPawq2CPvQqDPen_lc_en'); // sandbox
}, 2000);

setTimeout(() => {
// paymentsSdk.setToken('f8q1zY9MC9QaPfGGLd6dnaJ6EqMWsWRs_lc_en');
const form = paymentsSdk.form.init({
// paymentMethodId: 1738,
paymentMethodId: 3175,
returnUrl:
'https://headless-checkout-app.web.app/return?token=oeptqWDZXW9nU0uKdvQp30vlXW8qaugW_lc_en',
});
}, 5000);
// const form = await paymentsSdk.form.init({
// // paymentMethodId: 1738,
// paymentMethodId: 3175,
// returnUrl: 'https://headless-checkout-app.web.app/return?token=oeptqWDZXW9nU0uKdvQp30vlXW8qaugW_lc_en',
// });
//
//
setTimeout(() => {
const naCallback = (na) => {
console.log('nextAction', na);
window.addEventListener('message', (message) => {
console.log('window.addEventListener', message);
});
if (na.type === 'open_new_tab') {
window.open(na.data.url);
}
};
paymentsSdk.form.onNextAction(naCallback);
}, 7000);

// then(() => {
// console.log('setToken')
// return paymentsSdk.setToken('f8q1zY9MC9QaPfGGLd6dnaJ6EqMWsWRs_lc_en');
// })

// .then(() => {
// return paymentsSdk.form.init({
// // paymentMethodId: 1738,
// paymentMethodId: 3175,
// returnUrl: 'https://headless-checkout-app.web.app/return?token=oeptqWDZXW9nU0uKdvQp30vlXW8qaugW_lc_en',
// });
// })

// .then((form) => {
// console.log('test', paymentsSdk)
//
// console.log('form', form);
// const naCallback = (na) => console.log('nextAction', na);
// paymentsSdk.form.onNextAction(naCallback);
// })
}
// await paymentsSdk.setToken('8sogaw0qcZbijxvfq1A8Ir6YMKykd5aJ_lc_en');
// await paymentsSdk.setToken('8sogJarHSKGCrbgCbcy24Gk2FPv86ODg_lc_en');
// await paymentsSdk.setToken('8sogPLisB328Snf9M9aChSwkZn4IzOzf_lc_en'); // sandbox
// await paymentsSdk.setToken('q4plmluaBWwtfzReIo5k9vYHDIEwPKRS_bg_201308_tb_FFFAD6');
</script>
</body>
</html>
2 changes: 2 additions & 0 deletions src/core/event-name.enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,6 @@ export const enum EventName {
finishLoadComponent = 'finishLoadComponent',
getFormStatus = 'getFormStatus',
applePayError = 'applePayError',
openApplePayPage = 'openApplePayPage',
submitApplePayForm = 'submitApplePayForm',
}
14 changes: 14 additions & 0 deletions src/core/guards/apple-pay/open-apple-pay-page.guard.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import 'reflect-metadata';
import { EventName } from '../../event-name.enum';
import { isOpenApplePayPageEventMessage } from './open-apple-pay-page.guard';

describe('Event message type guard', () => {
it('Should return true', () => {
expect(
isOpenApplePayPageEventMessage({ name: EventName.openApplePayPage })
).toBeTruthy();
});
it('Should return false', () => {
expect(isOpenApplePayPageEventMessage({})).toBeFalsy();
});
});
12 changes: 12 additions & 0 deletions src/core/guards/apple-pay/open-apple-pay-page.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Message } from '../../message.interface';
import { isEventMessage } from '../event-message.guard';
import { EventName } from '../../event-name.enum';

export const isOpenApplePayPageEventMessage = (
messageData: unknown
): messageData is Message<{ redirectUrl: string } | null | undefined> => {
if (isEventMessage(messageData)) {
return messageData.name === EventName.openApplePayPage;
}
return false;
};
26 changes: 16 additions & 10 deletions src/features/headless-checkout/headless-checkout.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { LocalizeService } from '../../core/i18n/localize.service';
import { getFinanceDetailsHandler } from './post-messages-handlers/get-finance-details.handler';
import { FormStatus } from '../../core/status/form-status.enum';
import { noopStub } from '../../tests/stubs/noop.stub';
import { headlessCheckoutAppUrl } from './environment';

const mockMessage: Message = {
name: EventName.initPayment,
Expand All @@ -19,7 +20,6 @@ const mockHandler: Handler<void> = (): null => {
};

class MockIframeElement {
public src = '';
public width = '';
public height = '';
public style = { border: '' };
Expand All @@ -46,6 +46,13 @@ describe('HeadlessCheckout', () => {

beforeEach(() => {
windowService = window;
spyOn(windowService, 'addEventListener').and.callFake(
(name: string, handlerWrapper: EventListenerOrEventListenerObject) => {
(handlerWrapper as (message: MessageEvent) => void)({
origin: headlessCheckoutAppUrl,
} as MessageEvent);
}
);
postMessagesClient = {
init: stub,
send: stub,
Expand Down Expand Up @@ -75,17 +82,16 @@ describe('HeadlessCheckout', () => {
const spy = spyOn(postMessagesClient, 'init');
spyOn(windowService.document.body, 'appendChild');
spyOn(windowService.document, 'createElement').and.callFake(
() => new MockIframeElement() as unknown as HTMLIFrameElement,
() => new MockIframeElement() as unknown as HTMLIFrameElement
);

await headlessCheckout.init({ isWebview: false });
expect(spy).toHaveBeenCalled();
});

it('Should init localization', () => {
const localizeSpy = spyOn(
localizeService,
'initDictionaries',
'initDictionaries'
).and.resolveTo();

void headlessCheckout.init({ isWebview: false });
Expand All @@ -104,7 +110,7 @@ describe('HeadlessCheckout', () => {
headlessCheckout.events.onCoreEvent(
EventName.initPayment,
mockHandler,
stub,
stub
);
expect(spy).toHaveBeenCalled();
});
Expand All @@ -113,7 +119,7 @@ describe('HeadlessCheckout', () => {
const spy = spyOn(postMessagesClient, 'listen');
spyOn(windowService.document.body, 'appendChild');
spyOn(windowService.document, 'createElement').and.callFake(
() => new MockIframeElement() as unknown as HTMLIFrameElement,
() => new MockIframeElement() as unknown as HTMLIFrameElement
);

await headlessCheckout.init({ isWebview: false });
Expand Down Expand Up @@ -145,7 +151,7 @@ describe('HeadlessCheckout', () => {
await headlessCheckout.getFinanceDetails();
expect(spy).toHaveBeenCalledWith(
{ name: EventName.financeDetails },
getFinanceDetailsHandler,
getFinanceDetailsHandler
);
});

Expand All @@ -166,7 +172,7 @@ describe('HeadlessCheckout', () => {
spyOn(windowService.customElements, 'get').and.returnValue(undefined);
spyOn(windowService.document.body, 'appendChild');
spyOn(windowService.document, 'createElement').and.callFake(
() => new MockIframeElement() as unknown as HTMLIFrameElement,
() => new MockIframeElement() as unknown as HTMLIFrameElement
);

await headlessCheckout.init({ isWebview: false });
Expand All @@ -175,11 +181,11 @@ describe('HeadlessCheckout', () => {

it('Should web components not be redefined', async () => {
spyOn(windowService.customElements, 'get').and.returnValue(
CustomElementMock,
CustomElementMock
);
spyOn(windowService.document.body, 'appendChild');
spyOn(windowService.document, 'createElement').and.callFake(
() => new MockIframeElement() as unknown as HTMLIFrameElement,
() => new MockIframeElement() as unknown as HTMLIFrameElement
);

const spy = spyOn(window.customElements, 'define');
Expand Down
Loading

0 comments on commit 40b7330

Please sign in to comment.