open-swe-dev-andrinoid[bot] 744115d230
feat: Add Microsoft Azure AD authentication environment variables to .env.example (#115)
* Apply patch [skip ci]

* Empty commit to trigger CI

* Apply patch [skip ci]

* Apply patch [skip ci]

* Apply patch [skip ci]

* Apply patch [skip ci]

* Apply patch [skip ci]

* Apply patch [skip ci]

* Apply patch [skip ci]

* Apply patch [skip ci]

* Apply patch [skip ci]

* Apply patch [skip ci]

---------

Co-authored-by: open-swe-dev-andrinoid[bot] <open-swe-dev-andrinoid@users.noreply.github.com>
2026-01-28 10:47:50 -06:00

102 lines
3.2 KiB
TypeScript

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" },
});
}
},
});