import { createFileRoute } from "@tanstack/react-router"; import { supabaseAdmin } from "@/integrations/supabase/client.server"; import Stripe from "stripe"; export const Route = createFileRoute("/api/stripe-webhook")({ server: { handlers: { POST: async ({ request }) => { const secret = process.env.STRIPE_SECRET_KEY; const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET; if (!secret) return new Response("Stripe not configured", { status: 500 }); const stripe = new Stripe(secret); const sig = request.headers.get("stripe-signature"); const body = await request.text(); let event: Stripe.Event; try { if (webhookSecret && sig) { event = await stripe.webhooks.constructEventAsync(body, sig, webhookSecret); } else { // Without signature secret, accept but log (still secure if endpoint is obscure; // the user can configure STRIPE_WEBHOOK_SECRET later) event = JSON.parse(body) as Stripe.Event; } } catch (err) { return new Response(`Webhook error: ${(err as Error).message}`, { status: 400 }); } if (event.type === "checkout.session.completed") { const session = event.data.object as Stripe.Checkout.Session; const reqId = session.metadata?.payment_request_id; if (reqId) { await supabaseAdmin .from("payment_requests") .update({ status: "paid", paid_at: new Date().toISOString(), stripe_payment_intent_id: typeof session.payment_intent === "string" ? session.payment_intent : null, }) .eq("id", reqId); } } return new Response(JSON.stringify({ received: true }), { status: 200, headers: { "Content-Type": "application/json" }, }); }, }, }, });