import { useAuth } from "@clerk/clerk-expo"; import { PaymentSheetError, useStripe } from "@stripe/stripe-react-native"; import type { Result } from "@stripe/stripe-react-native/lib/typescript/src/types/PaymentMethod"; import type { IntentCreationCallbackParams } from "@stripe/stripe-react-native/lib/typescript/src/types/PaymentSheet"; import { router } from "expo-router"; import { useState } from "react"; import { Alert, Image, Text, View } from "react-native"; import ReactNativeModal from "react-native-modal"; import { images } from "@/constants"; import { fetchAPI } from "@/lib/fetch"; import { useLocationStore } from "@/store"; import type { PaymentProps } from "@/types/type"; import { CustomButton } from "./custom-button"; export const Payment = ({ fullName, email, amount, driverId, rideTime, }: PaymentProps) => { const { userAddress, userLongitude, userLatitude, destinationLatitude, destinationAddress, destinationLongitude, } = useLocationStore(); const { userId } = useAuth(); const { initPaymentSheet, presentPaymentSheet } = useStripe(); const [success, setSuccess] = useState(false); const confirmHandler = async ( paymentMethod: Result, _shouldSavePaymentMethod: boolean, intentCreationCallback: (result: IntentCreationCallbackParams) => void, ) => { const { paymentIntent, customer } = await fetchAPI( "/(api)/(stripe)/create", { method: "POST", headers: { "Content-type": "application/json", }, body: JSON.stringify({ name: fullName || email, email, amount, paymentMethodId: paymentMethod.id, }), }, ); if (paymentIntent.client_secret) { const { result } = await fetchAPI("/(api)/(stripe)/pay", { method: "POST", headers: { "Content-type": "application/json", }, body: JSON.stringify({ payment_method_id: paymentMethod.id, payment_intent_id: paymentIntent.id, customer_id: customer, }), }); if (result.client_secret) { await fetchAPI("/(api)/ride/create", { method: "POST", headers: { "Content-type": "application/json", }, body: JSON.stringify({ origin_address: userAddress, destination_address: destinationAddress, origin_latitude: userLatitude, origin_longitude: userLongitude, destination_latitude: destinationLatitude, destination_longitude: destinationLongitude, ride_time: rideTime.toFixed(0), fare_price: parseInt(amount) * 100, // in cents payment_status: "paid", driver_id: driverId, user_id: userId, }), }); intentCreationCallback({ clientSecret: result.client_secret, }); } } }; const initializePaymentSheet = async () => { const { error } = await initPaymentSheet({ merchantDisplayName: "Ryde, Inc.", intentConfiguration: { mode: { amount: parseInt(amount) * 100, currencyCode: "USD", }, confirmHandler, }, style: "alwaysLight", returnURL: "ryde://book-ride", // make sure protocol matches scheme in app.json }); if (error) { Alert.alert( "Error", "Something went wrong while initializing your payment. Please try again.", ); } }; const openPaymentSheet = async () => { await initializePaymentSheet(); const { error } = await presentPaymentSheet(); if (error) { if (error.code !== PaymentSheetError.Canceled) Alert.alert(`Error code: ${error.code}`, error.message); } else { setSuccess(true); } }; return ( <> setSuccess(false)} > Check Ride Booked! Thank you for your booking.{"\n"} Your reservation has been placed. {"\n"} Please proceed with your trip. { setSuccess(false); router.push("/(root)/(tabs)/home"); }} className="mt-5" /> ); };