I'm feeling frustrated trying to get a raw body passed for the Stripe webhook in NextJS!
Despite trying numerous solutions from various sources, I just can't seem to get it to work.
Calling upon the developers with special powers (of which I am still honing).
An error message received from Stripe Test:
No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe?
This is my test of the NextJS webhook endpoint:
import { buffer } from 'micro';
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
export default async function handler(req, res) {
console.log("Payment intent")
let event = req.body
console.log(event)
if (process.env.STRIPE_WEBHOOK_ENDPOINT_SECRET) {
// Get the signature sent by Stripe
const signature = req.headers['stripe-signature'];
console.log(signature)
try {
event = stripe.webhooks.constructEvent(
req.body,
signature,
process.env.STRIPE_WEBHOOK_ENDPOINT_SECRET
);
} catch (err) {
console.log(`⚠️ Webhook signature verification failed.`, err.message);
return res.sendStatus(400);
}
}
console.log(event.type)
// Handle the event
switch (event.type) {
case 'payment_intent.succeeded':
console.log("Success!")
break;
default:
console.log(`Unhandled event type ${event.type}`);
}
}
I have also experimented with this setup:
import { buffer } from 'micro';
import Cors from 'micro-cors';
const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY);
const webhookSecret = process.env.STRIPE_WEBHOOK_ENDPOINT_SECRET_NEW;
// Stripe requires the raw body to construct the event.
export const config = {
api: {
bodyParser: false,
},
};
const cors = Cors({
allowMethods: ['POST', 'HEAD'],
});
const webhookHandler = async (req, res) => {
if (req.method === 'POST') {
const buf = await buffer(req);
console.log(buf.toString())
const sig = req.headers['stripe-signature'];
console.log(process.env.STRIPE_SECRET_KEY)
console.log(webhookSecret)
console.log(sig)
let event;
try {
event = stripe.webhooks.constructEvent(
buf.toString(),
sig,
webhookSecret
);
} catch (err) {
console.log(`❌ Error message: ${err.message}`);
res.status(400).send(`Webhook Error: ${err.message}`);
return;
}
if (event.type === 'payment_intent.succeeded') {
const paymentIntent = event.data.object;
console.log(`💰 PaymentIntent status: ${paymentIntent.status}`);
} else if (event.type === 'payment_intent.payment_failed') {
const paymentIntent = event.data.object;
console.log(
`❌ Payment failed: ${paymentIntent.last_payment_error?.message}`
);
} else if (event.type === 'charge.succeeded') {
const charge = event.data.object;
console.log(`💵 Charge id: ${charge.id}`);
} else {
console.warn(`🤷♀️ Unhandled event type: ${event.type}`);
}
res.json({ received: true });
} else {
res.setHeader('Allow', 'POST');
res.status(405).end('Method Not Allowed');
}
};
export default cors(webhookHandler);