a tool for shared writing and social publishing
at feature/analytics 69 lines 2.0 kB view raw
1import { NextRequest, NextResponse } from "next/server"; 2import { getStripe } from "stripe/client"; 3import { inngest } from "app/api/inngest/client"; 4 5export async function POST(req: NextRequest) { 6 const body = await req.text(); 7 const signature = req.headers.get("stripe-signature"); 8 if (!signature) { 9 return NextResponse.json({ error: "Missing signature" }, { status: 400 }); 10 } 11 12 let event; 13 try { 14 event = getStripe().webhooks.constructEvent( 15 body, 16 signature, 17 process.env.STRIPE_WEBHOOK_SECRET as string, 18 ); 19 } catch (err) { 20 console.error("Stripe webhook signature verification failed:", err); 21 return NextResponse.json({ error: "Invalid signature" }, { status: 400 }); 22 } 23 24 switch (event.type) { 25 case "checkout.session.completed": 26 await inngest.send({ 27 name: "stripe/checkout.session.completed", 28 data: { sessionId: event.data.object.id }, 29 }); 30 break; 31 32 case "customer.subscription.created": 33 case "customer.subscription.updated": 34 await inngest.send({ 35 name: "stripe/customer.subscription.updated", 36 data: { subscriptionId: event.data.object.id }, 37 }); 38 break; 39 40 case "customer.subscription.deleted": 41 await inngest.send({ 42 name: "stripe/customer.subscription.deleted", 43 data: { subscriptionId: event.data.object.id }, 44 }); 45 break; 46 47 case "invoice.payment_failed": { 48 const invoice = event.data.object; 49 const sub = invoice.parent?.subscription_details?.subscription; 50 const subId = 51 typeof sub === "string" 52 ? sub 53 : typeof sub === "object" && sub 54 ? sub.id 55 : ""; 56 await inngest.send({ 57 name: "stripe/invoice.payment.failed", 58 data: { 59 invoiceId: invoice.id, 60 subscriptionId: subId, 61 customerId: invoice.customer as string, 62 }, 63 }); 64 break; 65 } 66 } 67 68 return NextResponse.json({ received: true }); 69}