2026-08-25-alipay-batch-pay-design.md 14 KB

批量付款到户有密 接入设计

日期:2026-08-25 状态:已与用户确认(2026-08-25)

1. 背景与目标

将支付宝邀测产品「批量付款到户有密」(批量转账到支付宝账户)接入 xjz-payment-platform。

业务目标:赋能企业客户批量付款 —— 平台代企业制单,企业财务在自己的支付宝端内输入一次支付密码确认,批量付款给外部支付宝账号(发薪、报销、佣金、供应商结算等)。资金不经过平台账户,付款方(企业)掌控资金,安全性高于现有记账本直付链路。

与现有体系的关系:现有资金链路是「支付宝安全发」(签约→进件→开通记账本→充值→单笔转账),与本产品是两个独立产品,并行共存,互不影响。

接入角色:付款方仅限平台入驻的企业客户(企业码场景);平台以企业绑定的服务商 AppID 调用 API(沿用现有 AlipayClientFactory.getClient(enterpriseId, bizType) 模式,资金接口证书加签)。

操作渠道:PC 网页版(制单授权 channel=pc、支付页 PC 版),每批最多 1000 笔。

收款方来源:仅外部支付宝账号(手填或 Excel 导入),不关联平台员工体系。

2. 产品关键约束(来自支付宝邀测文档)

2.1 API 清单

环节 接口 用途
制单授权 alipay.fund.authorize.uni.apply 生成授权短链接(PC/小程序),付款方端内授权
授权查询 alipay.fund.authorize.uni.query 查询单一协议授权状态
授权通知 alipay.fund.authorize.status.notify 签约/解约异步通知(订阅 from 蚂蚁消息)
批次下单 alipay.fund.batch.create 创建批量付款单据
渲染支付 alipay.fund.trans.render.pay 生成 PC/小程序支付页,付款方输密码完成
批次通知 alipay.fund.batch.order.changed 批次状态异步通知
批次查询 alipay.fund.batch.detail.query 批次+明细状态查询(兜底)
批次关单 alipay.fund.batch.close 主动关闭未支付批次
电子回单(二期 alipay.data.bill.ereceiptagent.apply / alipay.data.bill.accountbookereceipt.query 申请/查询回单,本期不做

2.2 关键参数

授权申请(uni.apply)

  • product_code = TRANSFER_API_STANDARD_AUTHORIZATION(固定)
  • biz_scene = STANDARD_CREATE_FUND_ORDER(固定)
  • authorize_link_type = SHORT_URL(固定)
  • channel = pc(PC 网页版)
  • principal_info.participant_id = 付款方支付宝 uid;participant_id_type = ALIPAY_USER_ID
  • 出参:authorize_link(短链接)

批次下单(batch.create)

  • product_code = BATCH_API_TO_ACC(固定);biz_scene = STANDARD_MESSAGE_BATCH_PAY(固定)
  • out_batch_no 商户唯一;total_trans_amounttotal_count
  • order_title 必填(展示在付款方账单);time_expire(绝对时间,格式 yyyy-MM-dd HH:mm
  • payer_info:付款方 uid + ext_info.agreement_no(制单授权协议号,传则校验该协议)
  • trans_order_list[]:每笔 out_biz_no(批内唯一)、trans_amount(≥1 元)、payee_info(identity + identity_type,LOGON_ID 时 name 必填且校验姓名一致)、remark
  • 转账场景报备(26 年新接入商户必传)transfer_scene_name + transfer_scene_report_infos[]info_type + info_content
  • 出参:batch_trans_id(支付宝批次号,有效期 30 天)

渲染支付(render.pay):入参 batch_trans_id,出参支付 URL(PC 版浏览器打开)。

2.3 额度与限制

  • 默认:单笔 5000 / 日 20000 / 月 600000 元;自助提额上限:单笔 50000 / 日 100000 / 月 1000000 元
  • 每批最多 1000 笔(PC 渠道),明细金额 ≥1 元
  • 部分明细因收款账户问题转账失败时,支付宝原路退回该明细金额(明细级别状态跟踪)

2.4 授权特性

  • 授权一旦完成永久生效;终止只能付款方在支付宝 APP 端手动解约
  • 授权链接一次有效,重新授权需换外部单号
  • 同一付款方与平台间已存在授权协议则不允许重复新增
  • 付款方和请求方一致时,跳过制单授权校验

2.5 接入前置条件

  • 邀测产品,需联系支付宝业务人员开通「批量付款到户有密」;商家平台开通「商家转账」产品
  • 应用网关:指向平台统一通知入口(现有 /payment/notify
  • 订阅 from 蚂蚁消息:alipay.fund.authorize.status.notifyalipay.fund.batch.order.changed
  • 资金支出接口强制证书加签(现有服务商资金类客户端已是证书模式)
  • 不支持服务商代开发 —— 由企业绑定服务商 AppID 模式接入(平台代持,已确认)

3. 业务流程

企业财务(PC)                     平台 (Java 后端)                        支付宝
   │                                  │                                     │
   │ ① 打开「制单授权」页面            │                                     │
   │◄─ 授权短链(PC) ──────────────────│─ fund.authorize.uni.apply ──────────►│
   │ 浏览器打开链接                    │                                     │
   │◄════════════ 支付宝授权页 ════════╪══════════════════════════════════════►│
   │ 输密码授权(永久生效,一次一链)   │                                     │
   │◄════════ 授权完成 ────────────────│─ status.notify 异步通知 ────────────►│
   │ ② 创建批次(≤1000笔外部账号)     │  fund.batch.create ─────────────────►│
   │◄─ 支付URL ────────────────────── │─ fund.trans.render.pay(PC) ─────────►│
   │ ③ 新窗口打开支付页                │                                     │
   │◄══════════ 支付宝端输一次密码 ════╪══════════════════════════════════════►│
   │ ④ 查批次列表/明细                 │◄─ fund.batch.order.changed 通知 ─────│
   │                                  │◄─ fund.batch.detail.query 兜底 ──────│

状态流转:批次 INIT(已受理)→ 支付后 SUCCESS(终态)/ 部分明细失败原路退回;DISUSE(关闭,终态,换外部单号重试);批次创建后 30 天未支付自动关单(或 time_expire 控制)。

4. 数据模型(3 张新表)

沿用现有 base entity 体系(PaymentEnterpriseBaseEntity:tenant_id、enterprise_id 等)。

4.1 pay_batch_authorize — 制单授权记录

字段 类型 说明
out_biz_no varchar(64) 授权外部单号(雪花),唯一
enterprise_id varchar(64) 所属企业
participant_id varchar(64) 付款方支付宝 uid
participant_id_type varchar(16) ALIPAY_USER_ID
agreement_no varchar(64) 制单授权协议号(授权完成后回填)
status varchar(32) AUTHING / AUTHED / UNBIND
authorize_link varchar(512) 生成的短链接
authorize_expire_time datetime 链接超时时间

4.2 pay_batch_order — 批次主表

字段 类型 说明
out_batch_no varchar(32) 商户批次唯一单号
batch_trans_id varchar(32) 支付宝批次订单号(唯一索引)
total_amount decimal(16,2) 批次总金额
total_count int 总笔数
order_title varchar(64) 批次标题(账单展示)
status varchar(32) INIT / SUCCESS / DISUSE / FAIL
time_expire datetime 超时关单时间
payer_uid varchar(64) 付款方 uid
agreement_no varchar(64) 制单授权协议号
transfer_scene_name varchar(64) 转账场景(26 年新接入必传)
transfer_scene_report_infos jsonb 场景报备信息 [{info_type, info_content}]
remark varchar(200) 业务备注
pay_url varchar(1024) render.pay 生成的支付 URL
receipt_file_id / receipt_status 电子回单(二期可做)
error_code / error_msg varchar 错误信息

4.3 pay_batch_detail — 批次明细表

字段 类型 说明
batch_id bigint 关联批次主键
out_biz_no varchar(64) 明细外部单号(批内唯一)
amount decimal(16,2) 明细金额(≥1 元)
remark varchar(100) 转账备注(展示在收款方账单)
payee_identity varchar(64) 收款方账号(uid/账号/openid)
payee_identity_type varchar(32) ALIPAY_LOGON_ID / ALIPAY_USER_ID / ALIPAY_OPEN_ID
payee_name varchar(256) 收款方姓名(LOGON_ID 必填,校验姓名一致)
status varchar(32) INIT / SUCCESS / FAIL
error_code / error_msg varchar 明细级错误

5. 后端设计(Java,module/payment/batch/ 新包)

5.1 AlipayBatchPayService

复用 AlipayClientFactory.getClient(enterpriseId, "BATCH_PAY")(服务商证书模式,bizType 走 pay_service_provider_profile 专属凭证,无专属配置回退服务商默认)。

  • authorizeApply(enterpriseId, participantId) → 调 uni.apply,落授权记录,返回短链接
  • queryAuthorize(enterpriseId, outBizNo) → 调 uni.query,更新授权状态
  • batchCreate(BatchCreateDTO) → 校验(授权存在、笔数 ≤1000、金额 ≥1 元、场景报备)→ 调 batch.create → 落批次+明细
    • 幂等:out_batch_no 唯一;返回 UNIQUE_VIOLATION 时查询批次后再决定
  • renderPay(outBatchNo) → 调 render.pay,回填 pay_url
  • batchQuery(outBatchNo) → 调 batch.detail.query,同步批次+明细状态(定时/手动兜底,沿用现有 transferSyncAllService 定时同步模式)
  • batchClose(outBatchNo) → 调 batch.close
  • 通知处理(供 handler 调用):授权状态更新、批次状态更新、明细逐笔更新

5.2 BatchPayController/payment/account/batch/*(挂在现有资金账户模块下)

接口 权限 说明
POST /authorize/apply module_payment:account:authorize 生成授权链接
GET /authorize/query module_payment:account:authorize 查询授权状态
GET /authorize/list module_payment:account:transfer:list 授权列表
POST /create module_payment:account:transfer 创建批次
POST /pay module_payment:account:transfer 生成支付 URL
GET /list module_payment:account:transfer:list 批次列表(分页/状态/时间筛选)
GET /detail module_payment:account:transfer:detail 批次详情+明细
POST /close module_payment:account:transfer 关闭批次
GET /export module_payment:account:transfer:list 导出(复用现有 transferExport 模式)

5.3 异步通知(复用现有入口,零新增端点)

  • AlipayNotifyMethod 枚举新增:FUND_AUTHORIZE_STATUS_NOTIFY("alipay.fund.authorize.status.notify")FUND_BATCH_ORDER_CHANGED("alipay.fund.batch.order.changed")
  • 新增 BatchPayHandler extends BaseNotifyHandler,注册上述两个 method,通过 NotifyContext 注入 batch mapper;处理:授权签约/解约更新授权表、批次状态更新 + 明细逐笔更新 + 记 pay_alipay_notify_log
  • 验签沿用现有 /payment/notify 入口的验签机制(实现时确认 NotificationService 按 app_id 解析公钥的细节)
  • 通知处理幂等:同一 notify_id / 终态不重复更新

6. 前端设计(资金账户模块新增「批量付款」)

  • 制单授权页:生成授权短链接(PC 复制/二维码),授权状态展示,重新授权按钮
  • 批次列表页:分页、状态筛选、时间筛选、导出;行操作:支付(打开支付 URL)、查看详情、关闭
  • 创建批次页:手填明细 / Excel 导入(模板下载:收款账号、类型、姓名、金额、备注);转账场景选择(现金营销/企业退款/佣金报酬/二手回收/业务结算/公益补助/行政补贴退款/保险理赔)+ 报备信息录入
  • 批次详情页:批次信息 + 明细表格(逐笔状态)+ 支付按钮
  • 支付页:pay_url 新窗口打开(支付宝 PC 支付页)

7. 错误处理与幂等

  • 批次创建:out_batch_no 唯一索引;系统异常/未明确错误码时保持原单号重试;UNIQUE_VIOLATION → 查批次状态,已受理则不再重复创建
  • 通知重复:以终态和 notify_id 判重
  • 明细部分失败:支付宝原路退回,明细级状态跟踪,批次状态为 SUCCESS(部分明细 FAIL),列表展示明细级失败原因
  • 授权链接过期/重复授权:提示重新生成(换 out_biz_no)
  • 批次超时:time_expire 控制,DISUSE 终态提示换单重试

8. 测试

  • Java 单测AlipayBatchPayService(Mock 支付宝 SDK 响应):授权申请/查询、批次创建幂等(UNIQUE_VIOLATION)、状态同步、通知处理幂等
  • 前端 Playwright:走通「生成授权链接 → 创建批次(导入明细)→ 生成支付 URL」链路,批次列表/详情渲染
  • 通知 handler 单测:两个新 msg_method 分发正确

9. 前置条件与风险

  • 邀测产品:需联系支付宝业务人员开通;未开通前联调不可行 → 联调用沙箱/文档响应 Mock
  • 转账场景报备为 26 年新接入必传 —— 前端录入 + 后端校验必填
  • 服务商需配置应用网关 + 订阅 from 蚂蚁消息(运营操作,需与客户确认)
  • 授权为永久性协议,平台不可解约 —— 授权管理页需明确提示
  • 额度限制(单笔 5000 默认)可能导致大额批次失败 —— 页面提示查看/调整转账额度