Prompt
How do I fix payment webhooks not firing for successful charges?
Latest observation
If payment webhooks aren’t firing for successful charges, the fix is usually in one of these areas:
1. Verify the webhook is actually configured
- Confirm the webhook endpoint exists in your payment provider dashboard.
- Make sure it’s subscribed to the right event types, such as:
payment_intent.succeededcharge.succeededcheckout.session.completedinvoice.paid
- Check whether you configured it in the test or live environment.
2. Confirm you’re listening for the right event
A “successful charge” may trigger a different event depending on the payment flow:
- Stripe Checkout: often
checkout.session.completed - PaymentIntents:
payment_intent.succeeded - Direct charges:
charge.succeeded - Subscriptions:
invoice.paidorinvoice.payment_succeeded
It’s common to expect charge.succeeded when your integration only emits payment_intent.succeeded.
3. Check endpoint response requirements
Most providers expect:
- A 2xx HTTP response
- Fast acknowledgment, usually within a few seconds
If your server:
- returns 4xx/5xx
- times out
- crashes
- blocks while doing long work
the provider may retry or mark delivery as failed.
4. Inspect delivery logs
In your payment provider dashboard:
- open webhook delivery history
- check whether events were sent
- inspect response codes and error messages
- look for retries or signature verification failures
This often reveals the exact problem quickly.
5. Make sure signature verification is correct
If your code rejects events due to bad signatures:
- ensure you’re using the correct signing secret
- verify raw request body handling is set up correctly
- do not parse/modify the body before signature verification
For example, with Stripe, signature verification fails if the raw body isn’t preserved.
6. Check networking / deployment issues
Common production issues:
- webhook URL not publicly reachable
- firewall or WAF blocking requests
- HTTPS certificate problems
- wrong DNS / load balancer routing
- endpoint only works locally
Test the endpoint from the internet, not just from your dev machine.
7. Ensure idempotency and event handling logic are correct
Sometimes the webhook is firing, but your app ignores it:
- event type mismatch
- duplicate detection too aggressive
- database transaction failure
- logic only handles one charge path
Log the full incoming event payload to confirm it arrives.
8. Review provider-specific limitations
Some providers:
- don’t send webhooks for certain failed/async payment methods immediately
- send events asynchronously after settlement
- require explicit enabling of event categories
Quick checklist
- Webhook URL correct
- Correct event types subscribed
- Live/test mode matches
- Endpoint returns 2xx quickly
- Signature verification passes
- Endpoint publicly accessible
- Delivery logs show successful attempt
- Your code handles the exact event you expect
If you want, I can help you debug this for a specific provider like Stripe, PayPal, Square, or Adyen.