update 更新文档

This commit is contained in:
jsowell
2026-05-28 16:48:01 +08:00
parent 3c68e331fc
commit 380a9053af
3 changed files with 500 additions and 0 deletions

View File

@@ -0,0 +1,456 @@
# 汇付开户 V2 流程与落地计划
## 背景
现有开户页已经从旧组件切到了 `jsowell-charge-ui/src/views/financial/accountUserInfo.vue`,但整体仍偏向“资料展示 + 操作按钮”。新版开户流程需要按汇付官方账户体系重新梳理为状态驱动的流程,明确个人用户、企业用户、结算账户三个对象之间的关系。
官方文档来源:
- 个人用户:<https://docs.adapay.tech/api/trade.html#member-create>
- 企业用户:<https://docs.adapay.tech/api/trade.html#corpmember>
- 结算账户:<https://docs.adapay.tech/api/trade.html#settle-account-create>
## 官方约束摘要
### 个人用户 Member
- 创建用户对象用于将商户侧 `member_id` 与 Adapay 系统关联,`member_id` 需在同一个 `app_id` 下唯一。
- 创建成功后可创建结算账户,用于用户分账。
- 若创建用户对象用于分账功能,官方文档说明 `tel_no``user_name``cert_type``cert_id` 不应上送。
- 当前项目个人开户只上送 `location``email``gender``nickname`,符合分账场景的轻量开户模型。
### 企业用户 CorpMember
- 创建企业用户对象本质是提交企业开户申请,同步返回 `pending` 表示申请已受理。
- 企业开户结果由异步通知返回。审核成功后企业用户创建成功;审核失败后可根据失败原因重新提交。
- 企业开户若同时上送 `bank_code``bank_acct_type``card_no``card_name`,审核成功后汇付会自动创建结算账户。
- 若企业开户未上送银行要素,不会自动创建结算账户,需要后续单独调用结算账户创建接口。
- 企业更新同样同步返回 `pending`,审核结果通过异步通知返回。
- 企业更新不支持修改银行代码、银行账户类型、银行卡号、银行卡开户姓名。结算账户信息变更应先删除结算账户,再使用原 `member_id` 重新创建。
### 结算账户 SettleAccount
- 结算账户用于承接用户分账金额结算,目前仅支持银行卡。
- 创建对私结算账户时会校验银行卡号、银行卡开户姓名、身份证号三要素。
- 结算账户由汇付生成唯一 `id`,用于查询和删除。
- 银行账户类型为 `2-对私` 时,建议绑定 I 类银行卡,否则单次结算超过 10000 元可能失败。
- 22:30 后创建成功的结算账户,结算会延后一个结算日。
- 更新银行卡必须删除原结算账户后重新创建,且需与原结算账户使用的身份证和银行卡户名保持一致。
## V2 产品流程
### 页面入口
入口保持不变:
- 路由:`/financial/merchant/index/:merchantId`
- 页面:`jsowell-charge-ui/src/views/financial/accountUserInfo.vue`
页面进入后只关心一个业务状态:当前运营商的汇付开户进度。
### 状态机
| V2 状态 | 来源判断 | 页面主状态 | 允许操作 |
| --- | --- | --- | --- |
| `NONE` | 无有效 `adapay_member_account` | 未开户 | 创建个人用户、创建企业用户 |
| `PERSONAL_OPENED_NO_SETTLE` | 个人用户已创建,未查询到结算账户 | 个人已开户,待创建结算账户 | 更新个人资料、创建对私结算账户 |
| `PERSONAL_COMPLETED` | 个人用户已创建,且存在结算账户 | 个人开户完成 | 更新个人资料、查看/删除结算账户 |
| `CORP_AUDITING` | 企业用户提交后,汇付 `audit_state=A` 或本地状态待审核 | 企业审核中 | 刷新、查看资料 |
| `CORP_FAILED` | 汇付 `audit_state=B/C` 或本地状态失败 | 企业开户失败 | 查看失败原因、重新提交企业开户 |
| `CORP_OPENED_NO_SETTLE` | 企业 `audit_state=D`,或企业审核通过但无结算账户 | 企业已开户,待创建结算账户 | 更新企业资料、创建对公结算账户 |
| `CORP_COMPLETED` | 企业 `audit_state=E` 或存在结算账户 | 企业开户完成 | 更新企业资料、查看/删除结算账户 |
企业审核状态沿用项目已有枚举:
| 汇付 `audit_state` | 含义 | V2 归类 |
| --- | --- | --- |
| `A` | 待审核 | `CORP_AUDITING` |
| `B` | 审核失败 | `CORP_FAILED` |
| `C` | 开户失败 | `CORP_FAILED` |
| `D` | 开户成功但未创建结算账户 | `CORP_OPENED_NO_SETTLE` |
| `E` | 开户和创建结算账户成功 | `CORP_COMPLETED` |
### 用户可见流程
```mermaid
flowchart TD
A["进入开户页"] --> B["查询开户聚合详情"]
B --> C{"是否已开户"}
C -->|否| D["选择个人/企业开户"]
D -->|个人| E["提交个人资料"]
E --> F["个人开户成功"]
F --> G["创建对私结算账户"]
G --> H["开户完成"]
D -->|企业| I["提交企业资料和附件"]
I --> J["企业审核中"]
J --> K{"审核结果"}
K -->|失败| L["展示失败原因并重新提交"]
L --> J
K -->|成功| M["创建对公结算账户"]
M --> H
C -->|是| N["按状态展示下一步动作"]
```
## 字段映射
### 个人用户创建
当前接口:
- 前端:`createAdapayMember`
- 后端:`POST /adapay/member/createAdapayMember`
- DTO`CreatePersonalMemberDTO`
- 汇付 SDK`Member.create`
| 页面字段 | 后端 DTO | 汇付字段 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| 运营商 ID | `merchantId` | 不直接传汇付 | Y | 后端根据运营商查询 `wechatAppId``app_id` |
| 昵称 | `nickname` | `nickname` | N | 当前页面设为必填,便于运营识别 |
| 性别 | `gender` | `gender` | N | 取值 `MALE` / `FEMALE` |
| 邮箱 | `email` | `email` | N | 当前页面校验邮箱格式 |
| 地址 | `location` | `location` | N | 当前页面设为必填 |
| 汇付会员 ID | 后端生成 | `member_id` | Y | 当前使用 `Constants.ADAPAY_MEMBER_PREFIX + IdUtils.getMemberId()` |
| 应用 ID | 后端配置 | `app_id` | Y | 从 `AdapayConfigFactory` 获取 |
V2 处理原则:
- 保持轻量个人开户,不新增实名字段。
- 个人用户创建成功后,本地 `adapay_member_account.status` 记为成功。
- 页面下一步引导创建对私结算账户。
### 企业用户创建
当前接口:
- 前端:`createCorpMember`
- 后端:`POST /adapay/member/createCorpMember`
- DTO`CreateCorpMemberDTO`
- 汇付 SDK`CorpMember.create`
| 页面字段 | 后端 DTO | 汇付字段 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| 运营商 ID | `merchantId` | 不直接传汇付 | Y | 后端根据运营商查询配置 |
| 企业名称 | `name` | `name` | Y | 长度不超过 50 |
| 省份编码 | `provCode` | `prov_code` | Y | 四位省市编码 |
| 地区编码 | `areaCode` | `area_code` | Y | 四位省市编码 |
| 统一社会信用码 | `socialCreditCode` | `social_credit_code` | Y | 长度 18 |
| 统一社会信用证有效期 | `socialCreditCodeExpires` | `social_credit_code_expires` | Y | `YYYYMMDD` |
| 经营范围 | `businessScope` | `business_scope` | Y | 长度不超过 200 |
| 法人姓名 | `legalPerson` | `legal_person` | Y | 长度不超过 20 |
| 法人身份证号 | `legalCertId` | `legal_cert_id` | Y | 长度不超过 20 |
| 法人身份证有效期 | `legalCertIdExpires` | `legal_cert_id_expires` | Y | `YYYYMMDD` |
| 法人手机号 | `legalMp` | `legal_mp` | Y | 11 位手机号 |
| 企业地址 | `address` | `address` | Y | 长度不超过 256 |
| 邮编 | `zipCode` | `zip_code` | N | 长度 6 |
| 企业电话 | `telphone` | `telphone` | N | 长度不超过 30 |
| 企业邮箱 | `email` | `email` | N | 长度不超过 40 |
| 附件列表 | `imgList` | `attach_file` | Y | 后端压缩为 zip 上传,最大 9 MB |
| 汇付会员 ID | 后端生成 | `member_id` | Y | 当前使用 `Constants.ADAPAY_CORP_MEMBER_PREFIX + IdUtils.getMemberId()` |
| 请求订单号 | 后端生成 | `order_no` | Y | 需保证同 `app_id` 下唯一 |
| 异步通知地址 | 后端配置 | `notify_url` | N | 当前使用 `ADAPAY_CALLBACK_URL` |
企业附件要求:
| 附件 | 当前页面 upload key | 汇付要求 |
| --- | --- | --- |
| 法人身份证正面 | `idCardFace` | 法人身份证正面照 |
| 法人身份证反面 | `idCardBack` | 法人身份证反面照 |
| 开户许可证 | `bankLicense` | 开户银行许可证照 |
| 营业执照 | `businessLicense` | 三证合一证件照 |
V2 处理原则:
- 企业开户阶段不随开户上送银行字段,避免审核成功后自动创建结算账户,统一改为审核通过后手动创建结算账户。
- 提交成功后页面展示“审核中”,不提示开户完成。
- 异步回调成功后再进入“待创建结算账户”或“已完成”状态。
### 结算账户创建
当前接口:
- 前端:`createSettleAccount`
- 后端:`POST /adapay/member/createSettleAccount`
- DTO`CreateSettleAccountDTO`
- 汇付 SDK`SettleAccount.create`
| 页面字段 | 后端 DTO | 汇付字段 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| 运营商 ID | `merchantId` | 不直接传汇付 | Y | 后端查询当前汇付会员 |
| 账户类型 | `bankAcctType` | `account_info.bank_acct_type` | Y | `1-对公``2-对私` |
| 银行卡号 | `cardId` | `account_info.card_id` | Y | 当前后端同时保留 `cardNo`V2 统一使用 `cardId` |
| 户名 | `cardName` | `account_info.card_name` | Y | 对公时必须与企业名称一致 |
| 身份证号 | `certId` | `account_info.cert_id` | 对私必填 | 对私三要素认证使用 |
| 证件类型 | `certType` | `account_info.cert_type` | N | 默认 `00-身份证` |
| 手机号 | `telNo` | `account_info.tel_no` | Y | 银行预留手机号 |
| 银行编码 | `bankCode` | `account_info.bank_code` | Y | 取银行编码列表 |
| 省份编码 | `provCode` | `account_info.prov_code` | Y | 开户银行省份 |
| 地区编码 | `areaCode` | `account_info.area_code` | Y | 开户银行地区 |
| 渠道 | 后端固定 | `channel` | Y | 固定 `bank_account` |
| 汇付会员 ID | 后端查询 | `member_id` | Y | 当前运营商绑定的汇付会员 |
| 应用 ID | 后端配置 | `app_id` | Y | 从汇付配置获取 |
V2 处理原则:
- 个人用户默认创建 `2-对私` 结算账户。
- 企业用户默认创建 `1-对公` 结算账户。
- 按官方 account_info 字段说明V2 前端应收集 `bankCode``provCode``areaCode`,包括对私账户也建议保留,减少生产环境参数不完整风险。
- 创建前后端都校验“当前会员不能已有结算账户”。
### 企业用户更新
当前接口:
- 前端:`updateAdapayMember`
- 后端:`POST /adapay/member/updateAdapayMember`
- DTO`UpdateCorpMemberDTO`
- 汇付功能号:`corp_members.update`
| 页面字段 | 汇付字段 | 必填 | V2 说明 |
| --- | --- | --- | --- |
| 企业基础信息 | `name``prov_code``area_code``business_scope` 等 | N | 仅用于企业资料变更 |
| 法人信息 | `legal_person``legal_cert_id``legal_cert_id_expires``legal_mp` | N | 更新后进入审核流程 |
| 附件 | `attach_file` | N | 当前实现要求重新上传四张附件V2 可继续要求,降低资料不一致风险 |
| 通知地址 | `notify_url` | N | 建议补齐,确保更新审核结果也能回调 |
V2 处理原则:
- 企业资料更新不处理银行卡信息。
- 若要换银行卡,走“删除结算账户 -> 重新创建结算账户”流程。
- 企业更新提交成功后页面进入 `CORP_AUDITING`,等待回调或主动刷新。
### 个人用户更新
当前接口:
- 前端:`updateAdapayMember`
- 后端根据 `adapayMemberId` 前缀判断后调用 `Member.update`
| 页面字段 | 汇付字段 | V2 说明 |
| --- | --- | --- |
| 昵称 | `nickname` | 保留 |
| 性别 | `gender` | 保留 |
| 邮箱 | `email` | 保留 |
| 地址 | `location` | 保留 |
V2 处理原则:
- 个人更新不改变开户状态。
- 若未来引入禁用用户,需单独设计 `disabled` 操作,不混入普通资料更新。
## 后端落地计划
### 1. 新增 V2 聚合响应模型
建议新增:
- `AdapayMemberOpenV2VO`
- `AdapayOpenStatusEnum`
- `AdapayOpenActionEnum`
响应结构建议:
```json
{
"merchantId": "1",
"status": "CORP_OPENED_NO_SETTLE",
"memberType": "CORP",
"adapayMemberId": "ACM29102732",
"auditState": "D",
"auditDesc": "",
"settleAccountStatus": "NONE",
"primaryAction": "CREATE_SETTLE_ACCOUNT",
"actions": [
"REFRESH",
"UPDATE_CORP_MEMBER",
"CREATE_SETTLE_ACCOUNT"
],
"member": {},
"settleAccount": null,
"tips": []
}
```
### 2. 新增 V2 查询接口
建议新增接口,不破坏现有页面调用:
- `POST /adapay/member/v2/detail`
职责:
- 查询 `adapay_member_account` 当前有效记录。
- 判断个人/企业用户类型。
- 查询汇付会员详情。
- 查询结算账户详情。
- 汇总 V2 状态、主操作、可用动作、提示信息。
### 3. 状态计算集中到后端
当前前端通过 `memberType``auditState``settleAccountList` 自行判断V2 改为后端统一计算。
建议规则:
- 无本地记录:`NONE`
- 个人 + 无结算账户:`PERSONAL_OPENED_NO_SETTLE`
- 个人 + 有结算账户:`PERSONAL_COMPLETED`
- 企业 + `audit_state=A``CORP_AUDITING`
- 企业 + `audit_state=B/C` 或本地 `status=2``CORP_FAILED`
- 企业 + `audit_state=D` 或审核通过但无结算账户:`CORP_OPENED_NO_SETTLE`
- 企业 + `audit_state=E` 或有结算账户:`CORP_COMPLETED`
### 4. 本地表状态增强
当前 `adapay_member_account.status` 只有:
- `0` 待审核
- `1` 审核通过
- `2` 创建失败
V2 建议新增字段,避免只靠 `remark` 存失败信息:
```sql
alter table adapay_member_account
add column audit_state varchar(8) null comment '汇付企业审核状态 A/B/C/D/E',
add column audit_desc varchar(512) null comment '汇付企业审核说明',
add column last_order_no varchar(64) null comment '最近一次企业开户/更新请求订单号';
```
兼容策略:
- 不强制迁移历史数据。
- 查询时优先使用汇付实时查询结果。
- 若汇付查询失败,再使用本地 `status``remark` 兜底。
### 5. 企业回调更新
现有回调处理在 `OrderService.corpMemberFailed``OrderService.corpMemberSucceeded`
V2 调整:
- 成功回调:写入 `audit_state``audit_desc``status=1`
- 失败回调:写入 `audit_state``audit_desc``status=2`
- 若回调中包含结算账户 ID同步写入 `settle_account_id`
- 清理 `ADAPAY_MEMBER_ACCOUNT + merchantId` 缓存。
### 6. 创建/更新动作校验
后端服务层统一校验:
- `CREATE_PERSONAL_MEMBER`:仅 `NONE` 可执行。
- `CREATE_CORP_MEMBER`:仅 `NONE``CORP_FAILED` 可执行。
- `UPDATE_PERSONAL_MEMBER`:仅个人已开户状态可执行。
- `UPDATE_CORP_MEMBER`:仅企业非审核中状态可执行。
- `CREATE_SETTLE_ACCOUNT`:仅已开户且无结算账户可执行;企业必须非审核中、非失败。
- `DELETE_SETTLE_ACCOUNT`:仅已有结算账户可执行,且需确认不会影响未结算分账。
## 前端落地计划
### 1. API 封装
`jsowell-charge-ui/src/api/adapayMember/adapayMember.js` 增加:
```js
export function getAdapayOpenDetailV2(data) {
return request({
url: '/adapay/member/v2/detail',
method: 'post',
data
})
}
```
### 2. 页面结构
`accountUserInfo.vue` 调整为:
1. 顶部状态总览:显示当前 V2 状态、汇付会员 ID、审核状态、结算账户状态。
2. 流程步骤条:未开户、提交资料、审核、结算账户、完成。
3. 主操作区:只渲染后端返回的 `primaryAction``actions`
4. 会员资料区:个人/企业按字段分组展示。
5. 结算账户区:独立展示,包含删除后重建提示。
6. 失败原因区:企业失败时展示 `auditDesc`,并给出重新提交入口。
### 3. 表单调整
个人开户表单:
- 昵称
- 性别
- 邮箱
- 地址
企业开户表单:
- 企业主体
- 法人信息
- 联系信息
- 附件上传
结算账户表单:
- 账户类型
- 银行卡号
- 户名
- 身份证号
- 手机号
- 银行编码
- 省份/地区
### 4. 交互规则
- 状态由后端响应驱动,前端不再手写复杂判断。
- 企业审核中:禁用更新、结算账户创建、重复提交。
- 企业失败:主按钮为“重新提交企业开户”。
- 企业成功但无结算账户:主按钮为“创建对公结算账户”。
- 个人无结算账户:主按钮为“创建对私结算账户”。
- 结算账户删除前提示:删除后支付分账将不可用,需重新创建后恢复。
## 分阶段实施清单
### 阶段一:后端状态与接口
- [ ] 新增 `AdapayOpenStatusEnum``AdapayOpenActionEnum`
- [ ] 新增 V2 聚合 VO。
- [ ] 新增 `/adapay/member/v2/detail` 接口。
- [ ]`AdapayService` 中增加状态计算方法。
- [ ] 后端统一动作校验,避免前端绕过状态限制。
### 阶段二:企业审核状态持久化
- [ ] 新增数据库字段 `audit_state``audit_desc``last_order_no`
- [ ] 更新 `AdapayMemberAccount` domain、mapper、XML。
- [ ] 调整企业创建、企业更新逻辑,记录 `last_order_no`
- [ ] 调整回调处理,写入审核状态和说明。
- [ ] 清理相关 Redis 缓存。
### 阶段三:前端 V2 页面
- [ ] 新增 V2 聚合查询 API。
- [ ] 改造 `accountUserInfo.vue` 数据源为 V2 detail。
- [ ] 增加状态步骤条和主操作区。
- [ ]`actions` 渲染按钮。
- [ ] 调整结算账户表单,补齐银行编码、省份、地区采集。
- [ ] 企业失败态展示审核说明并支持重新提交。
### 阶段四:回归与联调
- [ ] 无开户记录 -> 创建个人用户 -> 创建对私结算账户。
- [ ] 无开户记录 -> 创建企业用户 -> 审核中展示。
- [ ] 企业审核失败 -> 展示失败原因 -> 重新提交。
- [ ] 企业审核成功但无结算账户 -> 创建对公结算账户。
- [ ] 已有结算账户 -> 禁止重复创建。
- [ ] 删除结算账户 -> 重新创建结算账户。
- [ ] 个人资料更新后刷新展示一致。
- [ ] 企业资料更新后进入审核中,回调后状态正确。
## 需要确认的问题
1. 企业开户 V2 是否确定不使用汇付“开户时自动创建结算账户”的能力?本计划建议不使用,统一手动创建,流程更清晰。
回答:确定不使用。
2. 企业资料更新后是否必须重新上传四张附件?官方为非必填,但当前系统要求重传;本计划建议继续重传。
回答:确定继续重传。
3. 个人结算账户是否也强制填写银行编码、省份、地区?官方 account_info 字段说明为非空字段,本计划建议 V2 补齐采集。
回答:确定补齐采集。
4. 删除结算账户前是否需要校验未结算分账/在途提现?本计划建议后续补一层业务校验。
回答:需要校验 。

View File

@@ -0,0 +1,41 @@
# 汇付开户流程优化
原来的开户流程不够清晰易用现在打算重新理一遍逻辑开发出汇付开户V2版本下面我列一下基本逻辑以及需求
## 创建用户
汇付的用户分两个类型,个人用户和企业用户
个人用户为对私的,不需要审核
企业用户为对公的,需要审核
### 个人用户
文档地址https://docs.adapay.tech/api/trade.html#member-create
#### 创建个人用户对象
创建用户对象用于将商户 member_id 与 Adapay 系统做关联,商户需要保证 member_id 在应用 app_id 下唯一。关联完成后, 可以创建结算账户用于用户分账功能。
注:若历史已创建结算账户成功的 member_id则可以直接使用收银台对象功能。
### 企业用户
文档地址https://docs.adapay.tech/api/trade.html#corpmember
#### 创建企业用户对象
创建企业用户对象是将商户 member_id 与 Adapay 系统做关联,商户需要保证 member_id 在应用 id 下唯一。 创建企业用户对象实际是发起企业用户申请,同步返回 pending 状态表示申请已受理,人工审核后,审核成功或失败结果会 异步消息通知 告知。
审核成功,则创建企业用户对象成功;审核失败,您可根据审核失败原因修改对应要素,重新调用创建企业用户对象发起申请。
创建企业用户对象若上送了银行代码、银行账户类型、银行卡号、银行卡开户姓名要素时人工审核成功后Adapay 系统自动创建企业用户结算账户对象;若未上送,则不会自动创建结算账户对象,但您可调用创建结算账户对象单独创建结算账户。
当银行账户类型为2-对私时,请务必绑定一张 Ⅰ类 银行卡,若绑定了一张 Ⅱ类 银行卡时当结算金额超过10000元时银行会提示金额超限导致结算失败。
### 结算账户
#### 创建结算账户对象
创建结算账户对象是为一个已创建用户对象创建结算账户,用于对用户分账金额的结算,目前仅支持绑定银行卡结算账户。
用户创建对私结算账户时,会对银行卡号、银行卡开户姓名、身份证号三要素认证,若认证失败,则创建结算账户失败。
每个结算账户对象 Adapay 系统会生成一个唯一的 id可用于查询结算账户对象或者删除结算账户对象。
当银行账户类型为2-对私时,请务必绑定一张 Ⅰ类 银行卡,若绑定了一张 Ⅱ类 银行卡时当结算金额超过10000元时银行会提示金额超限导致结算失败。
若创建结算账户对象是在2230分之后创建成功的那么该用户的结算会延后一个结算日结算若是在2230分之前用户会正常结算。
注:若用户想更新银行卡,则需要先调用删除结算账户对象,再使用原 member_id 重新创建结算账户对象,且必须与原创建结算账户使用的身份证和银行卡户名保持一致。