import { define } from "../../../utils.ts"; import { createPaymentTransaction, getTransactionByStripeId, } from "../../../services/paymentService.ts"; import Stripe from "stripe"; export const handler = define.handlers({ async POST(ctx) { try { const raw = await ctx.req.text(); const sandbox = Deno.env.get("DISABLE_EXTERNAL_APIS") === "true" || Deno.env.get("SANDBOX_MODE") === "true"; if (sandbox) { // Accept simulated event: { type, data: { id, amount, lease_id, payment_method } } const { type, data } = JSON.parse(raw || "{}"); if (type === "payment_intent.succeeded" && data?.id) { const existing = await getTransactionByStripeId(data.id); if (!existing) { const amountNumber = typeof data.amount === "number" ? data.amount : Number(data.amount); const amount = Number.isFinite(amountNumber) ? amountNumber : 0; await createPaymentTransaction( data.lease_id, amount, Date.now(), data.payment_method || "ach", "completed", data.id, ); } } return new Response(JSON.stringify({ received: true }), { status: 200, headers: { "Content-Type": "application/json" }, }); } // Production Stripe verification const secret = Deno.env.get("STRIPE_WEBHOOK_SECRET"); const sigHeader = ctx.req.headers.get("stripe-signature"); if (!secret || !sigHeader) { return new Response(JSON.stringify({ error: "Missing signature" }), { status: 400, headers: { "Content-Type": "application/json" }, }); } let event; try { event = Stripe.webhooks.constructEvent( raw, sigHeader, secret, ); } catch (err) { const errorMessage = err instanceof Error ? err.message : String(err); return new Response( JSON.stringify({ error: `Webhook verification failed: ${errorMessage}`, }), { status: 400, headers: { "Content-Type": "application/json" }, }, ); } if (event?.type === "payment_intent.succeeded") { const obj = event.data?.object ?? {}; const stripeId = obj.id as string; const amountCents = obj.amount_received ?? obj.amount ?? 0; const amount = Math.round(Number(amountCents)) / 100; const leaseId = obj.metadata?.lease_id ?? ""; const method = obj.payment_method_types?.[0] ?? "card"; const existing = await getTransactionByStripeId(stripeId); if (!existing) { await createPaymentTransaction( leaseId, amount, Date.now(), method, "completed", stripeId, ); } } return new Response(JSON.stringify({ received: true }), { status: 200, headers: { "Content-Type": "application/json" }, }); } catch (err) { return new Response(JSON.stringify({ error: String(err) }), { status: 500, headers: { "Content-Type": "application/json" }, }); } }, });