add stripe (#121)

* add some stripe stuff

* more stripe stuff

* more stripe things

* more stripr stuff

* more stripe stuff

* more stripe stuff

* add more stuff

* add more stripe stuff

* more stuff

* fix types
This commit is contained in:
KM Koushik
2025-03-23 07:06:56 +11:00
committed by GitHub
parent 6cfe41cd86
commit 403ad8b93e
34 changed files with 1352 additions and 238 deletions
@@ -0,0 +1,77 @@
import { headers } from "next/headers";
import { NextResponse } from "next/server";
import Stripe from "stripe";
import { env } from "~/env";
import { syncStripeData } from "~/server/billing/payments";
import { db } from "~/server/db";
const stripe = new Stripe(env.STRIPE_SECRET_KEY!, {
apiVersion: "2025-01-27.acacia",
});
const allowedEvents: Stripe.Event.Type[] = [
"checkout.session.completed",
"customer.subscription.created",
"customer.subscription.updated",
"customer.subscription.deleted",
"customer.subscription.paused",
"customer.subscription.resumed",
"customer.subscription.pending_update_applied",
"customer.subscription.pending_update_expired",
"customer.subscription.trial_will_end",
"invoice.paid",
"invoice.payment_failed",
"invoice.payment_action_required",
"invoice.upcoming",
"invoice.marked_uncollectible",
"invoice.payment_succeeded",
"payment_intent.succeeded",
"payment_intent.payment_failed",
"payment_intent.canceled",
];
export async function POST(req: Request) {
const body = await req.text();
const signature = headers().get("Stripe-Signature");
if (!signature) {
console.error("No signature");
return new NextResponse("No signature", { status: 400 });
}
if (!env.STRIPE_WEBHOOK_SECRET) {
console.error("No webhook secret");
return new NextResponse("No webhook secret", { status: 400 });
}
try {
const event = stripe.webhooks.constructEvent(
body,
signature,
env.STRIPE_WEBHOOK_SECRET
);
if (!allowedEvents.includes(event.type)) {
return new NextResponse("OK", { status: 200 });
}
// All the events I track have a customerId
const { customer: customerId } = event?.data?.object as {
customer: string; // Sadly TypeScript does not know this
};
// This helps make it typesafe and also lets me know if my assumption is wrong
if (typeof customerId !== "string") {
throw new Error(
`[STRIPE HOOK][CANCER] ID isn't string.\nEvent type: ${event.type}`
);
}
await syncStripeData(customerId);
return new NextResponse("OK", { status: 200 });
} catch (err) {
console.error("Error processing webhook:", err);
return new NextResponse("Webhook error", { status: 400 });
}
}