Skip to content

Commit

Permalink
feat(PAYMENTS-15256): set secure component styles
Browse files Browse the repository at this point in the history
  • Loading branch information
simbirromanmakarov committed Sep 22, 2023
1 parent 82de587 commit 5f58ed5
Show file tree
Hide file tree
Showing 9 changed files with 211 additions and 26 deletions.
140 changes: 140 additions & 0 deletions examples/secure-component-styles/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
<!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>Secure component styles</title>

<style>
/* Global styles */
#form-container {
padding: 12px 0;
}

psdk-text {
display: block;
width: 400px;
height: 40px;
margin-bottom: 12px;
}

psdk-text iframe {
border: none;
width: inherit;
height: inherit;
}
</style>

<!--
Link the SDK bundle.
NOTE: In this example, we use a local build just for convenience purposes.
-->
<script src="./dist/main.js"></script>
<!-- <script src="../../dist/main.js"></script> -->
</head>

<body>
<h1>Secure component styles</h1>

<div id="form-container">
<psdk-text name="email"></psdk-text>
<psdk-text name="zip"></psdk-text>
</div>

<!--
Add legal component to provide links to legal documents
-->
<psdk-legal></psdk-legal>

<!-- Initialization script -->
<script>
if (typeof PayStationSdk === 'undefined') {
alert(`
It seems SDK library is undefined.
Please, link CDN source or create local build (recommended to test purposes only).
`);
throw new Error('PayStationSdk not found');
}
/**
* To learn more about creating tokens,
* please read https://developers.xsolla.com/api/pay-station/operation/create-token/
*/
const accessToken = '8sogVNwcYkzm6UeULtAJOYMPMCBaXvI1_lc_en';

if (!accessToken) {
alert('No token provided. Please, check the documentation');
throw new Error('No token provided');
}

/**
* The SDK is available under the PayStationSdk namespace.
* To begin initialization, obtain a reference to the headlessCheckout object.
*/
const { headlessCheckout } = PayStationSdk;

async function initPayStationSdk() {
/**
* Call the `init()` method with the provided environment object.
* The isWebView parameter is required and indicates whether your
* integration type is a webview or not.
* You can set sandbox payment mode with `sandbox` parameter
* Please note that this command executes asynchronously.
*/
await headlessCheckout.init({
isWebView: false,
sandbox: true,
});

/**
* Set styles for secure components
*/
await headlessCheckout.setSecureComponentStyles(`
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap');
input {
padding: 12px;
border: 1px solid grey;
border-radius: 8px;
font-family: 'Roboto', sans-serif;
font-size: 14px;
}
input:focus {
outline: none;
}
`);

/**
* After the Payments SDK has been initialized, the next step is setting the token.
* To learn more about creating tokens,
* please read https://developers.xsolla.com/api/pay-station/operation/create-token/
*/
await headlessCheckout.setToken(accessToken);

/**
* Define payment method id.
* To get lists of payment methods use psdk-payment-methods.
* Please see `examples/select-method` for more details
*/
const paypalPaymentMethodId = 24;

/**
* Initialize payment.
* returnUrl will be opened after payment completed on PayPal side.
* Please see `examples/paypal/return.html` for more details
*/
const form = await headlessCheckout.form.init({
paymentMethodId: paypalPaymentMethodId,
returnUrl: 'http://return',
});
}

// initialize sdk
initPayStationSdk();
</script>
</body>
</html>
15 changes: 2 additions & 13 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
"devDependencies": {
"@commitlint/cli": "^17.7.1",
"@commitlint/config-conventional": "^17.7.0",
"@types/i18next": "^13.0.0",
"@types/jasmine": "^4.3.5",
"@typescript-eslint/eslint-plugin": "^6.5.0",
"@typescript-eslint/parser": "^6.5.0",
Expand Down
1 change: 1 addition & 0 deletions src/core/event-name.enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ export const enum EventName {
nextAction = 'nextAction',
warning = 'warning',
getTextComponentConfig = 'getTextComponentConfig',
setSecureComponentStyles = 'setSecureComponentStyles',
}
6 changes: 6 additions & 0 deletions src/features/headless-checkout/headless-checkout.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ describe('HeadlessCheckout', () => {
expect(spy).toHaveBeenCalled();
});

it('Should set secure component styles', async () => {
const spy = spyOn(postMessagesClient, 'send');
await headlessCheckout.setSecureComponentStyles('styles');
expect(spy).toHaveBeenCalled();
});

it('Should throw exception if empty token', async () => {
try {
await headlessCheckout.setToken('');
Expand Down
35 changes: 23 additions & 12 deletions src/features/headless-checkout/headless-checkout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { headlessCheckoutAppUrl } from './environment';
import { FinanceDetails } from '../../core/finance-details/finance-details.interface';
import { getFinanceDetailsHandler } from './post-messages-handlers/get-finance-details.handler';
import { FormStatus } from '../../core/status/form-status.enum';
import { setSecureComponentStylesHandler } from './post-messages-handlers/set-secure-component-styles.handler';

@singleton()
export class HeadlessCheckout {
Expand All @@ -52,7 +53,7 @@ export class HeadlessCheckout {
onCoreEvent: <T>(
eventName: EventName,
handler: Handler<T>,
callback: (value?: T) => void
callback: (value?: T) => void,
): (() => void) => {
return this.postMessagesClient.listen(eventName, handler, callback);
},
Expand Down Expand Up @@ -81,7 +82,7 @@ export class HeadlessCheckout {
}
this.formSpy.formWasInit = true;
this.formStatus = FormStatus.active;
})
}),
) as Promise<Form>;
},

Expand All @@ -93,7 +94,7 @@ export class HeadlessCheckout {
if (nextAction) {
callbackFn(nextAction);
}
}
},
);
},

Expand Down Expand Up @@ -124,7 +125,7 @@ export class HeadlessCheckout {
private readonly postMessagesClient: PostMessagesClient,
private readonly localizeService: LocalizeService,
private readonly headlessCheckoutSpy: HeadlessCheckoutSpy,
private readonly formSpy: FormSpy
private readonly formSpy: FormSpy,
) {}

public async init(environment: {
Expand All @@ -145,7 +146,7 @@ export class HeadlessCheckout {
getErrorHandler,
(error) => {
throw new Error(error);
}
},
);
}

Expand Down Expand Up @@ -173,7 +174,17 @@ export class HeadlessCheckout {
return this.postMessagesClient.send<void>(msg, (message) =>
setTokenHandler(message, () => {
this.headlessCheckoutSpy.appWasInit = true;
})
}),
);
}

public async setSecureComponentStyles(styles: string): Promise<void> {
return this.postMessagesClient.send(
{
name: EventName.setSecureComponentStyles,
data: styles,
},
setSecureComponentStylesHandler,
);
}

Expand All @@ -188,7 +199,7 @@ export class HeadlessCheckout {

return this.postMessagesClient.send<FinanceDetails | null>(
msg,
getFinanceDetailsHandler
getFinanceDetailsHandler,
) as Promise<FinanceDetails | null>;
}

Expand All @@ -208,7 +219,7 @@ export class HeadlessCheckout {

return this.postMessagesClient.send<PaymentMethod[]>(
msg,
getRegularMethodsHandler
getRegularMethodsHandler,
) as Promise<PaymentMethod[]>;
}

Expand All @@ -228,7 +239,7 @@ export class HeadlessCheckout {

return this.postMessagesClient.send<PaymentMethod[]>(
msg,
getQuickMethodsHandler
getQuickMethodsHandler,
) as Promise<PaymentMethod[]>;
}

Expand All @@ -239,7 +250,7 @@ export class HeadlessCheckout {

return this.postMessagesClient.send<SavedMethod[]>(
msg,
getSavedMethodsHandler
getSavedMethodsHandler,
) as Promise<SavedMethod[]>;
}

Expand All @@ -250,7 +261,7 @@ export class HeadlessCheckout {

return this.postMessagesClient.send<UserBalance>(
msg,
getUserBalanceHandler
getUserBalanceHandler,
) as Promise<UserBalance>;
}

Expand All @@ -263,7 +274,7 @@ export class HeadlessCheckout {
};

return this.postMessagesClient.send<Status>(msg, (message) =>
getPaymentStatusHandler(message)
getPaymentStatusHandler(message),
) as Promise<Status>;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { EventName } from '../../../core/event-name.enum';
import { Message } from '../../../core/message.interface';
import { PaymentMethod } from '../../../core/payment-method.interface';
import { setSecureComponentStylesHandler } from './set-secure-component-styles.handler';

const mockMessage: Message<{ methods: PaymentMethod[] }> = {
name: EventName.setSecureComponentStyles,
};

describe('setSecureComponentStylesHandler', () => {
it('Should handle data', () => {
expect(setSecureComponentStylesHandler(mockMessage)).toEqual({
isHandled: true,
});
});

it('Should return null', () => {
expect(
setSecureComponentStylesHandler({
name: EventName.getPaymentMethodsList,
}),
).toBeNull();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Handler } from '../../../core/post-messages-client/handler.type';
import { Message } from '../../../core/message.interface';
import { EventName } from '../../../core/event-name.enum';

export const setSecureComponentStylesHandler: Handler<void> = (
message: Message,
): { isHandled: boolean } | null => {
if (message.name === EventName.setSecureComponentStyles) {
return {
isHandled: true,
};
}
return null;
};
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ describe('PaymentFormFieldsManager', () => {

beforeEach(() => {
windowService = window;
container.clearInstances();

container.clearInstances();

Expand Down

0 comments on commit 5f58ed5

Please sign in to comment.