From d113dc80352967214287e47094217e2626c12f85 Mon Sep 17 00:00:00 2001 From: simbirromanmakarov Date: Tue, 22 Aug 2023 11:40:30 +0400 Subject: [PATCH 1/3] fix(PAYMENTS-15239): emit selected method id on li element click --- .../payment-method-attributes.enum.ts | 3 +++ .../payment-method.template.ts | 4 ++-- .../payment-methods.component.ts | 23 ++++++++----------- 3 files changed, 15 insertions(+), 15 deletions(-) create mode 100644 src/features/headless-checkout/web-components/payment-methods/payment-method-attributes.enum.ts diff --git a/src/features/headless-checkout/web-components/payment-methods/payment-method-attributes.enum.ts b/src/features/headless-checkout/web-components/payment-methods/payment-method-attributes.enum.ts new file mode 100644 index 0000000..7d6f0de --- /dev/null +++ b/src/features/headless-checkout/web-components/payment-methods/payment-method-attributes.enum.ts @@ -0,0 +1,3 @@ +export enum PaymentMethodAttributes { + methodId = 'data-method-id', +} diff --git a/src/features/headless-checkout/web-components/payment-methods/payment-method.template.ts b/src/features/headless-checkout/web-components/payment-methods/payment-method.template.ts index bf4a7f2..137f411 100644 --- a/src/features/headless-checkout/web-components/payment-methods/payment-method.template.ts +++ b/src/features/headless-checkout/web-components/payment-methods/payment-method.template.ts @@ -11,8 +11,8 @@ export const getPaymentMethodTemplate = (method: PaymentMethod): string => { } else { iconName = method.iconName; } - return `
  • - + return `
  • + ${method.name} diff --git a/src/features/headless-checkout/web-components/payment-methods/payment-methods.component.ts b/src/features/headless-checkout/web-components/payment-methods/payment-methods.component.ts index 310d9e0..6626838 100644 --- a/src/features/headless-checkout/web-components/payment-methods/payment-methods.component.ts +++ b/src/features/headless-checkout/web-components/payment-methods/payment-methods.component.ts @@ -7,6 +7,7 @@ import { PaymentMethodsAttributes } from './payment-methods-attributes.enum'; import { PaymentMethodsEvents } from './payment-methods-events.enum'; import { HeadlessCheckoutSpy } from '../../../../core/spy/headless-checkout-spy/headless-checkout-spy'; import { HeadlessCheckout } from '../../headless-checkout'; +import { PaymentMethodAttributes } from './payment-method-attributes.enum'; export class PaymentMethodsComponent extends WebComponentAbstract { private readonly headlessCheckout: HeadlessCheckout; @@ -43,9 +44,7 @@ export class PaymentMethodsComponent extends WebComponentAbstract { this.headlessCheckoutSpy.listenAppInit(() => this.connectedCallback()); return; } - void this.headlessCheckout - .getRegularMethods() - .then(this.paymentMethodsLoadedHandler); + this.loadRegularMethods(); } protected getHtml(): string { @@ -62,8 +61,14 @@ export class PaymentMethodsComponent extends WebComponentAbstract { if (!this.headlessCheckoutSpy.appWasInit) { return; } + this.loadRegularMethods(); + } + + private loadRegularMethods(): void { + const country = + this.getAttribute(PaymentMethodsAttributes.country) ?? undefined; void this.headlessCheckout - .getRegularMethods() + .getRegularMethods(country) .then(this.paymentMethodsLoadedHandler); } @@ -115,15 +120,7 @@ export class PaymentMethodsComponent extends WebComponentAbstract { } private getPaymentMethodId(target: HTMLElement): string | null | undefined { - const attributeName = 'data-method-id'; - - if (typeof target?.closest === 'function') { - return target.closest('a')?.getAttribute(attributeName); - } - return ( - target.getAttribute(attributeName) ?? - target.parentElement?.getAttribute(attributeName) - ); + return target.closest('li')?.getAttribute(PaymentMethodAttributes.methodId); } private setupSearch(): void { From f1cbbe9eb976dabace057e45baadde1442016d1d Mon Sep 17 00:00:00 2001 From: simbirromanmakarov Date: Tue, 22 Aug 2023 12:14:11 +0400 Subject: [PATCH 2/3] fix(PAYMENTS-15239): change text component selector --- src/core/web-components/web-component-tag-name.enum.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/web-components/web-component-tag-name.enum.ts b/src/core/web-components/web-component-tag-name.enum.ts index 68c9c03..0cdbbdc 100644 --- a/src/core/web-components/web-component-tag-name.enum.ts +++ b/src/core/web-components/web-component-tag-name.enum.ts @@ -1,5 +1,5 @@ export enum WebComponentTagName { - TextComponent = 'psdk-text-component', + TextComponent = 'psdk-text', SubmitButtonComponent = 'psdk-submit-button', PaymentMethodsComponent = 'psdk-payment-methods', PriceTextComponent = 'psdk-price-text', From 19003b125c0265da23328098832c4fa06b6d9384 Mon Sep 17 00:00:00 2001 From: simbirromanmakarov Date: Tue, 22 Aug 2023 12:15:16 +0400 Subject: [PATCH 3/3] docs(PAYMENTS-15239): add paypal integration guide --- README.md | 120 +++++++++----- examples/paypal/index.html | 174 +++++++++++++++++++++ examples/{cdn => select-method}/index.html | 7 +- 3 files changed, 256 insertions(+), 45 deletions(-) create mode 100644 examples/paypal/index.html rename examples/{cdn => select-method}/index.html (92%) diff --git a/README.md b/README.md index d099add..5be8952 100644 --- a/README.md +++ b/README.md @@ -40,12 +40,17 @@ Except for secure inputs, the client has full control over the component's style ## PaymentSdk library interface ```typescript -declare const HeadlessCheckout: { +declare const headlessCheckout: { /** * Load secure Core Iframe. * Load components to CustomElementRegistry. https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry */ - init(environment: { isWebview: boolean }): Promise; + init(environment: { isWebview?: boolean; sandbox?: boolean }): Promise; + + /** + * Remove secure Core Iframe. + */ + destroy(): void; /** * Initialize the payment with a token. @@ -54,19 +59,29 @@ declare const HeadlessCheckout: { setToken(token: string): Promise; /** - * Get all payment methods, including saved accounts. - * Use a country token if it hasn't been passed yet. - * regular - list of available payment methods sorted according to relevance. - * quick - list of available quick payment methods, e.g., Google and Apple Pay buttons. - * saved - list of saved user payment accounts. - * balance - special payment method for users that have an Xsolla balance. Null if the balance is not sufficient for the payment. + * Returns available payment methods, excluding quick payment options. + */ + getRegularMethods(country?: string): Promise; + + /** + * Returns available quick payment options, e.g., Apple Pay, Google Pay. + */ + getQuickMethods(country?: string): Promise; + + /** + * Returns a user’s saved methods. */ - getMethods(country?: string): Promise<{ - regular: PaymentMethod[]; - quick: PaymentMethod[]; - saved: Account[]; - balance: PaymentMethod | null; - }>; + getSavedMethods(): Promise; + + /** + * Returns a user’s balance. + */ + getUserBalance(): Promise; + + /** + * Returns financial information about the payment. + */ + getFinanceDetails(): Promise; /** * Payment form. @@ -129,11 +144,6 @@ declare const HeadlessCheckout: { */ getStatus(invoiceId?: number): Promise; - /** - * Delete saved user account. - */ - deleteAccount(accountId: number): Promise; - /** * Can be used instead of SDK components for creating custom components. * List of events will be added later. @@ -143,11 +153,6 @@ declare const HeadlessCheckout: { onCoreEvent: (event: Event) => void; send(event: Event): void; }; - - /** - * Create an iframe with secure elements like form input and use it for component creation. - */ - createSecureComponent(name: string): HTMLIFrameElement; }; ``` @@ -157,19 +162,19 @@ declare const HeadlessCheckout: { | **Component** | **Selector** | **Status** | | --------------------- | -------------------- | ---------- | -| Apple Pay Button | ❔ | πŸ•‘ | -| Checkbox | ❔ | πŸ•‘ | -| Delete Account Button | ❔ | πŸ•‘ | -| Finance Details | ❔ | πŸ•‘ | -| Google Pay Button | ❔ | πŸ•‘ | -| Payment Form Messages | ❔ | πŸ•‘ | | Payment Methods | psdk-payment-methods | βœ… | -| Receipt | ❔ | πŸ•‘ | | Saved Methods | ❔ | πŸ•‘ | +| Payment Form Messages | ❔ | πŸ•‘ | +| Checkbox | ❔ | πŸ•‘ | | Select | ❔ | πŸ•‘ | -| Status | ❔ | πŸ•‘ | -| Submit | psdk-submit-button | βœ… | +| Apple Pay Button | ❔ | πŸ•‘ | +| Google Pay Button | ❔ | πŸ•‘ | +| Delete Account Button | ❔ | πŸ•‘ | +| Submit Button | psdk-submit-button | βœ… | | User Balance | ❔ | πŸ•‘ | +| Finance Details | psdk-finance-details | βœ… | +| Status | psdk-status | βœ… | +| Receipt | ❔ | πŸ•‘ | ![Regular SDK web components](./readme_images/sdk_web_components_scheme.png 'Regular SDK web components') @@ -181,11 +186,11 @@ Using SDK components is straightforward: you only need to paste the HTML tag of ### Secure components -| **Component** | **Selector** | **Status** | -| --------------------- | ---------------- | ---------- | -| Card Number Component | psdk-card-number | βœ… | -| Phone Component | ❔ | πŸ•‘ | -| Text Component | ❔ | πŸ•‘ | +| **Component** | **Selector** | **Status** | +| --------------------- | ------------ | ---------- | +| Text Component | psdk-text | βœ… | +| Phone Component | ❔ | πŸ•‘ | +| Card Number Component | ❔ | πŸ•‘ | ![SDK secure componentscheme](./readme_images/secure_component_scheme.png 'SDK secure componentscheme') @@ -197,10 +202,10 @@ Secure components have access to sensitive user data, and are encapsulated in if ### Special components -| **Component** | **Selector** | **Status** | -| ------------- | ------------ | ---------- | -| Legal | ❔ | πŸ•‘ | -| Payment Form | ❔ | πŸ•‘ | +| **Component** | **Selector** | **Status** | +| ------------- | ----------------- | ---------- | +| Legal | psdk-legal | βœ… | +| Payment Form | psdk-payment-form | βœ… | The `Payment Form` component creates missed payment form components to ensure the client does not omit required payment form components. The client receives a warning message from the SDK, but still allows users to complete the payment. @@ -233,7 +238,7 @@ The `Legal` component contains information about Xsolla's legal documents. Clien To start using the Pay Station SDK, include the SDK bundle in your project. You can do this in any convenient way, such as adding the SDK bundle as npm-package or simply adding a CDN link in the ` + + + +

    PayPal payment integration

    + +
    +
    + + + + + + + + + + + diff --git a/examples/cdn/index.html b/examples/select-method/index.html similarity index 92% rename from examples/cdn/index.html rename to examples/select-method/index.html index 2be2b0f..35f8f48 100644 --- a/examples/cdn/index.html +++ b/examples/select-method/index.html @@ -31,6 +31,7 @@

    Pay Station SDK

    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, @@ -40,6 +41,7 @@

    Pay Station SDK

    if (!accessToken) { alert(`No token provided. Please, check the documentation`); + throw new Error('No token provided'); } async function initPayStationSdk() { /** @@ -56,6 +58,7 @@

    Pay Station SDK

    */ await headlessCheckout.init({ isWebView: false, + sandbox: true, }); /** @@ -75,8 +78,8 @@

    Pay Station SDK

    * To add extra logic to a component, you can subscribe to * its events and place your code in a callback function. */ - paymentMethods.addEventListener('selectionChange', (e) => { - console.log(e); + paymentMethods.addEventListener('selectionChange', (event) => { + console.log(event.detail); }); }