Next.js Discord

Discord Forum

Stripe webhook not working with Nextjs

Answered
Scale parasitoid posted this in #help-forum
Open in Discord
Scale parasitoidOP
I am trying to integrate Stripe in my Nextjs application, but I am facing errors implementing the webhook in the API.
The error that I get from the console is: { message: 'No stripe-signature header value was provided.' }

To make stripe working, I need to get the req.headers['stripe_signature'] however i am not able to access the property of this JSON, so the sig variable is undefined. I am following the Stripe docs, and this is what it does in the documentation as well.

Has anybody had any experience trying to implemente the stripe webhook that can help solve this problem?

import Stripe from "stripe"; const stripe = new Stripe(process.env.STRIPE_SECRET_KEY); export async function POST (req, res) { const sig = await req.headers['stripe-signature']; console.log("printing the signature:" + sig); //prints undefined let event = req.body; console.log("before the try catch"); try { event = stripe.webhooks.constructEvent(req.body, sig, process.env.STRIPE_WEBHOOK_SECRET_KEY); } catch (err) { console.log(err); return res.json({ message: "hello" }, { status: 403 }); } console.log("before the switch"); switch (event.type) { case 'payment_intent.succeeded': const paymentIntentSucceeded = event.data.object; console.log("Webhook verified"); break; // ... handle other event types default: console.log(Unhandled event type ${event.type}); } console.log("before the last return"); return res.json({ message: 'finished' }, { status: 200 }); }

console output:

see screenshot attached
Answered by Ray
also the second parameter is not res object for route handler in app router
View full answer

53 Replies

try const sig = req.headers.get('stripe-signature') instead
also the second parameter is not res object for route handler in app router
Answer
and you cannot access body directly
you should do stripe.webhooks.constructEvent(await req.text(), sig, process.env.STRIPE_WEBHOOK_SECRET_KEY);
and use NextResponse.json({}, { status: 403 }) instead of res.json
Scale parasitoidOP
const sig = req.headers.get('stripe-signature')still gives me undefined result
try make a post request with postman or something
Scale parasitoidOP
ooooh wait I got it
i was doing const sig = req.headers.get['stripe-signature'] instead of const sig = req.headers.get('stripe-signature')
I had to replace the square braces with round ones
yea because it's a function
Scale parasitoidOP
now it's telling me that NextResponse.json is not a function
did you import it
Scale parasitoidOP
yes
import { NextResponse } from "next/server";
Scale parasitoidOP
import NextResponse from "next/server";
import Stripe from "stripe";

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);

export async function POST (req, NextResponse) {

const sig = await req.headers.get('stripe-signature');

console.log("printing the signature:" + sig); //prints undefined

let event = req.body;

console.log("before the try catch");

try {
event = stripe.webhooks.constructEvent(await req.text(), sig, process.env.STRIPE_WEBHOOK_SECRET_KEY);
} catch (err) {
console.log(err);
return NextResponse.json({ message: "hello" }, { status: 403 });
}

console.log("before the switch");

switch (event.type) {
case 'payment_intent.succeeded':
const paymentIntentSucceeded = event.data.object;
console.log("Webhook verified");
break;
// ... handle other event types
default:
console.log(Unhandled event type ${event.type});
}

console.log("before the last return");

return NextResponse.json({ message: 'finished' }, { status: 200 });

}
import { NextResponse } from "next/server";
name import
Scale parasitoidOP
even with that it's not working
import {NextResponse} from "next/server";
import Stripe from "stripe";

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);

export async function POST (req, NextResponse) {

const sig = await req.headers.get('stripe-signature');

console.log("printing the signature:" + sig); //prints undefined

let event = req.body;

console.log("before the try catch");

try {
event = stripe.webhooks.constructEvent(await req.text(), sig, process.env.STRIPE_WEBHOOK_SECRET_KEY);
} catch (err) {
console.log(err);
return NextResponse.json({ message: "hello" }, { status: 403 });
}

console.log("before the switch");

switch (event.type) {
case 'payment_intent.succeeded':
const paymentIntentSucceeded = event.data.object;
console.log("Webhook verified");
break;
// ... handle other event types
default:
console.log(Unhandled event type ${event.type});
}

console.log("before the last return");

return NextResponse.json({ message: 'finished' }, { status: 200 });

}
const sig = await req.headers.get('stripe-signature');
you don't need to await on here
Scale parasitoidOP
I removed it now
but still doesn't solve the problem with NextResponse
what is weird is that at the import it's telling me that it's value is never read
try restart typescript server
remove line 10, you cannot access req.body
oh nm you not using typescript. try restart the dev server
Scale parasitoidOP
I restarted the server, still nothing unfortunately
what error you got
Scale parasitoidOP
NextResponse is still greyed out, and it's still giving me NextResponse.json is not a function
try use new Response.json()
Scale parasitoidOP
error TypeError: Response.json is not a constructor
node -v
Scale parasitoidOP
this is so weird because I am already using NextResponse.json() in another API route
ah
Scale parasitoidOP
node -v: v20.6.1
try comment out every thing and just put return NextResponse.json({}) there
Scale parasitoidOP
same problem
NextResponse.json is not a function
ok i see the problem
export async function POST (req, NextResponse) {
remove the NextResposne here
Scale parasitoidOP
it works
so the POST request only accepts 1 parameter?
two
export async function GET(
  request: Request,
  { params }: { params: { slug: string } }
) {
  const slug = params.slug // 'a', 'b', or 'c'
}
Scale parasitoidOP
but this is a POST not a GET
it same
@Ray it same
POST(req: Request) {

It does not seem so
problem solved?
Scale parasitoidOP
yes problem is solved
thank you