UNPKG

@lmapp/react-native-cloudpayments

Version:

πŸš€ ΠœΠΎΡ‰Π½Ρ‹ΠΉ SDK для ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΠΈ ΠΏΠ»Π°Ρ‚Π΅ΠΆΠ΅ΠΉ CloudPayments Π² React Native. ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° Apple Pay, Google Pay, Π‘Π‘ΠŸ, банковских ΠΊΠ°Ρ€Ρ‚. Полная типизация TypeScript. iOS 12+ ΠΈ Android 21+

271 lines (250 loc) β€’ 8.93 kB
"use strict"; /** * @fileoverview Π₯ΡƒΠΊ для управлСния событиями CloudPayments SDK * @description Π‘Π°Π·ΠΎΠ²Ρ‹ΠΉ Ρ…ΡƒΠΊ для подписки Π½Π° события ΠΈ управлСния состояниСм SDK * @author Leonid Molchanov * @since 1.0.0 */ import { useCallback, useEffect, useRef, useState } from 'react'; import { eventEmitter } from "../../events/index.js"; import { EPaymentFormEventName } from "../../types/index.js"; // ============================================================================ // CONSTANTS // ============================================================================ /** * Бобытия ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ для подписки * @description Π‘Π°Π·ΠΎΠ²Ρ‹ΠΉ Π½Π°Π±ΠΎΡ€ событий, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ подписываСтся Ρ…ΡƒΠΊ Ссли Π½Π΅ ΡƒΠΊΠ°Π·Π°Π½Ρ‹ enabledEvents */ const DEFAULT_ENABLED_EVENTS = [EPaymentFormEventName.PAYMENT_FORM]; /** * ΠΠ°Ρ‡Π°Π»ΡŒΠ½ΠΎΠ΅ состояниС SDK */ const INITIAL_STATE = { isLoading: false, isError: false, isSuccess: false, status: 'idle', error: null, transactionId: null, progress: null }; // ============================================================================ // HOOK IMPLEMENTATION // ============================================================================ /** * Π₯ΡƒΠΊ для управлСния событиями CloudPayments SDK * * @description Π‘Π°Π·ΠΎΠ²Ρ‹ΠΉ Ρ…ΡƒΠΊ для подписки Π½Π° события SDK ΠΈ управлСния состояниСм. * ΠŸΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΠ΅Ρ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ для обновлСния состояния ΠΈ автоматичСски подписываСтся * Π½Π° события ΠΏΠ»Π°Ρ‚Π΅ΠΆΠ½ΠΎΠΉ Ρ„ΠΎΡ€ΠΌΡ‹. * * @param options - ΠžΠΏΡ†ΠΈΠΈ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ Ρ…ΡƒΠΊΠ° * @returns ΠžΠ±ΡŠΠ΅ΠΊΡ‚ с состояниСм ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°ΠΌΠΈ управлСния * * @example Π‘Π°Π·ΠΎΠ²ΠΎΠ΅ использованиС * ```typescript * const { state, actions } = useCloudPaymentsEvents({ * onSuccess: (data) => console.log('УспСх:', data.transactionId), * onError: (data) => console.log('Ошибка:', data.message) * }); * * // ИспользованиС ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² управлСния состояниСм * const handleStart = () => { * actions.setStatus('processing'); * }; * * const handleError = (message: string) => { * actions.setError(message, EPaymentFormErrorCode.PAYMENT_FAILED); * }; * ``` * * @example ΠšΠ°ΡΡ‚ΠΎΠΌΠ½Ρ‹Π΅ события * ```typescript * const { state, actions } = useCloudPaymentsEvents({ * enabledEvents: [EPaymentFormEventName.PAYMENT_FORM], * onSuccess: (data) => { * actions.setStatus('success', { transactionId: data.transactionId }); * } * }); * ``` * * @since 1.0.0 */ export const useCloudPaymentsEvents = (options = {}) => { // ============================================================================ // STATE & REFS // ============================================================================ const [state, setState] = useState(INITIAL_STATE); const subscriptionsRef = useRef([]); const transactionProcessedRef = useRef(false); const { enabledEvents = DEFAULT_ENABLED_EVENTS, onSuccess, onError, onCancel } = options; // ============================================================================ // HELPER FUNCTIONS // ============================================================================ /** * ОбновлСниС состояния Ρ…ΡƒΠΊΠ° */ const updateState = useCallback(updates => { setState(prevState => ({ ...prevState, ...updates })); }, []); /** * Установка статуса с автоматичСским ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ΠΌ Ρ„Π»Π°Π³ΠΎΠ² */ const setStatus = useCallback((status, additionalUpdates = {}) => { updateState({ status, isLoading: status === 'initializing' || status === 'processing', isError: status === 'error', isSuccess: status === 'success', ...additionalUpdates }); }, [updateState]); /** * Установка ошибки */ const setError = useCallback((message, code, details) => { const error = { message, code, details }; setStatus('error', { error }); }, [setStatus]); /** * Установка прогрСсса */ const setProgress = useCallback((stage, percentage) => { const progress = { stage, percentage }; updateState({ progress }); }, [updateState]); /** * ΠžΡ‡ΠΈΡΡ‚ΠΊΠ° состояния */ const resetState = useCallback(() => { setState(INITIAL_STATE); }, []); // ============================================================================ // EVENT HANDLERS // ============================================================================ /** * ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ событий ΠΏΠ»Π°Ρ‚Π΅ΠΆΠ½ΠΎΠΉ Ρ„ΠΎΡ€ΠΌΡ‹ */ const handlePaymentFormEvent = useCallback(event => { switch (event.action) { case 'willDisplay': setStatus('initializing'); break; case 'didDisplay': setStatus('processing'); break; case 'willHide': // Π€ΠΎΡ€ΠΌΠ° готовится ΠΊ ΡΠΊΡ€Ρ‹Ρ‚ΠΈΡŽ break; case 'didHide': // Π€ΠΎΡ€ΠΌΠ° скрыта - сбрасываСм состояниС Ссли Π½Π΅ Π±Ρ‹Π»ΠΎ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ if (!transactionProcessedRef.current) { setStatus('cancelled'); onCancel?.(); } // БбрасываСм Ρ„Π»Π°Π³ для ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ ΠΏΠ»Π°Ρ‚Π΅ΠΆΠ° transactionProcessedRef.current = false; break; case 'cancelled': // ΠΠžΠ’ΠžΠ•: ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎΠ³ΠΎ события ΠΎΡ‚ΠΌΠ΅Π½Ρ‹ ΠΏΠ»Π°Ρ‚Π΅ΠΆΠ° transactionProcessedRef.current = true; setStatus('cancelled'); onCancel?.(); break; case 'transaction': // ΠžΡ‚ΠΌΠ΅Ρ‡Π°Π΅ΠΌ Ρ‡Ρ‚ΠΎ транзакция Π±Ρ‹Π»Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Π½Π° transactionProcessedRef.current = true; if (event.statusCode) { // УспСшная транзакция const transactionId = event.transactionId || null; setStatus('success', { transactionId }); if (onSuccess && transactionId) { onSuccess({ transactionId, message: event.message }); } } else { // Ошибка Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ const message = event.message || 'ΠŸΡ€ΠΎΠΈΠ·ΠΎΡˆΠ»Π° ошибка ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΏΠ»Π°Ρ‚Π΅ΠΆΠ°'; const code = event.errorCode; setError(message, code); if (onError) { onError({ message, code }); } } break; default: console.warn('НСизвСстноС дСйствиС ΠΏΠ»Π°Ρ‚Π΅ΠΆΠ½ΠΎΠΉ Ρ„ΠΎΡ€ΠΌΡ‹:', event.action); } }, [setStatus, setError, onSuccess, onError, onCancel]); // ============================================================================ // EFFECTS // ============================================================================ /** * Подписка Π½Π° события ΠΏΡ€ΠΈ ΠΌΠΎΠ½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° */ useEffect(() => { const subscriptions = []; // ΠŸΠΎΠ΄ΠΏΠΈΡΡ‹Π²Π°Π΅ΠΌΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π° ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅ΠΌΡ‹Π΅ события enabledEvents.forEach(eventName => { switch (eventName) { case EPaymentFormEventName.PAYMENT_FORM: subscriptions.push(eventEmitter.addListener(eventName, handlePaymentFormEvent)); break; case EPaymentFormEventName.PAYMENT: case EPaymentFormEventName.CARD: case EPaymentFormEventName.THREE_DS: // Пока Π½Π΅ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Ρ‹, Π½ΠΎ Π³ΠΎΡ‚ΠΎΠ²Ρ‹ ΠΊ добавлСнию console.log(`Π‘ΠΎΠ±Ρ‹Ρ‚ΠΈΠ΅ ${eventName} Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠ°Π½ΠΎ Π² Π±ΡƒΠ΄ΡƒΡ‰ΠΈΡ… вСрсиях`); break; default: console.warn(`НСподдСрТиваСмоС событиС: ${eventName}`); } }); subscriptionsRef.current = subscriptions; // ΠžΡ‡ΠΈΡΡ‚ΠΊΠ° подписок ΠΏΡ€ΠΈ Ρ€Π°Π·ΠΌΠΎΠ½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠΈ return () => { subscriptions.forEach(subscription => subscription.remove()); subscriptionsRef.current = []; }; }, [enabledEvents, handlePaymentFormEvent]); // ============================================================================ // RETURN // ============================================================================ return { state, actions: { setStatus, setError, setProgress, updateState, resetState } }; }; //# sourceMappingURL=useCloudPaymentsEvents.js.map