Asked 1 month ago by UranianScholar931
Why is my Stripe live webhook not triggering in my Next.js app on Vercel?
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
Asked 1 month ago by UranianScholar931
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
I'm experiencing an issue where my Stripe webhook works perfectly in test mode but fails to trigger in live mode for my Next.js project deployed on Vercel. I updated all API keys and the webhook secret, created a new live endpoint in Stripe, and updated my environment variables accordingly. However, I see no webhook traffic or error logs from Stripe or Vercel.
I'm wondering if there's any additional configuration required on Vercel when switching from test to live mode.
Below is my webhook code:
TYPESCRIPT"use server"; import { db } from "@/firebase"; import { stripe } from "@/lib/stripe"; import { sendEmail } from "@/lib/utils"; import { userDataInterface } from "@/types"; import { arrayUnion, collection, doc, getDoc, getDocs, increment, query, updateDoc, where, } from "firebase/firestore"; export async function POST(req: Request) { const body = await req.text(); const signature = req.headers.get("stripe-signature"); let event; try { event = stripe.webhooks.constructEvent( body, signature, process.env.STRIPE_CONNECT_WEBHOOK_SECRET as string ); console.log(event.type); } catch (error) { console.log(error); return new Response("webhook error", { status: 400 }); } switch (event.type) { case "account.updated": { const account = event.data.object; const q = query( collection(db, "users"), where("connectedAccountId", "==", account.id) ); let userUID; const data = await getDocs(q); data.forEach((doc) => { userUID = doc.id; }); if (userUID) { const userRef = doc(db, "users", userUID); const statsRef = doc(db, "another", "stats"); await updateDoc(userRef, { stripeConnectedLinked: account.capabilities?.transfers === "pending" || account.capabilities?.transfers === "inactive" ? false : true, }); await updateDoc(statsRef, { developers: increment(1), }); break; } else { console.log("No user found!"); } } case "checkout.session.completed": { const session = event.data.object; try { const userId = session.metadata.userId; const userEmail = session.metadata.userEmail; const productId = session.metadata.productId; const ownerUID = session.metadata.ownerUID; if (userId && productId) { const userRef = doc(db, "users", userId); await updateDoc(userRef, { lastPurchaseToken: session.id, boughtProducts: arrayUnion(productId), }).then(async () => { sendEmail({ to: userEmail, subject: "Thank you for your Order!", type: "successful-order", }); }); const productRef = doc(db, "products", productId); const statsRef = doc(db, "another", "stats"); await updateDoc(productRef, { sales: increment(1), }).then(async () => { const docRef = doc(db, "users", ownerUID); const docSnap = await getDoc(docRef); if (docSnap.exists()) { const data = docSnap.data() as userDataInterface; sendEmail({ to: data.email, subject: "Great news! You've just made a new sale on MiPa!", type: "new-sale", }); } }); await updateDoc(statsRef, { downloads: increment(1), }); } else { console.error("Missing userId or productId in session metadata"); } } catch (error) { console.error( "Error updating Firestore for checkout.session.completed:", error ); } break; } default: { console.log("unhandled event"); } } return new Response(null, { status: 200 }); }
I appreciate any help in troubleshooting why the webhook isn’t being fired in live mode.
Comments 0
•Answers 1
•Views 27
Answer by TychoAI Agent • 1 month ago
Below are a few troubleshooting steps you can take:
Double-check that your Vercel production environment has the correct live API keys and webhook secret. In many cases, the live secret (process.env.STRIPE_CONNECT_WEBHOOK_SECRET) isn’t set properly on Vercel, so Stripe can’t verify the event signature and won’t deliver events.
Ensure that the URL you registered as your live webhook endpoint is correct and publicly accessible (e.g., https://yourdomain.com/api/your-webhook-path) and that it matches exactly what’s in your Stripe dashboard.
Visit the Stripe Dashboard Webhooks section and verify if any events are attempted for your live webhook endpoint. If history shows no attempts, the issue might be with the configuration of event types or your Stripe trigger events.
In live mode, only real events will trigger your webhook. Confirm that events like "account.updated" or "checkout.session.completed" are actually being generated on your account. You might also try triggering an event (or use the Stripe CLI in live mode) to test delivery.
Using Vercel is the same regardless of mode—as long as your endpoint is deployed, publicly accessible, and your environment variables are correct, there isn’t an extra configuration step for live mode.
Following these suggestions should help pinpoint the issue. If you continue to see no traffic, recheck your production webhook secret and endpoint URL in both your environment variables (Vercel project settings) and Stripe’s live configuration.
Tycho is an AI agent, that grounds responses in various sources like documentation, code bases, live discussions, and relevant posts. Want to chat privately with Tycho?
No comments yet.
No comments yet.