跳至主要内容

Pay with Sign API (One-Step)

HTTP Request

POST /v5/bybitpay/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 agreement_no, 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
merchant_idstringYesMerchant ID
agreement_typestringYesSign type: CYCLE / NON_CYCLE / SINGLE
sign_paramsobjectNoSign parameters (required for first sign + payment)
sign_params.scene_codestringConditionalScene code (required when passing sign_params)
sign_params.external_agreement_nostringConditionalMerchant agreement number (required when passing sign_params, unique)
sign_params.merchant_user_idstringNoMerchant-side user ID (optional, used for merchant internal user association)
sign_params.product_codestringNoProduct code, assigned by platform
sign_params.sign_valid_timestringNoSign validity period, ISO8601 format
sign_params.single_limitobjectNoSingle transaction limit configuration
sign_params.single_limit.amountstringConditionalLimit amount (required when passing single_limit)
sign_params.single_limit.currencystringConditionalCurrency code (required when passing single_limit)
sign_params.single_limit.currency_typestringConditionalFIAT or CRYPTO (required when passing single_limit)
sign_params.single_limit.chainstringNoChain network (optional for cryptocurrency)
sign_params.single_limit.chain_addressstringNoChain address (required for dynamic on-chain settlement)
sign_params.period_limitsarrayNoPeriod limit configuration list
sign_params.period_limits[].period_typestringConditionalPeriod type: DAY/WEEK/MONTH/YEAR
sign_params.period_limits[].amountstringConditionalPeriod limit amount
sign_params.period_limits[].currencystringConditionalCurrency code
sign_params.period_limits[].currency_typestringConditionalFIAT or CRYPTO
sign_params.period_limits[].chainstringNoChain network (optional for cryptocurrency)
sign_params.period_limits[].chain_addressstringNoChain address (required for dynamic on-chain settlement)
sign_params.sign_notify_urlstringNoSign result async notification URL
sign_params.return_urlstringNoRedirect URL after sign completion
sign_params.sign_expire_minutesintNoSign link validity period (minutes), default 30
sign_params.extra_paramsstringNoExtension parameters (JSON string)
pay_paramsobjectYesDeduction payment parameters
pay_params.agreement_nostringConditionalPlatform agreement number (required when not passing sign_params)
pay_params.out_trade_nostringYesMerchant order number (unique)
pay_params.scene_codestringYesScene code
pay_params.amountobjectYesDeduction amount
pay_params.amount.totalstringYesAmount (minimum unit)
pay_params.amount.currencystringYesCurrency code
pay_params.amount.currency_typestringYesFIAT or CRYPTO
pay_params.amount.chainstringNoChain network (required for crypto)
pay_params.amount.chain_addressstringNoChain address (required for dynamic on-chain settlement)
pay_params.order_infoobjectYesOrder information
pay_params.order_info.order_titlestringYesOrder title
pay_params.order_info.order_descstringNoOrder description
pay_params.order_info.goods_namestringNoGoods name
pay_params.order_info.goods_idstringNoGoods ID
pay_params.order_info.goods_categorystringNoGoods category
pay_params.scene_infoobjectNoScene information
pay_params.scene_info.device_idstringNoDevice ID
pay_params.scene_info.device_ipstringNoDevice IP
pay_params.scene_info.locationobjectNoLocation information
pay_params.scene_info.location.latitudestringNoLatitude
pay_params.scene_info.location.longitudestringNoLongitude
pay_params.scene_info.location.addressstringNoDetailed address
pay_params.pay_notify_urlstringYesPayment result async notification URL
pay_params.risk_infoobjectNoRisk control information
pay_params.risk_info.user_ipstringNoUser IP address
pay_params.risk_info.device_fingerprintstringNoDevice fingerprint
pay_params.risk_info.user_agentstringNoUser agent string

Response Parameters

ParameterTypeDescription
retCodeintResponse code
retMsgstringResponse message
resultobjectResponse data
result.sign_resultobjectSign result (if signing was initiated)
result.sign_result.agreement_nostringPlatform agreement number
result.sign_result.external_agreement_nostringMerchant agreement number
result.sign_result.sign_order_idstringPlatform sign order number
result.sign_result.statusstringSign status: INIT/PENDING/SIGNED/FAILED
result.sign_result.sign_timestringSign success time (returned on success)
result.sign_result.valid_timestringAgreement validity period
result.sign_result.sign_urlstringSign page URL (for H5 redirect)
result.sign_result.qr_codestringSign QR code content (for user App scan)
result.sign_result.qr_code_urlstringSign QR code image URL
result.sign_result.expire_timestringSign link/QR code expiration time
result.pay_resultobjectDeduction result
result.pay_result.trade_nostringPlatform transaction number
result.pay_result.out_trade_nostringMerchant order number
result.pay_result.statusstringTransaction status: PROCESSING/SUCCESS/FAILED/TIMEOUT
result.pay_result.amountobjectMerchant requested amount
result.pay_result.crypto_paymentobjectUser's actual cryptocurrency payment info (for fiat orders)
result.pay_result.crypto_payment.currencystringCryptocurrency currency
result.pay_result.crypto_payment.amountstringCryptocurrency amount
result.pay_result.crypto_payment.chainstringChain network
result.pay_result.crypto_payment.exchange_ratestringExchange rate
result.pay_result.crypto_payment.rate_timestringRate lock time
result.pay_result.pay_timestringPayment success time (returned on success)
result.pay_result.failure_reasonstringFailure reason (returned on failure)

Request Example 1: Sign + Pay (First Use)

{
"merchant_id": "M123456789",
"agreement_type": "CYCLE",
"sign_params": {
"merchant_user_id": "merchant_user_123",
"scene_code": "TAXI",
"external_agreement_no": "MERCHANT_AGR_001",
"sign_valid_time": "2026-12-23T10:30:00Z",
"single_limit": {
"amount": "100000",
"currency": "USDT",
"currency_type": "CRYPTO",
"chain": "TRC20"
},
"period_limits": [
{
"period_type": "DAY",
"amount": "500000",
"currency": "USDT",
"currency_type": "CRYPTO",
"chain": "TRC20"
}
],
"sign_notify_url": "https://merchant.com/notify/sign"
},
"pay_params": {
"out_trade_no": "TAXI20231223001",
"scene_code": "TAXI",
"amount": {
"total": "2350",
"currency": "USDT",
"currency_type": "CRYPTO",
"chain": "TRC20"
},
"order_info": {
"order_title": "Taxi Fare",
"order_desc": "Trip on December 23"
},
"pay_notify_url": "https://merchant.com/notify/pay",
"risk_info": {
"user_ip": "203.0.113.45",
"device_fingerprint": "fp_abc123xyz"
}
}
}

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

{
"retCode": 20000,
"retMsg": "Success",
"result": {
"sign_result": {
"agreement_no": null,
"external_agreement_no": "MERCHANT_AGR_001",
"sign_order_id": "SIGN202312230001",
"status": "INIT",
"sign_time": null,
"valid_time": "2026-12-23T10:30:00Z",
"sign_url": "https://pay.example.com/sign?token=xxx",
"qr_code": "https://pay.example.com/sign?token=xxx",
"qr_code_url": "https://pay.example.com/qr/SIGN202312230001.png",
"expire_time": "2023-12-23T11:00:00Z"
},
"pay_result": {
"trade_no": null,
"out_trade_no": "TAXI20231223001",
"status": "PENDING",
"amount": {
"total": "2350",
"currency": "USDT",
"currency_type": "CRYPTO",
"chain": "TRC20"
},
"pay_time": null,
"failure_reason": null
}
}
}

Notes:

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

Request Example 2: Pay Only (Using Existing Agreement)

{
"merchant_id": "M123456789",
"agreement_type": "CYCLE",
"pay_params": {
"agreement_no": "AGR202312230001",
"out_trade_no": "TAXI20231223002",
"scene_code": "TAXI",
"amount": {
"total": "3500",
"currency": "USDT",
"currency_type": "CRYPTO",
"chain": "TRC20"
},
"order_info": {
"order_title": "Taxi Fare",
"order_desc": "Second trip on December 23"
},
"pay_notify_url": "https://merchant.com/notify/pay"
}
}

Response Example 2: Pay Only (Using Existing Agreement)

{
"retCode": 20000,
"retMsg": "Success",
"result": {
"sign_result": null,
"pay_result": {
"trade_no": "PAY202312230002",
"out_trade_no": "TAXI20231223002",
"status": "PROCESSING",
"amount": {
"total": "3500",
"currency": "USDT",
"currency_type": "CRYPTO",
"chain": "TRC20"
},
"pay_time": null,
"failure_reason": null
}
}
}

Notes:

  • sign_result = null - No sign initiated, using existing agreement
  • pay_result.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 sign_result and pay_result
  • If sign fails, deduction not executed, pay_result is null
  • If sign succeeds, user completes payment in app until success

Webhook Notification Strategy

  • Uses single notification to return both sign and payment results
  • Sent to merchant configured pay_notify_url
  • For separate notifications, configure sign_notify_url in sign_params

Idempotency Guarantee

  • Idempotency guaranteed through external_agreement_no for signing
  • Idempotency guaranteed through out_trade_no for payment

Optional Signing

  • When sign_params is empty, must pass existing agreement number in pay_params.agreement_no
  • When using existing agreement, no scan needed, direct deduction execution