Struggling to integrate data from Stripe check out events into my orders database, facing issues with finding the signature while testing the web hook.
Check out route: app/api/webhooks/checkout/route.ts
import Cors from "micro-cors";
import { headers } from "next/headers";
import { NextResponse, } from "next/server";
import Stripe from "stripe";
import prisma from "@/prisma/utils";
import { Users, Orders } from '@prisma/client';
import { sendEmail } from "@/email/utils";
import type { Readable } from 'node:stream';
import type { NextApiRequest } from "next";
import getRawBody from "raw-body";
import { buffer } from "micro";
const stripe = new Stripe(process.env.NEXT_PUBLIC_STRIPE_SECRET_KEY!);
const cors = Cors({
allowMethods: ["POST", "HEAD"],
});
export const config = {
api: {
bodyParser: false,
}
}
const secret = process.env.STRIPE_WEBHOOK_SECRET || "";
export async function POST(req: NextApiRequest) {
try {
const body = await buffer(req);
const sig = req.headers['stripe-signature']! as string;
const event = stripe.webhooks.constructEvent(body.toString(), sig!, secret);
if (event.type === "checkout.session.completed") {
if (!event.data.object.customer_email) {
throw new Error(`missing user email, ${event.id}`);
} else {
//if email exists then do some stuff
const id = event.data.object.id
const createdAt = new Date(event.data.object.created * 1000)
const order = await prisma.orders.findUnique({
where: {
id,
},
});
const email = event.data.object.customer_details!.email!
const user = await prisma.users.findUnique({
where: {
email,
}
});
const line_items = await stripe.checkout.sessions.listLineItems(
id
);
console.log('line items:' + line_items)
const products = JSON.stringify([
line_items!.data.map((item: any) => {
return {
item: item.description, //defualts to name
quantity: item.quantity,
price: item.price,
}
})
])
if(order){
throw new Error(`order already exist, ${id}`);
} else {
await prisma.orders.create({
data: {
id,
createdAt,
user_id: user!.id,
user_name: event.data.object.customer_details!.name!,
address: event.data.object.customer_details!.address!.line1!,
address_2: event.data.object.customer_details!.address!.line2!,
city: event.data.object.customer_details!.address!.city!,
state: event.data.object.customer_details!.address!.state!,
zip: Number(event.data.object.customer_details!.address!.postal_code!),
profit: Number(event.data.object.amount_total),
shipped: false,
deliverd: false,
products,
},
});
}
}
}
return NextResponse.json({ result: event, ok: true });
} catch (error) {
console.error(error);
return NextResponse.json(
{
message: "something went wrong",
ok: false,
},
{ status: 500 }
);
}
}
Encountering various errors while trying different methods:
Error using raw-body lib: TypeError - argument stream must be a stream.
Error using buffer from micro lib: HttpError - Invalid body and originalError: TypeError - stream.on is not a function.
Error using plain body like
req.body
: No signatures found matching the expected signature for payload.
Tried using body = req.text()
and switching request type from NextApiRequest
to Request
.
Tried adding bodyParser: false
.
Attempted changing
const sig = req.headers['stripe-signature']! as string;
to const sig = req.headers.get('stripe-signature')!
.Also explored using
sig = headers.get('stripe-signature')
.