The Stripe SDK uses Buffer internally, which doesn't exist on Vercel Edge Runtime or Cloudflare Workers. You need to verify the signature manually using the Web Crypto API.
ReferenceError: Buffer is not defined or stripe.webhooks.constructEvent is not a function on Edge Runtime.// app/api/webhooks/stripe/route.ts
export const runtime = 'edge'; // or 'nodejs' to avoid this entirely
import { NextResponse } from 'next/server';
const secret = process.env.STRIPE_WEBHOOK_SECRET!;
export async function POST(request: Request) {
const body = await request.text();
const sig = request.headers.get('stripe-signature');
if (!sig) {
return NextResponse.json({ error: 'Missing stripe-signature' }, { status: 400 });
}
let event: any;
try {
// Parse the Stripe-Signature header
const parts = sig.split(',');
const timestamp = parts.find(p => p.startsWith('t='))?.slice(2);
const v1 = parts.find(p => p.startsWith('v1='))?.slice(3);
if (!timestamp || !v1) throw new Error('Invalid signature format');
// Import HMAC key using Web Crypto API (works on Edge)
const key = await crypto.subtle.importKey(
'raw',
new TextEncoder().encode(secret),
{ name: 'HMAC', hash: 'SHA-256' },
false,
['verify']
);
// Stripe signs: timestamp + '.' + payload
const signed = new TextEncoder().encode(\`\${timestamp}.\${body}\`);
const sigBytes = Uint8Array.from(
v1.match(/.{2}/g)!.map(h => parseInt(h, 16))
);
const valid = await crypto.subtle.verify('HMAC', key, sigBytes, signed);
if (!valid) throw new Error('Signature mismatch');
event = JSON.parse(body);
} catch (err: any) {
return NextResponse.json({ error: \`Webhook Error: \${err.message}\` }, { status: 400 });
}
switch (event.type) {
case 'checkout.session.completed':
// fulfill order
break;
}
return NextResponse.json({ received: true });
}
If you don't specifically need Edge Runtime, switching to Node.js runtime lets you use the Stripe SDK directly:
// app/api/webhooks/stripe/route.ts
export const runtime = 'nodejs'; // ← add this line
import Stripe from 'stripe'; // now works normally
import { NextResponse } from 'next/server';
// ... rest of the standard handler
Generate the Edge Runtime handler with the Edge toggle enabled.
Open WebhookFix →