发起转账
接口说明
商户系统通过该接口按通道直连发起转账(商户余额转给收款人,如营销奖励、报销打款、佣金结算等场景)。
转账为通道直连能力,须指定 channel(wechat/alipay/douyin)与该通道的 channelMchNo(通道商户号)。
幂等语义:幂等维度为 通道 + 商户转账号(bizTransferNo)+ 商户号。同组合重复发起会被拦截(noDuplicate);发起失败的订单会保留失败单据,复用原商户转账号重新发起即可重试(复用原单),无需更换单号。
请求地址
POST /unipay/transfer
- 认证:RSA 签名(
@PaymentVerify) - 响应:
DaxResult<TransferCreateResult>
请求参数
基础参数同 统一支付 - 基础参数,业务参数:
| 参数 | 类型 | 必填 | 最大长度 | 描述 |
|---|---|---|---|---|
| channel | string | 是 | — | 转账通道(wechat / alipay / douyin) |
| channelMchNo | string | 是 | 32 | 通道商户号(凭证组装与通道路由用) |
| bizTransferNo | string | 是 | 100 | 商户转账号(幂等键,同一商户同一通道下唯一;失败后复用原单号重试) |
| amount | long | 是 | — | 转账金额(分,最小 1 分,最大一亿元) |
| title | string | 否 | 100 | 转账标题 |
| reason | string | 否 | 200 | 转账原因 / 备注 |
| payeeType | string | 是 | 32 | 收款人账号类型(见下方码表) |
| payeeAccount | string | 是 | 100 | 收款人账号 |
| payeeName | string | 否 | 100 | 收款人姓名(微信规则见下方说明) |
| attach | string | 否 | 500 | 商户扩展参数,回调时原样返回 |
| notifyUrl | string | 否 | 200 | 异步通知地址 |
| reportInfos | object[] | 否 | — | 转账场景报备信息(微信转账场景必填,见下方说明) |
| transferScene | string | 否 | 32 | 转账场景标识(支付宝 / 抖音使用,见下方说明) |
payeeType 码表(通道 × 收款人类型)
对应后端枚举 TransferPayeeTypeEnum,各通道支持的取值不同:
| payeeType | 说明 | 微信 | 支付宝 | 抖音 |
|---|---|---|---|---|
| openid | 微信 / 抖音用户 openid | ✅ | — | ✅ |
| user_id | 支付宝用户 ID(2088 开头) | — | ✅ | — |
| open_id | 支付宝 openid | — | ✅ | — |
| login_name | 支付宝登录账号(手机号 / 邮箱) | — | ✅ | — |
| phone | 抖音手机号(复用 payeeAccount 字段上送) | — | — | ✅ |
transferScene 与 reportInfos(通道差异)
| 通道 | transferScene | reportInfos |
|---|---|---|
| 微信 | 不传,使用通道商户配置中绑定的转账场景 | 部分场景必填(如营销奖励类),infoType 为微信协议固定中文(如 活动名称),infoContent 为商户填写内容;留空由通道兜底校验 |
| 支付宝 | 转账场景配置 ID(商户在通道侧开通的转账场景,如 1001 通用转账) | 不使用 |
| 抖音 | 场景枚举码(通道主数据定义,发起时由调用方选择传入,如 1001) | 不使用 |
微信收款人姓名(payeeName)规则
- 转账金额 小于 0.3 元:禁止填写(
payeeName须为空) - 转账金额 大于等于 2000 元:必填(须与收款人实名一致)
- 其余金额段:选填
请求示例
json
{
"mchNo": "M200000001",
"appId": "APP001",
"reqId": "REQ20241201040",
"reqTime": "2024-12-01 12:40:00",
"sign": "Base64签名值",
"channel": "alipay",
"channelMchNo": "2088xxxxxxxxxxxx",
"bizTransferNo": "TRANS20241201001",
"amount": 10000,
"title": "佣金结算",
"reason": "12月推广佣金",
"payeeType": "user_id",
"payeeAccount": "2088yyyyyyyyyyyy",
"transferScene": "1001",
"notifyUrl": "https://your-domain.com/notify"
}响应参数
DaxResult<TransferCreateResult>,data 字段结构:
| 参数 | 类型 | 描述 |
|---|---|---|
| transferNo | string | 平台转账单号 |
| bizTransferNo | string | 商户转账号 |
| status | string | 转账状态(见下方码表;正常返回为 processing 或 success) |
| confirmUrl | string | 确认收款链接(仅微信转账且待收款人确认时返回,发给收款人在微信内打开;平台未配置网关地址时为空) |
转账状态(PayFundStatusEnum)
| status | 说明 |
|---|---|
| init | 初始化(转账单已创建,待上送通道) |
| processing | 处理中(通道受理中 / 微信待收款人确认领取) |
| success | 转账成功 |
| fail | 转账失败(可复用原商户转账号重试) |
| close | 转账关闭(仅通道支持关闭的场景,可通过商户端关单) |
| cancel | 已撤销 |
响应示例
json
{
"code": 0,
"msg": "success",
"data": {
"transferNo": "TF2024120112345700001",
"bizTransferNo": "TRANS20241201001",
"status": "processing"
},
"sign": "Base64签名值",
"resTime": "2024-12-01 12:40:00",
"reqId": "REQ20241201040"
}使用建议
- 发起失败即可重试:通道校验失败(如收款人信息不符、余额不足)时接口返回错误响应,单据已置失败;直接复用原
bizTransferNo重新发起即复用原单重试,无需换单号。 - 微信转账需收款人确认:发起成功返回
processing后,须引导收款人打开confirmUrl(或平台转账确认页)确认领取,超时未领取将由通道退回;可通过 转账同步 查询最终状态。 - 异步通知:转账终态确定后平台按
notifyUrl推送(事件transfer.success/transfer.fail/transfer.close);未收到通知时调用 转账同步 主动拉取。 - 结果查询:调用 转账单查询 获取凭证完整状态;失败单会回填通道侧错误信息(
errorMsg)。