Z Zise Developers 简体中文
Global Acquiring › Guides

The complete decode → quote → pay sequence, including how to handle processing.

Decode, Quote, and Pay

Read Configuration When the Screen Opens


GET /v1/qrpay/config

Whether this member can use QR payments, which currencies they can pay with, each balance, and the limits. When available: false, reason explains why, and assets is empty.

⚠ assets is filtered by the server and ordered by the member's payment preferences— the first entry is the default debit asset. You do not specify the debit currency: preferred_asset means only “try this first”; valid values are the assets[].asset entries here.

⚠ require_step_up is always true: every payment requires end-user confirmation on our hosted page. Include that step in your checkout design rather than waiting for POST /v1/qrpay/payments to return 400.

Decode


POST /v1/qrpay/decode   { "code_value": "<扫到的字符串>" }

Returns the QR scheme, recipient, and whether the amount is fixed or must be entered by the user.

Unrecognized means unrecognized: an error is returned. Do not implement fuzzy matching— a wrong guess could pay another merchant.

Quote


POST /v1/qrpay/quotes

Returns one quote for each payable asset held by the member.

⚠ Call this first to build the confirmation page. Calling payment directly means the user sees the amount

for the first time only after funds have been locked.

Pay


POST /v1/qrpay/payments
{
  "code_value": "<同一张码>",
  "currency": "THB",          ← 只在自定义金额码上传
  "amount": "350.00",         ← 同上
  "preferred_asset": "USDT"   ← 可选
}

⚠ There is no quote_id or payment authorization ticket. This endpoint obtains a fresh quote itself

before locking funds. The actual debit may differ from the preceding quote by a few smallest units;

the payment response is authoritative.

Three Parameter Pitfalls

ParameterKey point
currency / amountSend only for user-entered-amount codes, in the acquirer-side fiat currency. Supplying these for a fixed-amount code changes the merchant's price; we forward them upstream, which rejects a mismatch
preferred_assetOnly means “try this first.” An asset the upstream cannot quote this time is rejected, without silently switching

⚠ You do not specify the debit currency. We select it using the member's payment preference order.

Silently debiting another currency makes the decision for the user.


processing Means an Unknown Result, Not Failure

This is the most important part of this flow.

If the network fails while notifying the upstream, the request may already have arrived and payment may already have been approved— so we never unfreeze funds at that point. We record processing for verification and reconciliation.

⚠⚠ You must wait for a webhook or poll by order ID.

Do not declare failure or automatically create another order. Doing so can charge twice for one purchase.


Three Failure Types and How to Handle Them

ResponseMeaningYour action
4xx business errorDefinitive failure; funds untouchedShow a human-readable message based on code
upstream_errorUpstream 5xx / network failureFunds have not moved in this case; retry unchanged
504 / network errorUnknown resultDo not treat as failure—retry with the same key or query the order

⚠ The last case is critical. A network failure on payments does not mean payment failed—

we may already have locked funds and notified the upstream. Telling the user “Payment failed, try again” can make them pay twice.


The Two Amounts Differ in Both Value and Currency

The amount we send upstream is the original text of the upstream quote, not the member's total payment (actual payment = upstream quote + our cost protection + markup + fee, and is naturally higher).

Therefore, customer_total (the digital asset paid by the member) and acquirer_amount (fiat received by the recipient) are not directly comparable.

Related Endpoints