Crypto Pay-In
Overview
The Crypto Pay-In API collects on-chain transfers from payers. The platform assigns a deposit address to the order, the payer transfers the specified quantity to that address, and once the transfer is confirmed on-chain the platform notifies the merchant via callback.
Two ordering modes are supported:
| Mode | Production path | Description |
|---|---|---|
| Cashier mode | /crypto/pay/prePay | Default mode. currency and netWork may be omitted; the response returns cashierUrl and the payer picks a coin-chain pair on the platform cashier to obtain a deposit address |
| Direct API mode | /crypto/pay/orderDirectly | currency and netWork are mandatory; the response returns the deposit address inAddress directly |
Access note
Both modes are gated by the merchant's cashier open mode (availablePayMode): prePay requires H5 to be enabled and orderDirectly requires API. Otherwise 0001 is returned with merchant do not support H5/API ordering!. Contact support to enable a mode.
Common request headers (including the mandatory Nonce), common body fields and the unified response envelope are described in Crypto Integration Overview.
Cashier mode (prePay)
Request path
Domain: Prefer unified host
openapi.toppayment.com(path unchanged); legacy crypto domain (global-digit-openapi.toppayment.com) remains available.
| Environment | URL |
|---|---|
| Sandbox | https://openapi.toppayment.com/crypto/sandbox/pay/prePay |
| Production | https://openapi.toppayment.com/crypto/pay/prePay |
Request headers
| Field | Required | Type | Description |
|---|---|---|---|
| Content-Type | M | String | Fixed value: application/json |
| Nonce | M | String(16-64) | Anti-replay random string, unique within 10 minutes, excluded from the signature |
Request body
| Field | Required | Type | Description |
|---|---|---|---|
| mchNo | M | String(32) | Merchant number In sandbox use the SD-prefixed sandbox merchant number |
| mchUserId | M | String(32) | Merchant-side user identifier Used to link the payer to your own system |
| payMoney | M | String | Collection quantity Numeric string with at most 6 decimal places Subject to the platform pre-order amount limits; out-of-range returns 0001Example: 10.5 |
| downNotifyUrl | M | String(255) | Asynchronous notification URL Must be a publicly reachable HTTP/HTTPS URL, see Callback |
| timestamp | M | String(13) | Request timestamp (13-digit milliseconds), within ±5 minutes |
| sign | M | String | Signature, see Signature |
| orderNum | O | String(64) | Merchant order number Generated by the platform when omitted. Must be unique per merchant; duplicates return 0001 |
| currency | O | String(16) | Coin May be omitted in cashier mode so the payer chooses it; if provided the cashier is locked to this coin Charset A-Z a-z 0-9 _, example: USDT |
| netWork | O | String(100) | Chain network Only effective when sent together with currency, example: TRC20 |
| expiryPeriod | O | String | Order validity in minutes Range 1–9999, defaults to 1440 (24 hours) |
| orderVersion | O | String(20) | Order version marker agreed with the platform, normally not needed |
| name | O | String(64) | Payer name |
| O | String(64) | Payer email | |
| phone | O | String(32) | Payer phone |
| tenantCode | O | String(32) | Sub-tenant code, defaults to the default tenant |
| countryCode | O | String(16) | Country code, not needed for crypto |
Request example
Content-Type: application/json
Nonce: 8f3c1a92b74e5d60c1f2
{
"mchNo": "{{mchNo}}",
"mchUserId": "USER_10001",
"payMoney": "10.5",
"orderNum": "CR1788506800926",
"downNotifyUrl": "https://example.com/notify/pay",
"expiryPeriod": "1440",
"name": "Jack Ma",
"email": "[email protected]",
"phone": "081234567890",
"timestamp": "1749451858772",
"sign": "replace with generated signature"
}
{
"mchNo": "{{mchNo}}",
"mchUserId": "USER_10001",
"payMoney": "10.5",
"orderNum": "CR1788506800927",
"currency": "USDT",
"netWork": "TRC20",
"downNotifyUrl": "https://example.com/notify/pay",
"timestamp": "1749451858772",
"sign": "replace with generated signature"
}
Response body
| Field | Required | Type | Description |
|---|---|---|---|
| success | M | Boolean | Whether the request succeeded |
| code | M | String | Response code 9999: success; otherwise see Exception Codes |
| msg | O | String | Response message, null on success |
| timeStamp | M | Number | Server response time (milliseconds) |
| data | M | Object | Response payload |
| orderNum | M | String | Merchant order number Platform-generated when omitted in the request |
| platOrderNum | M | String | Platform order number The key used for later inquiries and callbacks |
| payMoney | M | Number | Collection quantity |
| currency | O | String | Coinnull when not specified in the request, decided once the payer picks on the cashier |
| netWork | O | String | Chain network, same as above |
| cashierUrl | M | String | Cashier URL Redirect the payer here to complete the payment |
| inAddress | O | String | Deposit addressnull at cashier-mode order creation; generated once the payer selects a coin-chain pair |
Response example
{
"success": true,
"code": "9999",
"msg": null,
"timeStamp": 1767840272829,
"data": {
"orderNum": "CR1788506800926",
"platOrderNum": "CR20260904152640640",
"payMoney": 10.500000,
"currency": null,
"netWork": null,
"cashierUrl": "https://cashier.example.com/CR20260904152640640",
"inAddress": null
}
}
{
"success": true,
"code": "9999",
"msg": null,
"timeStamp": 1767840272829,
"data": {
"orderNum": "CR1788506800927",
"platOrderNum": "CR20260904152640641",
"payMoney": 10.500000,
"currency": "USDT",
"netWork": "TRC20",
"cashierUrl": "https://cashier.example.com/CR20260904152640641",
"inAddress": null
}
}
No redirect after payment
The crypto cashier does not support redirecting back to the merchant page once payment completes. The payer must return to your site on their own, and you should confirm the result through the Callback or Order Inquiry.
Direct API mode (orderDirectly)
The merchant specifies currency and netWork in the request. The platform requests a deposit address from the channel and returns inAddress directly, without going through the cashier.
Request path
Domain: Prefer unified host
openapi.toppayment.com(path unchanged); legacy crypto domain (global-digit-openapi.toppayment.com) remains available.
| Environment | URL |
|---|---|
| Sandbox | https://openapi.toppayment.com/crypto/sandbox/pay/directlyPay |
| Production | https://openapi.toppayment.com/crypto/pay/orderDirectly |
Sandbox path difference
The sandbox direct-order path is /crypto/sandbox/pay/directlyPay (/crypto/sandbox/pay/transOrder is also accepted), which differs in name from the production /crypto/pay/orderDirectly. Request and response bodies are identical.
Request body
Differences compared with cashier mode:
| Field | Required | Type | Description |
|---|---|---|---|
| currency | M | String(16) | Coin Mandatory in direct mode, example: USDT |
| netWork | M | String(100) | Chain network Mandatory in direct mode, example: TRC20 |
All other fields are the same as cashier mode. A missing currency or netWork returns 0001; no available channel for the coin returns 0003.
Request example
Content-Type: application/json
Nonce: 2b7de401a5c96f83d0e1
{
"mchNo": "{{mchNo}}",
"mchUserId": "USER_10001",
"payMoney": "10.5",
"orderNum": "CRAPI1788506800931",
"currency": "USDT",
"netWork": "TRC20",
"downNotifyUrl": "https://example.com/notify/pay",
"expiryPeriod": "1440",
"timestamp": "1749451858772",
"sign": "replace with generated signature"
}
Response body
Fields are identical to cashier mode. In direct mode, focus on:
| Field | Required | Type | Description |
|---|---|---|---|
| inAddress | M | String | Deposit address Instruct the payer to transfer payMoney of currency to this address |
| cashierUrl | O | String | Cashier URL Still returned in direct mode, but rely on inAddress |
Response example
{
"success": true,
"code": "9999",
"msg": null,
"timeStamp": 1767840272829,
"data": {
"orderNum": "CRAPI1788506800931",
"platOrderNum": "CR20260904152640642",
"payMoney": 10.500000,
"currency": "USDT",
"netWork": "TRC20",
"cashierUrl": "https://cashier.example.com/CR20260904152640642",
"inAddress": "TP5wzCqNsJFNT83m1VXdF2Aj1ageFWgqW2"
}
}
Notes
The transferred quantity must match the order
The on-chain transfer must match payMoney exactly and must use the currency and netWork of the order. A mismatched quantity, wrong chain or wrong coin may prevent automatic crediting and require manual intervention.
- The deposit address is bound to the order. Never reuse an
inAddressfrom a previous order. - Orders expire after
expiryPeriod; expired orders return statusEXPIREDon inquiry. - Reusing the same
mchNo+orderNumreturns0001(The order already exists!); concurrent duplicate submissions return0004.
Next steps
- Order status and fees: Crypto Order Inquiry
- Payment result notification: Crypto Callback
