tasko/app/api/webhook/route.ts

86 lines
2.2 KiB
TypeScript
Raw Normal View History

2024-02-16 01:49:19 +00:00
import Stripe from 'stripe';
import { headers } from 'next/headers';
import { NextResponse } from 'next/server';
2024-02-15 02:30:10 +00:00
2024-02-16 01:49:19 +00:00
import { db } from '@/lib/db';
import { stripe } from '@/lib/stripe';
import arcjet, { fixedWindow } from '@/lib/arcjet';
const aj = arcjet.withRule(
fixedWindow({
mode: 'LIVE',
max: 10,
window: '60s',
})
);
2024-02-15 02:30:10 +00:00
export async function POST(req: Request) {
const decision = await aj.protect(req);
if (decision.isDenied())
return new NextResponse(
JSON.stringify({ error: 'Too many requests', reason: decision.reason }),
{ status: 429 }
);
2024-02-15 02:30:10 +00:00
const body = await req.text();
const signature = (await headers()).get('Stripe-Signature') as string;
2024-02-15 02:30:10 +00:00
let event: Stripe.Event;
try {
event = stripe.webhooks.constructEvent(
body,
signature,
process.env.STRIPE_WEBHOOK_SECRET!
);
} catch (error) {
return new NextResponse(JSON.stringify(error), { status: 400 });
}
const session = event.data.object as Stripe.Checkout.Session;
2024-02-16 01:49:19 +00:00
if (event.type === 'checkout.session.completed') {
2024-02-15 02:30:10 +00:00
const subscription = await stripe.subscriptions.retrieve(
session.subscription as string
);
if (!session?.metadata?.orgId) {
2024-02-16 01:49:19 +00:00
return new NextResponse(JSON.stringify({ error: 'Missing orgId' }), {
2024-02-15 02:30:10 +00:00
status: 400,
});
}
await db.orgSubscription.create({
data: {
orgId: session.metadata.orgId,
stripeSubscriptionId: subscription.id,
stripeCustomerId: session.customer as string,
stripePriceId: subscription.items.data[0].price.id,
stripeCurrentPeriodEnd: new Date(
subscription.current_period_end * 1000
),
},
});
}
2024-02-16 01:49:19 +00:00
if (event.type === 'invoice.payment_succeeded') {
2024-02-15 02:30:10 +00:00
const subscription = await stripe.subscriptions.retrieve(
session.subscription as string
);
await db.orgSubscription.update({
where: {
stripeSubscriptionId: subscription.id,
},
data: {
stripePriceId: subscription.items.data[0].price.id,
stripeCurrentPeriodEnd: new Date(
subscription.current_period_end * 1000
),
},
});
}
return NextResponse.json(null, { status: 200 });
}