支付中台开放接口文档(详细版) v1.2

支付中台开放接口文档(详细版)

版本 v1.2更新日期 2026-10-12接口前缀 /openapi/v1

适用对象:已在本平台开通「开放 API」应用并完成商户绑定的合作方系统。

本文档覆盖 支付、退款、入账方(分账接收方)管理、订单分账、订单分账资金归还、订单分账完结、余额分账 七大类共 13 个接口,以及配套的 签名鉴权、幂等、异步回调通知 机制。

1. 接入概览

1.1 接口清单

分类接口方法路径幂等要求
支付支付下单POST/openapi/v1/payments需要
支付查询支付订单GET/openapi/v1/payments/{outTradeNo}—
退款申请退款POST/openapi/v1/refunds需要
退款查询退款GET/openapi/v1/refunds/{refundRequestNo}—
入账方申请入账方POST/openapi/v1/receivers—
入账方查询入账方申请进度GET/openapi/v1/receivers/{recipientId}—
订单分账发起订单分账POST/openapi/v1/profit-sharing/orders需要
订单分账查询订单分账结果GET/openapi/v1/profit-sharing/orders/{businessNo}—
资金归还申请订单分账资金归还POST/openapi/v1/profit-sharing/order-returns需要
资金归还查询资金归还结果GET/openapi/v1/profit-sharing/order-returns/{businessNo}—
订单分账发起订单分账完结POST/openapi/v1/profit-sharing/order-completions需要
余额分账发起余额分账POST/openapi/v1/profit-sharing/balances需要
余额分账查询余额分账结果GET/openapi/v1/profit-sharing/balances/{businessNo}—

1.2 业务流程总览

  1. 1接入方 → 平台申请入账方,进入「入账方审核 / 签约」
  2. 2平台 → 接入方审核签约通过后获得 recipientId
  3. 3接入方 → 平台支付下单(settlementMode=DELAYED)
  4. 4平台 → 接入方支付结果回调
  5. 5接入方 → 平台发起订单分账 / 余额分账
  6. 6平台 → 接入方分账结果回调
  7. 7接入方 → 平台需要时发起退款 / 资金归还
  8. 8平台 → 接入方退款 / 归还结果回调

1.3 接入准备

  1. 向平台申请开通开放 API 应用,平台将发放以下凭证:
    • appId:应用标识;
    • apiSecret:请求签名密钥(≥32 字符);
    • callbackSecret:回调验签密钥(≥32 字符,仅用于校验平台推送,不参与请求签名)。
  2. 将需要操作的商户商编与应用完成绑定(一个应用可绑定多个商户号)。
  3. 准备接收异步通知的 HTTPS 地址。

2. 通用约定

项目约定
通信协议HTTPS(生产环境)
请求格式Content-Type: application/json; charset=UTF-8
响应格式JSON,UTF-8
金额单位元,Decimal 字符串/数值,最多 2 位小数
时间格式请求:ISO-8601 本地时间(如 2026-10-12T10:00:00);响应:yyyy-MM-dd HH:mm:ss 或 ISO-8601(回调 occurredAt)
请求体上限1 MB(超出直接拒绝)
单号规则outTradeNo / businessNo / refundRequestNo 长度 ≤64;退款请求号仅允许 [A-Za-z0-9_]

2.1 统一响应包络

所有接口(含鉴权失败)返回统一结构:

{ "code": "00000", "msg": "成功", "data": { } }
code含义典型场景
00000成功业务受理成功(业务结果仍需看 data.status)
A0001参数错误字段缺失、格式不合法、金额非法
A0002未认证签名不正确、时间戳过期、nonce 重放、应用被禁用
A0003无权限操作了未绑定商户、商户间越权
B0001业务异常订单状态不允许、重复提交冲突、渠道拒绝
C0001系统异常开放接口未启用、防重放服务不可用、渠道异常

注意:code=00000 仅代表请求处理成功。支付、退款、分账等异步业务的最终结果以 data.status、异步回调或主动查询为准。

3. 请求签名(鉴权)

所有开放接口均需通过 HMAC-SHA256 签名鉴权。签名不通过时返回 HTTP 401 + code=A0002。

3.1 请求头

请求头必填格式要求说明
X-App-Id是[A-Za-z0-9._-]{3,64}平台分配的应用标识
X-Timestamp是10 位 Unix 秒级时间戳与服务器时差不得超过 ±300 秒
X-Nonce是[A-Za-z0-9._-]{16,128}一次性随机串;在 TTL 内不可重复,否则判定重放
X-Signature是64 位十六进制(大小写不敏感)按下述算法计算
X-Idempotency-Key写接口必填非空见 4. 幂等机制

3.2 签名算法

第一步:构造规范化串(各段以 \n 连接,共 6 行):

HTTP_METHOD          ← 大写,如 POST
requestPath          ← 如 /openapi/v1/payments(不含域名、不含 query)
rawQueryString       ← 原样 query 串;无则空字符串
timestamp            ← X-Timestamp 的值
nonce                ← X-Nonce 的值
sha256Hex(body)      ← 请求体原文的 SHA-256 十六进制;GET/无 body 时空串的 SHA-256

第二步:计算签名:

signature = hex( HmacSHA256( canonicalString, apiSecret ) )   ← 小写十六进制

第三步:将签名放入 X-Signature 请求头。

3.3 常见鉴权失败原因

HTTP 状态提示信息原因与处理
503开放接口未启用平台侧未开放,请联系平台
401开放接口鉴权失败请求头缺失或格式错误;appId 未开通或已被禁用
401请求时间戳已过期本地时钟与服务器时差超过 ±300 秒,请校准时间后重试
401开放接口签名不正确规范化串构造有误或 apiSecret 不正确
401请求已被处理或检测到重放X-Nonce 在有效期内被重复使用,请每次请求生成新随机串

签名注意事项

  • rawQueryString 必须与实际请求 URL 完全一致(含编码与顺序),建议先拼签名再拼 URL;
  • 请求体必须以原始字节参与 SHA-256,不可重新序列化后再算;
  • GET 请求 body 为空,sha256Hex("") = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855;
  • 服务器时间请使用 NTP 校准,避免时间戳过期。

4. 幂等机制

所有资金类写操作(支付下单、退款、订单分账、资金归还、订单分账完结、余额分账)均支持幂等:

  • 写接口必须携带请求头 X-Idempotency-Key(建议取业务单号或其摘要),缺失时请求被拒绝;
  • 同一幂等键在 24 小时 内重复请求,平台直接返回首次处理结果,不会重复发起资金操作;
  • 首次处理失败时幂等键自动释放,修正后可重试;
  • 相同幂等键的并发请求会收到「请求处理中」提示,请稍后查询结果。

建议:X-Idempotency-Key 与业务单号保持强关联(例如取 outTradeNo / refundRequestNo / businessNo 的哈希),同一笔业务重试时不得更换。

5. 支付接口

5.1 支付下单

POST /openapi/v1/payments

创建支付订单并提交渠道受理。USER_SCAN(扫码)模式返回收银台链接;其余模式返回渠道唤起凭证。

请求体:

字段类型必填长度说明
merchantNostring是≤64商户商编
outTradeNostring是≤64调用方唯一订单号,重试保持不变
amountdecimal是—订单金额(元),必须 >0
paymentMethodstring是≤16支付产品:WECHAT / ALIPAY / UNIONPAY
paymentModestring是≤32支付方式,见下表
businessScenestring否≤32支付场景,默认 OFFLINE
authorizationDirectorystring否≤512支付授权目录,完整 HTTP/HTTPS 地址
goodsNamestring是≤128商品名称
userIdstring条件≤128支付用户标识;MINI_PROGRAM / WECHAT_OFFIACCOUNT / ALIPAY_LIFE / JS_PAY 必填
userIpstring是≤64用户真实公网 IP
notifyUrlstring是≤512支付结果通知地址(HTTPS)
settlementNotifyUrlstring否≤512延迟结算(清算)结果通知地址;为空沿用 notifyUrl
redirectUrlstring否≤512支付完成前端跳转地址;仅展示用途,不可作为支付终态依据
memostring否≤85对账备注
paymentOptionsstring否≤2048渠道扩展信息 JSON,仅特定支付模式需要
terminalIdstring否≤64线下终端 ID
terminalInfostring否≤2048商家终端场景信息 JSON
settlementModestring否≤32IMMEDIATE(默认,实时结算)/ DELAYED(延迟结算);后续要发起订单分账必须为 DELAYED
expireTimestring否—订单过期时间,ISO-8601 本地时间

paymentMode 取值:

值说明特殊要求
USER_SCAN用户扫商户码(收银台模式)下单后返回收银台链接 paymentData,状态 PAYING
MINI_PROGRAM微信小程序支付必填 userId(openid)
WECHAT_OFFIACCOUNT微信公众号支付必填 userId
ALIPAY_LIFE支付宝生活号支付必填 userId
JS_PAYJS 支付必填 userId
SDK_PAY / H5_PAY / DIRECT_PAY / UNCONSCIOUS_PAYSDK / H5 / 直连 / 免密—

付款码(B 扫 C)等其他产品不在本接口支持范围。

响应 data:

字段类型说明
outTradeNostring调用方订单号
paymentNostring平台支付流水号
amountdecimal订单金额(元)
currencystring币种
statusstring支付状态,见 10.1
settlementStatusstring结算状态(延迟结算订单关注)
settlementAmountdecimal已结算金额(元)
unSplitAmountdecimal未分账余额(元),供分账参考
settlementTimestring结算时间
paymentDatastring渠道唤起凭证:USER_SCAN 为收银台 URL;其余为渠道 prePay 凭证(如 prePayTn)
paidAmountdecimal实付金额(元)
refundAmountdecimal累计退款金额(元)
paidTime / expireTimestring支付时间 / 过期时间
errorCode / errorMessagestringPAYMENT_FAILED(支付未完成)/ PAYMENT_CLOSED(订单已关闭);无错为 null
syncedAtstring最近一次渠道状态同步时间

示例请求:

POST /openapi/v1/payments HTTP/1.1
Content-Type: application/json; charset=UTF-8
X-App-Id: app-20260901-001
X-Timestamp: 1760233200
X-Nonce: 8f14e45fceea167a5a36dedd4bea2543
X-Signature: 3f7a1c...(64 位 hex)
X-Idempotency-Key: 9a8b7c6d-pay-0001

{
  "merchantNo": "10080000001",
  "outTradeNo": "ORDER202610120001",
  "amount": 1.00,
  "paymentMethod": "WECHAT",
  "paymentMode": "USER_SCAN",
  "goodsName": "会员充值",
  "userIp": "61.135.169.121",
  "notifyUrl": "https://api.partner.com/callback/payment",
  "settlementMode": "DELAYED"
}

示例响应:

{
  "code": "00000",
  "msg": "成功",
  "data": {
    "outTradeNo": "ORDER202610120001",
    "paymentNo": "TR2026101200000001",
    "amount": 1.00,
    "currency": "CNY",
    "status": "PAYING",
    "paymentData": "https://cashier.example.com/pay?merchantNo=10080000001&tn=TR2026101200000001",
    "settlementStatus": null,
    "errorCode": null,
    "errorMessage": null
  }
}

5.2 查询支付订单

GET /openapi/v1/payments/{outTradeNo}?merchantNo={merchantNo}&refresh=true
参数位置必填说明
outTradeNopath是调用方订单号
merchantNoquery是商户商编
refreshquery否默认 true:主动向支付机构同步最新状态并校准本地结果;false 仅查本地

响应结构同 5.1 响应。

6. 退款接口

6.1 申请退款

POST /openapi/v1/refunds

请求体:

字段类型必填长度说明
merchantNostring是≤64商户商编
refundRequestNostring是≤64调用方退款请求号,全局唯一,仅允许 [A-Za-z0-9_],重试保持不变
outTradeNostring是≤64原支付的调用方订单号
amountdecimal是—退款金额(元),>0,累计不超过原订单实付金额
reasonstring否≤128退款原因
notifyUrlstring是≤512退款状态通知地址(HTTPS)

同步成功仅代表退款请求已受理,最终以 status、回调或查询为准。

响应 data:

字段类型说明
refundRequestNostring退款请求号
outTradeNostring原订单号
refundAmountdecimal申请退款金额(元)
actualRefundAmountdecimal实际退款金额(元)
userReceivedAmountdecimal用户实收退款(元)
returnedFeedecimal退回手续费(元)
reasonstring退款原因
statusstring退款状态,见 10.3
acceptanceStatusstring渠道受理结果:ACCEPTED / REJECTED / UNKNOWN
errorCodestring见 12.2 退款错误码
errorMessagestring错误描述
retryableboolean是否可用原请求号重试
nextActionstringNONE / QUERY / WAIT_CALLBACK / RETRY_SAME_ID / MANUAL_PROCESS
requestedAt / succeededAtstring发起 / 成功时间
syncedAtstring最近同步时间
createdAt / updatedAtstring记录创建 / 更新时间

6.2 查询退款

GET /openapi/v1/refunds/{refundRequestNo}?merchantNo={merchantNo}&refresh=true

refresh=true(默认)时主动向支付机构同步状态。响应结构同上。

7. 入账方管理接口

入账方(分账接收方)是余额分账的资金接收主体。先申请入账方,审核签约通过后,以 recipientId(入账方申请号)参与余额分账。

7.1 申请入账方

POST /openapi/v1/receivers

请求体:

字段类型必填长度说明
merchantNostring是≤64商户商编(须已绑定)
receiverTypestring是≤32TO_PUBLIC_MANAGER(对公)/ TO_PRIVATE_MANAGER(对私)
receiverNamestring是≤128入账方名称:对公=企业名称,对私=个人姓名
licenceNostring是≤64证件号:对公=营业执照号,对私=身份证号
mobilestring条件≤32手机号,对私必填
legalNamestring条件≤64法人姓名,对公必填
legalLicenceNostring条件≤64法人证件号,对公必填
bankCodestring是≤32银行总行编码,如 ICBC
bankCardNostring是≤64银行账户号
labelstring否≤64入账方标签/备注
settlementProductstring否≤16结算产品:T1 / D1 / HN(定时结算);不填用商户默认
settlementDatestring否≤16定时结算时间 HH:mm,仅 HN 填写,06:00~23:00 整点
cnapsCodestring否≤32联行号(大额支付行号)

响应 data:

字段类型说明
recipientIdstring入账方申请号,即后续余额分账接口的 recipientId
merchantNostring商户商编
receiverTypestring入账方类型
receiverNamestring入账方名称
bankCardMaskedstring脱敏银行卡号
bankCardLastFourstring银行卡后四位
statusstringSUBMITTING / REVIEWING / COMPLETED / FAILED
auditOpinionstring审核意见
signUrlstring签约链接(审核通过后返回)

7.2 查询入账方申请进度

GET /openapi/v1/receivers/{recipientId}?merchantNo={merchantNo}

查询时会先同步渠道最新审核状态再返回。status=COMPLETED 且返回 signUrl 时,入账方完成签约即可用于余额分账。

8. 分账接口

8.1 发起订单分账

POST /openapi/v1/profit-sharing/orders

对本系统支付接口创建、支付成功(SUCCESS)且未退款的订单发起分账;原收款商户号由平台根据 outTradeNo 自动识别。

⚠️ 前置条件:原订单必须以 settlementMode=DELAYED 创建,并已完成清算。实时结算订单发起会收到渠道 OPR15035 错误(平台已转译为友好提示)。

请求体:

字段类型必填说明
receiveMerchantNostring是(≤32)分账接收商户号(收款方→接收方)
businessNostring是(≤64)业务幂等号,重试保持不变
outTradeNostring是(≤64)原支付的调用方订单号
notifyUrlstring是(≤512)订单分账结果通知地址(HTTPS)
allocationModestring否AMOUNT(默认,按金额)/ PERCENTAGE(按比例)
allocationBaseAmountdecimal条件按比例分账时的分账基准金额(元)
releaseRemainingAmountboolean否分账完成后是否释放剩余可分账金额,默认 false
detailsarray否接收商户的分账明细,当前固定最多 1 条;不传时自动套用该商户生效中的 API_SPECIFIED 订单分账规则模板

details[] 明细:

字段类型必填说明
amountdecimal条件AMOUNT 模式必填,分账金额(元),>0
percentagedecimal条件PERCENTAGE 模式必填,范围 (0,100],多条合计必须=100
descriptionstring否分账说明(≤128)

响应 data:

字段类型说明
businessNostring业务幂等号
outTradeNostring原订单号
statusstring分账状态,见 10.4
divideAmountdecimal分账总金额(元)
divideRulestring分账规则标识(PERCENTAGE / AMOUNT)
createdAt / completedAtstring创建 / 完成时间
errorCode / errorMessagestring失败时 PROFIT_SHARING_FAILED /「分账处理失败」
nextActionstringWAIT_CALLBACK(处理中)/ QUERY(状态未知)/ REVIEW_AND_RETRY(失败复查)/ NONE
details[]array明细:recipientId、amount、percentage、receivedAmount(到账)、fee(手续费)、status、errorMessage

8.2 查询订单分账结果

GET /openapi/v1/profit-sharing/orders/{businessNo}?receiveMerchantNo={receiveMerchantNo}

按业务幂等号查询,平台根据回调订阅记录自动识别分账方商户。响应同 8.1。

8.3 申请订单分账资金归还

POST /openapi/v1/profit-sharing/order-returns

将已分出的订单分账资金按金额归还给分账方;平台根据 outTradeNo + 分账幂等号自动关联原分账明细。

请求体:

字段类型必填说明
outTradeNostring是(≤64)原订单号
businessNostring是(≤64)本次归还的业务幂等号
amountdecimal是归还金额(元),>0
reasonstring否归还原因(≤128)

响应 data:businessNo、outTradeNo、status、amount、reason、createdAt、completedAt、errorCode、errorMessage、nextAction。

8.4 查询订单分账资金归还结果

GET /openapi/v1/profit-sharing/order-returns/{businessNo}?outTradeNo={outTradeNo}

8.5 发起订单分账完结

POST /openapi/v1/profit-sharing/order-completions

释放原订单分账后剩余的冻结资金。完结分账使用独立于原分账的请求号,同一订单仅允许完结一次;重复调用时平台幂等回放已受理结果,不会重复完结。

行为说明:

  • 前置条件:该订单存在一笔支付成功且分账成功的订单分账,否则报「原订单分账尚未成功,不能发起完结分账」;
  • 发起订单分账时若 releaseRemainingAmount=true(分账成功自动解冻剩余金额),则无需再完结;
  • 订单分账确认成功后,平台默认会自动发起完结(自动解冻的除外);自动完结失败或需要指定说明时,可用本接口显式完结;
  • 完结没有独立的异步回调:PROCESSING / UNKNOWN 状态请以相同参数重新调用本接口(幂等回放)或查询订单分账结果确认。

请求体:

字段类型必填长度说明
outTradeNostring是≤64原支付的调用方订单号
businessNostring否≤64完结业务幂等号;缺省为 COMPLETE-{outTradeNo}
descriptionstring否≤128 字节(UTF-8)完结分账说明

响应 data:

字段类型说明
businessNostring完结业务幂等号
outTradeNostring原订单号
statusstringPROCESSING / SUCCESS / FAILED / UNKNOWN
releasedAmountdecimal本次完结释放的剩余冻结金额(元);渠道未返回时为 null
createdAt / completedAtstring完结申请 / 完成时间
errorCode / errorMessagestring失败时 ORDER_COMPLETE_FAILED + 描述
nextActionstringNONE(已终态)/ QUERY(处理中或未知:重试本接口或查询)/ REVIEW_AND_RETRY(失败复查后重试)

示例请求:

{ "outTradeNo": "ORDER202610120001", "description": "订单分账完成,释放剩余资金" }

示例响应:

{
  "code": "00000",
  "msg": "成功",
  "data": {
    "businessNo": "COMPLETE-ORDER202610120001",
    "outTradeNo": "ORDER202610120001",
    "status": "SUCCESS",
    "releasedAmount": 7.60,
    "createdAt": "2026-10-12 10:30:00",
    "completedAt": "2026-10-12 10:30:01",
    "errorCode": null,
    "errorMessage": null,
    "nextAction": "NONE"
  }
}

8.6 发起余额分账

POST /openapi/v1/profit-sharing/balances

从分账方易宝资金账户余额中向入账方划拨资金。平台固定使用 accountType=YEEPAY_ACCOUNT、divideVerifyType=STANDARD_DIVIDE、接收方类型 RECEIVER。

请求体:

字段类型必填说明
merchantNostring是(≤64)分账方商户商编
businessNostring是(≤64)业务幂等号,重试保持不变
notifyUrlstring是(≤512)余额分账结果通知地址(HTTPS)
detailsarray是(1~30 条)分账明细

details[] 明细:

字段类型必填说明
recipientIdstring是(≤64)入账方申请号(7.1 返回值)
amountdecimal是分账金额(元),>0
descriptionstring否分账明细描述(≤32)
feeModestring否手续费承担方式:DEDUCT_FROM_AMOUNT(默认,从分账金额内扣)/ CHARGE_SEPARATELY(额外收取)
purposestring否分账用途(≤40)

响应 data:结构同 8.1 响应。

幂等与重试:同一 businessNo 重试时若上次状态为 PROCESSING/UNKNOWN 会直接回放本地结果,不会重复划拨;仅上次 FAIL 的记录可沿用原号重试。

8.7 查询余额分账结果

GET /openapi/v1/profit-sharing/balances/{businessNo}?merchantNo={merchantNo}

9. 异步回调通知

9.1 事件类型

业务eventType触达时机
支付payment.status.changed支付状态变化(成功/失败/关闭等)
结算payment.settlement.changed延迟结算订单清算状态变化(仅订阅了 settlementNotifyUrl)
退款refund.status.changed退款状态变化
订单分账profit-sharing.order.status.changed订单分账状态变化
余额分账profit-sharing.balance.status.changed余额分账状态变化

同一业务状态未变化时不会重复推送;终态事件投递后订阅自动失效。订阅有效期默认 30 天。

9.2 通知报文

POST application/json; charset=UTF-8,body 为下单/发起时登记的 notifyUrl 接收:

{
  "eventId": "3f8a2b6c-....-....",
  "eventType": "payment.status.changed",
  "occurredAt": "2026-10-12T10:05:30.123Z",
  "appId": "app-20260901-001",
  "merchantNo": "10080000001",
  "businessNo": "ORDER202610120001",
  "status": "SUCCESS",
  "data": { }
}
字段说明
eventId投递唯一 ID,消费方据此幂等去重
eventType事件类型,同请求头 X-Callback-Event-Type
occurredAt事件发生时间(ISO-8601 UTC)
businessNo对应业务单号:支付=outTradeNo、退款=refundRequestNo、分账=businessNo
status最新状态(同 10 状态字典)
data业务明细(支付/退款/分账的详细字段,与对应查询接口的 data 结构一致或为其子集)

9.3 回调请求头与验签

请求头说明
X-Callback-App-Id应用标识
X-Callback-Timestamp秒级时间戳
X-Callback-Nonce32 位随机串
X-Callback-Event-Id投递 ID(= body.eventId)
X-Callback-Event-Type事件类型
X-Callback-Signature回调签名(64 位 hex)

回调签名验证:

canonical = timestamp + "\n" + nonce + "\n" + eventId + "\n" + sha256Hex(rawBody)
expected  = hex( HmacSHA256( canonical, callbackSecret ) )
校验:expected 与 X-Callback-Signature 小写比较一致

请务必用原始报文字节计算 SHA-256,并用 callbackSecret(不是 apiSecret)验签。

9.4 应答要求

  • 收到回调后请先验签、落库,再应答;
  • 处理成功:响应 HTTP 2xx 且响应 body 恰为文本 SUCCESS;
  • 其余情况(非 2xx 或 body ≠ SUCCESS)平台视为失败进入重试;
  • 请保证接口幂等:同一 eventId 可能被重复投递。

9.5 重试策略

属性值
重试间隔30 秒 → 2 分钟 → 10 分钟 → 30 分钟 → 2 小时 → 6 小时 → 24 小时
最大尝试次数8 次(含首次),超过后停止重试,请联系平台人工处理
超时连接 5 秒 / 读取 10 秒

9.6 注意事项

  • notifyUrl 必须为 HTTPS,不得携带用户信息与 #fragment;
  • 同一 businessNo 的回调地址与商户绑定关系创建后不可变更(重复发起时保持一致即可);
  • 回调可能乱序:请以查询接口 refresh=true 的结果为准做最终校准;
  • 若长时间未收到回调,主动调用对应查询接口兜底。

10. 状态字典

10.1 支付状态

状态说明终态
PAYING支付中(含 USER_SCAN 待扫码)否
SUCCESS支付成功是
FAILED支付失败是
CLOSED订单关闭(超时未付/关单)是
REFUNDED已全额退款是

10.2 结算状态

延迟结算(settlementMode=DELAYED)订单的清算状态,随 payment.settlement.changed 回调或查询接口的 settlementStatus / settlementAmount / unSplitAmount / settlementTime 体现;清算完成是发起订单分账的前提。

10.3 退款状态

状态说明nextAction
PROCESSING退款处理中WAIT_CALLBACK
SUCCESS退款成功NONE
FAILED退款失败;retryable=true 时可用原请求号重试RETRY_SAME_ID / NONE
ACTION_REQUIRED需人工介入(原 SUSPEND)MANUAL_PROCESS
CLOSED退款关闭(原 CANCEL)NONE
UNKNOWN状态未知QUERY

10.4 分账状态(订单/余额通用)

状态说明nextAction
CREATED已创建待提交WAIT_CALLBACK
PROCESSING渠道处理中WAIT_CALLBACK
SUCCESS分账成功NONE
FAILED分账失败REVIEW_AND_RETRY(FAIL 记录可沿用原 businessNo 重试)
UNKNOWN状态未知QUERY

details[].status 为单笔明细状态,枚举同上;整单 status 存在任一明细 PROCESSING 即为 PROCESSING,全部 SUCCESS 才为 SUCCESS。

10.5 入账方状态

状态说明
SUBMITTING提交渠道中
REVIEWING渠道审核中
COMPLETED完成(签约通过后可用于余额分账)
FAILED申请失败,见 auditOpinion

11. 签名与调用示例

11.1 Node.js 签名与调用

const crypto = require('crypto')

const BASE_URL = 'https://api.your-platform.com'
const APP_ID = 'app-20260901-001'
const API_SECRET = 'your-api-secret-at-least-32-chars'

function sign(method, path, query, bodyStr) {
  const timestamp = String(Math.floor(Date.now() / 1000))
  const nonce = crypto.randomBytes(16).toString('hex')           // 32 位
  const bodySha256 = crypto.createHash('sha256').update(bodyStr, 'utf8').digest('hex')
  const canonical = [method.toUpperCase(), path, query, timestamp, nonce, bodySha256].join('\n')
  const signature = crypto.createHmac('sha256', API_SECRET).update(canonical, 'utf8').digest('hex')
  return { timestamp, nonce, signature }
}

async function createPayment() {
  const path = '/openapi/v1/payments'
  const body = JSON.stringify({
    merchantNo: '10080000001',
    outTradeNo: 'ORDER202610120002',
    amount: 1.00,
    paymentMethod: 'WECHAT',
    paymentMode: 'USER_SCAN',
    goodsName: '会员充值',
    userIp: '61.135.169.121',
    notifyUrl: 'https://api.partner.com/callback/payment',
    settlementMode: 'DELAYED'
  })
  const { timestamp, nonce, signature } = sign('POST', path, '', body)
  const resp = await fetch(BASE_URL + path, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json; charset=UTF-8',
      'X-App-Id': APP_ID,
      'X-Timestamp': timestamp,
      'X-Nonce': nonce,
      'X-Signature': signature,
      'X-Idempotency-Key': 'idem-' + 'ORDER202610120002'
    },
    body
  })
  console.log(await resp.json())
}

11.2 Java 签名片段

String canonical = String.join("\n",
        "POST", path, rawQuery, timestamp, nonce, sha256Hex(bodyBytes));
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
String signature = HexFormat.of().formatHex(mac.doFinal(canonical.getBytes(StandardCharsets.UTF_8)));

11.3 回调验签示例(Node.js)

app.post('/callback/payment', express.raw({ type: '*/*' }), (req, res) => {
  const timestamp = req.header('X-Callback-Timestamp')
  const nonce     = req.header('X-Callback-Nonce')
  const eventId   = req.header('X-Callback-Event-Id')
  const signature = String(req.header('X-Callback-Signature') || '').toLowerCase()

  const bodySha256 = crypto.createHash('sha256').update(req.body).digest('hex')
  const canonical  = [timestamp, nonce, eventId, bodySha256].join('\n')
  const expected   = crypto.createHmac('sha256', CALLBACK_SECRET)
                           .update(canonical, 'utf8').digest('hex')

  if (expected !== signature) return res.status(401).end()

  const event = JSON.parse(req.body.toString('utf8'))
  // 1. 按 event.eventId 幂等落库  2. 业务处理
  res.status(200).send('SUCCESS')   // 固定应答文本
})

12. 错误码与常见问题

12.1 平台错误码

见 2.1 统一响应包络。鉴权类失败为 HTTP 401 + A0002,开关类失败为 HTTP 503 + C0001。

12.2 退款错误码映射

errorCode说明retryable
INVALID_REFUND_AMOUNT退款金额不符合要求(余额不足/超可退金额等)否
PAYMENT_NOT_FOUND原支付订单不存在否
PAYMENT_STATUS_INVALID原支付订单状态不允许退款否
TOO_MANY_REQUESTS渠道限频,请稍后查询退款状态是
INSUFFICIENT_FUNDS退款资金不足否
REFUND_FAILED其他退款处理失败视渠道返回

12.3 常见问题(FAQ)

Q1:发起订单分账报「原支付订单的结算方式不支持订单分账」?
订单创建时 settlementMode 为 IMMEDIATE。订单分账仅支持延迟结算订单:请使用 settlementMode=DELAYED 创建新订单,支付成功并完成清算后再申请。
Q2:code=00000 但业务没成功?
00000 表示接口调用成功。支付/退款/分账为异步业务,请以 data.status、回调通知或查询接口为准。
Q3:签名一直失败?
按顺序排查:① 时间戳与服务器时差 ≤300 秒;② query 串与实际 URL 完全一致;③ body 用原始字节算 SHA-256;④ apiSecret 正确且未泄;⑤ 签名头是 64 位十六进制。
Q4:返回「请求已被处理或检测到重放」?
X-Nonce 在 TTL 内重复。每次请求生成新的随机 nonce;若为业务重试请更换 X-Idempotency-Key 场景或先查询原单状态。
Q5:回调收不到 / 收到但状态没更新?
① 确认 notifyUrl 公网可达且为 HTTPS;② 应答必须是 2xx + body SUCCESS;③ 业务状态未变化时平台不会重复推送;④ 长时间未收到可主动调用查询接口(refresh=true)兜底。
Q6:余额分账 recipientId 从哪里来?
先调用「申请入账方」接口,审核签约完成(status=COMPLETED)后返回的 recipientId 即可用于余额分账明细。
Q7:同一笔余额分账想重试?
仅当上次状态为 FAIL 时,可沿用原 businessNo 重新发起;PROCESSING/UNKNOWN 请先查询,SUCCESS 会直接回放原结果,不会重复划拨。