UNPKG

zips-react-native-sdk-test

Version:

Lightweight ZIPS Payment Gateway SDK for React Native - Complete payment solution with ZApp wallet payments and Access Bank integration

170 lines (169 loc) 7.96 kB
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; import { useState, useCallback, useEffect } from 'react'; import Toast from 'react-native-toast-message'; import { Text, TouchableOpacity, } from 'react-native'; import PaymentModal from './PaymentModal'; import { QueryClientProvider } from '@tanstack/react-query'; import { queryClient } from '../tanstack-query/queryClient'; import { useZipsContext, ZipsProvider } from '../context/ZipsProvider'; import { NetBankingProvider, useNetBankingContext, } from '../context/NetBankingProvider'; import { WalletProvider } from '../context/WalletProvider'; import { CardProvider } from '../context/CardProvider'; import Zips from 'zips-typescript-sdk'; export default function PaymentButton(props) { return (_jsx(QueryClientProvider, { client: queryClient, children: _jsx(ZipsProvider, { children: _jsx(NetBankingProvider, { children: _jsx(WalletProvider, { children: _jsx(CardProvider, { children: _jsx(PaymentButtonInner, { ...props }) }) }) }) }) })); } function PaymentButtonInner({ apiKey, paymentDetails, onSuccess, onError, buttonText = 'Pay Now', environment = 'sandbox', style, children, }) { const { isLoading, isPaid, order, setTransactionDetails, setZips, setIsLoading, error, setError, transactionDetails, setPaymentMethod, setCurrentStep, } = useZipsContext(); const { resetNetBanking } = useNetBankingContext(); const [showModal, setShowModal] = useState(false); const handleButtonPress = useCallback(async () => { if (isLoading) return; // Clear error state when starting a new payment attempt if (error) { setError(null); } // Verify payment details first const isVerified = await verifyPaymentDetails(); // Only show modal if verification is successful if (isVerified) { setShowModal(true); } }, [isLoading, error, setError]); const handleModalClose = useCallback(() => { // Only reset states, don't clear transaction details that might be needed setShowModal(false); resetNetBanking(); setPaymentMethod({}); setCurrentStep('method-selection'); }, []); // Modern default button styles - compact and elegant const defaultButtonStyle = { backgroundColor: '#1D4ED8', // Modern blue borderRadius: 16, // More rounded paddingVertical: 14, paddingHorizontal: 24, minHeight: 48, alignItems: 'center', justifyContent: 'center', flexDirection: 'row', alignSelf: 'flex-start', // Don't take full width shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 8, elevation: 4, // Android shadow }; // Modern text styles const defaultTextStyle = { color: '#FFFFFF', fontSize: 16, fontWeight: '600', textAlign: 'center', letterSpacing: 0.5, }; // Compute final button styles const buttonStyle = { ...defaultButtonStyle, ...style, // User style overrides defaults }; // Default children if none provided const defaultChildren = _jsx(Text, { style: defaultTextStyle, children: buttonText }); const verifyPaymentDetails = async () => { setIsLoading(true); try { // Perform verification logic here const zips = new Zips(apiKey); const payment = await zips.payments.create({ amount: paymentDetails.amount, currency: paymentDetails.currency || 'GMD', firstName: paymentDetails.firstName, lastName: paymentDetails.lastName, phoneNumber: paymentDetails.phoneNumber, merchantAccountId: paymentDetails.merchantAccountId, name: paymentDetails.name, projectId: paymentDetails.projectId, quantity: paymentDetails.quantity, description: paymentDetails.description, }); if (!payment) { throw new Error('Payment creation failed'); } const transaction = await zips.transactions.single(payment === null || payment === void 0 ? void 0 : payment.referenceNumber); if (!transaction) { throw new Error('Transaction not found'); } console.log(transaction === null || transaction === void 0 ? void 0 : transaction.data); setTransactionDetails(transaction === null || transaction === void 0 ? void 0 : transaction.data); return true; // Return true on success } catch (error) { console.log('SDK ERROR', error); // Handle error gracefully setError(error); return false; // Return false on error } finally { setIsLoading(false); } }; useEffect(() => { if (apiKey) { setZips({ apiKey, paymentDetails, environment, }); } }, [apiKey, environment, paymentDetails]); useEffect(() => { if (order) { Toast.show({ type: 'success', text1: 'Payment Successful', text2: `Your payment of ${order.amount} was successful.`, swipeable: true, autoHide: true, avoidKeyboard: true, visibilityTime: 2000, }); setTimeout(() => { onSuccess({ ...order, ...transactionDetails, status: 'success', }); setShowModal(false); resetNetBanking(); setPaymentMethod({}); resetNetBanking(); }, 2000); } }, [order, onSuccess, resetNetBanking]); useEffect(() => { var _a, _b, _c, _d, _e, _f, _g; if (error) { // Only show toast for backend errors (not network/axios errors) const isBackendError = ((_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.status) && ((_b = error === null || error === void 0 ? void 0 : error.response) === null || _b === void 0 ? void 0 : _b.data); if (isBackendError) { Toast.show({ type: 'error', text1: 'Payment Error', text2: ((_e = (_d = (_c = error === null || error === void 0 ? void 0 : error.response) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d.message) === null || _e === void 0 ? void 0 : _e.toString()) || ((_g = (_f = error === null || error === void 0 ? void 0 : error.response) === null || _f === void 0 ? void 0 : _f.data) === null || _g === void 0 ? void 0 : _g.toString()) || 'An error occurred during payment processing', swipeable: true, autoHide: true, avoidKeyboard: true, }); } // Always call onError for developer handling onError(error); } }, [error, onError]); return (_jsxs(_Fragment, { children: [_jsx(TouchableOpacity, { style: { ...buttonStyle, opacity: isLoading || isPaid ? 0.5 : 1, }, onPress: handleButtonPress, disabled: isLoading || isPaid, activeOpacity: 0.8, accessibilityRole: "button", accessibilityState: { disabled: isLoading || isPaid }, accessibilityLabel: buttonText, children: isLoading ? (_jsx(Text, { style: defaultTextStyle, children: "Verifying..." })) : (children || defaultChildren) }), _jsx(PaymentModal, { visible: showModal, onClose: handleModalClose })] })); }