#belle_webhooks
1 messages ¡ Page 1 of 1 (latest)
đ Welcome to your new thread!
â˛ď¸ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question.
âąď¸ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.
đ This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1341938536903081997
đ Have more to share? Add more details, code, screenshots, videos, etc. below.
I have a stripeWebhookController.ts file that looks like this:
import { Request, Response } from "express";
import Stripe from "stripe";
import dotenv from "dotenv";
import { createOrder, createOrderItem } from "../models/orderModel";
import { getCheckoutCart } from "../models/cartModel";
dotenv.config();
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: "2023-08-16",
});
// This endpoint should receive the raw body
export const stripeWebhook = async (req: Request, res: Response): Promise<void> => {
console.log("Webhook hit");
const sig = req.headers["stripe-signature"];
let event: Stripe.Event;
try {
event = stripe.webhooks.constructEvent(
req.body,
sig as string,
process.env.STRIPE_WEBHOOK_SECRET!
);
} catch (err: any) {
console.error(`Webhook signature verification failed: ${err.message}`);
res.status(400).send(`Webhook Error: ${err.message}`);
return;
}
// Handle the checkout.session.completed event
if (event.type === "checkout.session.completed") {
const session = event.data.object as Stripe.Checkout.Session;
// Retrieve the authenticated user ID from client_reference_id
const userId = session.client_reference_id;
if (!userId) {
console.error("Missing user ID in session.");
res.status(400).end();
return;
}
const cartId = session.metadata?.cartId;
if (!cartId) {
console.error("Missing cartId in session metadata.");
res.status(400).end();
return;
}
let cartItems: any[] = [];
try {
cartItems = await getCheckoutCart(cartId);
console.log("cart items from checkout cart: ", cartItems);
} catch (err) {
console.error("Error fetching checkout cart: ", err);
res.status(400).end();
return;
}
// Calculate total amount from cart items
const totalAmount = cartItems.reduce(
(sum: number, item: any) => sum + Number(item.price) * (item.quantity || 1),
0
);
try {
// Create the order record
const order = await createOrder(userId, session.id, totalAmount, "paid");
console.log("Order creayed with ID: ", order.id);
// Insert order items
for (const item of cartItems) {
await createOrderItem(
order.id,
item.file_id,
item.file_key,
item.title,
item.price,
item.seller_id
);
}
console.log("Order finalized: ", order.id);
} catch (err) {
console.error("Error finalizing order in webhook: ", err);
}
}
// Acknowledge receipt of the event
res.status(200).json({ received: true });
}```
This is the output from Stripe CLI when I complete a checkout:
2025-02-19 19:55:12 --> checkout.session.completed [evt_1QuO2lLcKemy5NBarKQFQZSw]
2025-02-19 19:55:12 <-- [404] POST http://localhost:3000/api/webhooks/stripe [evt_1QuO2lLcKemy5NBarKQFQZSw]
[Wed, 19 Feb 2025 20:04:41 EST] ERROR websocket.Client.writePump: Error when writing ping message: websocket: close sent
I have the route exposed on this endpoint, which calls my stripeWebhook function:
import { Router } from "express";
import { stripeWebhook } from "../controllers/stripeWebhookController";
const router = Router();
router.post("/stripe", stripeWebhook);
export default router;```
I'm at my wits end trying to figure out why the endpoint function is not being hit correctly haha you guys are my last hope
Hi there, a 404 is a resource not found error (https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404), meaning that your server is unable to hanle the request path (i.e., /api/webhooks/stripe )
Since you are using express, you'll want to consult their documentation (https://expressjs.com/en/guide/routing.html) and configure your server accoringly so that it's able to respond to the POST /api/webhooks/stripe requests
That's the problem, I'm like, 97% sure that my index.ts is configured correctly to work for this:
// For Stripe webhooks, use raw body parser
app.post(
"/api/webhooks",
bodyParser.raw({ type: "application/json" }),
(req, res, next) => {
webhookRouter(req, res, next);
}
);
// Middleware to parse JSON requests
app.use(express.json());```
the post request goes to /api/webhooks/stripe, it should not be returning a 404 not found
I have several other routes on my website that are also correctly configured with express, get, post, delete, etc, and none of them give me a 404
You might want to restart the server and try again. Or reach out to the express community for help.
I noticed that you are using a middleware for parsing JSON, it may cause signature verificaiton errors (https://docs.stripe.com/webhooks/signature). Once you fix the routing problem, you should remove the json middle and pass raw request body to your webhook event handler.
Ok, do you know if express has a similar discord server I could join? Or any other way for me to get in contact with the express community? I tried searching on google but nothing came up besides general programming help
https://expressjs.com/en/support/ I saw a slack icon on their support page. Maybe you want to use it and see if you can reach out to them?
Ok that sounds good, thank you so much! I'll try that