How to Handle Stripe and Paystack Webhooks in Next.js (The App Router Way)
Source: Dev.to
Why webhook signature verification often fails
The #1 reason developers struggle with SaaS payments is Webhook Signature Verification.
You set everything up, the test payment goes through, but your server returns a 400 Bad Request or a Signature Verification Failed error.
In the Next .js App Router, the problem usually stems from how the request body is parsed. Stripe and Paystack require the raw request body to verify the signature, but Next .js often parses it as JSON before you can access the raw payload.
Golden pattern for handling Stripe and Paystack webhooks (2026)
Create a file at app/api/webhooks/route.ts. In the App Router you can use req.text() to obtain the raw body and avoid automatic parsing.
import { NextResponse } from "next/server";
import crypto from "crypto";
export async function POST(req: Request) {
// 1️⃣ Get the raw body as text
const body = await req.text();
// 2️⃣ Grab the signature from headers
const signature =
req.headers.get("x-paystack-signature") ||
req.headers.get("stripe-signature");
if (!signature) {
return NextResponse.json(
{ error: "No signature" },
{ status: 400 }
);
}
// 3️⃣ Verify the signature (example for Paystack)
const hash = crypto
.createHmac("sha512", process.env.PAYSTACK_SECRET_KEY!)
.update(body)
.digest("hex");
if (hash !== signature) {
return NextResponse.json(
{ error: "Invalid signature" },
{ status: 401 }
);
}
// 4️⃣ Parse the body and handle the event
const event = JSON.parse(body);
if (event.event === "charge.success") {
// Handle successful payment in your database
console.log(
"Payment successful for:",
event.data.customer.email
);
}
return NextResponse.json(
{ received: true },
{ status: 200 }
);
}
Middleware considerations
If you have global middleware protecting your routes, exclude the webhook path. Otherwise, the payment provider may be redirected to a login page instead of reaching your API.
What happens if webhooks fail?
When webhook verification fails, users won’t receive their “Pro” access, leading to increased churn. Proper handling is the difference between a side project and a real business.
Further reading
- Full implementation (including Stripe, Paystack, and database logic): How to add Stripe or Paystack payments to your SaaS
- SassyPack overview (solves “Day 1” technical headaches for founders): SassyPack
Happy coding!