refactor: restructure stripe webhook handler for improved readability and error handling

This commit is contained in:
Marco Pedone 2025-09-09 09:38:29 +02:00
parent be0cd554a6
commit aa8fb57ab4

View file

@ -5,13 +5,12 @@ import type { PaymentsId } from "~/schemas/public/Payments";
import { appRouter } from "~/server/api/root";
import { createTRPCContext, t } from "~/server/api/trpc";
const stripe = new Stripe(env.STRIPE_SECRET_KEY);
const endpointSecret = env.STRIPE_WEBHOOK_SECRET;
export default async function handler(
const handler = async (
req: NextApiRequest,
res: NextApiResponse,
) {
): Promise<void> => {
const stripe = new Stripe(env.STRIPE_SECRET_KEY);
if (req.method === "POST") {
const ctx = await createTRPCContext({ req: req, res: res });
const createCaller = t.createCallerFactory(appRouter);
@ -19,17 +18,22 @@ export default async function handler(
const sig = req.headers["stripe-signature"];
let event: Stripe.Event | undefined;
let event: Stripe.Event;
if (!sig) {
res.status(400).send("Webhook Error: Missing Stripe signature");
return;
}
try {
const body = await buffer(req);
event = stripe.webhooks.constructEvent(body, sig, endpointSecret);
event = stripe.webhooks.constructEvent(
body,
sig,
env.STRIPE_WEBHOOK_SECRET,
);
} catch (err) {
console.error("Error verifying webhook signature:", err);
return res.status(400).send(`Webhook Error: ${(err as Error).message}`);
res.status(400).send(`Webhook Error: ${(err as Error).message}`);
return;
}
// Handle the event
@ -39,10 +43,12 @@ export default async function handler(
const { id, metadata } = paymentIntent;
if (!metadata) {
return res.status(400).send("No metadata in payment intent");
res.status(400).send("No metadata in payment intent");
return;
}
if (!metadata.paymentId || !(typeof metadata.paymentId === "string")) {
return res.status(400).send("No orderId or userId in metadata");
res.status(400).send("No orderId or userId in metadata");
return;
}
await caller.stripe.whIntentCreated({
@ -57,10 +63,12 @@ export default async function handler(
const { id, metadata } = paymentIntent;
if (!metadata) {
return res.status(400).send("No metadata in payment intent");
res.status(400).send("No metadata in payment intent");
return;
}
if (!metadata.paymentId || !(typeof metadata.paymentId === "string")) {
return res.status(400).send("No orderId or userId in metadata");
res.status(400).send("No orderId or userId in metadata");
return;
}
await caller.stripe.whIntentSucceeded({
paymentId: metadata.paymentId as PaymentsId,
@ -105,7 +113,7 @@ export default async function handler(
res.setHeader("Allow", "POST");
res.status(405).end("Method Not Allowed");
}
}
};
export const config = {
api: {
@ -128,3 +136,5 @@ const buffer = (req: NextApiRequest) => {
req.on("error", reject);
});
};
export default handler;