import { useState, useCallback } from 'react'; import { Alert } from 'react-native'; import { useStripe } from '@stripe/stripe-react-native'; import { PlaceOrderResponse, WalletTopUpPaymentSessionResponse } from '@interfaces'; import { verifyPaymentApi } from '@api'; /** * Custom hook that encapsulates the entire Stripe card payment flow: * 1. Extract session info from the place-order response * 2. Initialize the Stripe Payment Sheet * 3. Present the Payment Sheet to the user * 4. Verify the payment on the backend via /payments/process * * Returns: * - processCardPayment: async function to run the full flow * - isPaymentProcessing: loading flag for UI */ export const useTopUp = () => { const { initPaymentSheet, presentPaymentSheet } = useStripe(); const [isPaymentProcessing, setIsPaymentProcessing] = useState(false); /** * Runs the complete Stripe card payment flow. * @param response – the PlaceOrderResponse from the backend (contains checkoutSessions) * @returns `true` if payment was verified successfully, `false` otherwise */ const topUpCardPayment = useCallback( async (response: WalletTopUpPaymentSessionResponse): Promise => { try { setIsPaymentProcessing(true); // ── 1. Extract session details ───────────────────────────────────── // const session = response.checkoutSessions?.[0]; // console.log('session', session); const clientSecret = response?.gatewayToken; // console.log('clientSecret', clientSecret); const gatewayOrderId = response?.gatewayOrderId; // console.log('gatewayOrderId', gatewayOrderId); if (!clientSecret) { Alert.alert('Error', 'Payment session token not found.'); return false; } // ── 2. Initialize Payment Sheet ──────────────────────────────────── const { error: initError } = await initPaymentSheet({ paymentIntentClientSecret: clientSecret, merchantDisplayName: 'SG Delivery', }); if (initError) { Alert.alert('Error', `Stripe init failed: ${initError.message}`); return false; } // ── 3. Present Payment Sheet ─────────────────────────────────────── const { error: presentError } = await presentPaymentSheet(); if (presentError) { if (presentError.code === 'Canceled') { Alert.alert( 'Payment Cancelled', 'You cancelled the payment process.', ); } else { console.log(presentError.message); Alert.alert('Payment Error', presentError.message); } return false; } // ── 4. Verify payment on backend ─────────────────────────────────── const verifyRes = await verifyPaymentApi({ gatewayOrderId: gatewayOrderId || '', gatewayPaymentId: gatewayOrderId || '', gatewaySignature: 'stripe_signature_verified', }); if (verifyRes.success) { return true; } else { Alert.alert( 'Verification Failed', verifyRes.message || 'Unable to confirm payment.', ); return false; } } catch (error: any) { Alert.alert( 'Payment Error', error?.message || 'Something went wrong during payment.', ); return false; } finally { setIsPaymentProcessing(false); } }, [initPaymentSheet, presentPaymentSheet], ); return { topUpCardPayment, isPaymentProcessing }; };