import { router } from "expo-router"; import * as WebBrowser from "expo-web-browser"; import { useState } from "react"; import { Alert, Image, Text, TouchableOpacity, View } from "react-native"; import ReactNativeModal from "react-native-modal"; import { images } from "@/constants"; import { fetchAPI } from "@/lib/fetch"; import { formatLBP } from "@/lib/pricing"; import { useLocationStore } from "@/store"; import type { PaymentProps } from "@/types/type"; import { CustomButton } from "./custom-button"; type PaymentMethod = "cash" | "card"; export const Payment = ({ fullName, email, amount, driverId, rideTime, }: PaymentProps) => { const { userAddress, userLongitude, userLatitude, destinationLatitude, destinationAddress, destinationLongitude, } = useLocationStore(); const [method, setMethod] = useState("cash"); const [success, setSuccess] = useState(false); const [processing, setProcessing] = useState(false); const recordRide = async (paymentStatus: string) => { 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: Math.round(parseFloat(amount) * 100), // in cents payment_status: paymentStatus, driver_id: driverId, }), }); }; // Cash is settled directly with the driver at drop-off. const payWithCash = async () => { setProcessing(true); try { await recordRide("cash"); setSuccess(true); } catch (err) { console.log("[PAYMENT]: ", err); Alert.alert( "Error", "Something went wrong while booking your ride. Please try again.", ); } finally { setProcessing(false); } }; const payWithCard = async () => { setProcessing(true); try { // 1. Create an Areeba checkout session on our server. const { orderId, checkoutUrl, successIndicator, error } = await fetchAPI( "/(api)/(areeba)/create", { method: "POST", headers: { "Content-type": "application/json", }, body: JSON.stringify({ name: fullName || email, email, amount, }), }, ); if (error || !checkoutUrl) throw new Error(error || "No checkout URL"); // 2. Open Areeba's hosted payment page. After payment the gateway // redirects back to the app (waseel://book-ride). const browserResult = await WebBrowser.openAuthSessionAsync( checkoutUrl, "waseel://book-ride", ); let resultIndicator: string | undefined; if (browserResult.type === "success" && browserResult.url) { resultIndicator = new URL(browserResult.url).searchParams.get( "resultIndicator", ) as string; } // 3. Verify the payment server-side before recording the ride. const verification = await fetchAPI("/(api)/(areeba)/verify", { method: "POST", headers: { "Content-type": "application/json", }, body: JSON.stringify({ orderId, resultIndicator, successIndicator }), }); if (verification.success) { await recordRide("paid"); setSuccess(true); } else { Alert.alert( "Payment not completed", "Your payment was cancelled or could not be verified. Please try again.", ); } } catch (err) { console.log("[PAYMENT]: ", err); Alert.alert( "Error", "Something went wrong while processing your payment. Please try again.", ); } finally { setProcessing(false); } }; const confirm = () => method === "cash" ? payWithCash() : Alert.alert("Pay by card", `Your card will be charged $${amount}.`, [ { text: "Cancel", style: "cancel" }, { text: "Continue", onPress: () => void payWithCard() }, ]); return ( <> Payment Method setMethod("cash")} className={`flex-1 items-center py-3 rounded-xl border ${ method === "cash" ? "bg-general-600 border-primary-500" : "bg-white border-general-700" }`} > 💵 Cash setMethod("card")} className={`flex-1 items-center py-3 rounded-xl border ${ method === "card" ? "bg-general-600 border-primary-500" : "bg-white border-general-700" }`} > 💳 Card setSuccess(false)} > Check Ride Booked! Thank you for your booking.{"\n"} Your reservation has been placed. {"\n"} {method === "cash" ? `Please have ${formatLBP(parseFloat(amount))} ready.` : null} { setSuccess(false); router.push("/(root)/(tabs)/home"); }} className="mt-5" /> ); };