I am receiving correctly Stripe webhooks POST req but having trouble handling the request.
Is there something I am missing? Console.logs don’t print to terminal.
Here is my code so far with the outline of what i want to handle when received checkout.session.completed
from stripe.
import { createClient } from '@supabase/supabase-js';
import { headers } from 'next/headers';
import { NextRequest, NextResponse } from 'next/server';
import { NextApiRequest, NextApiResponse } from 'next';
import Stripe from 'stripe';
import { Resend } from 'resend';
import EmailTemplate from '@/components/email-template';
const resend = new Resend(process.env.NEXT_RESEND_API_KEY);
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);
const stripe = new Stripe(`${process.env.STRIPE_SECRET_KEY}`, {
apiVersion: '2023-08-16',
});
type ResponseData = {
message: string;
};
//Handling incoming POST req
async function POST(request: NextRequest) {
try {
const body = await request.text();
const endpointSecret = process.env.STRIPE_SECRET_WEBHOOK_KEY!;
const sig = headers().get('stripe-signature') as string;
// const sig = headers().get('Stripe-Signature') as string;
let event: Stripe.Event;
//read the event data from stripe
try {
event = stripe.webhooks.constructEvent(body, sig, endpointSecret);
} catch (err) {
return new Response(`Webhook Error: ${err}`, {
status: 400,
});
}
console.log(`Received event !webhook!: ${event?.type}`);
// Handle the event: checkout.session.completed
switch (event.type) {
case 'checkout.session.completed':
const session: any = event.data.object;
console.log('!Checkout session completed!:', session.payment_status);
// get customer name, email
const customerEmail = session.customer_details.email;
const customerName = session.customer_details.name;
// create the customer in db
const { data: customer, error: errorCustomer } = await supabase
.from('Customer')
.insert({ customerName, customerEmail })
.select()
.single();
if (errorCustomer) throw new Error(errorCustomer.message);
// update order in sb with paymentStatus + customerId
const { data: orderData, error: errorOrder } = await supabase
.from('Order')
.update({
customerId: customer.customerId,
paymentStatus: session.payment_status,
})
.eq('orderId', session.id)
.select();
if (errorOrder) throw new Error(errorOrder.message);
// create coupon and promotion code
if (session.amount_total !== 0) {
const coupon = await stripe.coupons.create({
name: 'business-100',
percent_off: 100,
duration: 'repeating',
duration_in_months: 1,
max_redemptions: 4,
});
if (!coupon) throw new Error('Coupon not created');
const promCode = await stripe.promotionCodes.create({
coupon: coupon.id,
max_redemptions: 4,
});
if (!promCode) throw new Error('Promotion code not created');
const { data, error: errorResend } = await resend.emails.send({
from: '[email protected]',
to: [customerEmail],
subject: 'Promotional code',
react: EmailTemplate({
firstName: `${customerName}`,
orderId: `${session.id}`,
promCode: `${promCode.code}`,
}),
text: `Hi there, here is your promotional code: ${promCode.code}`,
});
if (errorResend) throw new Error(errorResend.message);
}
break;
default:
}
return NextResponse.json({ received: true });
} catch (error) {
return NextResponse.json({ error }, { status: 400 });
}
}
async function GET(request: NextApiRequest, response: NextApiResponse) {
// Bad Request or how ever you want to respond.
return response.status(400).json({ error: 'Bad Request' });
}
export { POST, GET };
Thank you in advance.
Stripe CLI post request webhooks are received – OK.
checkout.session.completed is received – OK
checkout.session.completed triggers supabase and further actions which are not happening despite correct POST reponses.
Ehtz is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.