import { useEffect, useState } from 'react'; export default function createHooks(StripeTerminal: any) { function useStripeTerminalState() { const [connectionStatus, setConnectionStaus] = useState( StripeTerminal.ConnectionStatusNotConnected, ); const [paymentStatus, setPaymentStatus] = useState(StripeTerminal.PaymentStatusNotReady); const [lastReaderEvent, setLastReaderEvent] = useState(StripeTerminal.ReaderEventCardRemoved); const [connectedReader, setConnectedReader] = useState(null); const [readerInputOptions, setReaderInputOptions] = useState(null); const [readerInputPrompt, setReaderInputPrompt] = useState(null); useEffect(() => { // Populate initial values StripeTerminal.getConnectionStatus().then((s: any) => setConnectionStaus(s)); StripeTerminal.getPaymentStatus().then((s: any) => setPaymentStatus(s)); StripeTerminal.getLastReaderEvent().then((e: any) => setLastReaderEvent(e)); StripeTerminal.getConnectedReader().then((r: any) => setConnectedReader(r)); // Setup listeners const listeners = [ StripeTerminal.addDidChangeConnectionStatusListener(({ status }: any) => { setConnectionStaus(status); StripeTerminal.getConnectedReader().then((r: any) => setConnectedReader(r)); }), StripeTerminal.addDidChangePaymentStatusListener(({ status }: any) => setPaymentStatus(status), ), StripeTerminal.addDidReportReaderEventListener(({ event }: any) => setLastReaderEvent(event), ), StripeTerminal.addDidRequestReaderInputListener(({ text }: any) => setReaderInputOptions(text), ), StripeTerminal.addDidRequestReaderDisplayMessageListener(({ text }: any) => setReaderInputPrompt(text), ), ]; // Cleanup: remove listeners return () => { listeners.forEach((l) => l.remove()); }; }, []); const cardInserted = lastReaderEvent === StripeTerminal.ReaderEventCardInserted; return { connectionStatus, connectedReader, paymentStatus, readerInputOptions, readerInputPrompt, cardInserted, clearReaderInputState: () => { setReaderInputOptions(null); setReaderInputPrompt(null); }, }; } function useStripeTerminalCreatePayment({ onSuccess, onFailure, onCapture, autoRetry, ...options }: any) { const state = useStripeTerminalState(); const { paymentStatus, cardInserted, clearReaderInputState } = state; const [hasCreatedPayment, setHasCreatedPayment] = useState(false); const [isCompleted, setIsCompleted] = useState(false); const [readerError, setReaderError] = useState(null); const [hasRetried, setHasRetried] = useState(false); useEffect(() => { if ( paymentStatus !== StripeTerminal.PaymentStatusNotReady && (!hasCreatedPayment || (readerError && !hasRetried && !cardInserted)) ) { setHasCreatedPayment(true); if (readerError) { setHasRetried(true); } StripeTerminal.createPayment(options) .then((intent: string) => { if (onCapture) { return onCapture(intent).then(onSuccess).catch(onFailure); } onSuccess(intent); }) .catch(({ error }: any) => { if (autoRetry) { StripeTerminal.abortCreatePayment() .then(() => { clearReaderInputState(); setHasRetried(false); setReaderError(error); }) .catch((e: any) => onFailure(e)); return; } onFailure(error); }) .finally(() => setIsCompleted(true)); } }, [paymentStatus, hasCreatedPayment, readerError, hasRetried, cardInserted]); // Cleanup: abort if unmounted midway through payment intent creation process. useEffect(() => { return () => { if (!isCompleted) { StripeTerminal.abortCreatePayment(); } }; }, []); return { ...state, readerError, }; } const ConnectionManagerStatusConnected = 'connected'; const ConnectionManagerStatusConnecting = 'connecting'; const ConnectionManagerStatusDisconnected = 'disconnected'; const ConnectionManagerStatusScanning = 'scanning'; function useStripeTerminalConnectionManager({ service }: any) { const state = useStripeTerminalState(); const { connectedReader } = state; const [managerConnectionStatus, setManagerConnectionStatus] = useState( ConnectionManagerStatusDisconnected, ); const [readersAvailable, setReadersAvailable] = useState([]); const [persistedReaderSerialNumber, setPersistedReaderSerialNumber] = useState(''); useEffect(() => { setManagerConnectionStatus( connectedReader ? ConnectionManagerStatusConnected : ConnectionManagerStatusDisconnected, ); }, [connectedReader]); useEffect(() => { // Populate initial values service.getPersistedReaderSerialNumber().then((s: any) => setPersistedReaderSerialNumber(s)); // Setup listeners // eslint-disable-next-line no-unused-vars const listeners: any = [ service.addListener('readersDiscovered', (readers: any) => setReadersAvailable(readers)), service.addListener('readerPersisted', (serialNumber: string) => setPersistedReaderSerialNumber(serialNumber), ), ]; // Cleanup: remove listeners return () => { service.emitter.removeListener('readersDiscovered'); service.emitter.removeListener('readerPersisted'); }; }, []); return { ...state, managerConnectionStatus, readersAvailable, persistedReaderSerialNumber, connectReader: (serialNumber: string) => { setManagerConnectionStatus(ConnectionManagerStatusConnecting); service.connect(serialNumber); }, discoverReaders: () => { setManagerConnectionStatus(ConnectionManagerStatusScanning); service.discover(); }, disconnectReader: () => { service.disconnect(); }, }; } return { useStripeTerminalState, useStripeTerminalCreatePayment, useStripeTerminalConnectionManager, }; }