diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/HcsMockController.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/HcsMockController.java
deleted file mode 100644
index 247f0e87..00000000
--- a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/HcsMockController.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/**
- * BladeX Commercial License Agreement
- * Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
- *
- * Use of this software is governed by the Commercial License Agreement
- * obtained after purchasing a license from BladeX.
- *
- * 1. This software is for development use only under a valid license
- * from BladeX.
- *
- * 2. Redistribution of this software's source code to any third party
- * without a commercial license is strictly prohibited.
- *
- * 3. Licensees may copyright their own code but cannot use segments
- * from this software for such purposes. Copyright of this software
- * remains with BladeX.
- *
- * Using this software signifies agreement to this License, and the software
- * must not be used for illegal purposes.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
- * not liable for any claims arising from secondary or illegal development.
- *
- * Author: Chill Zhuang (bladejava@qq.com)
- */
-package org.springblade.transport.controller;
-
-import cn.hutool.core.util.StrUtil;
-import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import lombok.extern.slf4j.Slf4j;
-import org.springblade.core.log.exception.ServiceException;
-import org.springblade.core.tenant.annotation.TenantIgnore;
-import org.springblade.core.tool.api.R;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * HCS 合规回调 Mock 端点
- *
- * 合同法务审批结果回调(D103)、付款法务审批结果回调(D104)、项目金蝶同步结果回调(D902)、
- * 合同金蝶同步结果回传接收(D903)四个入站回调的纯 mock 实现:仅校验来源系统标识后返回固定结果,
- * 不读写业务数据、不联动状态。真实处理逻辑保留在对应 Support 中,联调时把端点切回
- * {@link } 并调用 Support 方法即可。
- *
- * @author Chill
- */
-@Slf4j
-@RestController
-@TenantIgnore
-@RequestMapping("hcs")
-@Tag(name = "HCS合规回调Mock", description = "HCS合规回调Mock端点(仅自测,返回固定 mock 数据)")
-public class HcsMockController {
-
- /**
- * 来源系统标识(合规方约定值,与 third-party.hcs.src-system 默认值一致)
- */
- private static final String SOURCE_SYSTEM = "WLTMS";
-
- /**
- * 合同法务审批结果回调(D103)
- */
- @PostMapping("/contractLegal/result")
- @ApiOperationSupport(order = 15)
- @Operation(summary = "合同法务审批结果回调Mock", description = "D103 合规推送合同特批(金蝶同步)结果,仅校验来源系统并返回 mock 数据")
- public R contractLegalResult(@RequestBody(required = false) Map param) {
- this.checkSourceSystem("合同法务审批结果", param);
- return R.data("mock特批结果已处理:approved");
- }
-
- /**
- * 付款法务审批结果回调(D104)
- */
- @PostMapping("/paymentLegal/result")
- @ApiOperationSupport(order = 16)
- @Operation(summary = "付款法务审批结果回调Mock", description = "D104 合规推送付款特批结果,仅校验来源系统并返回 mock 数据")
- public R paymentLegalResult(@RequestBody(required = false) Map param) {
- this.checkSourceSystem("付款法务审批结果", param);
- return R.data("mock付款特批结果接收已处理:approved");
- }
-
- /**
- * 项目金蝶同步结果回调(D902)
- */
- @PostMapping("/projectLegal/result")
- @ApiOperationSupport(order = 18)
- @Operation(summary = "项目金蝶同步结果回调Mock", description = "D902 合规推送项目金蝶同步结果,仅校验来源系统并返回 mock 数据")
- public R projectLegalResult(@RequestBody(required = false) Map param) {
- this.checkSourceSystem("项目金蝶同步结果", param);
- return R.data("mock项目金蝶同步结果接收已处理:approved");
- }
-
- /**
- * 合同金蝶同步结果回传接收(D903)
- */
- @PostMapping("/contractKingdee/result")
- @ApiOperationSupport(order = 19)
- @Operation(summary = "合同金蝶同步结果回传接收Mock", description = "D903 合规推送合同金蝶最终同步结果,仅校验来源系统并返回 mock 数据")
- public R contractKingdeeResult(@RequestBody(required = false) Map param) {
- this.checkSourceSystem("合同金蝶同步结果", param);
- return R.data("mock合同金蝶同步结果接收处理:approved");
- }
-
- /**
- * 来源系统校验:仅接受合规方约定的来源标识,防伪造回传
- *
- * @param bizName 业务名称(日志用)
- * @param param 回调报文
- */
- private void checkSourceSystem(String bizName, Map param) {
- String sourceSystem = param == null ? null : Objects.toString(param.get("sourceSystem"), null);
- if (!StrUtil.equalsIgnoreCase(sourceSystem, SOURCE_SYSTEM)) {
- log.warn("{}推送来源系统标识错误:sourceSystem={}", bizName, sourceSystem);
- throw new ServiceException("来源系统标识错误");
- }
- }
-}
diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/support/hcs/HcsContractSyncSupport.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/support/hcs/HcsContractSyncSupport.java
index 4766bbd5..e8634615 100644
--- a/blade-service/blade-transport/src/main/java/org/springblade/transport/support/hcs/HcsContractSyncSupport.java
+++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/support/hcs/HcsContractSyncSupport.java
@@ -337,22 +337,29 @@ public class HcsContractSyncSupport {
}
/**
- * 查询单方客商风险:按名称反查客商编号(§9-U6 编码体系联调确认),反查不到记 skip 留痕不阻断
+ * 查询单方客商风险:按名称反查客商档案(§9-U6 编码体系联调确认),反查不到记 skip 留痕不阻断;
+ * 内部组织客商默认无风险跳过(与展示/提交/付款链路口径一致,不调 C101-1)
*/
private RiskResult queryRisk(ContractManage contractManage, String standing, String partyName) {
- String customerCode = queryCustomerCode(partyName);
- if (StringUtil.isBlank(customerCode)) {
+ CustomerArchive customerArchive = queryCustomerArchive(partyName);
+ if (customerArchive == null) {
writeCheckLog(contractManage, HcsSyncConstant.CHECK_RESULT_SKIP,
standing + "方[" + partyName + "]反查不到客商编号,跳过风险校验(§9-U6)", null);
return new RiskResult(null, null, false);
}
+ // 内部组织类型客商默认无风险,不调 C101-1(与展示/提交/付款链路口径一致)
+ if (HcsCreditCheckSupport.isInternalCustomer(customerArchive)) {
+ writeCheckLog(contractManage, HcsSyncConstant.CHECK_RESULT_SKIP,
+ standing + "方[" + partyName + "]为内部组织客商,默认无风险跳过校验", null);
+ return new RiskResult(null, null, false);
+ }
HcsRiskQueryDTO param = new HcsRiskQueryDTO();
// 【必填】客商编号:按甲乙方名称反查 CustomerArchive 客商编码(§9-U6)
- param.setFdNumber(customerCode);
+ param.setFdNumber(customerArchive.getCustomerCode());
HcsResult result = hcsClient.getRelativeRisk(param);
if (result == null || !result.isSuccess()) {
log.error("HCS客商风险查询失败响应:{},contractNo={},standing={},fdNumber={}",
- result == null ? "无响应" : String.format("msg=%s, traceId=%s", result.getMsg(), result.getTraceId()), contractManage.getContractNo(), standing, customerCode);
+ result == null ? "无响应" : String.format("msg=%s, traceId=%s", result.getMsg(), result.getTraceId()), contractManage.getContractNo(), standing, customerArchive.getCustomerCode());
throw new HcsException("C101-1 客商风险查询失败:" + (result == null ? "响应为空" : result.getMsg()));
}
HcsRiskVO risk = result.getData();
@@ -534,8 +541,8 @@ public class HcsContractSyncSupport {
// 甲乙方各反查一次客商档案,编号与内部组织判定共用查询结果
CustomerArchive partyAArchive = queryCustomerArchive(contractManage.getPartyA());
CustomerArchive partyBArchive = queryCustomerArchive(contractManage.getPartyB());
- boolean partyAInternal = isInternalCustomer(partyAArchive);
- boolean partyBInternal = isInternalCustomer(partyBArchive);
+ boolean partyAInternal = HcsCreditCheckSupport.isInternalCustomer(partyAArchive);
+ boolean partyBInternal = HcsCreditCheckSupport.isInternalCustomer(partyBArchive);
String partyAType;
String partyBType;
if (partyAInternal || partyBInternal) {
@@ -672,14 +679,6 @@ public class HcsContractSyncSupport {
return templateId;
}
- /**
- * 按名称反查客商编码(照 KingdeeApBillSyncSupport#queryCustomerCode 惯例,查不到返回 null)
- */
- private String queryCustomerCode(String partyName) {
- CustomerArchive customerArchive = queryCustomerArchive(partyName);
- return customerArchive == null ? null : customerArchive.getCustomerCode();
- }
-
/**
* 按名称反查客商档案(全称或简称精确匹配,查不到返回 null)
*/
@@ -693,15 +692,6 @@ public class HcsContractSyncSupport {
.last("limit 1"));
}
- /**
- * 内部组织客商判定(集团内我方签约主体,档案登记 customerKind=internal/内部组织)
- */
- private boolean isInternalCustomer(CustomerArchive customerArchive) {
- return customerArchive != null
- && (HcsSyncConstant.CUSTOMER_KIND_INTERNAL.equals(customerArchive.getCustomerKind())
- || "内部组织".equals(customerArchive.getCustomerKind()));
- }
-
/**
* 关联项目取值:合同所选项目对应合同系统项目ID(blade_project_apply.hcs_fd_id,C102-1 立项同步回填),
* 未选择项目、立项单不存在或未同步合规时返回 null 不传(fdProject 选填)
diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/support/hcs/HcsCreditCheckSupport.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/support/hcs/HcsCreditCheckSupport.java
index 8d2d8288..2b158e4e 100644
--- a/blade-service/blade-transport/src/main/java/org/springblade/transport/support/hcs/HcsCreditCheckSupport.java
+++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/support/hcs/HcsCreditCheckSupport.java
@@ -118,7 +118,7 @@ public class HcsCreditCheckSupport {
return;
}
// 内部组织类型客商默认无风险,不查 C101-1(与 queryCustomerRisk 展示口径一致)
- if (HcsSyncConstant.CUSTOMER_KIND_INTERNAL.equals(customerArchive.getCustomerKind())) {
+ if (isInternalCustomer(customerArchive)) {
writeCheckLog(payment, HcsSyncConstant.CHECK_TYPE_RISK, HcsSyncConstant.CHECK_RESULT_SKIP,
"收款方[" + payment.getPayeeName() + "]为内部组织客商,默认无风险跳过校验", null);
return;
@@ -212,7 +212,7 @@ public class HcsCreditCheckSupport {
riskVO.setCustomerCode(customerCode);
riskVO.setCustomerName(customerArchive == null ? customerCode : customerArchive.getFullName());
// 内部组织类型客商默认无风险;档案不存在按外部客商查询(不静默放行)
- boolean internal = customerArchive != null && HcsSyncConstant.CUSTOMER_KIND_INTERNAL.equals(customerArchive.getCustomerKind());
+ boolean internal = isInternalCustomer(customerArchive);
riskVO.setCustomerKind(internal ? HcsSyncConstant.CUSTOMER_KIND_INTERNAL : "external");
if (internal) {
riskVO.setRisky(Boolean.FALSE);
@@ -236,7 +236,9 @@ public class HcsCreditCheckSupport {
riskVO.setRiskLevelName(riskLevelName(blackStatus, riskLevel));
riskVO.setRisky(risky);
if (risky) {
- riskVO.setRiskTip("【" + riskVO.getCustomerName() + "】:被列入外部黑名单;涉贪污受贿裁判相关提及方(3年以上及其他);被执行人信息;买卖合同纠纷;劳动纠纷;重大纠纷");
+ // 风险提示固定短文案(C101-1 未返回风险项明细,不拼接枚举清单):黑名单与高风险区分表述
+ riskVO.setRiskTip("【" + riskVO.getCustomerName() + "】:"
+ + (BLACK_STATUS_YES.equalsIgnoreCase(blackStatus) ? "被列入外部黑名单" : "为高风险客商"));
}
try {
HcsContractCheckLog checkLog = new HcsContractCheckLog();
@@ -271,6 +273,19 @@ public class HcsCreditCheckSupport {
return queryCustomerRisk(customerCode);
}
+ /**
+ * 内部组织客商判定(集团内我方签约主体,档案登记 customerKind=internal/内部组织);
+ * 展示、提交校验、付款校验、合同推送、signer 单位类型各链路统一复用本判定
+ *
+ * @param customerArchive 客商档案
+ * @return 是否内部组织客商
+ */
+ public static boolean isInternalCustomer(CustomerArchive customerArchive) {
+ return customerArchive != null
+ && (HcsSyncConstant.CUSTOMER_KIND_INTERNAL.equals(customerArchive.getCustomerKind())
+ || "内部组织".equals(customerArchive.getCustomerKind()));
+ }
+
/**
* 风险等级转义(C101-1 枚举 0=低风险/1=中风险/2=高风险):黑名单状态优先展示,无等级返回空
*/