跳至主要内容

Pay with Sign API (One-Step)

HTTP Request​

POST /v5/pay/agreement/pay-with-sign

Complete both agreement signing and deduction payment in a single API call. This API supports two modes: Sign + Pay (for first-time users) and Pay Only (using existing agreement).


Feature Description​

This API supports merchants to complete both agreement signing and deduction payment in a single call. Signing is optional, merchants can choose:

  1. Sign + Pay Mode: Pass sign parameters, system creates agreement first, then executes deduction immediately after successful signing
  2. Pay Only Mode: Do not pass sign parameters, only pass existing agreementNo, execute deduction directly based on signed agreement

Applicable Scenarios:

  • First payment scenario: Complete both signing and first payment in one step when user uses the service for the first time
  • Quick payment scenario: Simplify merchant integration, reduce API call count

Request Parameters​

ParameterTypeRequiredDescription
merchantIdstringYesMerchant ID
agreementTypestringYesSign type: CYCLE / NON_CYCLE / SINGLE
signParamsobjectNoSign parameters (required for first sign + payment)
signParams.sceneCodestringConditionalScene code (required when passing signParams)
signParams.externalAgreementNostringConditionalMerchant agreement number (required when passing signParams, unique)
signParams.merchantUserIdstringNoMerchant-side user ID (optional, used for merchant internal user association)
signParams.productCodestringNoProduct code, assigned by platform
signParams.signValidTimestringNoSign validity period, ISO8601 format
signParams.singleLimitobjectNoSingle transaction limit configuration
signParams.singleLimit.amountstringConditionalLimit amount (required when passing singleLimit)
signParams.singleLimit.currencystringConditionalCurrency code (required when passing singleLimit)
signParams.singleLimit.currencyTypestringConditionalFIAT or CRYPTO (required when passing singleLimit)
signParams.singleLimit.chainstringNoChain network (optional for cryptocurrency, e.g., BSC, TRX, ARBI, LTC, SOL, ETH, TON, APTOS)
signParams.singleLimit.chainAddressstringNoChain address (required in dynamic chain settlement mode)
signParams.periodLimitsarrayNoPeriod limit configuration list
signParams.periodLimits[].periodTypestringConditionalPeriod type: DAY/WEEK/MONTH/YEAR
signParams.periodLimits[].amountstringConditionalPeriod limit amount
signParams.periodLimits[].currencystringConditionalCurrency code
signParams.periodLimits[].currencyTypestringConditionalFIAT or CRYPTO
signParams.periodLimits[].chainstringNoChain network (optional for cryptocurrency, e.g., BSC, TRX, ARBI, LTC, SOL, ETH, TON, APTOS)
signParams.periodLimits[].chainAddressstringNoChain address (required in dynamic chain settlement mode)
signParams.signNotifyUrlstringNoSign result async notification URL
signParams.returnUrlstringNoRedirect URL after sign completion
signParams.signExpireMinutesintNoSign link validity period (minutes), default 30
signParams.extraParamsstringNoExtension parameters (JSON string)
payParamsobjectYesDeduction payment parameters
payParams.agreementNostringConditionalPlatform agreement number (required when not passing signParams)
payParams.outTradeNostringYesMerchant order number (unique)
payParams.sceneCodestringYesScene code
payParams.amountobjectYesDeduction amount
payParams.amount.totalstringYesAmount (minimum unit)
payParams.amount.currencystringYesCurrency code
payParams.amount.currencyTypestringYesFIAT or CRYPTO
payParams.amount.chainstringNoChain network (required in dynamic chain settlement mode, e.g., BSC, TRX, ARBI, LTC, SOL, ETH, TON, APTOS)
payParams.amount.chainAddressstringNoChain address (required in dynamic chain settlement mode)
payParams.orderInfoobjectYesOrder information
payParams.orderInfo.orderTitlestringYesOrder title
payParams.orderInfo.orderDescstringNoOrder description
payParams.orderInfo.goodsNamestringNoGoods name
payParams.orderInfo.goodsIdstringNoGoods ID
payParams.orderInfo.goodsCategorystringYesGoods category (4-digit code, see Appendix.MCC Industry Categories)
payParams.sceneInfoobjectNoScene information
payParams.sceneInfo.deviceIdstringNoDevice ID
payParams.sceneInfo.deviceIpstringNoDevice IP
payParams.sceneInfo.locationobjectNoLocation information
payParams.sceneInfo.location.latitudestringNoLatitude
payParams.sceneInfo.location.longitudestringNoLongitude
payParams.sceneInfo.location.addressstringNoDetailed address
payParams.payNotifyUrlstringYesPayment result async notification URL
payParams.riskInfoobjectNoRisk control information
payParams.riskInfo.userIpstringNoUser IP address
payParams.riskInfo.deviceFingerprintstringNoDevice fingerprint
payParams.riskInfo.userAgentstringNoUser agent string

Response Parameters​

ParameterTypeDescription
retCodeintResponse code
retMsgstringResponse message
resultobjectResponse data
result.signResultobjectSign result (if signing was initiated)
result.signResult.agreementNostringPlatform agreement number
result.signResult.externalAgreementNostringMerchant agreement number
result.signResult.signOrderIdstringPlatform sign order number
result.signResult.statusstringSign status: INIT/PENDING/SIGNED/FAILED
result.signResult.signTimestringSign success time (returned on success)
result.signResult.validTimestringAgreement validity period
result.signResult.signUrlstringSign page URL (for H5 redirect)
result.signResult.qrCodestringSign QR code content (for user App scan)
result.signResult.qrCodeUrlstringSign QR code image URL
result.signResult.expireTimestringSign link/QR code expiration time
result.payResultobjectDeduction result
result.payResult.tradeNostringPlatform transaction number
result.payResult.outTradeNostringMerchant order number
result.payResult.statusstringTransaction status: PROCESSING/SUCCESS/FAILED/TIMEOUT
result.payResult.amountobjectMerchant requested amount
result.payResult.amount.totalstringAmount (minimum unit)
result.payResult.amount.currencystringCurrency code
result.payResult.amount.currencyTypestringCurrency type: FIAT / CRYPTO
result.payResult.cryptoPaymentobjectUser's actual cryptocurrency payment info (for fiat orders)
result.payResult.cryptoPayment.currencystringCryptocurrency currency
result.payResult.cryptoPayment.amountstringCryptocurrency amount
result.payResult.cryptoPayment.chainstringChain network (e.g., BSC, TRX, ARBI, LTC, SOL, ETH, TON, APTOS)
result.payResult.cryptoPayment.exchangeRatestringExchange rate
result.payResult.cryptoPayment.rateTimestringRate lock time
result.payResult.cryptoPayment.transOrderNostringDownstream deduction transaction number
result.payResult.payTimestringPayment success time (empty before success)
result.payResult.failureReasonstringFailure reason (returned on failure)

Request Example 1: Sign + Pay (First Use)​

{
"merchantId": "M123456789",
"agreementType": "CYCLE",
"signParams": {
"merchantUserId": "merchant_user_123",
"sceneCode": "TAXI",
"productCode": "PROD_001",
"externalAgreementNo": "MERCHANT_AGR_001",
"signValidTime": "2026-12-23T10:30:00Z",
"singleLimit": {
"amount": "100000",
"currency": "USDT",
"currencyType": "CRYPTO",
"chain": "TRC20"
},
"periodLimits": [
{
"periodType": "DAY",
"amount": "500000",
"currency": "USDT",
"currencyType": "CRYPTO",
"chain": "TRC20"
}
],
"signNotifyUrl": "https://merchant.com/notify/sign"
},
"payParams": {
"outTradeNo": "TAXI20231223001",
"sceneCode": "TAXI",
"amount": {
"total": "2350",
"currency": "USDT",
"currencyType": "CRYPTO",
"chain": "TRC20"
},
"orderInfo": {
"orderTitle": "Taxi Fare",
"orderDesc": "Trip on December 23",
"goodsCategory": "4121"
},
"payNotifyUrl": "https://merchant.com/notify/pay",
"riskInfo": {
"userIp": "203.0.113.45",
"deviceFingerprint": "fp_abc123xyz"
}
}
}

Response Example 1: Sign + Pay (Waiting for User Scan)​

{
"retCode": 20000,
"retMsg": "Success",
"result": {
"signResult": {
"agreementNo": null,
"externalAgreementNo": "MERCHANT_AGR_001",
"signOrderId": "SIGN202312230001",
"status": "INIT",
"signTime": null,
"validTime": "2026-12-23T10:30:00Z",
"signUrl": "https://pay.example.com/sign?token=xxx",
"qrCode": "https://pay.example.com/sign?token=xxx",
"qrCodeUrl": "https://pay.example.com/qr/SIGN202312230001.png",
"expireTime": "2023-12-23T11:00:00Z"
},
"payResult": {
"tradeNo": null,
"outTradeNo": "TAXI20231223001",
"status": "PENDING",
"amount": {
"total": "2350",
"currency": "USDT",
"currencyType": "CRYPTO",
"chain": "TRC20"
},
"payTime": null,
"failureReason": null
}
}
}

Notes:

  • signResult.status = "INIT" - Sign request created, waiting for user scan
  • payResult.status = "PENDING" - Payment order created, waiting for sign completion to auto-execute
  • Merchant should display qrCodeUrl or signUrl for user to scan
  • Final result returned via Webhook async notification

Request Example 2: Pay Only (Using Existing Agreement)​

{
"merchantId": "M123456789",
"agreementType": "CYCLE",
"payParams": {
"agreementNo": "AGR202312230001",
"outTradeNo": "TAXI20231223002",
"sceneCode": "TAXI",
"amount": {
"total": "3500",
"currency": "USDT",
"currencyType": "CRYPTO",
"chain": "TRC20"
},
"orderInfo": {
"orderTitle": "Taxi Fare",
"orderDesc": "Second trip on December 23",
"goodsCategory": "4121"
},
"payNotifyUrl": "https://merchant.com/notify/pay"
}
}

Response Example 2: Pay Only (Using Existing Agreement)​

{
"retCode": 20000,
"retMsg": "Success",
"result": {
"signResult": null,
"payResult": {
"tradeNo": "PAY202312230002",
"outTradeNo": "TAXI20231223002",
"status": "PROCESSING",
"amount": {
"total": "3500",
"currency": "USDT",
"currencyType": "CRYPTO",
"chain": "TRC20"
},
"payTime": null,
"failureReason": null
}
}
}

Notes:

  • signResult = null - No sign initiated, using existing agreement
  • payResult.status = "PROCESSING" - Deduction payment processing
  • Final result returned via Webhook async notification

Important Notes​

Async Flow​

  • Signing requires user scan confirmation, it's an async flow
  • Sync response returns sign QR code and initial status (INIT/PENDING)
  • Final result returned via Webhook async notification

Business Flow​

  1. Call API → Returns sign QR code
  2. Merchant displays QR code → User scans with App
  3. User completes sign → System auto-triggers deduction
  4. Webhook notification → Returns sign and payment results

Result Processing​

  • Results returned separately in signResult and payResult
  • If sign fails, deduction not executed, payResult is null
  • If sign succeeds, user completes payment in app until success

Webhook Notification Strategy​

  • Sign result and payment result are sent as independent notifications to their respective notify URLs
  • Sign result (success/rejected/failed) sent to signNotifyUrl
  • Payment result (success/failed) sent to payNotifyUrl
  • If user rejects sign, only sign rejected notification is sent, deduction will not be executed
  • If sign fails (system error), only sign failed notification is sent, deduction will not be executed

Idempotency Guarantee​

  • Idempotency guaranteed through externalAgreementNo for signing
  • Idempotency guaranteed through outTradeNo for payment

Optional Signing​

  • When signParams is empty, must pass existing agreement number in payParams.agreementNo
  • When using existing agreement, no scan needed, direct deduction execution