typescriptadvanced
Webhook Handler with Signature Verification
Handle incoming webhooks with signature verification and idempotent processing.
typescriptPress ⌘/Ctrl + Shift + C to copy
// app/api/webhooks/stripe/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { createHmac, timingSafeEqual } from 'crypto';
function verifySignature(
payload: string,
signature: string,
secret: string
): boolean {
const parts = Object.fromEntries(
signature.split(',').map((part) => {
const [key, value] = part.split('=');
return [key, value];
})
);
const timestamp = parts['t'];
const sig = parts['v1'];
// Prevent replay attacks
const age = Math.floor(Date.now() / 1000) - parseInt(timestamp);
if (age > 300) return false; // 5 min tolerance
const signedPayload = `${timestamp}.${payload}`;
const expected = createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');
return timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}
export async function POST(request: NextRequest) {
const body = await request.text();
const signature = request.headers.get('stripe-signature');
if (!signature) {
return NextResponse.json({ error: 'Missing signature' }, { status: 400 });
}
const secret = process.env.STRIPE_WEBHOOK_SECRET!;
if (!verifySignature(body, signature, secret)) {
return NextResponse.json({ error: 'Invalid signature' }, { status: 401 });
}
const event = JSON.parse(body);
// Idempotent processing
const processed = await isEventProcessed(event.id);
if (processed) {
return NextResponse.json({ received: true, duplicate: true });
}
switch (event.type) {
case 'checkout.session.completed':
await handleCheckoutComplete(event.data.object);
break;
case 'invoice.paid':
await handleInvoicePaid(event.data.object);
break;
default:
console.log(`Unhandled event type: ${event.type}`);
}
await markEventProcessed(event.id);
return NextResponse.json({ received: true });
}Use Cases
- payment webhooks
- CMS events
- third-party integrations
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
typescriptintermediate
API Route Rate Limiting
Add rate limiting to Next.js API routes with sliding window, IP-based limits, and custom responses.
Best for: API abuse prevention
#nextjs#api
typescriptintermediate
Type-Safe API Route Handler
Next.js App Router route handler with input validation, typed responses, and proper error handling.
Best for: CRUD API endpoints
#api#route-handler
typescriptintermediate
Next.js Route Handlers (API Routes)
Build RESTful API endpoints using Next.js App Router route handlers with typed responses.
Best for: Building REST APIs within a Next.js application
#nextjs#api
typescriptadvanced
Next.js Middleware for Authentication
Protect routes with Next.js middleware using token verification and role-based redirects.
Best for: Protecting authenticated routes at the edge
#nextjs#middleware