概览
StablePay 商户开放接口提供 代收(Payment) 与 代付(Payout) 两类业务能力。所有接口为 POST application/json,使用 MD5 签名认证。
接入前请向 StablePay 商务申请商户账号,登录商户后台 → API 对接 页面获取以下凭据:
merchantId— 商户 ID(请求必带)apiKey— 商户密钥(仅用于本地签名,不要传输)aesKey/aesIv— 部分敏感字段加密用(如启用)
联调流程
- 商户后台获取
merchantId+apiKey - 在后台 API 对接 页配置
支付 URL/代付 URL(接收异步通知) - (可选)在 IP 白名单 配置允许调用的 IP;不配置则放行所有 IP
- 按本文档签名规则组装请求 → 调用
create接口下单 - 使用返回的
orderNo或自有merchantOrderNo调用query查询订单状态 - 订单状态变更时,平台会向您配置的回调 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 字段。算法如下:
- 取出请求体中所有非空参数(值为
""、null或缺省的字段不参与签名),剔除sign本身。 - 金额类字段(如
amount)转成%.2f字符串。 - 把参数按
key升序(ASCII)排序,拼接为k1=v1&k2=v2&...&kn=vn。 - 末尾追加
&key={apiKey}。 - 对最终字符串做 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¬ifyUrl=https://your.site/notify&key=<您的 apiKey>
对上述字符串 MD5 → 转大写 → 即为 sign。
= 和 & 之间不留空格;URL 字符(如 : /)不做编码;中文/空格保持原样。创建代收订单
/api/payment/create商户向用户收款时调用。下单成功后平台返回平台订单号;用户付款 / 平台对账完成后通过异步通知或主动查询接口获取最终状态。
请求参数
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| merchantId | string | 必填 | 商户 ID |
| merchantOrderNo | string | 必填 | 商户系统订单号,单商户内唯一 |
| amount | number | 必填 | 下单金额,> 0,保留两位小数 |
| customerName | string | 选填 | 付款人姓名 |
| customerEmail | string | 选填 | 付款人邮箱 |
| customerPhone | string | 选填 | 付款人手机号 |
| notifyUrl | string | 选填 | 异步通知地址,覆盖商户后台默认配置 |
| returnUrl | string | 选填 | 付款完成后浏览器跳回地址 |
| remark | string | 选填 | 备注,原样回显 |
| sign | string | 必填 | 签名,详见签名规则 |
响应 data
| 字段 | 类型 | 说明 |
|---|---|---|
| orderNo | string | 平台订单号(以 STABLEPAYIN 开头) |
| merchantOrderNo | string | 回显商户订单号 |
| amount | string | 金额,保留两位小数 |
| status | string | 初始状态固定 PENDING |
| expiryDate | int64 | 订单过期时间(Unix 秒),默认 1 小时 |
返回示例
{
"code": 0,
"message": "success",
"data": {
"orderNo": "STABLEPAYIN20260428000001",
"merchantOrderNo": "E2E_IN_001",
"amount": "500.00",
"status": "PENDING",
"expiryDate": 1714203600
}
}
查询代收订单
/api/payment/query请求参数
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| merchantId | string | 必填 | 商户 ID |
| merchantOrderNo | string | 二选一 | 商户订单号 |
| orderNo | string | 二选一 | 平台订单号 |
| sign | string | 必填 | 签名 |
merchantOrderNo 与 orderNo 至少传其一。
响应 data
| 字段 | 类型 | 说明 |
|---|---|---|
| orderNo | string | 平台订单号 |
| merchantOrderNo | string | 商户订单号 |
| amount | string | 下单金额 |
| paidAmount | string | 实际到账金额 |
| status | string | 订单状态,见订单状态 |
| utr | string | 银行端流水号(成功后才有) |
| createTime | int64 | 创建时间(Unix 秒) |
| updateTime | int64 | 最近更新时间(Unix 秒) |
创建代付订单
/api/payout/create商户向第三方账户付款时调用。下单瞬间扣减商户可用余额(金额 + 手续费),订单失败后退款回账。
请求参数
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| merchantId | string | 必填 | 商户 ID |
| merchantOrderNo | string | 必填 | 商户系统订单号,单商户内唯一 |
| amount | number | 必填 | 付款金额,> 0,保留两位小数 |
| beneName | string | 必填 | 收款人姓名 |
| beneAccount | string | 必填 | 收款人账号 |
| beneIfsc | string | 必填 | 收款行 IFSC 代码 |
| benePhone | string | 选填 | 收款人手机号 |
| beneEmail | string | 选填 | 收款人邮箱 |
| bankName | string | 选填 | 收款银行名 |
| transferType | string | 选填 | 转账方式,缺省 BANK_TRANSFER |
| notifyUrl | string | 选填 | 异步通知地址,覆盖商户后台默认配置 |
| remark | string | 选填 | 备注 |
| sign | string | 必填 | 签名 |
响应 data
| 字段 | 类型 | 说明 |
|---|---|---|
| orderNo | string | 平台订单号(以 STABLEPAYOUT 开头) |
| merchantOrderNo | string | 回显商户订单号 |
| amount | string | 金额 |
| processFee | string | 手续费 |
| status | string | 初始状态固定 PENDING |
余额不足。查询代付订单
/api/payout/query请求参数
同代收查询:传 merchantId + (merchantOrderNo 或 orderNo) + sign。
响应 data
| 字段 | 类型 | 说明 |
|---|---|---|
| orderNo | string | 平台订单号 |
| merchantOrderNo | string | 商户订单号 |
| amount | string | 付款金额 |
| processFee | string | 手续费 |
| status | string | 订单状态,见订单状态 |
| utr | string | 银行端流水号 |
| createTime | int64 | 创建时间 |
| updateTime | int64 | 更新时间 |
订单状态
| status | 说明 |
|---|---|
PENDING | 已创建,等待处理 |
SUCCESS | 成功(代收=已到账,代付=已打款) |
FAILED | 失败(代付会自动解冻并退回余额) |
EXPIRED | 已过期(仅代收) |
业务错误码
| code | 含义 |
|---|---|
| 0 | 成功 |
| 400 | 参数错误(缺字段、字段类型不对等) |
| 401 | 签名验证失败 |
| 403 | 商户不存在 / IP 不在白名单 / 功能未开通 |
| 500 | 服务端错误(含余额不足、订单号重复等业务异常) |
cURL 示例
以代付下单为例(请把 merchantId、sign、baseURL 替换为您自己的):
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())