Read the raw body, verify, then parse. Most generated handlers parse first and fail verification in production.
Snippet
Copied 17 timesimport Stripe from "stripe";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
export async function POST(req: Request) {
const body = await req.text();
const sig = req.headers.get("stripe-signature")!;
let event: Stripe.Event;
try {
event = stripe.webhooks.constructEvent(body, sig, process.env.STRIPE_WEBHOOK_SECRET!);
} catch (e) {
return new Response(`Bad signature: ${(e as Error).message}`, { status: 400 });
}
// handle event.type here; return 200 fast, do slow work in a queue
return new Response("ok");
}