Article focus
Start with the order model
The store needs a stable order before it starts a payment attempt.
Create an order with a stable identifier before redirecting the customer to checkout. A payment attempt then belongs to that order and can be retried, reconciled or refunded without losing the commercial context.
Separate the order state from the payment attempt state. An order may be awaiting payment, have a pending attempt or be ready for fulfilment only after the backend receives a verified paid result.
- Keep the amount immutable for each attempt.
- Store the provider payment id.
- Avoid treating a browser redirect as payment confirmation.
Handle failed and pending payments as normal states
Customers close tabs, networks time out and providers can answer later.
A store should show the customer a clear next step without inventing a final order result. The backend continues to check a pending payment through verified provider status or a trusted callback.
Do not create a fresh order whenever a customer retries a payment. Create a controlled new payment attempt for the same order and protect it with idempotency rules.
- Give pending payments a recovery path.
- Do not ship before verified payment.
- Log every payment attempt against the order.
Deliver a verified event to operations
Payment should update CRM, delivery and fiscal workflows through one controlled event.
After verification, send the relevant business fields to CRM or ERP and create downstream tasks from the normalized payment event. This avoids a shipping team receiving an order that was only marked paid by the frontend.
Define which actions are synchronous for the customer and which belong in queues. A customer-facing success page should stay fast while accounting, notifications and fiscal tasks remain observable in the backend.
- Use a normalized paid event.
- Keep asynchronous work observable.
- Provide support with an order timeline.
FAQ
Should an order be created before or after payment?
Usually before payment, with a stable order id that each payment attempt references.
What if the customer closes the payment page?
Keep the order pending and verify the provider status on the backend or through a trusted callback.
Can the same order be paid again?
The store should control retries and block a second confirmed payment for a closed order.