#yjjj_webhooks
1 messages · Page 1 of 1 (latest)
👋 Welcome to your new thread!
⏲️ We'll be here soon! We typically respond in a few minutes, but in some cases we might need a bit more time (e.g., server's busy, you've got a complex question, etc.).
⏱️ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can 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/1246057704028635228
📝 Have more to share? Add details, code, screenshots, videos, etc. below.
You'll need to share your code, particularly the part that is throwing the exception
Also, a evt_xxx ID that isn't being processed
Do you do signature verification at your endpoint? If so, likely one of two issues:
- Uses the wrong
whsec_xxxsecret for the endpoint - Your code/provider is malforming the request payload which you pass to the
constructEventfn. It needs to be the raw event payload
Google Cloud right? They have this rawBody object you need to use: https://cloud.google.com/functions/docs/writing/write-http-functions#parsing_http_requests
Here is the relevant code snippet:
`const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, {
apiVersion: "2022-11-15",
});
const secret = process.env.STRIPE_WEBHOOK_SECRET_KEY || "";
export const config = {
api: {
bodyParser: false,
},
};
customInitApp();
async function handleCheckoutSessionCompleted(event, db) {
... code to update user credits to firebase
}
export default async function handler(req, res) {
console.log("Received Stripe webhook event.");
if (req.method !== "POST") {
console.error("Method Not Allowed");
return res.status(405).send("Method Not Allowed");
}
let event;
try {
const buf = await buffer(req);
console.log("Buffered request: ", buf.toString());
const sig = req.headers["stripe-signature"];
console.log("Stripe signature: ", sig);
if (!sig) {
console.error("Stripe signature missing.");
throw new Error("Stripe signature missing.");
}
event = stripe.webhooks.constructEvent(buf.toString(), sig, secret);
console.log("Event constructed: ", event);
} catch (err) {
console.error(err.message);
return res.status(400).send(`Webhook Error: ${err.message}`);
}
const db = getFirestore();
try {
switch (event.type) {
case "checkout.session.completed":
console.log("Checkout session completed.");
await handleCheckoutSessionCompleted(event, db);
break;
default:
console.log(`Unhandled event type ${event.type}`);
}
res.status(200).json({ received: true });
} catch (err) {
console.error(err.message);
return res.status(400).send(`Webhook Error: ${err.message}`);
}
}
`
I suspect req is malformed as per the link I shared. What you need is req.rawBody:
Cloud Functions automatically parses the request body for you based on the request's Content-Type header using body-parser, so you can access the req.body and req.rawBody objects in your HTTP handler.
Which is likely why the code works fine locally, but errors when deployed
Thank you✨ I will try using req.rawBody as you mentioned. However, I am deploying my application to Cloud Run, not Cloud Functions, so I'm not sure if this approach will work in my case.
I appreciate your help!
I couldn't find any specific Cloud Run documentation, but I suspect it's likely the same issue as they probably use the same function engine
I'd be surprised if you catch block around constructEvent isn't catching the exception here though
Yeah, that's why I am very confused.
These are serverless functions right?
Yes
Hmm
Here is one of the related event ID: evt_1PMRx0EUlaWkbeP0Dhs2VuuO
Yeah you can see it's timing out
We expect a 2xx response within a couple of minutes and we're not receiving that
I think you're going to need to debug further with the Cloud Run runtime and figure out why the code isn't executing. Try and just deploy a random hello world function that returns a 200 and remove all the webhook logic
Ok, thank you for the suggestion.🙌
Hopefully the events can reach that and we get the 200 response
Otherwise could maybe be a firewall/connectivity issue but then I'd guess you'd never see the log at all