NextJS and stripe webhook
Unanswered
California pilchard posted this in #help-forum
California pilchardOP
Okay im using Supabase as backend for my nextjs application, I have this route :
import Stripe from 'stripe';
import { stripe } from '@/lib/stripe/stripe';
import {
upsertProductRecord,
upsertPriceRecord,
manageSubscriptionStatusChange,
deletePriceRecord,
deleteProductRecord,
} from '@/lib/supabase/supabase-admin';
export async function POST(request: Request) {
const body = await request.text();
const sig = request.headers.get('stripe-signature') as string;
const webhookSecret = process.env.NEXT_PUBLIC_STRIPE_WEBHOOK_SECRET;
let event: Stripe.Event;
console.log(`🔔 Webhook received: sig:${sig}, body:${body}, webhookSecret:${webhookSecret}`);
try {
if (!sig || !webhookSecret)
return new Response('Webhook secret not found.', { status: 400 });
event = stripe.webhooks.constructEvent(body, sig, webhookSecret);
console.log(`🔔 Webhook received: ${event.type}`);
} catch (err: any) {
console.log(`❌ Error message: ${err.message}`);
return new Response(`Webhook Error: ${err.message}`, { status: 400 });
}
if (relevantEvents.has(event.type)) {
try {
switch (event.type) {
case 'product.created':
case 'product.updated':
await upsertProductRecord(event.data.object as Stripe.Product);
break;
{...}
default:
throw new Error('Unhandled relevant event!');
}
} catch (error) {
console.log(error);
return new Response(
'Webhook handler failed. View your Next.js function logs.',
{
status: 400
}
);
}
} else {
return new Response(`Unsupported event type: ${event.type}`, {
status: 400
});
}
return new Response(JSON.stringify({ received: true }));
}
57 Replies
California pilchardOP
Its very new because its was working before idk why but there is the log from stripe :
I try on local (with dev nextjs) and
Webhook Error: No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe?
Learn more about webhook signing and explore webhook integration examples for various frameworks at https://github.com/stripe/stripe-node#webhook-signing
I try on local (with dev nextjs) and
stripe.webhooks.constructEvent
seems to work properlyuhm i see
the production build is on vercel?
i just read the docs and u need to parse the raw body
cause in your current setup u parse it to text
what happens if u directly pass request.body
California pilchardOP
No im using Coolify with the Dockerfile give as example by nextjs
but all
Supabase
and Stripe
examlpe do thisAnd seems weird if its working on
dev
mode but not after build in CoolifyCalifornia pilchardOP
Using
request.body
i have this :The argument of type 'ReadableStream<Uint8Array> | null' is not assignable to the parameter of type 'string | Buffer'.
Cannot assign type 'null' to type 'string | Buffer'.ts(2345)
California pilchardOP
But this seems weird because in production mode, I have already a console.log and I can see
const body = await request.text();
return something goodeven if
stripe.webhooks.constructEvent
failyeah thats obviously works
but i think they expect the body as unparsed and not consumed
just raw buffer
i could be wrong
but try that
try this
const rawBody = await buffer(req);
const body = JSON.parse(rawBody.toString());
@California pilchard buffer function is from this lib -> micro
npm i micro
after that u can try passing rawBody directly and if that throws something try it with the parsed json body from the raw body
California pilchardOP
I have this error on buffer :
Maybe I can try updating stripe lib ?
The argument of type 'Request' is not assignable to the parameter of type 'IncomingMessage'. The type 'Request' is missing the following properties from type 'IncomingMessage': aborted, httpVersion, httpVersionMajor, httpVersionMinor, and 50 others.
Maybe I can try updating stripe lib ?
where did that happen?
converting to buffer?
California pilchardOP
When over buffer in vscode because my
request
variable was underline in redu used buffer from micro?
California pilchardOP
yes
can u try disabling typescript for that?
//@ts-ignore
i found a thread talking about this exact issue
California pilchardOP
nah cant dodge this :
POST /api/stripe 500 in 345ms
⨯ HttpError: Invalid body
at createError (webpack-internal:///(rsc)/./node_modules/micro/dist/src/lib/index.js:34:17)
at eval (webpack-internal:///(rsc)/./node_modules/micro/dist/src/lib/index.js:139:43)
at async POST (webpack-internal:///(rsc)/./src/app/api/stripe/route.ts:25:18)
at async /Users/loup/Projects/DEV/Recomend/recomend-web-app/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:6:53238
at async e_.execute (/Users/loup/Projects/DEV/Recomend/recomend-web-app/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:6:44501)
at async e_.handle (/Users/loup/Projects/DEV/Recomend/recomend-web-app/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:6:54492)
at async doRender (/Users/loup/Projects/DEV/Recomend/recomend-web-app/node_modules/next/dist/server/base-server.js:1372:42)
at async cacheEntry.responseCache.get.routeKind (/Users/loup/Projects/DEV/Recomend/recomend-web-app/node_modules/next/dist/server/base-server.js:1594:28)
this happened when passing in the whole req?
California pilchardOP
but this was for nextjs using page route not app router if I well understood
yes
what happens when u just pass the body?
req.body
California pilchardOP
⨯ TypeError: Cannot read properties of undefined (reading 'content-type')
at eval (webpack-internal:///(rsc)/./node_modules/micro/dist/src/lib/index.js:119:29)
at async POST (webpack-internal:///(rsc)/./src/app/api/stripe/route.ts:25:18)
at async /Users/loup/Projects/DEV/Recomend/recomend-web-app/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:6:53238
at async e_.execute (/Users/loup/Projects/DEV/Recomend/recomend-web-app/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:6:44501)
at async e_.handle (/Users/loup/Projects/DEV/Recomend/recomend-web-app/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:6:54492)
at async doRender (/Users/loup/Projects/DEV/Recomend/recomend-web-app/node_modules/next/dist/server/base-server.js:1372:42)
at async cacheEntry.responseCache.get.routeKind (/Users/loup/Projects/DEV/Recomend/recomend-web-app/node_modules/next/dist/server/base-server.js:1594:28)
Im gonna try to build image locally and run it in my computer
just to see if its depend of hoster
i could help u out via vscode liveshare
alr
California pilchardOP
well its working on my computer...
Maybe the problem come from coolify
hello i also want to know on stripe can we schedule custom email before the subscription end on stripe webhook?
California pilchardOP
sry idk about it, maybe open a help post for ur request
okay thanks
California pilchardOP
maybe the problem come from :
in fact in local i have
sig:t=1726852343,v1=54917084b5ffae814c0fff332aa43e90e4a922c4637d5e3a5bc098a23bbe4f4c,v0=a091a14f897e3b23cab124129011c10738480e174c6500c88292627c0a39b2bd
in fact in local i have
t
, v1
and v0
but when calling api route from production i have only t
and v1
California pilchardOP
arhh im tired of nextjs ahah so hard to debug
California pilchardOP
it seems there is something wront in NextJS 14.2.1 (or higher) https://stackoverflow.com/questions/78565636/stripe-signature-verification-is-failing-in-nextjs-14-2-3