import React, { useState, useEffect, useCallback, useRef } from "react"; import { loadStripe } from "@stripe/stripe-js"; import { EmbeddedCheckoutProvider, EmbeddedCheckout, } from "@stripe/react-stripe-js"; import { stripeAPI, rentalAPI } from "../services/api"; const stripePromise = loadStripe( process.env.REACT_APP_STRIPE_PUBLISHABLE_KEY || "" ); interface EmbeddedStripeCheckoutProps { rentalData: any; onSuccess: () => void; onError: (error: string) => void; } const EmbeddedStripeCheckout: React.FC = ({ rentalData, onSuccess, onError, }) => { const [clientSecret, setClientSecret] = useState(""); const [creating, setCreating] = useState(false); const [sessionId, setSessionId] = useState(""); const hasCreatedSession = useRef(false); const createCheckoutSession = useCallback(async () => { // Prevent multiple session creations if (hasCreatedSession.current) return; try { setCreating(true); hasCreatedSession.current = true; const response = await stripeAPI.createSetupCheckoutSession({ rentalData }); setClientSecret(response.data.clientSecret); setSessionId(response.data.sessionId); } catch (error: any) { hasCreatedSession.current = false; // Reset on error so it can be retried onError( error.response?.data?.error || "Failed to create checkout session" ); } finally { setCreating(false); } }, [rentalData, onError]); useEffect(() => { createCheckoutSession(); }, [createCheckoutSession]); const handleComplete = useCallback(() => { // For embedded checkout, we need to retrieve the session to get payment method (async () => { try { if (!sessionId) { throw new Error("No session ID available"); } // Get the completed checkout session const sessionResponse = await stripeAPI.getCheckoutSession(sessionId); const { status: sessionStatus, setup_intent } = sessionResponse.data; if (sessionStatus !== "complete") { throw new Error("Payment setup was not completed"); } if (!setup_intent?.payment_method) { throw new Error("No payment method found in setup intent"); } // Extract payment method ID - handle both string ID and object cases const paymentMethodId = typeof setup_intent.payment_method === 'string' ? setup_intent.payment_method : setup_intent.payment_method.id; if (!paymentMethodId) { throw new Error("No payment method ID found"); } // Create the rental with the payment method ID const rentalPayload = { ...rentalData, stripePaymentMethodId: paymentMethodId }; await rentalAPI.createRental(rentalPayload); onSuccess(); } catch (error: any) { onError(error.response?.data?.error || error.message || "Failed to complete rental request"); } })(); }, [sessionId, rentalData, onSuccess, onError]); if (creating) { return (
Loading...

Preparing secure checkout...

); } if (!clientSecret) { return (

Unable to load checkout

); } return (
); }; export default EmbeddedStripeCheckout;