Payment status is a business control, not just a label for the customer interface. A clear state model helps the checkout, backend, webhook handler and operations team agree on what has happened, what may happen next and when fulfillment is allowed.
Model payment status as a state machine
Define each status by evidence and permitted transitions rather than by appearance. A newly created payment can wait for a transfer, an observed transfer can wait for confirmation and a confirmed payment can become eligible for fulfillment. The backend should reject transitions that skip required evidence or move a terminal state backward.
Keep the payment state separate from the local order state. A payment may be confirming while the order remains unpaid, and a paid payment may still wait for inventory or account activation. This separation prevents payment events from overwriting unrelated business decisions.
- Document the evidence required for every state
- Allow only explicit forward transitions
- Store payment and fulfillment states separately
Use pending for a payment that still needs a transfer
Pending should mean that the payment order exists but no matching transfer has been accepted. The checkout can continue showing the exact amount, selected network, destination and expiry information while the server monitors for a corresponding transaction.
Do not interpret a wallet opening, QR scan or browser return as progress beyond pending. Those events describe customer activity, not settlement evidence. If the payment expires before a valid transfer is observed, move it to a distinct expired state instead of silently leaving it pending.
- Start new payment orders in pending
- Keep the exact payment instructions visible
- Expire unpaid orders through an explicit transition
Use confirming after a matching transfer is observed
Confirming indicates that a relevant blockchain transaction has been detected but has not yet reached the application's acceptance rule. Record the transaction hash, observed amount, network and current confirmation count so the state can be explained and reconciled later.
The merchant application should continue withholding fulfillment while a payment is confirming. Network observation can change, and the payment service may need additional evidence before reporting success. Displaying this intermediate state helps customers understand that the transfer was seen without promising completion too early.
- Attach the observed transaction to the payment
- Track confirmation progress on the server
- Keep fulfillment disabled during confirmation
Reserve paid for the fulfillment decision
Paid should be the single state that authorizes the merchant workflow to continue. With bestuPay, the merchant server receives a signed webhook when the payment reaches the successful state and should verify the HMAC-SHA256 signature over the raw request body before trusting it.
Process the paid transition idempotently. Store the event identifier or another durable deduplication key before activating a subscription, releasing a download or marking an order ready. A repeated webhook must acknowledge the existing result without performing fulfillment again.
- Fulfill only from the documented paid state
- Verify webhook authenticity before updating the order
- Make repeated paid events harmless
Route exception states to deliberate handling
Underpaid, overpaid, late and ambiguous transfers should not be compressed into paid or failed. Preserve the observed amount and transaction details, then route the payment to a clearly named exception state so an operator can review it without losing the original evidence.
Define who owns each exception, what information support can provide and which corrective actions are allowed. Keep manual decisions in an audit trail and notify the merchant application through the same verified server-side path used for automated updates. This makes recovery visible without weakening normal payment controls.
- Keep exception states distinct and searchable
- Record every manual decision with its context
- Reconcile merchant orders through verified server events