A webhook is not a regular form submit
A callback from a payment system must pass authenticity, amount and order-state checks before business status changes.
A webhook is sent by an external system, not by the customer. The handler should be small, predictable and safe for repeated delivery. Heavy downstream work should usually move to a queue.
Minimum checks include event authenticity, amount and currency match, order existence, valid status transition and duplicate protection. Only then should the business status change.
- Verify signature or the provider-specific trusted mechanism.
- Match amount, currency and order id.
- Check whether the current status is already final.
- Store the raw event in an audit log.
- Return a fast technical response to the provider.
Statuses should be a state machine
Without explicit transition rules, late events can move an order from paid back to pending or failed.
Payment statuses should be described as a state machine. There are initial, intermediate and final states. Final statuses should not be overwritten accidentally by older events.
For example, when an order is already paid, a late pending callback must not roll the order back. Refund is a separate business event, not simply failed.
- Created and Pending are not final states.
- Paid, Failed and Cancelled are final for the payment attempt.
- Refunded or partially refunded is a separate branch after a successful payment.
- Every forbidden transition should be logged.
Retries and queues protect against temporary failures
CRM, ERP or fiscal APIs can be unavailable, but the payment event must not be lost.
When payment success must be delivered to CRM, ERP or a fiscal service, the safer path is a queue. The webhook is persisted quickly, and internal integrations consume the event with retries.
This reduces the risk of money being captured while the order remains unchanged due to a temporary third-party outage. The log should show successful deliveries, pending retries and cases requiring manual review.
- Persist the event before processing.
- Use exponential backoff for retries.
- Have a dead-letter state for manual review.
- Do not repeat the charge when retrying internal delivery.
FAQ
Should a webhook immediately update the order?
Only after authenticity, amount, currency, order id and status transition checks pass.
What if CRM is down after a successful payment?
Persist the payment event and deliver it to CRM through a retry queue. A temporary CRM failure should not lose the payment status.
Can one webhook be received more than once?
Yes. The handler must be idempotent so repeated events do not create duplicate orders, receipts or status changes.