73 lines
2.3 KiB
TypeScript
73 lines
2.3 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { stripeClient } from "../../../../../lib/stripeClient";
|
|
|
|
export const runtime = "nodejs";
|
|
|
|
export async function POST(req: Request) {
|
|
const webhookSecret = process.env.STRIPE_SUBSCRIPTION_WEBHOOK_SECRET;
|
|
if (!webhookSecret) {
|
|
return NextResponse.json(
|
|
{ error: "Missing STRIPE_SUBSCRIPTION_WEBHOOK_SECRET." },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
|
|
const signature = req.headers.get("stripe-signature");
|
|
if (!signature) {
|
|
return NextResponse.json({ error: "Missing Stripe signature." }, { status: 400 });
|
|
}
|
|
|
|
const rawBody = Buffer.from(await req.arrayBuffer());
|
|
|
|
try {
|
|
const event = stripeClient.webhooks.constructEvent(
|
|
rawBody,
|
|
signature,
|
|
webhookSecret
|
|
);
|
|
|
|
switch (event.type) {
|
|
case "customer.subscription.updated": {
|
|
const subscription = event.data.object as any;
|
|
const accountId = subscription.customer_account;
|
|
const priceId = subscription.items?.data?.[0]?.price?.id;
|
|
const quantity = subscription.items?.data?.[0]?.quantity;
|
|
const cancelAtPeriodEnd = subscription.cancel_at_period_end;
|
|
const pauseCollection = subscription.pause_collection;
|
|
|
|
// TODO: Store subscription status in your DB for accountId.
|
|
// Suggested fields: status, priceId, quantity, cancelAtPeriodEnd, pauseCollection.
|
|
break;
|
|
}
|
|
case "customer.subscription.deleted": {
|
|
const subscription = event.data.object as any;
|
|
const accountId = subscription.customer_account;
|
|
// TODO: Revoke access for accountId in your DB.
|
|
break;
|
|
}
|
|
case "payment_method.attached":
|
|
case "payment_method.detached":
|
|
case "customer.updated":
|
|
case "customer.tax_id.created":
|
|
case "customer.tax_id.deleted":
|
|
case "customer.tax_id.updated":
|
|
case "billing_portal.configuration.created":
|
|
case "billing_portal.configuration.updated":
|
|
case "billing_portal.session.created": {
|
|
// TODO: Update billing info in your DB if needed.
|
|
break;
|
|
}
|
|
default: {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return NextResponse.json({ received: true });
|
|
} catch (err: any) {
|
|
return NextResponse.json(
|
|
{ error: err?.message || "Webhook handler failed." },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
}
|