Z Zise Developers 简体中文
Global Acquiring › Guides

Order states, refunds, and an easy accounting mistake: completed does not mean the full amount remains settled.

Orders and Refunds


GET /v1/qrpay/orders          ← 列表
GET /v1/qrpay/orders/{id}     ← 详情(含逐笔退款明细)

States

ValueMeaningLocation of funds
pendingFunds locked; upstream not yet notified (very brief)Locked
processingUpstream notified; awaiting a final stateLocked
completedUpstream succeededSettled
failedUpstream definitively failedUnfrozen
expiredTimed out without a final stateUnfrozen
canceledMember abandoned before upstream notificationUnfrozen
refundedFully refundedReturned

⚠ completed is not an absolute terminal state. The recipient merchant may initiate a refund later;

a completed order can become refunded (or remain completed while refunded_total increases).

Do not permanently remove an order from synchronization after it reaches completed.

⚠ Alert and suspend handling for unknown states; never default them to “processing.”

Showing a failed order as still running leaves the user waiting indefinitely.


The Key Point: status Cannot Tell You How Much Was Collected

Partial refunds do not change status. Only a full refund (settled amount minus our revenue) moves it to refunded.

Therefore:


这一单最终收了多少 = customer_total − refunded_total

⚠ Checking only state treats an order with a 90% refund as fully settled. Reports show inflated revenue,

even though each order looks individually valid—no assertion catches it.

Per-refund details—when and how much was refunded, including the acquirer-side amount—are available from the detail endpoint.

Amount Formats Differ Between the Two Endpoints

Endpointrefunded_total format
GET /v1/qrpay/orders (list)Fixed-point decimal string ("12.34")
GET /v1/qrpay/orders/{id} (detail)Integer string in smallest units ("12340000")

⚠ Do not reuse one parser for both. This is a historical inconsistency, not a design goal—

but it is now part of the contract, and changing it would break existing merchant integrations.


failure_code May Be Empty

Upstream failure reasons are free text. If no public code can be mapped, we return an empty string, not api_error.

⚠ A consistently wrong value is worse than an absent field—you would branch on it.


Refunds: You Cannot Initiate Them, but Must Handle Them

Your responsibility is to handle incoming refunds:

  1. Subscribe to the QR Payment Order Status webhook
  2. Query the order after receipt to read refunded_total (the webhook only signals a change)
  3. Merge forward using status_version; do not let a slow response overwrite newer state

The Scheme List Is Live


GET /v1/qrpay/schemes

It is not a static constant—the upstream scheme table changes, and we synchronize it. Schemes no longer returned upstream disappear from the list, while historical orders retain their original scheme information.

⚠ Do not copy the scheme table into your code. If you do, your interface will continue prompting users

to scan a scheme after the upstream has removed it.

Related Endpoints