XD-OP-01 · DOC

快速开始(5 分钟跑通首单)

这一篇只做一件事:让你的服务端成功创建一个支付订单、把收款材料交给买家,并收到支付终态。字段级细节见 API 参考,报错见错误码与排障。

小豆支付开放平台是面向已有自有系统的商家的支付接入服务:通过服务器对服务器的接口,把支付宝与微信收款接进商家自己的系统,并以签名事件通知回传支付状态;资金由持牌支付公司收付结算。个人也能申请:主体类型选「个人」,身份证 + 本人银行卡即可完成商户进件。央行持牌机构清算,安全可靠的个人和企业支付接口。

本篇只做一件事:让你的服务端成功创建一个支付订单、把收款材料交给买家、并收到支付终态。字段级细节见 API 参考,报错见 错误码与排障。

0. 前置条件

项说明
appId应用标识,开通后在门户「应用凭证」页可见
keyId(kid)你自己的签名密钥标识,mkid_ 开头(21 字符)——在你上传公钥时由平台派生、门户「应用凭证」页回显;也可按 凭证与密钥管理 · 1.1 本地派生。平台不会预先发一个 kid;没上传过公钥就没有 kid
RSA2 私钥只在你自己的服务器上生成与保存,私钥永不上传、永不进浏览器
Base URL登录卖家门户 →「应用凭证」页的接入地址(平台在此下发;本资料与示例一律写作 <BASE_URL>,不要从资料里抄任何 host,也不要写死在代码里——当配置项管理)
出口 IP你的服务器出口 IP 需在门户的 IP 白名单内(校验默认开启,未加白名单的请求会被拒;可在门户自助关闭,不建议)
申报域名归属(可选)申报域名由你自己填写,不核验也能开通;建议完成一次核验(DNS TXT 或回源文件二选一),归属更明确。做法见 接入指南 · 域名归属验证
平台公钥验平台响应/事件签名用;取自 接入指南 · 平台公钥与指纹(与门户同源)

1. 生成一次请求签名(六头)

每个请求都要带六个头:X-XD-App-Id、X-XD-Timestamp、X-XD-Nonce、X-XD-Key-Id、X-XD-Request-Id、X-XD-Sign。 签名算法是 RSA-SHA256,签名覆盖一段固定格式的规范串(含请求体原始字节的 SHA-256)。

直接复制对应语言的示例(在公开仓与「下载接入包」的 examples/ 内;「下载文档包」不含示例):

规范串构成与逐字段约束见 安全红线 · 请求签名。

2. 创建订单

POST <BASE_URL>/api/open/v1/payments
Content-Type: application/json
X-XD-App-Id: xdop_xxxxxxxxxxxxxxxx
X-XD-Timestamp: 1758888888
X-XD-Nonce: 6f1c2f7a9d0b4e51
X-XD-Key-Id: mkid_xxxxxxxxxxxxxxxx
X-XD-Request-Id: 018f2c1e-8b21-7c3a-9f10-2b7c9a1d4e55
X-XD-Sign: <Base64 签名值>

{
  "outTradeNo": "SHOP20260926A0001",
  "channel": "ALIPAY_H5",
  "amountFen": 100,
  "currency": "CNY",
  "subject": "示例商品",
  "payerClientIp": "203.0.113.10"
}

上面这单里有六个必填字段:outTradeNo、channel、amountFen、currency、subject、payerClientIp(买家公网 IP,由你的服务端转交)。少一个即 400;请求体是严格模式,多传 schema 之外的字段同样 400。

⚠️ 示例里的三个值只能看,不能照抄:

  • X-XD-Timestamp: 1758888888 是规范串自检用的固定值。真实请求必须带当前时间(秒级 epoch,时间窗 ±300 秒),照抄这个过去的时间戳会被 401 拒。
  • payerClientIp: 203.0.113.10 是 RFC 5737 文档示例网段,属于服务端明确拒绝的保留段(连同 10/8、172.16/12、192.168/16、127/8、CGNAT 等一并拒绝)——照抄会得到 400 OPEN_API_BODY_INVALID。这里必须填买家的真实公网 IP(由你的服务端转交)。
  • X-XD-Key-Id 必须填你自己的真实 kid(mkid_ 开头;门户「应用凭证」上传公钥后复制,或按 12 · 1.1 本地派生)。填占位值/平台公钥 kid/任意字符串都会因找不到匹配公钥而 401。

成功返回 201(业务幂等重放返回 200):

{
  "requestId": "018f2c1e-8b21-7c3a-9f10-2b7c9a1d4e55",
  "openOrderId": "op_01J8ZQ7K3M5N6P7Q8R9S0T1U2V",
  "outTradeNo": "SHOP20260926A0001",
  "status": "CREATED",
  "channel": "ALIPAY_H5",
  "tradeScope": "CARD_VIRTUAL",
  "links": ["ALIPAY_AGGREGATION_NATIVE"],
  "amountFen": 100,
  "currency": "CNY",
  "expireAt": "2026-09-26T12:34:56.000Z",
  "payUrl": "https://<平台收银页地址>/cashier/<token>",
  "qrCode": "https://qr.alipay.com/bax0example000000000000",
  "payUrlExpireHint": 1790426096,
  "feeProjection": {
    "ruleVersion": "<生效配置版本>",
    "tier": "STANDARD",
    "thresholdFen": 0,
    "merchantRateBps": 0,
    "companyServiceFeeRateBps": 0,
    "merchantSettlementFen": 0,
    "companyServiceFeeFen": 0
  },
  "replayed": false
}

上例中的 feeProjection 数值已抹零占位——费率与金额一律以上线时该字段的实际返回为准;对外统一费率与手续费在仓库 README.md 写明(本资料正文不重复列数字),限额数字不在本资料。

三个关键字段:

  • payUrl:平台收银页地址(买家可打开的收款页)。
  • qrCode:官方收款码。仅支付宝渠道、且服务端校验为官方前缀时才下发;商家可在自有 PC 页面直接渲染成二维码,与平台收银页同形。只在下发响应有效,查询接口恒为 null。
  • expireAt:订单支付窗口截止时间,以服务端下发为准。

3. 把收款材料交给买家

三种标准用法(终端语义与红线见 收银页对接与终端能力矩阵):

用法怎么做适用
自渲染官方收款码取响应中的 qrCode,在自有 PC 页面渲染二维码桌面买家扫码
渲染收银页二维码把 payUrl 渲染成二维码,买家手机扫码进平台收银页桌面→手机
302 跳转收银页把买家浏览器 302 到 payUrl手机买家直接进入

qrCode 与 payUrl 都由服务端下发,不要在客户端拼接、改写或转发到第三方;渲染前做一次前缀防呆复检。

4. 拿支付终态

收银页打开、收银页回跳、用户点击完成都不是支付终态。 终态只有两条来源:

  1. 事件通知(推荐):在门户「应用配置变更」里配置 notifyUrl(平台自动校验、提交即生效,前置条件见 webhook 验签),平台会把 PAYMENT_SUCCEEDED 等事件推给你的服务器,用平台公钥验签后按 eventId 去重落账。
  2. 主动查单:GET <BASE_URL>/api/open/v1/payments/{outTradeNo}(本地权威读,零外部外呼)。

两条路径都要接:事件是主路径,查单是对账与补偿路径。

5. 退款与对账

  • 退款:POST <BASE_URL>/api/open/v1/refunds(outRefundNo 业务幂等),见 退款与对账。
  • 费率与结算口径不写死在代码里:每笔订单响应里的 feeProjection 就是该笔的生效口径,见 费率与限额。

6. 本地先跑一遍

demo/h5-cashier/(只在公开仓提供;不在门户的两个下载包内)是一个零外部依赖的本地 demo(loopback + mock),把下单、收银页三端形态、事件验签、查单、关单、退款整条链跑通,不需要任何生产凭证:

node demo/h5-cashier/server.js
# 浏览器打开终端提示的本地地址

7. 首单常见失败

现象先看
401 验签失败规范串与六头形态:是不是把 query 排序、原始 body 字节、Content-Type 规范化写错了;也可能是不在 ±300 秒时间窗内,或应用不在 ACTIVE 状态
403 来源 IP 判定失败出口 IP 是否在白名单内、来源校验是否被你自己关闭;请求是否绕过了你配置的代理
400 请求体非法是否存在 schema 之外的字段(请求体是严格模式,未知字段直接拒)
413 请求体过大请求体有流式硬上限,超大 attach/description 会被拒
422 通道不可用该通道的链路尚未放行,或申报范围(tradeScope)与通道不符

完整错误码与决策树见 错误码与排障。

内容源:open-platform/docs/01-quickstart.md · 最后更新 2026-10-12 下载本文 .md 在 GitHub 查看