yeg
2026-09-17 6ad28d8b0d2a961c806033056b904e475c7fcbdf
docs(scratch): 留档汇付关闭商户后商户端与收款闸门的表现

结论:商户端「商户进件」页会依旧显示关闭前那张截图——GET /status 是纯读库、进件进度快照只有
「刷新进度」才写、而 approved 后该按钮在商户端是隐藏的,也没有定时任务刷它。

真正会变的是收款能力:它读 merchant_onboarding_application 上的另一份通道快照,
由 MerchantPaymentCapabilityScheduler 每 30 分钟扫、只刷超过 6 小时的申请,因此关闭商户后
最长约 6 小时才会在本地下单时被拦下(斗拱子商户状态异常 / 取现能力不可用 / 微信收款能力未就绪)。
登录、营业状态、订单列表与首页统计不受影响;核销本身不校验就绪,但核销后的交易确认能否成功
需实测,属支付链路。

同时留档两处已确认的体验缺陷(本轮按用户要求不改代码):
一是进件页会出现「六项全已确认、标题却说待办理」,因为 merchantNormal/bank 不在展示的六项里;
二是 approved 后没有只读的收款能力自查入口,进件页状态与真实收款能力会长期不一致。
1个文件已添加
109 ■■■■■ 已修改文件
.scratch/merchant-closure-impact/issues/huifu-merchant-closure-impact.md 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.scratch/merchant-closure-impact/issues/huifu-merchant-closure-impact.md
New file
@@ -0,0 +1,109 @@
# 在汇付合作伙伴控台关闭商户后,我们这边会怎样
状态:**仅留档,不改代码**。下面「遗留一 / 遗留二」是已确认的体验缺陷,用户明确本轮不动。
汇付的说法:控台关闭商户后该商户的所有支付相关功能受限,无法继续收款,微信/支付宝等已开通能力不可用;
恢复需要在控台重新启用商户。
## 结论速览
1. **商户端的「商户进件」页会依旧显示关闭前那张截图**("商户进件已完成" + 六项全"已确认")。
   不是因为它还正常,而是那页读的是本地存的快照,且 approved 之后商户自己点不到"刷新进度"。
2. **真正会变的是「能不能收款」**,它读的是另一份快照、由另一个定时任务刷新,最迟约 6 小时后生效,
   表现是商户/人才在**创建订单的那一刻**被拒,而不是进件页出提示。
3. 登录、营业状态(营业中/休息中)、订单列表、首页统计都不受影响。
4. 核销本身不做就绪校验;核销后的**交易确认能不能过是未知项**,需实测(属支付链路)。
## 证据:进件页为什么不变
- `GET /api/merchant/onboarding/status` 是纯读库,不查汇付:
  `MerchantSettlementService.onboardingStatus`(`MerchantSettlementService.java:111`)只按
  `merchant_id + store_id` 取最新一条 `initial_bank_card_id is not null` 的申请,然后交给
  `MerchantOnboardingProgressService.view`。页面打开多少次都不会去问通道。
- 该页状态由 `complete(stages)`决定(`MerchantOnboardingProgressService.java:183`):
  要求 `bank == true`、`merchantNormal == true`、以及六项全部 `confirmed`。
  `merchantNormal` 来自通道查询的 `mer_stat`(同文件 68 行)。
- `stages_json` 只有"刷新进度"才会写。可达路径只有三条,都不是自动的:
  - `POST /api/merchant/onboarding/refresh` —— 商户端"刷新进度"按钮;
  - `MerchantSettlementAdminService.refreshOnboarding` —— 后台手动;
  - `MerchantSettlementService.refreshRecoveryAfterCommit` —— 回调 / 重新提交等内部路径。
- 而 approved 之后,商户端那个按钮是隐藏的:
  `rencaika_merchant/pages/merchant-onboarding-pending/merchant-onboarding-pending.uvue:77`
  的 `canRefresh = refreshable && onboardingStatus != 'approved'`。
- 全仓四个 `@Scheduled`(`MerchantPaymentCapabilityScheduler`、`PaymentFundConfirmationRetry`、
  `PendingOrderExpiryScheduler`、`PaymentReconciliationScheduler`)**没有一个**刷进件进度快照。
所以:关闭商户只影响通道侧,我们的申请状态仍是 `approved`,进件页也就一直是截图那样。
## 证据:会变的是收款闸门
判定"这个商户现在能不能收钱"的是 `MerchantPaymentReadinessService.readiness`,它读的是
**另一份快照**——`merchant_onboarding_application` 上的 `merchant_stat / cash_switch_status /
auto_settle_status / capability_verified_at`:
- 刷新时机:`MerchantPaymentCapabilityScheduler` 每 30 分钟扫一次,只刷
  `capability_verified_at` 超过 6 小时的申请(`application.yml:126-129`,
  `HUIFU_CAPABILITY_STALE_HOURS` 默认 6)。后台管理员点一次能力刷新
  (`MerchantSettlementAdminService.refreshPaymentCapability`)可立刻刷新。
- 因此存在一个**最长约 6 小时的空窗**:这段时间我们这边仍认为可收款、允许下单,
  失败会推迟到真正发起支付时由通道拒绝(这一段的表现属支付链路,未实测)。
- 刷新后按命中顺序报错(`MerchantPaymentReadinessService.java`):
  - `mer_stat` 非 `NORMAL` → `斗拱子商户状态异常(XXX),暂时无法收款`(159-160 行,
    `isMerchantNormal` 在 296 行:空值或 `NORMAL` 视为正常);
  - 取现/结算开关被改 → `商户取现能力不可用,暂时无法收款`;
  - 微信业务配置被回收 → `微信收款能力未就绪:…`(`missingWechatCapabilities`,282 行,
    读的是进件进度里的 `wechat` / `realname` 两项);
  - 快照完全没核实过 → `商户收款能力待确认,暂时无法收款`。
- 闸门挂在哪:`OrderService.java:50`(订单 `payAmount > 0` 时取收款子商户)与
  `ManualConsumptionService.java:79`(商户端扫人才码的到店消费单)。两条路径都是
  `requireCollectingMerchant` 抛 `409 CONFLICT`,商户端/人才端以 toast 显示上面那条文案。
- 这套判定只在通道校验开启时成立:`providerVerificationRequired()` = `merchantCapabilityRequired`
  (`HUIFU_MERCHANT_CAPABILITY_REQUIRED` 默认 true,未配置时回落到 `enabled`)。
  本地把汇付关掉时走 `localOnly`,不查通道,"关闭商户"在本地看不出来。
## 不受影响
- **登录**:`business/merchant/auth/` 下没有任何 readiness 校验,登录照常。
- **营业状态**:小程序里的"营业中/休息中"是商户自己的开关(`MerchantManagementService.isBusinessOpen`),
  与通道状态无关。
- **订单列表、首页统计**:不读通道状态;首页交易总额仍按已核销口径统计(见
  `../../order-payment-display/issues/bug-1-merchant-dashboard-total.md`)。
## 未定死的一点
**核销**:`MerchantVerificationService` 不查 readiness,所以已支付订单在本地仍可核销成功;
但核销会触发交易确认(`PaymentFundConfirmationService` 调通道),关闭商户下这笔交易确认能否成功、
钱是否还留在延迟户,代码里看不出来,**需要实测**。若实测失败,属支付链路范围,
按仓库约定整理现象/根因/证据/建议改法交给该业务负责人,不跨域改。
## 遗留一:进件页会出现"六项全已确认,标题却说待办理"的矛盾态
一旦某次刷新发现 `merchantNormal == false`,`complete()` 不成立,页面变成
`收款能力开通中` + `请刷新进度核实各项能力,并按待办理项补齐缺失能力`;
但展示用的 `LABELS` 只有六项(basic/wechat/appId/realname/delay/settlement,
`MerchantOnboardingProgressService.java:19`),`merchantNormal` 与 `bank` 不在其中,
商户看不到到底缺哪一项,只会以为是页面出错。
建议改法(本轮不动):把 `merchantNormal`(通道商户状态)与 `bank`(结算银行卡核实)也作为
可展示的阶段返回给商户端,或对"商户被通道停用"这一类单独给一句能自解释的文案
(例如"通道商户状态异常,请联系汇付或后台处理"),不要让"待办理 + 六项全绿"同时出现。
## 遗留二:approved 之后没有自查手段,进件页状态与收款能力长期不一致
`canRefresh` 在 approved 时恒为 false,又没有定时刷新进件进度,所以进件页会一直显示
"已完成",而收款可能早已被闸门拦下;商户对环境变化的感知完全依赖"下一次下单被拒"。
建议改法(本轮不动,需产品确认):给已 approved 的商户一个只读的"收款能力"自查入口
(例如商户中心显示通道商户状态与最近核实时间),或在进件页对已 approved 状态也允许刷新;
另外可评估是否给"已 approved 申请"加一个低频的进度刷新,让进件页状态不再长期停在旧快照上。
## 怎么验
1. 汇付控台关闭该商户 → 后台点一次能力刷新(或等最长 6 小时),然后查
   `select merchant_stat, auto_settle_status, cash_switch_status, capability_verified_at
   from merchant_onboarding_application where merchant_id = ?` 看通道把哪些字段改成了什么,
   据此判断上面三条文案会命中哪一条。
2. 用该商户账密登录商户端,扫人才码下一笔到店消费单:
   报"斗拱子商户状态异常"说明闸门按预期生效;下单仍成功说明快照还没刷新(6 小时窗口内),
   此时真正付款会被通道拒绝。
3. 汇付控台重新启用商户 → 再刷一次即可恢复;`isMerchantNormal` 看到 `NORMAL` 就放行。