Collection API compat1 (legacy protocol)
For merchants already integrated with the old system's collection API: merchant ID, key, signature, parameters and responses are all unchanged. Only the gateway address changes to this platform's https://api.xx2system.xyz. Merchants opened on this platform (merchant ID starting with M) use it too, sending the merchant ID as is.
Common rules
| API | URL | Response |
|---|---|---|
| Create order | https://api.xx2system.xyz/api/pay/create_order | application/json |
| Query order | https://api.xx2system.xyz/api/pay/query_order | application/json |
| Balance | https://api.xx2system.xyz/api/account/mch_balance | text/plain;charset=UTF-8 |
| Payer name page (opened by the payer) | https://api.xx2system.xyz/api/pay/input_name | text/html;charset=UTF-8 |
| Payer name page submit (by the payer) | https://api.xx2system.xyz/api/pay/input_name/submit | text/html;charset=UTF-8 |
- Any method works (GET or POST); parameters may be in a form body or in the query string; if a name repeats, the last value wins.
- You may also put all parameters into one JSON string in the single parameter
params(all other loose parameters are then ignored). - JSON bodies are not read: sending
application/jsonis the same as sending no parameters. - Values for create order and query order must not contain characters such as
&,<or>(rejected as XSS). SonotifyUrlcan carry at most one query parameter of its own. - Failures are HTTP 200 too; look at
retCode:SUCCESSorFAIL, with the reason inretMsg. - Optional common parameters:
reqTime(yyyyMMddHHmmss; the difference from now is not checked) andversion(must be1.0).
Create order create_order
Request parameters
| Parameter | Required | Rule | Description |
|---|---|---|---|
mchId | yes | digits; or a merchant ID issued by this platform (MCH + 5 digits), sent as is | Merchant ID |
productId | yes | digits only | Existing merchants keep the one they use today; for the official product ID code, please contact customer service |
mchOrderNo | yes | letters, digits, underscore and hyphen only;at most 60 (UTF-16 code units: an emoji or a rare CJK character counts as 2) | Your order number, unique per merchant |
amount | yes | integer in the currency's minor unit, greater than 0 | Amount in the currency's minor unit |
notifyUrl | yes | at most 512 (UTF-16 code units: an emoji or a rare CJK character counts as 2) | Payment result callback URL (format not checked; no &) |
subject | yes | at most 64 (UTF-16 code units: an emoji or a rare CJK character counts as 2) | Goods title |
body | yes | at most 256 (UTF-16 code units: an emoji or a rare CJK character counts as 2) | Goods description |
sign | yes | 32 hex characters, see Signatures | Signature (MD5), see Signatures |
param2 | no | at most 64 (UTF-16 code units: an emoji or a rare CJK character counts as 2) | Payer name; if omitted, the channel settings decide between a fixed name and the payer name page |
param1 | no | at most 64 (UTF-16 code units: an emoji or a rare CJK character counts as 2) | Your own value, returned in the callback |
extra | no | at most 512 (UTF-16 code units: an emoji or a rare CJK character counts as 2) | Extension data required by a few channels |
clientIp | no | at most 128 (UTF-16 code units: an emoji or a rare CJK character counts as 2) | Payer IP; the request source when omitted |
returnUrl | no | at most 512 (UTF-16 code units: an emoji or a rare CJK character counts as 2) | Page to return to after paying, used by a few channels |
device | no | at most 64 (UTF-16 code units: an emoji or a rare CJK character counts as 2) | Device information |
currency | no | at most 3 (UTF-16 code units: an emoji or a rare CJK character counts as 2) | Currency, value not checked, cny when omitted |
reqTime | no | yyyyMMddHHmmss | Request time; the difference from now is not checked |
version | no | must be 1.0 | API version |
appId | no | do not send it (a non-empty value is rejected as an unknown app) | App ID |
- The amount is in the currency's minor unit, digits only, greater than 0.
mchOrderNomust be unique per merchant: a duplicate gets该商户订单已存在[mchOrderNo=…]and the original order is not returned.- Without
param2(payer name) the channel settings decide: either a fixed name is used, or the payer first enters a name on our page (see “Payer name page” below).
Successful response
There are only two payMethod values:
formJump: send the payer topayUrl;payParamsholds the same address.cardInfo: the receiving card details (accountName,accountNo,bankNameinpayParams); there is nopayUrl.
{"retCode":"SUCCESS","sign":"FC72E9A94FE742797A6939FD5975B5D0","payMethod":"formJump","payUrl":"https://cashier.example.com/pay/8a1b2c","payParams":{"payMethod":"formJump","payUrl":"https://cashier.example.com/pay/8a1b2c"}}{"retCode":"SUCCESS","sign":"299712E3593CB68C0AFF5901493FF777","payMethod":"cardInfo","payParams":{"accountName":"张三","accountNo":"6222021234567890123","bankName":"中国工商银行"}}When the response is signed, payParams is one value: its first-level keys are sorted and it is written as compact JSON (see Signatures).
Failure response
{"retCode":"FAIL","retMsg":"暂无可用支付通道,请稍后重试"}- Most failures carry no
sign; only failures returned normally by a channel are signed. - Common failure texts are listed under Error codes.
Payer name page
When the channel needs the payer's name and you did not send param2, the successful response is a formJump whose payUrl points to this platform's name page https://api.xx2system.xyz/api/pay/input_name?t=…. The payer enters a name there and then goes on to the payment page or sees the card details. The page is in Chinese only. Handle it like any other redirect; no code change is needed.
Example
Example key (fake):demo-key-NOT-REAL-do-not-use-0001
Parameters
mchId=20000001
productId=8001
mchOrderNo=ORDER20260918001
amount=10000
notifyUrl=https://merchant.example.com/notify
subject=goods
body=goods
param1=shop-7
param2=张三
reqTime=20260918120000
String to sign
amount=10000&body=goods&mchId=20000001&mchOrderNo=ORDER20260918001¬ifyUrl=https://merchant.example.com/notify¶m1=shop-7¶m2=张三&productId=8001&reqTime=20260918120000&subject=goods&key=demo-key-NOT-REAL-do-not-use-0001
sign
86032564C62F16F220F9DBAD7D88C690
Request body
mchId=20000001&productId=8001&mchOrderNo=ORDER20260918001&amount=10000¬ifyUrl=https%3A%2F%2Fmerchant.example.com%2Fnotify&subject=goods&body=goods¶m1=shop-7¶m2=%E5%BC%A0%E4%B8%89&reqTime=20260918120000&sign=86032564C62F16F220F9DBAD7D88C690Query order query_order
Request parameters
| Parameter | Required | Rule | Description |
|---|---|---|---|
mchId | yes | digits; or a merchant ID issued by this platform (MCH + 5 digits), sent as is | Merchant ID |
mchOrderNo | one of two | Your order number, unique per merchant | |
payOrderId | one of two | Order number (looked up again as your order number if not found) | |
executeNotify | no | true: if the order has succeeded, send the callback once more | |
sign | yes | 32 hex characters, see Signatures | Signature (MD5), see Signatures |
reqTime | no | yyyyMMddHHmmss | Request time; the difference from now is not checked |
version | no | must be 1.0 | API version |
- If
payOrderIdis given it is looked up first; if nothing is found it is tried again as your order number. executeNotify=true: if the order has succeeded, the callback is sent once more (only the stringtrue, any case;1does not count).
Successful response
These 14 fields are always present; missing values are empty strings (empty strings are not signed):
| Parameter | Description |
|---|---|
retCode | SUCCESS or FAIL |
sign | Signature (MD5) |
mchId | Merchant ID |
appId | App ID (normally empty) |
productId | For the official product ID code, please contact customer service |
payOrderId | Your order number (as in the old system, this field carries your order number) |
mchOrderNo | Your order number |
amount | Ordered amount (minor units) |
currency | Currency |
status | Order status, see the table below |
channelUser | Channel user |
channelOrderNo | Upstream order number |
channelAttach | Upstream extra data |
paySuccTime | Success time in milliseconds; empty string if none |
| Status | Meaning |
|---|---|
-2 | Closed |
-1 | Payment failed |
0 | Created (payer has not gone to pay yet) |
1 | Paying |
2 | Paid |
3 | Completed (after your callback reply was success) |
4 | Refunded or reversed |
{"retCode":"SUCCESS","sign":"60570E9E22C1CC62C5A425625B2B2260","mchId":"20000001","appId":"","productId":"8001","payOrderId":"ORDER20260918001","mchOrderNo":"ORDER20260918001","amount":"10000","currency":"cny","status":"2","channelUser":"","channelOrderNo":"UP20260918000123","channelAttach":"","paySuccTime":"1789704005000"}Failure response
Failure texts are mostly English (as in the old system) and unsigned, for example:
{"retCode":"FAIL","retMsg":"支付订单不存在"}Orders placed before you switched to this platform cannot be found here (you get 支付订单不存在): rely on the callback for those, or look them up in the old portal.
Example
Example key (fake):demo-key-NOT-REAL-do-not-use-0001
Parameters
mchId=20000001
mchOrderNo=ORDER20260918001
String to sign
mchId=20000001&mchOrderNo=ORDER20260918001&key=demo-key-NOT-REAL-do-not-use-0001
sign
23A303C6B04E6C7BD44039988E47DC1C
Request body
mchId=20000001&mchOrderNo=ORDER20260918001&sign=23A303C6B04E6C7BD44039988E47DC1CBalance mch_balance
Request parameters
| Parameter | Required | Rule | Description |
|---|---|---|---|
mchId | yes | digits; or a merchant ID issued by this platform (MCH + 5 digits), sent as is | Merchant ID |
sign | yes | 32 hex characters, see Signatures | Signature (MD5), see Signatures |
reqTime | no | yyyyMMddHHmmss | Request time; the difference from now is not checked |
version | no | must be 1.0 | API version |
Response
{"mchId":20000001,"balance":500000,"sign":"B7F182CA8F4B91FA5F91A3885B163C86","retCode":"SUCCESS","availableBalance":489800}- The three numbers are not quoted (as in the old system); amounts are in the currency's minor unit. For merchants opened on this platform (merchant ID starting with M),
mchIdis a quoted string. balanceis the total balance;availableBalanceis what is available (total minus frozen).- The signature covers
retCode,mchId,balanceandavailableBalance(numbers as text).
Failures are unsigned, and errDes equals retMsg:
{"errCode":"0010","errDes":"验证签名不通过.","retCode":"FAIL","retMsg":"验证签名不通过."}Example
Example key (fake):demo-key-NOT-REAL-do-not-use-0001
Parameters
mchId=20000001
String to sign
mchId=20000001&key=demo-key-NOT-REAL-do-not-use-0001
sign
7695B044D612C28A79D0E33156A4B593
Request body
mchId=20000001&sign=7695B044D612C28A79D0E33156A4B593