Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
63 changes: 33 additions & 30 deletions src/components/AdyenCheckout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,13 @@ import React, {
useState,
useMemo,
} from 'react';
import {
type EmitterSubscription,
NativeEventEmitter,
type NativeModule,
} from 'react-native';
import { type EmitterSubscription, NativeEventEmitter } 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';
} from '../modules/session/SessionHelperModule';
import type {
AdyenError,
PaymentMethodsResponse,
Expand All @@ -28,15 +23,19 @@ import type {
SubmitModel,
Order,
SessionsResult,
RemovesStoredPayment,
} 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';
import type {
AddressLookup,
AddressLookupItem,
} from '../core/configurations/AddressLookup';
import { AdyenCheckoutContext } from '../hooks/useAdyenCheckout';
import type { PartialPaymentComponent } from '../core/configurations/PartialPaymentConfiguration';
import { getWrapper } from '../modules/base/getWrapper';
import type { EventListenerWrapper } from '../modules/base/EventListenerWrapper';

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

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

Expand All @@ -145,32 +144,39 @@ 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 = [
eventEmitter.addListener(Event.onSubmit, (response: SubmitModel) =>
submitPayment(response.paymentData, response.extra)
),
eventEmitter.addListener(Event.onError, (error: AdyenError) =>
onError?.(error, nativeComponent)
onError?.(error, nativeComponent as unknown as AdyenComponent)
),
];

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

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 +185,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 +210,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 +237,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 +283,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';
35 changes: 0 additions & 35 deletions src/core/AdyenCheckoutError.ts

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
15 changes: 14 additions & 1 deletion src/core/configurations/PartialPaymentConfiguration.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { PartialPaymentComponent } from '../../wrappers/PartialPaymentsComponentWrapper';
import type { AdyenComponent } from '../AdyenNativeModules';
import type { Balance, Order, PaymentMethodData } from '../types';

export interface PartialPaymentConfiguration {
Expand Down Expand Up @@ -44,3 +44,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';
16 changes: 1 addition & 15 deletions src/core/constants.ts
Original file line number Diff line number Diff line change
@@ -1,17 +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';

Expand All @@ -38,7 +24,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';
78 changes: 61 additions & 17 deletions src/core/types.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,6 @@
import type { Configuration } from './configurations/Configuration';
import type { ResultCode } from './constants';

/**
* General type for card.
*/
export class Card {
/** PAN of card. */
number?: string;

/** Month in format MM. */
expiryMonth?: string;

/** Year in format YYYY. */
expiryYear?: string;

/** 3 or 4 digits. */
cvv?: string;
}

/**
* {@link https://docs.adyen.com/api-explorer/Checkout/70/post/payments#responses-200-action API Explorer /payments action}
*/
Expand Down Expand Up @@ -287,3 +271,63 @@ export type SessionsResult = {
*/
sessionData: string;
};

/**
* Interface for removing stored payment method.
*/
export interface RemovesStoredPayment {
removeStored(success: boolean): void;
}

/**
* Options for dismissing the payment component.
*/
export interface HideOption {
/** Alert message after dismiss. Used for Android DropIn and Components only */
message?: string;
}

/**
* Universal interface for an Adyen Native module.
*/
export interface AdyenComponent {
/**
* Dismiss the component from the screen.
* @param success - Indicates whether the component was dismissed successfully.
* @param option - Additional options for dismissing the component (optional).
*/
hide(success: boolean, option?: HideOption): void;
}

/**
* Universal interface for an Adyen Native payment component.
*/
export interface AdyenPaymentComponent extends AdyenComponent {
/**
* Show the component above the current screen.
* @param paymentMethods - The available payment methods.
* @param configuration - The configuration for the component.
*/
open(paymentMethods: PaymentMethodsResponse, configuration: any): void;
}

/**
* Describes an Adyen Component capable of handling payment actions.
*/
export interface AdyenActionComponent extends AdyenPaymentComponent {
/**
* Handle a payment action received by the component.
* @param action - The payment action to be handled.
*/
handle(action: PaymentAction): void;
}

/**
* Describes an Adyen Component capable of handling payment action if specific conditions are met.
*/
export interface ConditionalPaymentComponent extends AdyenComponent {
isAvailable(
paymentMethods: PaymentMethod,
configuration: Configuration
): Promise<boolean>;
}
2 changes: 2 additions & 0 deletions src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { useAdyenCheckout } from './useAdyenCheckout';
export type { AdyenCheckoutContextValue } from './useAdyenCheckout';
Loading
Loading