StablePay 商户对接文档

请输入访问密码以查看文档

概览

StablePay 商户开放接口提供 代收(Payment)代付(Payout) 两类业务能力。所有接口为 POST application/json,使用 MD5 签名认证。

接入前请向 StablePay 商务申请商户账号,登录商户后台 → API 对接 页面获取以下凭据:

  • merchantId  —  商户 ID(请求必带)
  • apiKey  —  商户密钥(仅用于本地签名,不要传输
  • aesKey / aesIv  —  部分敏感字段加密用(如启用)
安全提醒:apiKey 永远不要出现在请求体或 URL 里。如不慎泄露,立即在后台重置

联调流程

  1. 商户后台获取 merchantId + apiKey
  2. 在后台 API 对接 页配置 支付 URL / 代付 URL(接收异步通知)
  3. (可选)在 IP 白名单 配置允许调用的 IP;不配置则放行所有 IP
  4. 按本文档签名规则组装请求 → 调用 create 接口下单
  5. 使用返回的 orderNo 或自有 merchantOrderNo 调用 query 查询订单状态
  6. 订单状态变更时,平台会向您配置的回调 URL 推送异步通知(按相同签名规则验签)

公共说明

请求方式

  • 方法:POST
  • Content-Type:application/json
  • 字符集:UTF-8

请求 base URL

由 StablePay 商务为您单独提供(如 https://api.example.com)。本文档中接口路径均为相对路径。

统一响应结构

{
  "code": 0,           // 0=成功,非0=失败
  "message": "success",
  "data": { ... }      // 业务数据,仅 code=0 时有意义
}

金额格式

所有金额字段在 请求体 中以 number 类型传输(如 500.00),在 签名计算 时必须格式化为保留两位小数的字符串(如 "500.00",而不是 "500""500.000")。

时间字段

所有时间字段为 Unix 时间戳(秒级,int64)。前端展示请自行转换。

签名规则

所有写接口(create)和查询接口(query)都需带 sign 字段。算法如下:

  1. 取出请求体中所有非空参数(值为 ""null 或缺省的字段不参与签名),剔除 sign 本身
  2. 金额类字段(如 amount)转成 %.2f 字符串。
  3. 把参数按 key 升序(ASCII)排序,拼接为 k1=v1&k2=v2&...&kn=vn
  4. 末尾追加 &key={apiKey}
  5. 对最终字符串做 MD5(32 位),转大写,作为 sign

示例

请求体(amount=500.00,merchantOrderNo=E2E_OUT_001):

{
  "merchantId":      "SP20260101000001",
  "merchantOrderNo": "E2E_OUT_001",
  "amount":          500.00,
  "beneName":        "Raj Kumar",
  "beneAccount":     "1234567890123456",
  "beneIfsc":        "HDFC0001234",
  "benePhone":       "9876543210",
  "notifyUrl":       "https://your.site/notify",
  "sign":            "<由本算法计算>"
}

排序拼接(注意 amount 用 500.00):

amount=500.00&beneAccount=1234567890123456&beneIfsc=HDFC0001234&beneName=Raj Kumar&benePhone=9876543210&merchantId=SP20260101000001&merchantOrderNo=E2E_OUT_001&notifyUrl=https://your.site/notify&key=<您的 apiKey>

对上述字符串 MD5 → 转大写 → 即为 sign

注意:拼接时 =& 之间不留空格;URL 字符(如 : /做编码;中文/空格保持原样。

创建代收订单

POST /api/payment/create

商户向用户收款时调用。下单成功后平台返回平台订单号;用户付款 / 平台对账完成后通过异步通知或主动查询接口获取最终状态。

请求参数

字段类型必填说明
merchantIdstring必填商户 ID
merchantOrderNostring必填商户系统订单号,单商户内唯一
amountnumber必填下单金额,> 0,保留两位小数
customerNamestring选填付款人姓名
customerEmailstring选填付款人邮箱
customerPhonestring选填付款人手机号
notifyUrlstring选填异步通知地址,覆盖商户后台默认配置
returnUrlstring选填付款完成后浏览器跳回地址
remarkstring选填备注,原样回显
signstring必填签名,详见签名规则

响应 data

字段类型说明
orderNostring平台订单号(以 STABLEPAYIN 开头)
merchantOrderNostring回显商户订单号
amountstring金额,保留两位小数
statusstring初始状态固定 PENDING
expiryDateint64订单过期时间(Unix 秒),默认 1 小时

返回示例

{
  "code": 0,
  "message": "success",
  "data": {
    "orderNo": "STABLEPAYIN20260428000001",
    "merchantOrderNo": "E2E_IN_001",
    "amount": "500.00",
    "status": "PENDING",
    "expiryDate": 1714203600
  }
}

查询代收订单

POST /api/payment/query

请求参数

字段类型必填说明
merchantIdstring必填商户 ID
merchantOrderNostring二选一商户订单号
orderNostring二选一平台订单号
signstring必填签名

merchantOrderNoorderNo 至少传其一。

响应 data

字段类型说明
orderNostring平台订单号
merchantOrderNostring商户订单号
amountstring下单金额
paidAmountstring实际到账金额
statusstring订单状态,见订单状态
utrstring银行端流水号(成功后才有)
createTimeint64创建时间(Unix 秒)
updateTimeint64最近更新时间(Unix 秒)

创建代付订单

POST /api/payout/create

商户向第三方账户付款时调用。下单瞬间扣减商户可用余额(金额 + 手续费),订单失败后退款回账。

请求参数

字段类型必填说明
merchantIdstring必填商户 ID
merchantOrderNostring必填商户系统订单号,单商户内唯一
amountnumber必填付款金额,> 0,保留两位小数
beneNamestring必填收款人姓名
beneAccountstring必填收款人账号
beneIfscstring必填收款行 IFSC 代码
benePhonestring选填收款人手机号
beneEmailstring选填收款人邮箱
bankNamestring选填收款银行名
transferTypestring选填转账方式,缺省 BANK_TRANSFER
notifyUrlstring选填异步通知地址,覆盖商户后台默认配置
remarkstring选填备注
signstring必填签名

响应 data

字段类型说明
orderNostring平台订单号(以 STABLEPAYOUT 开头)
merchantOrderNostring回显商户订单号
amountstring金额
processFeestring手续费
statusstring初始状态固定 PENDING
余额校验:下单金额 + 手续费必须 ≤ 商户可用余额,否则返回 余额不足

查询代付订单

POST /api/payout/query

请求参数

代收查询:传 merchantId + (merchantOrderNoorderNo) + sign

响应 data

字段类型说明
orderNostring平台订单号
merchantOrderNostring商户订单号
amountstring付款金额
processFeestring手续费
statusstring订单状态,见订单状态
utrstring银行端流水号
createTimeint64创建时间
updateTimeint64更新时间

订单状态

status说明
PENDING已创建,等待处理
SUCCESS成功(代收=已到账,代付=已打款)
FAILED失败(代付会自动解冻并退回余额)
EXPIRED已过期(仅代收)

业务错误码

code含义
0成功
400参数错误(缺字段、字段类型不对等)
401签名验证失败
403商户不存在 / IP 不在白名单 / 功能未开通
500服务端错误(含余额不足、订单号重复等业务异常)

cURL 示例

以代付下单为例(请把 merchantIdsignbaseURL 替换为您自己的):

curl -X POST https://api.example.com/api/payout/create \
  -H "Content-Type: application/json" \
  -d '{
    "merchantId":      "SP20260101000001",
    "merchantOrderNo": "E2E_OUT_001",
    "amount":          500.00,
    "beneName":        "Raj Kumar",
    "beneAccount":     "1234567890123456",
    "beneIfsc":        "HDFC0001234",
    "benePhone":       "9876543210",
    "notifyUrl":       "https://your.site/notify",
    "sign":            "ABCDEF0123456789ABCDEF0123456789"
  }'

Python 示例

展示完整签名 + 下单流程;可直接保存为 demo.py 运行。

import hashlib, requests, time

BASE_URL = "https://api.example.com"
MERCHANT_ID  = "SP20260101000001"
API_KEY      = "<在商户后台 API 对接页复制>"
AMOUNT       = 500.00

def compute_sign(params: dict, api_key: str) -> str:
    filtered = {k: str(v) for k, v in params.items() if k != "sign" and str(v) != ""}
    raw = "&".join(f"{k}={filtered[k]}" for k in sorted(filtered)) + f"&key={api_key}"
    return hashlib.md5(raw.encode()).hexdigest().upper()

def create_payout():
    sign_params = {
        "merchantId":      MERCHANT_ID,
        "merchantOrderNo": f"DEMO_{int(time.time())}",
        "amount":          f"{AMOUNT:.2f}",   # 签名时用字符串
        "beneName":        "Raj Kumar",
        "beneAccount":     "1234567890123456",
        "beneIfsc":        "HDFC0001234",
        "benePhone":       "9876543210",
        "notifyUrl":       "https://your.site/notify",
    }
    body = dict(sign_params)
    body["sign"]   = compute_sign(sign_params, API_KEY)
    body["amount"] = AMOUNT                   # 请求体里 amount 是 float
    return requests.post(f"{BASE_URL}/api/payout/create", json=body, timeout=15).json()

print(create_payout())