外观
商户收款接口
接口地址:https://api.urpye.com
商户密钥由平台生成并确认配置后启用,不随请求发送。通道编码由平台提供,下单必填。以下 UUID 和密钥 demo_merchant_secret_replace_me 仅用于示例。
1. 创建收款
http
POST /receipts
Content-Type: application/json请求示例
bash
curl --request POST 'https://api.urpye.com/receipts' \
--header 'Content-Type: application/json' \
--data '{
"merchantId": "123456789012345678",
"merchantTradeNo": "ORDER_20260727_001",
"channelCode": "f7ce8569-ae9b-4b0b-8d31-90e4fbd88f2a",
"method": "alipay",
"amount": "2000",
"productName": "AI Credits",
"productDescription": "Purchase 1000 credits",
"notifyUrl": "https://merchant.example.com/payment/notify",
"timestamp": 1785110400,
"sign": "32b061d61b06c2a5571718ab8cef6897af79c3080801800b39f87620fce405fd"
}'替换商户 ID、通道编码、密钥和通知地址,使用当前时间戳重新计算签名。请求时间与服务器相差不得超过 300 秒。
参数说明
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
merchantId | string | 是 | 平台分配的商户 ID |
merchantTradeNo | string | 是 | 商户订单号,同一商户下唯一,最多 128 字符 |
channelCode | string | 是 | 平台提供的通道编码,36 字符、小写、带连字符的 UUID v4 |
method | string | 是 | 当前仅支持 alipay |
amount | string | 是 | 正整数金额,单位为分;2000 表示 20 元 |
productName | string | 是 | 商品名称,最多 255 字符 |
productDescription | string | 否 | 商品描述,最多 2048 字符 |
notifyUrl | string | 是 | 公网 HTTP/HTTPS 通知地址,最多 2048 字符 |
timestamp | integer | 是 | 正整数 Unix 时间戳,单位为秒 |
sign | string | 是 | 64 位 HMAC-SHA256 十六进制签名 |
成功响应
首次创建返回 HTTP 201;相同订单号和业务参数、原链接有效时,返回 HTTP 200。
json
{
"code": 0,
"message": "success",
"data": {
"merchantTradeNo": "ORDER_20260727_001",
"channelCode": "f7ce8569-ae9b-4b0b-8d31-90e4fbd88f2a",
"amount": "2000",
"url": "https://qr.alipay.com/sample",
"sign": "2f168d5334959156729bc18d734a1be947a7582e07f3af96be4f010183ea7c9d"
}
}验签并核对订单号、通道及金额后打开 data.url。链接有效期约 3–5 分钟,支付结果通过通知或查单确认。
2. 签名
创建及查询请求必须签名,创建响应 data 和通知必须验签:
- 排除
sign和值为null的字段,保留空字符串。 - 按字段名排序,生成紧凑 JSON;保留原始值及类型,中文不转义。
- 请求原文为
HTTP方法 + "\n" + 路径 + "\n" + JSON;方法大写,路径不包含域名和查询串。 - 创建响应和通知的原文只包含上述 JSON。使用商户密钥计算 UTF-8 HMAC-SHA256,输出 64 位小写十六进制。
GET 参数全部按解码后的字符串签名,只加入实际传递的参数,不补默认值;查询参数不能重复。POST 保持 JSON 类型,timestamp 为整数。URL 编码在签名完成后进行。
python
import hashlib
import hmac
import json
import re
def signing_content(payload):
return json.dumps(
{key: value for key, value in payload.items() if key != "sign" and value is not None},
ensure_ascii=False, sort_keys=True, separators=(",", ":"), allow_nan=False,
)
def create_sign(payload, secret):
return hmac.new(secret.encode("utf-8"), signing_content(payload).encode("utf-8"), hashlib.sha256).hexdigest()
def create_request_sign(payload, secret, method, path):
content = f"{method.upper()}\n{path}\n{signing_content(payload)}"
return hmac.new(secret.encode("utf-8"), content.encode("utf-8"), hashlib.sha256).hexdigest()
def verify_sign(payload, secret):
sign = payload.get("sign")
return (
isinstance(sign, str)
and re.fullmatch(r"[a-fA-F0-9]{64}", sign) is not None
and hmac.compare_digest(create_sign(payload, secret), sign.lower())
)
# 创建:payload["sign"] = create_request_sign(payload, secret, "POST", "/receipts")
# 查询:params["sign"] = create_request_sign(params, secret, "GET", "/receipts/list")
# 创建响应:verify_sign(response["data"], secret)
# 通知:verify_sign(notification, secret)3. 收款结果通知
http
POST {notifyUrl}
Content-Type: application/json
Accept: text/plainjson
{
"merchantTradeNo": "ORDER_20260727_001",
"channelCode": "f7ce8569-ae9b-4b0b-8d31-90e4fbd88f2a",
"method": "alipay",
"amount": "2000",
"status": "paid",
"timestamp": 1785110480,
"sign": "03a2d5c24d8810d39ee33996610a42262346dc503cd54ded29aa70c3a226588b"
}channelCode 为订单实际使用的通道;amount 单位为分;status 为 paid(已支付)或 closed(已关闭);timestamp 为结果确认时间,单位为秒。
通知验签使用当前商户密钥,不对通知时间戳应用 300 秒请求时效限制。密钥重置后,未送达通知会使用新密钥重新签名。
验签、核对订单及金额,按商户订单号幂等处理后返回:
http
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
success- HTTP
2xx+ 纯文本success表示接收成功,忽略大小写和首尾空白。 - 超时 10 秒,不跟随重定向;自动投递最多 5 次,重复通知须幂等处理。
- 链接到期不自动关闭订单,也不发送关闭通知。
4. 错误与重试
错误示例(HTTP 401):
json
{
"code": 401,
"msg": "签名校验失败"
}| HTTP 状态码 | 说明 |
|---|---|
400 | 参数或金额不支持,通道不存在、停用或与支付方式不匹配 |
401 | 签名错误或请求已过期 |
403 | 商户停用、密钥未确认或无权限 |
404 | 商户或订单不存在 |
409 | 订单参数冲突或暂不可创建 |
410 | 原订单已关闭或链接到期 |
422 | JSON 或字段格式错误 |
429 | 请求频繁,按 Retry-After 等待 |
500 | 服务异常或创建结果未确认 |
501 | 支付方式暂不支持 |
502 | 创建收款被拒绝 |
HTTP 422 的错误位于 detail 数组;HTTP 502 的错误说明位于 msg.message。
超时后先查单。同一订单号重试须保持通道和其他业务参数一致,更换通道返回 409;可更新 timestamp 和 sign,结果未确认时不要换号下单。
5. 商户订单列表
http
GET /receipts/list查询参数
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
merchantId | string | 是 | 平台分配的商户 ID |
channelCode | string | 否 | 按通道编码精确筛选,格式同下单参数 |
pageNum | integer | 否 | 页码,默认 1 |
pageSize | integer | 否 | 每页数量,默认 20,范围 1–100 |
merchantTradeNo | string | 否 | 商户订单号,精确匹配 |
status | string | 否 | 订单状态,见下表 |
beginTime | string | 否 | 创建时间起点,包含;带时区的 ISO 8601 时间 |
endTime | string | 否 | 创建时间终点,不包含;带时区的 ISO 8601 时间 |
timestamp | string | 是 | 当前 Unix 秒级时间戳,查询参数按字符串签名 |
sign | string | 是 | 64 位 HMAC-SHA256 签名 |
查单无需额外 Header。时间示例:2026-10-02T00:00:00+08:00,URL 中的 + 需编码为 %2B;同时传入起止时间时须满足 beginTime < endTime。
请求示例
bash
curl --get 'https://api.urpye.com/receipts/list' \
--data-urlencode 'merchantId=123456789012345678' \
--data-urlencode 'pageNum=1' \
--data-urlencode 'pageSize=20' \
--data-urlencode 'timestamp=1785110400' \
--data-urlencode 'sign=ab7362ab94709932ddb8fd7e8bb5eea95a48722aa63b2e899e9f7db9dfd28522'成功响应
HTTP 200:
json
{
"code": 0,
"message": "success",
"data": {
"rows": [
{
"orderId": "364070014577283072",
"merchantTradeNo": "ORDER_20260727_001",
"channelCode": "f7ce8569-ae9b-4b0b-8d31-90e4fbd88f2a",
"method": "alipay",
"amount": "2000",
"productName": "AI Credits",
"status": "awaiting_payment",
"createTime": "2026-10-02T02:00:00.000Z",
"paidAt": null,
"closedAt": null
}
],
"pageNum": 1,
"pageSize": 20,
"total": 1,
"hasNext": false
}
}rows 为当前页订单,total 为匹配总数,hasNext 表示是否有下一页。amount 单位为分,时间使用 UTC(Z);订单 ID 使用字符串。
| 状态 | 说明 |
|---|---|
creating | 创建中 |
awaiting_payment | 待支付 |
paid | 已支付 |
closed | 已关闭 |
creation_failed | 创建失败 |
creation_unknown | 创建结果未确认 |
authorization_required | 授权不可用,创建未完成 |
单笔查单
bash
curl --get 'https://api.urpye.com/receipts' \
--data-urlencode 'merchantId=123456789012345678' \
--data-urlencode 'merchantTradeNo=ORDER_20260727_001' \
--data-urlencode 'timestamp=1785110400' \
--data-urlencode 'sign=c717eff6236fde00038d31fdc2008253f5b4066c6256bd2552f46852b8939da9'也支持 GET /receipts/{orderId},传入 merchantId、timestamp 和 sign,使用实际路径(例如 /receipts/364070014577283072)签名。单笔查询无需传通道编码;响应中 channelCode 为实际通道,requestKey 为商户订单号。所有商户接口和通知中的 amount 均为分字符串,例如 "2000" 表示人民币 20 元。