feat: 客商提审接入国资委黑名单校验(A801-5)

- submitApproval 前置实时查询金蝶黑名单(enable=1),按统一社会信用代码大写精确匹配
- 禁止交易类(A)硬拦截报错并提示失信类别与列入事由;风险警示类(B)默认放行告警,thirdparty.bfi.blacklist.blockRiskWarning=true 时一并拦截
- 黑名单查询异常不阻断准入,记 error 日志放行(金蝶可用性口径待联调确认)
This commit is contained in:
刘泉佳
2026-10-01 23:47:49 +08:00
parent cc54b4ca91
commit 048bcaf8ad
@@ -45,6 +45,7 @@ import org.springblade.thirdparty.bfi.pojo.dto.BfiCustomerQueryDTO;
import org.springblade.thirdparty.bfi.pojo.vo.BfiBillSaveResultErrorVO;
import org.springblade.thirdparty.bfi.pojo.vo.BfiBillSaveResultItemVO;
import org.springblade.thirdparty.bfi.pojo.vo.BfiBillSaveResultVO;
import org.springblade.thirdparty.bfi.pojo.vo.BfiBlacklistVO;
import org.springblade.thirdparty.bfi.pojo.vo.BfiCustomerVO;
import org.springblade.thirdparty.bfi.pojo.vo.BfiPageVO;
import org.springblade.thirdparty.bfi.service.IBfiService;
@@ -229,6 +230,13 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl<CustomerArchiveM
@Value("${thirdParty.bfi.customer.lockLeaseSeconds:1800}")
private long customerSyncLockLeaseSeconds;
/**
* 客商提审命中金蝶黑名单风险警示类(B)时是否一并拦截;
* 默认 false 仅放行告警,禁止交易类(A)始终拦截,与集团合规口径确认后可调整
*/
@Value("${thirdparty.bfi.blacklist.blockRiskWarning:false}")
private boolean blacklistBlockRiskWarning;
@Override
public IPage<CustomerArchiveVO> selectCustomerArchivePage(IPage<CustomerArchiveVO> page, CustomerArchiveVO customer) {
List<CustomerArchiveVO> records = baseMapper.selectCustomerArchivePage(page, customer, currentScopeUserId());
@@ -303,6 +311,7 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl<CustomerArchiveM
validateBase(detail);
validateScoreForApproval(detail);
validateApproval(detail);
validateBlacklist(detail);
CustomerArchive before = Objects.requireNonNull(BeanUtil.copyProperties(detail, CustomerArchive.class));
CustomerArchive after = copyCustomer(before);
after.setApprovalStatus(APPROVAL_REVIEWING);
@@ -1041,6 +1050,46 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl<CustomerArchiveM
}
}
/**
* 国资委黑名单校验(A801-5):客商提审进入准入审批前实时查询金蝶黑名单,
* 按统一社会信用代码精确匹配;命中禁止交易类(A)硬拦截,
* 风险警示类(B)默认放行告警、可经 {@code thirdparty.bfi.blacklist.blockRiskWarning} 配置拦截,
* 其他类别放行告警;黑名单查询异常不阻断准入(放行并记录错误日志),金蝶可用性口径待联调确认
*
* @param customer 客商
*/
private void validateBlacklist(CustomerArchiveVO customer) {
String creditCode = customer.getUnifiedCreditCode();
if (Func.isEmpty(creditCode)) {
return;
}
List<BfiBlacklistVO> blacklist;
try {
blacklist = bfiService.queryBlacklist("1");
} catch (Exception exception) {
log.error("查询金蝶黑名单失败,黑名单校验放行,fullName={},unifiedCreditCode={}",
customer.getFullName(), creditCode, exception);
return;
}
String code = creditCode.trim().toUpperCase();
BfiBlacklistVO hit = blacklist.stream()
.filter(item -> Func.isNotEmpty(item.getNumber()) && code.equals(item.getNumber().trim().toUpperCase()))
.findFirst()
.orElse(null);
if (hit == null) {
return;
}
String category = Func.isEmpty(hit.getAwrpCombofieldTitle()) ? hit.getAwrpCombofield() : hit.getAwrpCombofieldTitle();
boolean forbidden = "A".equals(hit.getAwrpCombofield());
boolean riskWarning = "B".equals(hit.getAwrpCombofield());
if (forbidden || (riskWarning && blacklistBlockRiskWarning)) {
throw new ServiceException(String.format("客商【%s】在国资委黑名单中(失信类别:%s,列入事由:%s),不允许提交准入审批",
customer.getFullName(), category, hit.getAwrpTextareafield()));
}
log.warn("客商命中金蝶黑名单风险警示类,放行,fullName={},unifiedCreditCode={},失信类别={},列入事由={}",
customer.getFullName(), creditCode, category, hit.getAwrpTextareafield());
}
private void validateUnique(CustomerArchiveVO customer) {
LambdaQueryWrapper<CustomerArchive> unifiedCreditCodeQuery = Wrappers.<CustomerArchive>lambdaQuery()
.eq(CustomerArchive::getUnifiedCreditCode, customer.getUnifiedCreditCode())