Payment Webhook Retries: How to Prevent Duplicate Fulfillment
A payment notification arriving twice should not ship an order twice, issue two invoices, or create two memberships. Reliable integrations must recognize repeated notifications and make each business action safe to repeat.
This matters after checkout. A customer can pay successfully while the connection between the payment platform, store, and fulfillment system still fails.
Separate the payment from the notification
A webhook tells another system that an event occurred. Repeated delivery of that notification is not proof of a second payment.
Stripe documents that webhook deliveries can repeat and arrive out of order. Its guidance includes tracking processed event IDs; separate events representing a duplicate can require comparing the object ID and event type. It also recommends signature verification and asynchronous processing. See Stripe's webhook documentation.
For other payment providers, check their own delivery and verification rules rather than assuming Stripe's behavior applies.
Define one identity for each business action
For a proposed integration, write down what makes an action unique. The answer might be one fulfillment request for a particular order, one access grant for a particular paid enrollment, or one accounting entry for a particular transaction.
An event ID helps identify repeated messages. A business-action key protects against different messages triggering the same downstream job. These serve different purposes.
For example, a hypothetical store receives a successful payment notification for order 8421. The integration records a fulfillment action for that order. If the same message arrives again, it recognizes the existing action instead of creating another shipment.
Record durable progress
A useful design review follows the notification through these stages:
- Verify the incoming message using the provider's documented method.
- Record it durably before acknowledging successful receipt.
- Determine the relevant order and intended business action.
- Prevent concurrent workers from creating the same action twice.
- Track the downstream result and retry failed work safely.
The fourth step needs more than a quick “does this exist?” check. Two workers can both see that nothing exists and both act. Have the engineer review transaction boundaries, uniqueness constraints, and downstream idempotency together.
Test failure paths before relying on automation
| Test scenario | Expected business result |
|---|---|
| Same notification delivered twice | One fulfillment request |
| Two workers handle the same action together | One completed business action |
| Downstream request times out after possibly succeeding | Verify its outcome before repeating it |
| Notifications arrive in an unexpected order | Resolve current payment state without assuming sequence |
| Customer returns to the thank-you page repeatedly | No additional fulfillment |
These are integration acceptance criteria, not promises that every plugin already meets them.
Give staff a reconciliation view
When payment is complete but fulfillment is uncertain, staff need a way to compare payment records, orders, and downstream actions. A delivery log alone cannot establish that the customer received the intended service.
Does a duplicate webhook mean a duplicate charge?
No. Compare the provider's underlying transaction records before concluding that a customer paid twice.
Can we just disable retries?
Retries help recover from delivery failures. The integration should handle them safely rather than depend on every first attempt succeeding.
CCMS works on WooCommerce payments and integrations. Discuss your store's payment workflow if money, orders, and fulfillment are falling out of sync.
Payments out of sync?
If money, orders, and fulfillment don't line up, we can review the workflow with you.
Contact CCMS