Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
357 changes: 357 additions & 0 deletions docs/Architecture.md

Large diffs are not rendered by default.

81 changes: 40 additions & 41 deletions src/components/AdyenCheckout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,32 @@ import React, {
useState,
useMemo,
} from 'react';
import {
type EmitterSubscription,
NativeEventEmitter,
type NativeModule,
} from 'react-native';
import { Event } from '../core/constants';
import type { AdyenComponent } from '../core/AdyenNativeModules';
import {
SessionHelper,
type SessionContext,
} from '../modules/SessionHelperModule';
import { getWrapper } from '../wrappers/getWrapper';
import { type EmitterSubscription, NativeEventEmitter } from 'react-native';
import type {
AddressLookup,
AddressLookupItem,
AdyenActionComponent,
AdyenComponent,
AdyenError,
Configuration,
Order,
PartialPaymentComponent,
PaymentDetailsData,
PaymentMethodData,
PaymentMethodsResponse,
SessionConfiguration,
PaymentMethodData,
PaymentDetailsData,
SessionsResult,
StoredPaymentMethod,
SubmitModel,
Order,
SessionsResult,
} from '../core/types';
import type { Configuration } from '../core/configurations/Configuration';
import { checkPaymentMethodsResponse, checkConfiguration } from '../core/utils';
import type { AddressLookup } from '../wrappers/AddressLookupComponentWrapper';
import type { AdyenActionComponent } from '../core/AdyenNativeModules';
import type { RemovesStoredPayment } from '../wrappers/RemoveStoredPaymentComponentWrapper';
import type { AddressLookupItem } from '../core/configurations/AddressLookup';
import type { PartialPaymentComponent } from '../wrappers/PartialPaymentsComponentWrapper';
} from '../core';
import { Event } from '../core';
import { AdyenCheckoutContext } from '../hooks/useAdyenCheckout';
import { getWrapper } from '../modules/base/getWrapper';
import { SessionHelper } from '../modules/session/SessionHelperModule';
import type { SessionContext } from '../modules/session/types';
import { checkConfiguration, checkPaymentMethodsResponse } from './utils';
import type { RemovesStoredPayment } from '../modules/dropin/DropInWrapper';
import type { ModuleWrapper } from '../modules/base/ModuleWrapper';

/**
* Props for AdyenCheckout
Expand Down Expand Up @@ -136,7 +131,7 @@ export const AdyenCheckout: React.FC<AdyenCheckoutProps> = ({
}, [session, sessionContext, config, onError, setSessionContext]);

const startEventListeners = useCallback(
(nativeComponent: AdyenActionComponent & NativeModule) => {
(nativeComponent: ModuleWrapper) => {
removeEventListeners();
const eventEmitter = new NativeEventEmitter(nativeComponent);

Expand All @@ -145,7 +140,11 @@ export const AdyenCheckout: React.FC<AdyenCheckoutProps> = ({
...data,
returnUrl: data.returnUrl ?? config.returnUrl,
};
onSubmit?.(payload, nativeComponent, extra);
onSubmit?.(
payload,
nativeComponent as unknown as AdyenActionComponent,
extra
);
}

subscriptions.current = [
Expand All @@ -157,20 +156,23 @@ export const AdyenCheckout: React.FC<AdyenCheckoutProps> = ({
),
];

if (nativeComponent.events.includes(Event.onComplete)) {
if (nativeComponent.isSupported(Event.onComplete)) {
subscriptions.current.push(
eventEmitter.addListener(Event.onComplete, (data: any) =>
onComplete?.(data, nativeComponent)
)
);
}

if (nativeComponent.events.includes(Event.onAdditionalDetails)) {
if (nativeComponent.isSupported(Event.onAdditionalDetails)) {
subscriptions.current.push(
eventEmitter.addListener(
Event.onAdditionalDetails,
(data: PaymentDetailsData) =>
onAdditionalDetails?.(data, nativeComponent)
onAdditionalDetails?.(
data,
nativeComponent as unknown as AdyenActionComponent
)
)
);
}
Expand All @@ -179,7 +181,7 @@ export const AdyenCheckout: React.FC<AdyenCheckoutProps> = ({
config.dropin?.onDisableStoredPaymentMethod;
if (
onDisableStoredPaymentMethodCallback &&
nativeComponent.events.includes(Event.onDisableStoredPaymentMethod)
nativeComponent.isSupported(Event.onDisableStoredPaymentMethod)
) {
const nativeModule = nativeComponent as unknown as RemovesStoredPayment;
subscriptions.current.push(
Expand All @@ -204,8 +206,8 @@ export const AdyenCheckout: React.FC<AdyenCheckoutProps> = ({
if (
onUpdateAddressCallback &&
onConfirmAddressCallback &&
nativeComponent.events.includes(Event.onAddressUpdate) &&
nativeComponent.events.includes(Event.onAddressConfirm)
nativeComponent.isSupported(Event.onAddressUpdate) &&
nativeComponent.isSupported(Event.onAddressConfirm)
) {
const nativeModule = nativeComponent as unknown as AddressLookup;
subscriptions.current.push(
Expand All @@ -231,9 +233,9 @@ export const AdyenCheckout: React.FC<AdyenCheckoutProps> = ({
onBalanceCheckCallback &&
onOrderRequestCallback &&
onOrderCancelCallback &&
nativeComponent.events.includes(Event.onCheckBalance) &&
nativeComponent.events.includes(Event.onRequestOrder) &&
nativeComponent.events.includes(Event.onCancelOrder)
nativeComponent.isSupported(Event.onCheckBalance) &&
nativeComponent.isSupported(Event.onRequestOrder) &&
nativeComponent.isSupported(Event.onCancelOrder)
) {
const component = nativeComponent as unknown as PartialPaymentComponent;
subscriptions.current.push(
Expand Down Expand Up @@ -277,18 +279,15 @@ export const AdyenCheckout: React.FC<AdyenCheckoutProps> = ({
const onBinLookupCallback = config.card?.onBinLookup;
if (
onBinLookupCallback &&
nativeComponent.events.includes(Event.onBinLookuop)
nativeComponent.isSupported(Event.onBinLookup)
) {
subscriptions.current.push(
eventEmitter.addListener(Event.onBinLookuop, onBinLookupCallback)
eventEmitter.addListener(Event.onBinLookup, onBinLookupCallback)
);
}

const onBinValueCallback = config.card?.onBinValue;
if (
onBinValueCallback &&
nativeComponent.events.includes(Event.onBinValue)
) {
if (onBinValueCallback && nativeComponent.isSupported(Event.onBinValue)) {
subscriptions.current.push(
eventEmitter.addListener(Event.onBinValue, onBinValueCallback)
);
Expand Down
4 changes: 4 additions & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './GooglePayButton';
export * from './ApplePayButton';
export { AdyenCheckout } from './AdyenCheckout';
export type { AdyenCheckoutProps } from './AdyenCheckout';
3 changes: 1 addition & 2 deletions src/core/utils.ts → src/components/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Platform } from 'react-native';
import type { Configuration } from './configurations/Configuration';
import type { PaymentMethodsResponse } from './types';
import type { Configuration, PaymentMethodsResponse } from '../core';

export const checkPaymentMethodsResponse = (
paymentMethodsResponse: PaymentMethodsResponse | undefined
Expand Down
35 changes: 0 additions & 35 deletions src/core/AdyenCheckoutError.ts

This file was deleted.

64 changes: 0 additions & 64 deletions src/core/AdyenNativeModules.tsx

This file was deleted.

21 changes: 0 additions & 21 deletions src/ComponentMap.ts → src/core/components.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,3 @@
import { type PaymentMethodsResponse } from './core/types';

/**
* Find payment method in JSON response or \paymentMethods API
*/
export function find(paymentMethods: PaymentMethodsResponse, typeName: string) {
return paymentMethods.paymentMethods.find(
(pm) => pm.type === mapCreatedComponentType(typeName)
);
}

/**
* Map component name to txVariable name from \paymentMethod response
* @param {string} pmType
* @returns {string} matching txVariable name or original name
*/
function mapCreatedComponentType(pmType: string) {
// Components created as 'card' need to be matched with paymentMethod response objects with type 'scheme'
return pmType === 'card' ? 'scheme' : pmType;
}

export const UNSUPPORTED_PAYMENT_METHODS = [
/** Payment methods that might be interpreted as redirect, but are actually not supported */
'wechatpayMiniProgram',
Expand Down
21 changes: 19 additions & 2 deletions src/core/configurations/PartialPaymentConfiguration.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import type { PartialPaymentComponent } from '../../wrappers/PartialPaymentsComponentWrapper';
import type { Balance, Order, PaymentMethodData } from '../types';
import type {
AdyenComponent,
Balance,
Order,
PaymentMethodData,
} from '../types';

export interface PartialPaymentConfiguration {
/**
Expand Down Expand Up @@ -44,3 +48,16 @@ export interface PartialPaymentConfiguration {
component: PartialPaymentComponent
): void;
}

export interface PartialPaymentComponent extends AdyenComponent {
provideBalance(
success: boolean,
balance: Balance | undefined,
error: Error | undefined
): void;
provideOrder(
success: boolean,
order: Order | undefined,
error: Error | undefined
): void;
}
8 changes: 8 additions & 0 deletions src/core/configurations/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export type * from './PartialPaymentConfiguration';
export type * from './AddressLookup';
export type * from './ThreeDSConfiguration';
export type * from './GooglePayConfiguration';
export type * from './CardsConfiguration';
export type * from './ApplePayConfiguration';
export type * from './DropInConfiguration';
export type * from './Configuration';
19 changes: 1 addition & 18 deletions src/core/constants.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,3 @@
import { Platform } from 'react-native';

export const UNKNOWN_PAYMENT_METHOD_ERROR =
'Unknown payment method or native module. \n\n' +
'Make sure your paymentMethods response contains: ';

export const UNSUPPORTED_PAYMENT_METHOD_ERROR = 'Unsupported payment method: ';

export const LINKING_ERROR =
`The package '@adyen/react-native' doesn't seem to be linked. Make sure: \n\n` +
Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
'- You rebuilt the app after installing the package\n' +
'- You are not using Expo managed workflow\n';

export const MISSING_CONTEXT_ERROR =
'useAdyenCheckout must be used within an AdyenCheckout';

/** Collection of events that components can trigger. */
export enum Event {
/** Event handler, called when the shopper selects the Pay button and payment details are valid. */
Expand All @@ -38,7 +21,7 @@ export enum Event {
/** Event handler, called when the partial payment order was canceled. */
onCancelOrder = `didCancelOrderCallback`,
/** Event handler, called when the BIN lookup data is available. */
onBinLookuop = `didBinLookupCallback`,
onBinLookup = `didBinLookupCallback`,
/** Event handler, called when the BIN (first 6 or 8 PAN digits) typed by the shopper in the PAN field changes. */
onBinValue = `didChangeBinValueCallback`,
}
Expand Down
4 changes: 4 additions & 0 deletions src/core/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export type * from './types';
export * from './constants';
export * from './configurations';
export * from './components';
Loading
Loading