UNPKG

@adyen/react-native

Version:

Wraps Adyen Checkout Drop-In and Components for iOS and Android for convenient use with React Native

165 lines (160 loc) 7.24 kB
import React, { useRef, useCallback, createContext, useEffect, useContext, useState } from 'react'; import { NativeEventEmitter } from 'react-native'; import { Event, MISSING_CONTEXT_ERROR } from './core/constants'; import { SessionHelper } from './modules/SessionHelperModule'; import { getWrapper } from './wrappers/getWrapper'; import { checkPaymentMethodsResponse, checkConfiguration } from './core/utils'; /** * Returns AdyenCheckout context. This context allows you to initiate payment with Drop-in or any payment method available in `paymentMethods` collection. */ const AdyenCheckoutContext = /*#__PURE__*/createContext(null); /** * Returns AdyenCheckout context. This context allows you to initiate payment with Drop-in or any payment method available in `paymentMethods` collection. */ const useAdyenCheckout = () => { const context = useContext(AdyenCheckoutContext); if (context != null) { return context; } throw new Error(MISSING_CONTEXT_ERROR); }; /** * Props for AdyenCheckout */ const AdyenCheckout = ({ config, paymentMethods, session, onSubmit, onError, onAdditionalDetails, onComplete, children }) => { const subscriptions = useRef([]); const [sessionStorage, setSession] = useState(undefined); useEffect(() => { return () => { removeEventListeners(); }; }, []); useEffect(() => { if (session) { createSession(); } }, [session]); const submitPayment = useCallback((configuration, data, nativeComponent, extra) => { const payload = { ...data, returnUrl: data.returnUrl ?? configuration.returnUrl }; onSubmit?.(payload, nativeComponent, extra); }, [onSubmit]); const removeEventListeners = useCallback(() => { subscriptions.current.forEach(s => s.remove()); }, [subscriptions]); const startEventListeners = useCallback((configuration, nativeComponent) => { const eventEmitter = new NativeEventEmitter(nativeComponent); subscriptions.current = [eventEmitter.addListener(Event.onSubmit, response => submitPayment(configuration, response.paymentData, nativeComponent, response.extra)), eventEmitter.addListener(Event.onError, error => onError?.(error, nativeComponent))]; if (nativeComponent.events.includes(Event.onComplete)) { subscriptions.current.push(eventEmitter.addListener(Event.onComplete, data => onComplete?.(data, nativeComponent))); } if (nativeComponent.events.includes(Event.onAdditionalDetails)) { subscriptions.current.push(eventEmitter.addListener(Event.onAdditionalDetails, data => onAdditionalDetails?.(data, nativeComponent))); } const onDisableStoredPaymentMethodCallback = configuration.dropin?.onDisableStoredPaymentMethod; if (onDisableStoredPaymentMethodCallback && nativeComponent.events.includes(Event.onDisableStoredPaymentMethod)) { const nativeModule = nativeComponent; subscriptions.current.push(eventEmitter.addListener(Event.onDisableStoredPaymentMethod, data => onDisableStoredPaymentMethodCallback(data, () => { nativeModule.removeStored(true); }, () => { nativeModule.removeStored(false); }))); } const onUpdateAddressCallback = configuration.card?.onUpdateAddress; const onConfirmAddressCallback = configuration.card?.onConfirmAddress; if (onUpdateAddressCallback && onConfirmAddressCallback && nativeComponent.events.includes(Event.onAddressUpdate) && nativeComponent.events.includes(Event.onAddressConfirm)) { const nativeModule = nativeComponent; subscriptions.current.push(eventEmitter.addListener(Event.onAddressUpdate, async prompt => { onUpdateAddressCallback(prompt, nativeModule); }), eventEmitter.addListener(Event.onAddressConfirm, address => { onConfirmAddressCallback(address, nativeModule); })); } const onBalanceCheckCallback = configuration.partialPayment?.onBalanceCheck; const onOrderRequestCallback = configuration.partialPayment?.onOrderRequest; const onOrderCancelCallback = configuration.partialPayment?.onOrderCancel; if (onBalanceCheckCallback && onOrderRequestCallback && onOrderCancelCallback && nativeComponent.events.includes(Event.onCheckBalance) && nativeComponent.events.includes(Event.onRequestOrder) && nativeComponent.events.includes(Event.onCancelOrder)) { const component = nativeComponent; subscriptions.current.push(eventEmitter.addListener(Event.onCheckBalance, async paymentData => { onBalanceCheckCallback(paymentData, balance => { component.provideBalance(true, balance, undefined); }, error => { component.provideBalance(false, undefined, error); }); }), eventEmitter.addListener(Event.onRequestOrder, () => { onOrderRequestCallback(order => { component.provideOrder(true, order, undefined); }, error => { component.provideOrder(false, undefined, error); }); }), eventEmitter.addListener(Event.onCancelOrder, ({ order, shouldUpdatePaymentMethods }) => { onOrderCancelCallback(order, shouldUpdatePaymentMethods, component); })); } const onBinLookupCallback = configuration.card?.onBinLookup; if (onBinLookupCallback && nativeComponent.events.includes(Event.onBinLookuop)) { subscriptions.current.push(eventEmitter.addListener(Event.onBinLookuop, onBinLookupCallback)); } const onBinValueCallback = configuration.card?.onBinValue; if (onBinValueCallback && nativeComponent.events.includes(Event.onBinValue)) { subscriptions.current.push(eventEmitter.addListener(Event.onBinValue, onBinValueCallback)); } }, [submitPayment, onAdditionalDetails, onComplete, onError, subscriptions]); const start = useCallback(typeName => { removeEventListeners(); const currentPaymentMethods = checkPaymentMethodsResponse(paymentMethods ?? sessionStorage?.paymentMethods); const { nativeComponent, paymentMethod } = getWrapper(typeName, currentPaymentMethods); checkConfiguration(config); startEventListeners(config, nativeComponent); if (paymentMethod) { const singlePaymentMethods = { paymentMethods: [paymentMethod] }; const singlePaymentConfig = { ...config, dropin: { skipListWhenSinglePaymentMethod: true } }; nativeComponent.open(singlePaymentMethods, singlePaymentConfig); } else { nativeComponent.open(currentPaymentMethods, config); } }, [config, paymentMethods, sessionStorage, startEventListeners, removeEventListeners]); const createSession = useCallback(() => { SessionHelper.createSession(session, config).then(sessionResponse => { setSession(sessionResponse); }).catch(e => { onError({ message: JSON.stringify(e), errorCode: 'sessionError' }, SessionHelper); }); }, [session, config, onError]); return /*#__PURE__*/React.createElement(AdyenCheckoutContext.Provider, { value: { start, config, paymentMethods: paymentMethods ?? sessionStorage?.paymentMethods } }, children); }; export { AdyenCheckout, useAdyenCheckout }; //# sourceMappingURL=AdyenCheckoutContext.js.map