From 242917765d2711b723e98764396054acef2a7297 Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期三, 16 九月 2026 00:47:50 +0800
Subject: [PATCH] feat(merchant): 分阶段开通对所有商户生效
---
talent-card-server/src/main/java/com/talentcard/server/business/merchant/MerchantOnboardingProgressService.java | 38 +++++++++++++++++++++++++++-----------
1 files changed, 27 insertions(+), 11 deletions(-)
diff --git a/talent-card-server/src/main/java/com/talentcard/server/business/merchant/MerchantOnboardingProgressService.java b/talent-card-server/src/main/java/com/talentcard/server/business/merchant/MerchantOnboardingProgressService.java
index 07fe25b..69ba5eb 100644
--- a/talent-card-server/src/main/java/com/talentcard/server/business/merchant/MerchantOnboardingProgressService.java
+++ b/talent-card-server/src/main/java/com/talentcard/server/business/merchant/MerchantOnboardingProgressService.java
@@ -16,8 +16,6 @@
/** Six independent evidence-backed stages; provider calls never hold application row locks. */
@Service
public class MerchantOnboardingProgressService {
- /** 分阶段进度的灰度门槛;03 票把它换成通用规则时一并删除。 */
- public static final String RECOVERY_HUIFU_ID = "6666000241335656";
private static final Map<String,String> LABELS = new LinkedHashMap<>();
static {
LABELS.put("basic", "基础审核"); LABELS.put("wechat", "微信支付");
@@ -29,20 +27,28 @@
public MerchantOnboardingProgressService(JdbcTemplate jdbc, HuifuOnboardingProgressGateway gateway) { this.jdbc=jdbc; this.gateway=gateway; }
/**
- * 分阶段进度当前只对指定存量商户放行。
+ * 分阶段进度适用于「已关联结算银行卡、且未被整体拒绝」的申请。
*
- * <p><b>这仍是一道灰度门槛,不是通用规则。</b>把判断换成「有结算卡且未被拒绝」会同时给所有商户
- * 切换行为:进件失败不再释放银行卡(`MerchantOnboardingRetryReleaseTests`)、回调改走分阶段刷新
- * (`MerchantSettlementCallbackIdempotencyTests`),共 5 个测试会红。那是策略变更,属于 03 票
- * 「分阶段手动推进 + 局部失败保留原商户号和银行卡」,不在 04 的清理范围内。
+ * <p>原先这里按 huifu_id 白名单只放行一张指定存量商户,新商户走不进这套视图。现在按申请自身的
+ * 状态判断:银行卡关联是分阶段视图核实原卡的前提({@code application()} 也用它做条件);
+ * 而被拒绝的申请仍留在旧的单状态模型,商户端才有重新提交的入口。
+ *
+ * <p>这一条同时决定「进件失败后不重建商户与银行卡」的适用范围:支持的申请走局部刷新与重试,
+ * 不支持的才允许关闭重来。旧策略里「通道配置失败就释放银行卡、让商户整单重提」已被规格
+ * 明确取代——基本进件成功后要保留原商户号和银行卡。
*/
- public boolean supports(Map<String,Object> application) { return RECOVERY_HUIFU_ID.equals(text(application.get("providerHuifuId"))); }
+ public boolean supports(Map<String,Object> application) {
+ return application.get("initialBankCardId") != null && !"rejected".equals(text(application.get("status")));
+ }
public Map<String,Object> view(Long id) { return view(application(id)); }
@org.springframework.transaction.annotation.Transactional(propagation = org.springframework.transaction.annotation.Propagation.NOT_SUPPORTED)
public Map<String,Object> refresh(Long applicationId, boolean retry) {
Map<String,Object> application=application(applicationId);
+ // 被拒绝的申请不归分阶段模型管:刷下去会把它从 rejected 翻回 pending,商户端的
+ // 「重新提交」入口就没了(supports() 对 rejected 返回 false,正是为了让出那个入口)。
+ if (!supports(application)) return view(application);
jdbc.update("insert ignore into merchant_onboarding_progress(application_id,stages_json) values (?, '{}')", applicationId);
String owner=UUID.randomUUID().toString();
if(jdbc.update("update merchant_onboarding_progress set sync_owner=?,sync_until=date_add(now(),interval 5 minute) where application_id=? and (sync_owner is null or sync_until<now())", owner, applicationId)==0) return view(application);
@@ -123,11 +129,17 @@
advanceDelay(applicationId,text(application.get("providerHuifuId")),owner,stages,retry);
}
jdbc.update("update merchant_onboarding_progress set stages_json=? where application_id=? and sync_owner=?",JSON.toJSONString(stages),applicationId,owner);
+ // 基本资料被通道驳回时要落到 rejected:一是让商户端出现「重新提交」入口(supports() 对
+ // rejected 返回 false,交回旧的单状态模型),二是别把一次明确拒绝一直显示成「审核中」。
+ // 后续配置失败不算拒绝——那种情况保留原商户号和银行卡,局部重试即可。
+ boolean basicRejected = "failed".equals(text(stages.get("basic")));
+ String applicationStatus = basicRejected ? "rejected" : complete(stages) ? "approved" : "pending";
jdbc.update("""
update merchant_onboarding_application a join merchant_onboarding_progress p on p.application_id=a.id
set a.status=?,a.reviewed_at=case when ? then now() else null end
where a.id=? and p.sync_owner=?
- """,complete(stages) ? "approved" : "pending",complete(stages),applicationId,owner);
+ """,applicationStatus,!"pending".equals(applicationStatus),applicationId,owner);
+ if (basicRejected) jdbc.update("update merchant_onboarding_application set reject_reason=? where id=?","基本资料审核未通过,请核对资料后重新提交",applicationId);
}
} catch (RuntimeException exception) {
jdbc.update("update merchant_onboarding_progress set sync_error=? where application_id=? and sync_owner=?","查询结果暂未确认,已保留最后有效进度,请稍后刷新",applicationId,owner);
@@ -225,10 +237,14 @@
progress.add(Map.of("key",entry.getKey(),"label",entry.getValue(),"status",status,"reason",stageReason(entry.getKey(),status),
"qrCode", "realname".equals(entry.getKey()) ? text(stages.get("realnameQr")) : ""));
}
+ // 被通道明确驳回基本资料的申请仍显示 rejected(并带通道给的驳回原因),不能被阶段计算
+ // 盖成 pending——那样商户端看不到「重新提交」。
+ boolean rejected = "rejected".equals(text(application.get("status")));
result.put("stages",progress); result.put("reason","请刷新进度,核实原申请与各项能力");
result.put("retryable", "failed".equals(stages.get("delay")));
- result.put("status",complete(stages) ? "approved" : "pending");
- result.put("reason",complete(stages) ? "收款能力已核实,沿用原商户号和结算银行卡" : "请刷新进度核实各项能力,并按待办理项补齐缺失能力");
+ result.put("status",rejected ? "rejected" : complete(stages) ? "approved" : "pending");
+ result.put("reason",rejected ? text(application.get("rejectReason"))
+ : complete(stages) ? "收款能力已核实,沿用原商户号和结算银行卡" : "请刷新进度核实各项能力,并按待办理项补齐缺失能力");
return result;
}
--
Gitblit v1.7.1