#belle_webhooks

1 messages ¡ Page 1 of 1 (latest)

idle tartanBOT
#

👋 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.

oblique lance
#

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

steep geyser
#

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

oblique lance
#

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

steep geyser
#

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.

oblique lance
#

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

steep geyser
#

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?

Find information about the support schedule for different Express.js versions, including which versions are currently maintained and end-of-life policies.

oblique lance
#

Ok that sounds good, thank you so much! I'll try that