From 380a9053af0cb2991316f1faf4515f75e6685569 Mon Sep 17 00:00:00 2001 From: jsowell <123@jsowell.com> Date: Thu, 28 May 2026 16:48:01 +0800 Subject: [PATCH] =?UTF-8?q?update=20=E6=9B=B4=E6=96=B0=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/汇付开户V2流程计划.md | 456 ++++++++++++++++++ docs/汇付开户流程优化.md | 41 ++ .../AdapayUnsplitRecordHandleServiceImpl.java | 3 + 3 files changed, 500 insertions(+) create mode 100644 docs/汇付开户V2流程计划.md create mode 100644 docs/汇付开户流程优化.md diff --git a/docs/汇付开户V2流程计划.md b/docs/汇付开户V2流程计划.md new file mode 100644 index 000000000..789cf3655 --- /dev/null +++ b/docs/汇付开户V2流程计划.md @@ -0,0 +1,456 @@ +# 汇付开户 V2 流程与落地计划 + +## 背景 + +现有开户页已经从旧组件切到了 `jsowell-charge-ui/src/views/financial/accountUserInfo.vue`,但整体仍偏向“资料展示 + 操作按钮”。新版开户流程需要按汇付官方账户体系重新梳理为状态驱动的流程,明确个人用户、企业用户、结算账户三个对象之间的关系。 + +官方文档来源: + +- 个人用户: +- 企业用户: +- 结算账户: + +## 官方约束摘要 + +### 个人用户 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. 删除结算账户前是否需要校验未结算分账/在途提现?本计划建议后续补一层业务校验。 +回答:需要校验 。 + diff --git a/docs/汇付开户流程优化.md b/docs/汇付开户流程优化.md new file mode 100644 index 000000000..e214a2b03 --- /dev/null +++ b/docs/汇付开户流程优化.md @@ -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元时,银行会提示金额超限导致结算失败。 + +注:若创建结算账户对象是在22:30分之后创建成功的,那么该用户的结算会延后一个结算日结算;若是在22:30分之前,用户会正常结算。 + +注:若用户想更新银行卡,则需要先调用删除结算账户对象,再使用原 member_id 重新创建结算账户对象,且必须与原创建结算账户使用的身份证和银行卡户名保持一致。 \ No newline at end of file diff --git a/jsowell-quartz/src/main/java/com/jsowell/quartz/service/impl/AdapayUnsplitRecordHandleServiceImpl.java b/jsowell-quartz/src/main/java/com/jsowell/quartz/service/impl/AdapayUnsplitRecordHandleServiceImpl.java index ac53c8fea..93e58dfc4 100644 --- a/jsowell-quartz/src/main/java/com/jsowell/quartz/service/impl/AdapayUnsplitRecordHandleServiceImpl.java +++ b/jsowell-quartz/src/main/java/com/jsowell/quartz/service/impl/AdapayUnsplitRecordHandleServiceImpl.java @@ -160,15 +160,18 @@ public class AdapayUnsplitRecordHandleServiceImpl implements AdapayUnsplitRecord } if (dueRefundAmount.compareTo(BigDecimal.ZERO) > 0 && !ensureRefundBeforeSplit(item, wechatAppId)) { + syncAndRefreshFlagsFromAdapay(paymentId, wechatAppId); return ItemResult.SKIPPED; } if (waitSplitAmount.compareTo(BigDecimal.ZERO) <= 0) { + syncAndRefreshFlagsFromAdapay(paymentId, wechatAppId); return ItemResult.SKIPPED; } BigDecimal confirmAmt = getLatestConfirmAmount(waitSplitAmount, item.getPayAmount(), item.getRefundAmount(), paymentId, wechatAppId); if (confirmAmt.compareTo(BigDecimal.ZERO) <= 0) { + syncAndRefreshFlagsFromAdapay(paymentId, wechatAppId); return ItemResult.SKIPPED; }