mirror of
https://codeup.aliyun.com/67c68d4e484ca2f0a13ac3c1/ydc/jsowell-charger-web.git
synced 2026-06-11 18:59:51 +08:00
535 lines
24 KiB
Markdown
535 lines
24 KiB
Markdown
# 汇付开户 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. 交互规则
|
||
|
||
- 状态由后端响应驱动,前端不再手写复杂判断。
|
||
- 企业审核中:禁用更新、结算账户创建、重复提交。
|
||
- 企业失败:主按钮为“重新提交企业开户”。
|
||
- 企业成功但无结算账户:主按钮为“创建对公结算账户”。
|
||
- 个人无结算账户:主按钮为“创建对私结算账户”。
|
||
- 结算账户删除前提示:删除后支付分账将不可用,需重新创建后恢复。
|
||
|
||
## Review 待修复计划
|
||
|
||
### 问题一:结算账户创建成功后缓存未失效
|
||
|
||
风险:
|
||
|
||
- `createSettleAccount` 成功写入 `settle_account_id` 后,当前使用 `updateAdapayMemberAccountByMemberId` 更新本地记录。
|
||
- `updateAdapayMemberAccountByMemberId` 只更新数据库,没有清理 `ADAPAY_MEMBER_ACCOUNT + merchantId` 缓存。
|
||
- `/adapay/member/v2/detail` 继续读取旧缓存时,页面可能仍显示“未创建结算账户”,导致状态停留在 `PERSONAL_OPENED_NO_SETTLE` 或 `CORP_OPENED_NO_SETTLE`。
|
||
|
||
修改计划:
|
||
|
||
- 在 `AdapayMemberAccountServiceImpl.updateAdapayMemberAccountByMemberId` 中补齐缓存清理。
|
||
- 优先使用传入对象的 `merchantId` 清理缓存。
|
||
- 若调用方只传 `adapayMemberId`,则先按 `adapayMemberId` 查询当前记录,拿到 `merchantId` 后清理缓存。
|
||
- 调整 `AdapayService.createSettleAccount`、`changeBankCard` 等调用点,尽量在更新对象中补充 `merchantId`,减少额外查询。
|
||
|
||
验收标准:
|
||
|
||
- 创建结算账户成功后,立即刷新 V2 页面,状态应变为 `PERSONAL_COMPLETED` 或 `CORP_COMPLETED`。
|
||
- 结算账户 ID、银行卡信息能立即展示,不依赖 Redis 过期。
|
||
|
||
### 问题二:删除结算账户缺少业务阻断校验
|
||
|
||
风险:
|
||
|
||
- 文档已确认删除结算账户前需要校验未结算分账/在途提现。
|
||
- 当前 `deleteSettleAccount` 只校验 V2 action 和结算账户是否存在,随后直接调用汇付删除并清空本地结算账户。
|
||
- 若存在未结算分账或在途提现,删除结算账户会影响后续结算、提现或分账状态追踪。
|
||
|
||
修改计划:
|
||
|
||
- 在 `AdapayService.deleteSettleAccount` 调用汇付删除前增加业务校验方法,例如 `assertSettleAccountCanDelete(merchantId)`。
|
||
- 校验维度先按现有数据能力落地,明确数据源和阻断状态:
|
||
- 在途提现:查询 `clearing_withdraw_info`,若存在 `withdraw_status = '0'` 的记录,阻断删除。
|
||
- 清分账单:查询 `clearing_bill_info`,若存在 `bill_status in ('0', '1', '3', '5')` 的记录,阻断删除,分别对应未清分、清分在途、提现申请中、等待处理。
|
||
- 未分账订单:查询 `order_unsplit_record`,若存在 `status = 'unsplit'` 且订单归属当前 `merchantId` 的记录,阻断删除。
|
||
- 为未分账订单补齐按商户查询能力:
|
||
- 在 `OrderUnsplitRecordMapper` 新增 `countUnsplitByMerchantId(merchantId)`。
|
||
- SQL 通过 `order_unsplit_record.order_code` 关联 `order_basic_info.order_code`,按 `order_basic_info.merchant_id` 过滤当前商户。
|
||
- 在 `OrderUnsplitRecordService` 增加同名方法,供 `AdapayService.assertSettleAccountCanDelete` 调用。
|
||
- 为提现和清分账单尽量使用轻量查询:
|
||
- 优先新增 `ClearingWithdrawInfoService.countProcessingByMerchantId(merchantId)`,只统计 `withdraw_status = '0'`。
|
||
- 优先新增 `ClearingBillInfoService.countBlockingByMerchantId(merchantId)`,只统计 `bill_status in ('0', '1', '3', '5')`。
|
||
- 若已有列表查询能满足,可先复用现有方法,但最终实现应避免在删除前加载大量历史记录。
|
||
- 阻断时返回明确错误信息,例如“存在在途提现,请完成后再删除结算账户”或“存在未结算分账,请完成结算后再删除结算账户”。
|
||
- 前端保留现有确认弹窗,但以后端校验结果作为最终准入。
|
||
|
||
验收标准:
|
||
|
||
- 无在途提现、无未结算分账时,可以删除结算账户并清空本地 `settle_account_id`。
|
||
- 存在 `withdraw_status = '0'` 的提现记录时,删除接口返回业务错误,汇付删除请求不会发起,本地结算账户不会清空。
|
||
- 存在 `bill_status in ('0', '1', '3', '5')` 的清分账单时,删除接口返回业务错误,汇付删除请求不会发起,本地结算账户不会清空。
|
||
- 存在 `status = 'unsplit'` 且归属当前商户的未分账订单时,删除接口返回业务错误,汇付删除请求不会发起,本地结算账户不会清空。
|
||
|
||
### 问题三:删除汇付用户未接入 V2 action 后端校验
|
||
|
||
风险:
|
||
|
||
- V2 计划要求后端统一动作校验,避免绕过前端按钮限制。
|
||
- 当前创建、更新、创建/删除结算账户已接入 `assertActionAllowed`。
|
||
- `deleteAdapayMember` 未校验 `DELETE_MEMBER`,直接调用接口时可能删除企业审核中的本地记录,导致后续汇付回调无法匹配记录。
|
||
|
||
修改计划:
|
||
|
||
- 在 `AdapayService.deleteAdapayMember` 开始处增加 `assertActionAllowed(dto.getMerchantId(), AdapayOpenActionEnum.DELETE_MEMBER)`。
|
||
- 保留现有 `adapayMemberId` 一致性校验和“需先删除结算账户”校验,作为二次保护。
|
||
- 确认 `resolveActions` 中仅允许以下状态删除会员:
|
||
- `PERSONAL_OPENED_NO_SETTLE`
|
||
- `CORP_FAILED`
|
||
- 若后续业务允许更多状态删除,再由状态机统一扩展,不在接口中散落判断。
|
||
|
||
验收标准:
|
||
|
||
- 企业审核中状态调用删除汇付用户接口,应返回“不允许执行删除”类业务错误。
|
||
- 企业失败且无结算账户时,可以删除本地失败记录。
|
||
- 个人已开户但未创建结算账户时,可以删除本地会员记录。
|
||
- 已有结算账户时仍必须先删除结算账户。
|
||
|
||
## 分阶段实施清单
|
||
|
||
### 阶段一:后端状态与接口
|
||
|
||
- [ ] 新增 `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. 删除结算账户前是否需要校验未结算分账/在途提现?本计划建议后续补一层业务校验。
|
||
回答:需要校验 。
|