Article focus
Starting point: keep cart, order and payment connected
The checkout must preserve amount, delivery and reservation context after the customer moves to the bank payment page.
The usual WooCommerce risk appears when an order is marked paid immediately after a return URL. A customer can close the tab, reopen a link or come back before the bank supplies a final result.
In this case, the order remains pending payment before the vPOS redirect. The backend stores order id, amount, currency and external payment id so the result can be verified and reconciled without manual guessing.
- Freeze cart, discount, delivery and currency before creating a payment session.
- Use one internal order id in every call and log.
- Do not create a new order when the customer retries payment.
- Store internal and external payment identifiers separately.
Implementation: webhook and server-side verification drive the state
The frontend gives the customer feedback, while the backend remains the source of truth for a payment result.
After payment, the customer returns to a result page while the backend independently accepts a callback or webhook and verifies signature, amount, currency, order id and the allowed state transition.
Repeated delivery does not create another order, receipt or notification. The handler uses idempotency and retains an attempt history. Pending, failed, paid and refunded remain separate events rather than one overwritten label.
- Verify event authenticity and critical fields on the server.
- Separate payment, order and fiscal receipt states.
- Keep an audit trail for duplicate callbacks and manual actions.
- Do not release goods for a pending payment.
After launch: refunds and daily reconciliation
The team must see successful payments as well as discrepancies between WooCommerce, the bank and internal records.
A refund is registered as a separate operation linked to the original payment. This preserves an audit trail for partial refunds, repeated webhooks and fiscal follow-up.
Daily reconciliation compares verified payments, cancellations, refunds and pending orders. The team receives an exception list instead of rebuilding the payment history from screenshots and messages.
- Do not delete the original payment when refunding.
- Investigate mismatches by order id and provider payment id.
- Review retries and expired payment links.
- Define a support path for disputed operations.
FAQ
Can WooCommerce mark an order paid from a return URL?
No. A return URL is for customer experience. The final state needs server-side verification or a correctly processed webhook.
How do we prevent duplicate payments or callbacks?
Keep stable order and payment ids, use an idempotency key, validate permitted state transitions and log every delivery attempt.
What matters for refunds?
A refund must be a separate operation linked to the original payment. It must not erase the order or original payment history.