From a703c73aac64bbfe164c7dc1849af8dc16a4c495 Mon Sep 17 00:00:00 2001 From: "open-swe-dev-andrinoid[bot]" Date: Wed, 21 Jan 2026 19:18:29 +0000 Subject: [PATCH] Apply patch [skip ci] --- routes/api/payments/create_intent.ts | 93 ++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 routes/api/payments/create_intent.ts diff --git a/routes/api/payments/create_intent.ts b/routes/api/payments/create_intent.ts new file mode 100644 index 0000000..a0a4315 --- /dev/null +++ b/routes/api/payments/create_intent.ts @@ -0,0 +1,93 @@ +import { define } from "../../../utils.ts"; +import { createPaymentTransaction } from "../../../services/paymentService.ts"; + +type CreateIntentBody = { + lease_id: string; + amount: number; + payment_method?: string; + currency?: string; +}; + +export const handler = define.handlers({ + async POST(ctx) { + try { + const body = await ctx.req.json() as CreateIntentBody; + const { lease_id, amount, payment_method = "ach", currency = "usd" } = + body || {} as CreateIntentBody; + + if (!lease_id || !amount || Number.isNaN(amount)) { + return new Response( + JSON.stringify({ success: false, error: "Invalid request body" }), + { status: 400, headers: { "Content-Type": "application/json" } }, + ); + } + + const sandbox = Deno.env.get("DISABLE_EXTERNAL_APIS") === "true" || + Deno.env.get("SANDBOX_MODE") === "true"; + + if (sandbox) { + const localId = `pi_local_${crypto.randomUUID()}`; + const [transaction] = await createPaymentTransaction( + lease_id, + amount, + Date.now(), + payment_method, + "completed", + localId, + ); + return new Response( + JSON.stringify({ success: true, mode: "local", transaction }), + { status: 200, headers: { "Content-Type": "application/json" } }, + ); + } + + // Production Stripe flow (guarded by env flags) + const secret = Deno.env.get("STRIPE_SECRET_KEY"); + if (!secret) { + return new Response( + JSON.stringify({ success: false, error: "Stripe not configured" }), + { status: 500, headers: { "Content-Type": "application/json" } }, + ); + } + + const params = new URLSearchParams(); + params.set("amount", String(Math.round(amount * 100))); + params.set("currency", currency); + params.set("automatic_payment_methods[enabled]", "true"); + + const resp = await fetch("https://api.stripe.com/v1/payment_intents", { + method: "POST", + headers: { + "Authorization": `Bearer ${secret}`, + "Content-Type": "application/x-www-form-urlencoded", + }, + body: params.toString(), + }); + + if (!resp.ok) { + const text = await resp.text(); + return new Response( + JSON.stringify({ success: false, error: text }), + { status: 502, headers: { "Content-Type": "application/json" } }, + ); + } + + const pi = await resp.json(); + return new Response( + JSON.stringify({ + success: true, + mode: "stripe", + client_secret: pi.client_secret, + payment_intent_id: pi.id, + }), + { status: 200, headers: { "Content-Type": "application/json" } }, + ); + } catch (err) { + return new Response( + JSON.stringify({ success: false, error: String(err) }), + { status: 500, headers: { "Content-Type": "application/json" } }, + ); + } + }, +}); +