Skip to content

Commit

Permalink
feat: autoregistering components. threeds added to registry by defaul…
Browse files Browse the repository at this point in the history
…t. threeds playground page
  • Loading branch information
ribeiroguilherme committed Sep 12, 2023
1 parent 21086ba commit c151b2e
Show file tree
Hide file tree
Showing 32 changed files with 716 additions and 2,056 deletions.
4 changes: 0 additions & 4 deletions packages/lib/src/AdyenCheckout.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
if (process.env.NODE_ENV === 'development') {
require('preact/debug');
}

import { CoreOptions } from './core/types';
import Checkout from './core';
import UIElement from './components/UIElement';
Expand Down
2 changes: 0 additions & 2 deletions packages/lib/src/components/Card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,11 @@ import { ClickToPayCheckoutPayload, IClickToPayService } from '../internal/Click
import ClickToPayWrapper from './components/ClickToPayWrapper';
import { UIElementStatus } from '../types';
import SRPanelProvider from '../../core/Errors/SRPanelProvider';
import { ThreeDS2Challenge, ThreeDS2DeviceFingerprint } from '../ThreeDS2';
import { TxVariants } from '../tx-variants';

export class CardElement extends UIElement<CardElementProps> {
public static type = TxVariants.scheme;
public static txVariants = [TxVariants.scheme, TxVariants.card];
public static dependencies = [ThreeDS2DeviceFingerprint, ThreeDS2Challenge];

private readonly clickToPayService: IClickToPayService | null;

Expand Down
6 changes: 2 additions & 4 deletions packages/lib/src/components/Dropin/Dropin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import createInstantPaymentElements from './elements/createInstantPaymentElement
import { hasOwnProperty } from '../../utils/hasOwnProperty';
import { PaymentMethodsConfiguration, PaymentResponse } from '../types';
import PaymentMethodsResponse from '../../core/ProcessResponse/PaymentMethodsResponse';
import { TxVariants } from '../tx-variants';
import SRPanelProvider from '../../core/Errors/SRPanelProvider';

const SUPPORTED_INSTANT_PAYMENTS = ['paywithgoogle', 'googlepay', 'applepay'];
Expand All @@ -27,13 +26,11 @@ function splitPaymentMethods(paymentMethodsResponse: PaymentMethodsResponse, ins
}

class DropinElement extends UIElement<DropinElementProps> {
public static type = TxVariants.dropin;

protected static defaultProps = defaultProps;

public dropinRef = null;

private paymentMethodsConfiguration: PaymentMethodsConfiguration = {};
private paymentMethodsConfiguration: PaymentMethodsConfiguration;
/**
* Reference to the component created from `handleAction` (Ex.: ThreeDS2Challenge)
*/
Expand All @@ -44,6 +41,7 @@ class DropinElement extends UIElement<DropinElementProps> {
this.submit = this.submit.bind(this);
this.handleAction = this.handleAction.bind(this);

this.props.paymentMethodComponents.forEach(PaymentMethod => this.core.register(PaymentMethod));
this.paymentMethodsConfiguration = this.props.paymentMethodsConfiguration || {};
}

Expand Down
1 change: 1 addition & 0 deletions packages/lib/src/components/Dropin/defaultProps.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export default {
instantPaymentTypes: [],
paymentMethodComponents: [],

isDropin: true,
onReady: () => {}, // triggered when the Dropin is fully loaded
Expand Down
3 changes: 3 additions & 0 deletions packages/lib/src/components/Dropin/elements/createElements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ const createElements = (
const PaymentMethodElement = core.getComponent(paymentMethod.type);

if (!PaymentMethodElement) {
console.warn(
`Dropin: '${paymentMethod.type}' component not found. Make sure to pass its Class to the Dropin 'paymentMethodComponents' parameter`
);
return null;
}

Expand Down
6 changes: 6 additions & 0 deletions packages/lib/src/components/Dropin/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Order, OrderStatus } from '../../types';
import UIElement from '../UIElement';
import { PaymentMethodsConfiguration, UIElementProps, UIElementStatus } from '../types';
import { NewableComponent } from '../../core/core.registry';

export type InstantPaymentTypes = 'paywithgoogle' | 'googlepay' | 'applepay';

Expand All @@ -10,6 +11,11 @@ export interface DropinElementProps extends UIElementProps {
*/
paymentMethodsConfiguration?: PaymentMethodsConfiguration;

/**
* Pass the payment method classes that are going to be used as part of the Drop-in.
*/
paymentMethodComponents?: NewableComponent[];

order?: Order;

/**
Expand Down
2 changes: 0 additions & 2 deletions packages/lib/src/components/SecuredFields/SecuredFields.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { CbObjOnBinLookup } from '../internal/SecuredFields/lib/types';
import { BrandObject } from '../Card/types';
import { getCardImageUrl } from '../internal/SecuredFields/utils';
import { TxVariants } from '../tx-variants';
import { ThreeDS2Challenge, ThreeDS2DeviceFingerprint } from '../ThreeDS2';
import { UIElementProps } from '../types';

interface SecuredFieldProps extends UIElementProps {
Expand All @@ -21,7 +20,6 @@ interface SecuredFieldProps extends UIElementProps {
export class SecuredFieldsElement extends UIElement<SecuredFieldProps> {
public static type = TxVariants.securedfields;
public static txVariants = [TxVariants.securedfields, TxVariants.card];
public static dependencies = [ThreeDS2DeviceFingerprint, ThreeDS2Challenge];

public static analyticsType = 'custom-scheme';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ export interface ThreeDS2DeviceFingerprintProps {
}

class ThreeDS2DeviceFingerprint extends UIElement<ThreeDS2DeviceFingerprintProps> {
public static type = TxVariants.threeDS2DeviceFingerprint; // does it need to be threeDS2Fingerprint? can't be threeDS2DeviceFingerprint?
// public static txVariants = [TxVariants.threeDS2Fingerprint, TxVariants.threeDS2DeviceFingerprint];
public static type = TxVariants.threeDS2DeviceFingerprint;

public static defaultProps = {
dataKey: 'fingerprintResult',
Expand Down
18 changes: 5 additions & 13 deletions packages/lib/src/components/UIElement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import DropinElement from './Dropin';
import { CoreOptions } from '../core/types';
import { Resources } from '../core/Context/Resources';
import { ICore } from '../core/core';
import { NewableComponent } from '../core/core.registry';

export abstract class UIElement<P extends UIElementProps = any> extends BaseElement<P> implements IUIElement {
protected componentRef: any;
Expand All @@ -27,21 +28,10 @@ export abstract class UIElement<P extends UIElementProps = any> extends BaseElem
*/
public static txVariants: string[] = [];

/**
* Defines the extra dependencies (Components) that it is needed for the specific UIElement
* Ex: Card depends on ThreeDS components
*/
public static dependencies: any[] = []; // FIX type

constructor(props?: P) {
super(props);

if (!this.core.getComponent(this.type)) {
throw new AdyenCheckoutError(
'IMPLEMENTATION_ERROR',
`The component of the type '${this.type}' is not registered in the Core. Make sure to register it before instantiating the Component.`
);
}
this.core.register(this.constructor as NewableComponent);

this.submit = this.submit.bind(this);
this.setState = this.setState.bind(this);
Expand All @@ -62,7 +52,9 @@ export abstract class UIElement<P extends UIElementProps = any> extends BaseElem
protected override buildElementProps(componentProps: P) {
const globalCoreProps = this.core.getCorePropsForComponent();
const isStoredPaymentMethod = !!componentProps.isStoredPaymentMethod;
const paymentMethodsResponseProps = isStoredPaymentMethod ? {} : this.core.paymentMethodsResponse.find(this.constructor['type']);
const paymentMethodsResponseProps = isStoredPaymentMethod
? {}
: this.core.paymentMethodsResponse.find(componentProps.type || this.constructor['type']);

const finalProps = {
showPayButton: true,
Expand Down
2 changes: 1 addition & 1 deletion packages/lib/src/components/WeChat/WeChat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { delay, countdownTime } from './config';
import { TxVariants } from '../tx-variants';

class WeChatPayElement extends QRLoaderContainer {
public static type = TxVariants.wechatpay;
public static type = TxVariants.wechatpay; // TO CHECK: seems like wechatpayQR is the default one
public static txVariants = [TxVariants.wechatpay, TxVariants.wechatpayQR];

formatProps(props) {
Expand Down
8 changes: 5 additions & 3 deletions packages/lib/src/components/tx-variants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ export enum TxVariants {
address = 'address',
bankTransfer_IBAN = 'bankTransfer_IBAN',
donation = 'donation',
dropin = 'dropin',
personal_details = 'personal_details',
/** internal */

Expand All @@ -20,11 +19,14 @@ export enum TxVariants {
scheme = 'scheme',
storedCard = 'storedCard',
securedfields = 'securedfields',
visa = 'visa',
/** Card */

/** ThreeDS */
threeDS2Challenge = 'threeDS2Challenge',
threeDS2Fingerprint = 'threeDS2Fingerprint',
threeDS2DeviceFingerprint = 'threeDS2DeviceFingerprint',
visa = 'visa',
/** Card */
/** ThreeDS */

/** Direct debit */
ach = 'ach',
Expand Down
7 changes: 1 addition & 6 deletions packages/lib/src/components/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import QiwiWallet from './QiwiWallet';
import Redirect from './Redirect';
import SecuredFields from './SecuredFields';
import Sepa from './Sepa';
import { ThreeDS2DeviceFingerprint, ThreeDS2Challenge } from './ThreeDS2';
import WeChat from './WeChat';
import PayNow from './PayNow';
import BcmcMobile from './BcmcMobile';
Expand All @@ -50,7 +49,6 @@ import Vipps from './Vipps';
import { PayuCashcard, PayuNetBanking } from './PayU';
import RatePay from './RatePay';
import Swish from './Swish';
import Dropin from './Dropin';
import Ach from './Ach';
import MBWay from './MBWay';
import Blik from './Blik';
Expand All @@ -73,7 +71,7 @@ import OnlineBankingSKElement from './OnlineBankingSK';
import PayByBank from './PayByBank';
import PromptPay from './PromptPay';
import Duitnow from './DuitNow';
import Trustly from "./Trustly";
import Trustly from './Trustly';
import { TxVariants } from './tx-variants';
import { PaymentActionsType } from '../types';

Expand All @@ -85,7 +83,6 @@ const componentsMap = {
[TxVariants.address]: Address,
[TxVariants.bankTransfer_IBAN]: BankTransfer,
[TxVariants.donation]: Donation,
[TxVariants.dropin]: Dropin,
[TxVariants.personal_details]: PersonalDetails,
/** internal */

Expand All @@ -102,8 +99,6 @@ const componentsMap = {
[TxVariants.scheme]: Card,
[TxVariants.storedCard]: Card,
[TxVariants.securedfields]: SecuredFields,
[TxVariants.threeDS2Challenge]: ThreeDS2Challenge,
[TxVariants.threeDS2Fingerprint]: ThreeDS2DeviceFingerprint,
[TxVariants.visa]: Card,
/** Card */

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ const actionTypes = {
statusType: 'loading',
useOriginalFlow: true
};

return createComponent(core, registry, 'threeDS2DeviceFingerprint', config);
},

Expand All @@ -71,7 +70,6 @@ const actionTypes = {
statusType: 'custom',
useOriginalFlow: true
};

return createComponent(core, registry, 'threeDS2Challenge', config);
},

Expand Down
32 changes: 15 additions & 17 deletions packages/lib/src/core/core.registry.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import UIElement from '../components/UIElement';
import Redirect from '../components/Redirect/Redirect';
import { ThreeDS2Challenge, ThreeDS2DeviceFingerprint, Redirect } from '../components';
import { TxVariants } from '../components/tx-variants';

function assertIsTypeofUIElement(item: any): item is typeof UIElement {
Expand All @@ -13,12 +13,22 @@ export interface IRegistry {
getComponent(type: string): NewableComponent | undefined;
}

const defaultComponents = {
[TxVariants.redirect]: Redirect,
[TxVariants.threeDS2Challenge]: ThreeDS2Challenge,
[TxVariants.threeDS2DeviceFingerprint]: ThreeDS2DeviceFingerprint
};

class Registry implements IRegistry {
public componentsMap: Record<string, NewableComponent> = {};
public componentsMap: Record<string, NewableComponent> = defaultComponents;

public supportedTxVariants: Set<string> = new Set(Object.values(TxVariants));

public add(...items: NewableComponent[]) {
this.componentsMap = this.createComponentsMap(items);
this.componentsMap = {
...this.componentsMap,
...this.createComponentsMap(items)
};
}

public getComponent(type: string): NewableComponent | undefined {
Expand All @@ -28,9 +38,7 @@ class Registry implements IRegistry {
}

if (this.supportedTxVariants.has(type)) {
console.warn(
`Core Registry: The component of '${type}' is unavailable. Make sure to register its Class before mounting the Payment method.`
);
console.warn(`CoreRegistry: The component of '${type}' is supported, but it is not registered internally.`);
return;
}

Expand All @@ -53,20 +61,10 @@ class Registry implements IRegistry {
};
});

component.dependencies.forEach(dependency => {
memo = {
...memo,
[dependency.type]: dependency
};
});
return memo;
}, {});

// TO CHECK: Should we add the threeDS ones here too as part of the includes ones? Doing so, we can get rid of the Element.dependencies = [] variable
return {
...componentsMap,
redirect: Redirect
};
return componentsMap;
}
}

Expand Down
11 changes: 9 additions & 2 deletions packages/lib/src/core/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@ import { SRPanel } from './Errors/SRPanel';
import registry, { NewableComponent } from './core.registry';
import { DEFAULT_LOCALE } from '../language/config';

console.log(registry);

export interface ICore {
initialize(): Promise<ICore>;
register(...items: NewableComponent[]): void;
update({ order }: { order?: Order }): Promise<ICore>;
remove(component): ICore;
submitDetails(details: any): void;
Expand Down Expand Up @@ -54,6 +53,14 @@ class Core implements ICore {
registry.add(...items);
}

/**
* Used internally by the PaymentMethod components to auto-register themselves
* @internal
*/
public register(...items: NewableComponent[]) {
registry.add(...items);
}

public getComponent(txVariant: string) {
return registry.getComponent(txVariant);
}
Expand Down
1 change: 1 addition & 0 deletions packages/playground/config/webpack.dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const htmlPages = [
{ name: 'Open Invoices', id: 'OpenInvoices' },
{ name: 'QR Codes', id: 'QRCodes' },
{ name: 'Custom Cards', id: 'SecuredFields' },
{ name: 'ThreeDS2', id: 'ThreeDS' },
{ name: 'Vouchers', id: 'Vouchers' },
{ name: 'Wallets', id: 'Wallets' },
{ name: 'Result', id: 'Result' }
Expand Down
9 changes: 9 additions & 0 deletions packages/playground/src/pages/Cards/Cards.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ <h2>Card</h2>
</div>
</div>

<div class="merchant-checkout__payment-method">
<div class="merchant-checkout__payment-method__header">
<h2>Card with Installments</h2>
</div>
<div class="merchant-checkout__payment-method__details">
<div class="card-field-installments"></div>
</div>
</div>

<div class="merchant-checkout__payment-method">
<div class="merchant-checkout__payment-method__header">
<h2>Card with Click to Pay</h2>
Expand Down
Loading

0 comments on commit c151b2e

Please sign in to comment.