✨ 金蝶推送项目编码真实化与合同入参送出(P0/P1)

- 新增公共方法 kingdeeProjectNumber:开关开启取 blade_project_apply.project_code 真实编码,未关联项目兜底 999;应付/应收/预付款/应付下推/开票五处赋值统一复用

- 应付/应收上游合同号按开关送出(awrp_src_bt=awrp_contract_info + awrp_src_con_no,仅 kingdee_id 非空的已同步合同)

- 开票申请送合同三件套:contractno/contractamount/contractdate(取申请日期)

- BfiProperties 新增 projectRealCodeEnabled、contractRefEnabled 开关,默认关闭;Nacos 模板同步补充
This commit is contained in:
刘泉佳
2026-11-04 23:10:05 +08:00
parent 3100fd046c
commit 23c0d66037
8 changed files with 86 additions and 27 deletions
@@ -55,6 +55,22 @@ public class BfiProperties {
*/ */
private String srcSys = BfiConstant.DATA_SOURCE_WLTMS; private String srcSys = BfiConstant.DATA_SOURCE_WLTMS;
/**
* 项目编码真实化开关(thirdparty.bfi.project-real-code-enabled):开启后推送金蝶的项目编码取
* blade_project_apply.project_code 真实值(前提:金蝶项目档案已存在且编码与 project_code 一致,
* 否则该单推送失败、失败原因回写单据可重推),单据未关联项目/编码为空仍兜底 999;
* 关闭维持联调临时值 999,出问题关开关即回退
*/
private boolean projectRealCodeEnabled = false;
/**
* 合同引用开关(thirdparty.bfi.contract-ref-enabled):开启后财务应付/应收送上游合同号
* (awrp_src_bt=awrp_contract_info + awrp_src_con_no,仅 blade_contract_manage.kingdee_id 非空的已同步合同,
* 防上游合同勾稽挂空)、开票申请送合同三件套(contractno/contractdate/contractamount,contractdate 取申请日期);
* 关闭维持不送,出问题关开关即回退
*/
private boolean contractRefEnabled = false;
/** /**
* 付款申请推送配置(A103-3 付款申请保存) * 付款申请推送配置(A103-3 付款申请保存)
*/ */
@@ -885,7 +885,8 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
+ "]无商品行,无法组装分录"); + "]无商品行,无法组装分录");
} }
BfiInvoiceApplySaveDTO param = this.buildInvoiceApplyParam(entity, sheetBillNo, seller, salerAddr, salerBank, BfiInvoiceApplySaveDTO param = this.buildInvoiceApplyParam(entity, sheetBillNo, seller, salerAddr, salerBank,
kingdeeDeptNumber, kingdeeOrgNumber, customer, firstArSrcCode, money(sheet.getInvoiceAmount()), items); kingdeeDeptNumber, kingdeeOrgNumber, customer, firstArSrcCode, money(sheet.getInvoiceAmount()), items,
contract, kingdeeContext);
log.info("金蝶开票申请推送:开票申请[{}]发票张[{}],billno=[{}],价税合计=[{}],分录{}条", log.info("金蝶开票申请推送:开票申请[{}]发票张[{}],billno=[{}],价税合计=[{}],分录{}条",
entity.getApplicationNo(), sheet.getSheetNo(), sheetBillNo, sheet.getInvoiceAmount(), items.size()); entity.getApplicationNo(), sheet.getSheetNo(), sheetBillNo, sheet.getInvoiceAmount(), items.size());
BfiBillSaveResultVO saveResult = bfiService.saveInvoiceApply(param); BfiBillSaveResultVO saveResult = bfiService.saveInvoiceApply(param);
@@ -941,10 +942,13 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
* *
* @param orgNumber 金蝶组织编码(项目业务部门反查平台公司) * @param orgNumber 金蝶组织编码(项目业务部门反查平台公司)
* @param firstArSrcCode 上游来源单据号:首张关联结算单的金蝶应收单防重键 awrp_src_code(多张结算单取第一张) * @param firstArSrcCode 上游来源单据号:首张关联结算单的金蝶应收单防重键 awrp_src_code(多张结算单取第一张)
* @param contract 首张关联结算单合同(合同三件套取数来源,开关开启时送出)
* @param kingdeeContext 金蝶同步上下文(缓存载体,项目编码取数用)
*/ */
private BfiInvoiceApplySaveDTO buildInvoiceApplyParam(InvoiceApplication entity, String billNo, private BfiInvoiceApplySaveDTO buildInvoiceApplyParam(InvoiceApplication entity, String billNo,
CustomerArchive seller, String salerAddr, String salerBank, String deptNumber, String orgNumber, CustomerArchive customer, CustomerArchive seller, String salerAddr, String salerBank, String deptNumber, String orgNumber, CustomerArchive customer,
String firstArSrcCode, BigDecimal sheetAmount, List<BfiInvoiceApplySaveEntryDTO> items) { String firstArSrcCode, BigDecimal sheetAmount, List<BfiInvoiceApplySaveEntryDTO> items,
ContractManage contract, KingdeeSyncContext kingdeeContext) {
BfiInvoiceApplySaveDTO param = new BfiInvoiceApplySaveDTO(); BfiInvoiceApplySaveDTO param = new BfiInvoiceApplySaveDTO();
// ==================== 以下为【必填】字段(BfiInvoiceApplySaveDTO 标注),非必填字段先注释保留 ==================== // ==================== 以下为【必填】字段(BfiInvoiceApplySaveDTO 标注),非必填字段先注释保留 ====================
// 【必填】组织.编码:合同平台公司金蝶组织编码 // 【必填】组织.编码:合同平台公司金蝶组织编码
@@ -1005,8 +1009,8 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
} }
// 【必填】客户.编码:受票方客商档案供应商编码(A901-1 金蝶编码),未维护时兜底客商编号 // 【必填】客户.编码:受票方客商档案供应商编码(A901-1 金蝶编码),未维护时兜底客商编号
param.setCustomnameidNumber(Func.isBlank(customer.getSupplierCode()) ? customer.getCustomerCode() : customer.getSupplierCode()); param.setCustomnameidNumber(Func.isBlank(customer.getSupplierCode()) ? customer.getCustomerCode() : customer.getSupplierCode());
// 【必填】项目.项目编码(联调期临时传金蝶测试档案值 999) // 【必填】项目.项目编码:开关开启取项目档案真实编码(金蝶档案须已存在且编码一致),未关联项目兜底 999
param.setAwrpProjectNumber(KingdeeBfiConstant.BFI_PROJECT_NUMBER_NONE); param.setAwrpProjectNumber(kingdeeApBillSyncSupport.kingdeeProjectNumber(entity.getProjectId(), kingdeeContext));
// ==================== 以下为非必填字段,先注释保留,联调确认后按需放开 ==================== // ==================== 以下为非必填字段,先注释保留,联调确认后按需放开 ====================
// 申请金额(不含税):分录不含税合计(放开时需按分摊后分录汇总) // 申请金额(不含税):分录不含税合计(放开时需按分摊后分录汇总)
// param.setInvoiceamount(invoiceamount); // param.setInvoiceamount(invoiceamount);
@@ -1020,6 +1024,14 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
// 上游单据号:首张关联结算单的金蝶应收单防重键 awrp_src_code(联调确认金蝶按防重键匹配源单,A302-4 预检已确认存在) // 上游单据号:首张关联结算单的金蝶应收单防重键 awrp_src_code(联调确认金蝶按防重键匹配源单,A302-4 预检已确认存在)
param.setAwrpSrcConNo(firstArSrcCode); param.setAwrpSrcConNo(firstArSrcCode);
// 合同三件套(非必传):开关开启时送出,contractdate 取申请日期(口径确认 2026-11-04),申请日期为空兜底当日
if (bfiProperties.isContractRefEnabled() && Func.isNotBlank(contract.getContractNo())) {
param.setContractno(contract.getContractNo());
param.setContractamount(contract.getContractAmount());
LocalDate contractDate = entity.getApplicationDate() == null ? LocalDate.now() : entity.getApplicationDate();
param.setContractdate(contractDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
}
// 数据来源系统 // 数据来源系统
param.setSystemsource(bfiProperties.getSrcSys()); param.setSystemsource(bfiProperties.getSrcSys());
@@ -1448,9 +1448,8 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
entry.setEApplyamount(applyAmount); entry.setEApplyamount(applyAmount);
// 期望付款日(非必传) // 期望付款日(非必传)
// entry.setEExpaydate(applyDateText); // entry.setEExpaydate(applyDateText);
// 【必填】项目.项目编码 // 【必填】项目.项目编码:开关开启取项目档案真实编码(金蝶档案须已存在且编码一致),未关联项目兜底 999
// entry.setProjectNumber(bfiProjectNumber(entity, context)); entry.setProjectNumber(kingdeeApBillSyncSupport.kingdeeProjectNumber(entity.getProjectId(), context));
entry.setProjectNumber(KingdeeBfiConstant.BFI_AP_BILL_PROJECT_NUMBER_TEST);
// 【必填】对方系统唯一行id(不能重复):付款申请号-1 // 【必填】对方系统唯一行id(不能重复):付款申请号-1
entry.setAwrpEntryCode(bfiEntryCode(entity.getPaymentNo(), 1)); entry.setAwrpEntryCode(bfiEntryCode(entity.getPaymentNo(), 1));
// 备注(非必传):携带关联履约计划id(进度款计划行合规阶段ID),用于合同系统关联履约付款数据与履约计划 // 备注(非必传):携带关联履约计划id(进度款计划行合规阶段ID),用于合同系统关联履约付款数据与履约计划
@@ -1557,8 +1556,8 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
entry.setEBebankNumber(bfiBebankNumber(entity, context)); entry.setEBebankNumber(bfiBebankNumber(entity, context));
// 【必填】申请金额:取付款申请填写的申请付款金额 // 【必填】申请金额:取付款申请填写的申请付款金额
entry.setEApplyamount(money(entity.getAppliedAmount()).setScale(2, RoundingMode.HALF_UP)); entry.setEApplyamount(money(entity.getAppliedAmount()).setScale(2, RoundingMode.HALF_UP));
// 【必填】项目.项目编码(联调期临时传金蝶测试档案值) // 【必填】项目.项目编码:开关开启取项目档案真实编码(金蝶档案须已存在且编码一致),未关联项目兜底 999
entry.setProjectNumber(KingdeeBfiConstant.BFI_AP_BILL_PROJECT_NUMBER_TEST); entry.setProjectNumber(kingdeeApBillSyncSupport.kingdeeProjectNumber(entity.getProjectId(), context));
// 期望付款日(非必传,不传时根据应付单自动带出) // 期望付款日(非必传,不传时根据应付单自动带出)
// entry.setEExpaydate(applyDateText); // entry.setEExpaydate(applyDateText);
// 备注(非必传):携带关联履约计划id(进度款计划行合规阶段ID),用于合同系统关联履约付款数据与履约计划 // 备注(非必传):携带关联履约计划id(进度款计划行合规阶段ID),用于合同系统关联履约付款数据与履约计划
@@ -1795,13 +1794,6 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
.map(DictBiz::getDictValue).findFirst().orElse(paymentMethod); .map(DictBiz::getDictValue).findFirst().orElse(paymentMethod);
} }
private String bfiProjectNumber(PaymentApplication entity, KingdeeSyncContext context) {
if (entity.getProjectId() == null) return KingdeeBfiConstant.BFI_PROJECT_NUMBER_NONE;
// 批量同步时按项目id缓存复用(同一项目只查一次),单笔同步退化为直接查询
ProjectApply project = context.projectCache().computeIfAbsent(entity.getProjectId(), projectApplyMapper::selectById);
return project == null || Func.isEmpty(project.getProjectCode()) ? KingdeeBfiConstant.BFI_PROJECT_NUMBER_NONE : project.getProjectCode();
}
/** /**
* 付款完成模拟(已停用):原在同步成功后模拟付款完成数据(paidAmount = 申请金额、MOCK-PAY- 前缀付款记录)。 * 付款完成模拟(已停用):原在同步成功后模拟付款完成数据(paidAmount = 申请金额、MOCK-PAY- 前缀付款记录)。
* 真实付款结果现由定时回写任务 syncKingdeePaymentResult 经 A103-2/A103-4 查询回填驱动, * 真实付款结果现由定时回写任务 syncKingdeePaymentResult 经 A103-2/A103-4 查询回填驱动,
@@ -355,12 +355,11 @@ public class KingdeeApBillSyncSupport {
param.setAwrpSrcSys(bfiProperties.getSrcSys()); param.setAwrpSrcSys(bfiProperties.getSrcSys());
// 【必填】外部系统来源单据号(候选键):正式结算单号_结算明细单据号1_单据号2...(复用预检已组装的防重键) // 【必填】外部系统来源单据号(候选键):正式结算单号_结算明细单据号1_单据号2...(复用预检已组装的防重键)
param.setAwrpSrcCode(apBillSrcCode); param.setAwrpSrcCode(apBillSrcCode);
// 来源单据(非必传,有上游合同时传 awrp_contract_info) // 来源单据 + 上游合同号(非必传):开关开启且合同已同步金蝶(kingdee_id 非空)时送出,防上游合同勾稽挂空
// param.setAwrpSrcBt(KingdeeBfiConstant.BFI_CONTRACT_SRC_BT); if (bfiProperties.isContractRefEnabled() && Func.isNotBlank(contract.getContractNo()) && Func.isNotBlank(contract.getKingdeeId())) {
// 上游外部系统单据号/上游合同号(非必传) param.setAwrpSrcBt(KingdeeBfiConstant.BFI_CONTRACT_SRC_BT);
// if (Func.isNotEmpty(contract.getContractNo())) { param.setAwrpSrcConNo(contract.getContractNo());
// param.setAwrpSrcConNo(contract.getContractNo()); }
// }
// 【必填】外部单据类型 // 【必填】外部单据类型
param.setAwrpSrcType(KingdeeBfiConstant.BFI_AP_BILL_SRC_TYPE); param.setAwrpSrcType(KingdeeBfiConstant.BFI_AP_BILL_SRC_TYPE);
@@ -382,8 +381,8 @@ public class KingdeeApBillSyncSupport {
entry.setEPricetaxtotal(entryGroup.amount()); entry.setEPricetaxtotal(entryGroup.amount());
// 金额(不含税):结算明细行结算金额(不含税),结算合计费用项行无不含税金额不传 // 金额(不含税):结算明细行结算金额(不含税),结算合计费用项行无不含税金额不传
entry.setEAmount(entryGroup.amountNoTax()); entry.setEAmount(entryGroup.amountNoTax());
// 【必填】项目.项目编码(联调期临时传金蝶测试档案值) // 【必填】项目.项目编码:开关开启取项目档案真实编码(金蝶档案须已存在且编码一致),未关联项目兜底 999
entry.setProjectNumber(KingdeeBfiConstant.BFI_AP_BILL_PROJECT_NUMBER_TEST); entry.setProjectNumber(this.kingdeeProjectNumber(settlement.getProjectId(), context));
// 【必填】外部系统来源分录标识(候选键):结算明细行取单据号,结算合计费用项行取结算单号-费用类型-费用项拼接 // 【必填】外部系统来源分录标识(候选键):结算明细行取单据号,结算合计费用项行取结算单号-费用类型-费用项拼接
entry.setAwrpEntryCode(entryGroup.entryCode()); entry.setAwrpEntryCode(entryGroup.entryCode());
// 分录备注(非必传) // 分录备注(非必传)
@@ -1171,6 +1170,26 @@ public class KingdeeApBillSyncSupport {
return config.getKingdeeDeptCode().trim(); return config.getKingdeeDeptCode().trim();
} }
/**
* 金蝶项目编码:开关 thirdparty.bfi.project-real-code-enabled 开启时取项目档案
* blade_project_apply.project_code 真实值(金蝶项目档案须已存在且编码一致,否则该单推送失败),
* 项目未关联/编码为空兜底 999;开关关闭维持联调临时值 999。
* 财务应付/应收分录、付款申请、开票申请单项目编码统一走本方法,批量同步按项目id缓存复用
*
* @param projectId 单据关联项目id
* @param context 金蝶同步上下文(缓存载体)
* @return 金蝶项目编码
*/
public String kingdeeProjectNumber(Long projectId, KingdeeSyncContext context) {
if (!bfiProperties.isProjectRealCodeEnabled() || projectId == null) {
return KingdeeBfiConstant.BFI_PROJECT_NUMBER_NONE;
}
// 批量同步时按项目id缓存复用(同一项目只查一次),单笔同步退化为直接查询
ProjectApply project = context.projectCache().computeIfAbsent(projectId, projectApplyMapper::selectById);
return project == null || Func.isBlank(project.getProjectCode())
? KingdeeBfiConstant.BFI_PROJECT_NUMBER_NONE : project.getProjectCode();
}
/** 金蝶组织/部门编码共用校验:项目存在且已维护业务部门 */ /** 金蝶组织/部门编码共用校验:项目存在且已维护业务部门 */
private ProjectApply requireOrgProject(Long projectId, KingdeeSyncContext context) { private ProjectApply requireOrgProject(Long projectId, KingdeeSyncContext context) {
if (projectId == null) { if (projectId == null) {
@@ -256,7 +256,11 @@ public class KingdeeArBillSyncSupport {
param.setAwrpSrcSys(bfiProperties.getSrcSys()); param.setAwrpSrcSys(bfiProperties.getSrcSys());
// 【必填】外部系统来源单据号(候选键):正式结算单号_结算明细单据号1_单据号2...(复用预检已组装的防重键) // 【必填】外部系统来源单据号(候选键):正式结算单号_结算明细单据号1_单据号2...(复用预检已组装的防重键)
param.setAwrpSrcCode(arBillSrcCode); param.setAwrpSrcCode(arBillSrcCode);
// 来源单据(非必传,有上游合同时传 awrp_contract_info),当前与应付单保持一致不传 // 来源单据 + 上游合同号(非必传):开关开启且合同已同步金蝶(kingdee_id 非空)时送出,与应付单同口径
if (bfiProperties.isContractRefEnabled() && Func.isNotBlank(contract.getContractNo()) && Func.isNotBlank(contract.getKingdeeId())) {
param.setAwrpSrcBt(KingdeeBfiConstant.BFI_CONTRACT_SRC_BT);
param.setAwrpSrcConNo(contract.getContractNo());
}
// 【必填】外部单据类型 // 【必填】外部单据类型
param.setAwrpSrcType(KingdeeBfiConstant.BFI_AR_BILL_SRC_TYPE); param.setAwrpSrcType(KingdeeBfiConstant.BFI_AR_BILL_SRC_TYPE);
@@ -289,8 +293,8 @@ public class KingdeeArBillSyncSupport {
row.setERecamount(entryGroup.amount()); row.setERecamount(entryGroup.amount());
// 金额(不含税):结算明细行结算金额(不含税),结算合计费用项行无不含税金额不传 // 金额(不含税):结算明细行结算金额(不含税),结算合计费用项行无不含税金额不传
row.setEAmount(entryGroup.amountNoTax()); row.setEAmount(entryGroup.amountNoTax());
// 【必填】项目.项目编码(联调期临时传金蝶测试档案值) // 【必填】项目.项目编码:开关开启取项目档案真实编码(金蝶档案须已存在且编码一致),未关联项目兜底 999
row.setProjectNumber(KingdeeBfiConstant.BFI_AP_BILL_PROJECT_NUMBER_TEST); row.setProjectNumber(kingdeeApBillSyncSupport.kingdeeProjectNumber(settlement.getProjectId(), context));
// 【必填】外部系统来源分录标识(候选键):结算明细行取单据号,结算合计费用项行取结算单号-费用类型-费用项拼接 // 【必填】外部系统来源分录标识(候选键):结算明细行取单据号,结算合计费用项行取结算单号-费用类型-费用项拼接
row.setAwrpEntryCode(entryGroup.entryCode()); row.setAwrpEntryCode(entryGroup.entryCode());
// 分录备注(非必传) // 分录备注(非必传)
+6
View File
@@ -162,6 +162,12 @@ thirdParty:
# 数据来源系统编码(推送金蝶公共参数:客商、付款申请等统一使用),默认 WLTMS(运输TMS) # 数据来源系统编码(推送金蝶公共参数:客商、付款申请等统一使用),默认 WLTMS(运输TMS)
srcSys: ${BFI_SRC_SYS:WLTMS} srcSys: ${BFI_SRC_SYS:WLTMS}
# 项目编码真实化开关:开启后推送金蝶的项目编码取 blade_project_apply.project_code 真实值
# (前提:金蝶项目档案已存在且编码与 project_code 一致,否则该单推送失败回写单据可重推;未关联项目兜底 999)
projectRealCodeEnabled: ${BFI_PROJECT_REAL_CODE_ENABLED:false}
# 合同引用开关:开启后财务应付/应收送上游合同号(仅 kingdee_id 非空的已同步合同)、开票申请送合同三件套(contractdate 取申请日期)
contractRefEnabled: ${BFI_CONTRACT_REF_ENABLED:false}
# 金蝶黑名单查询(A801-5 客商提审拦截):禁止交易类(A)始终拦截; # 金蝶黑名单查询(A801-5 客商提审拦截):禁止交易类(A)始终拦截;
# 风险警示类(B)默认放行告警,开启后一并拦截 # 风险警示类(B)默认放行告警,开启后一并拦截
blacklist: blacklist:
+5
View File
@@ -127,6 +127,11 @@ thirdParty:
readTimeoutSeconds: ${BFI_READ_TIMEOUT_SECONDS:120} readTimeoutSeconds: ${BFI_READ_TIMEOUT_SECONDS:120}
# 数据来源系统编码(推送金蝶公共参数:客商、付款申请等统一使用),默认 WLTMS(运输TMS) # 数据来源系统编码(推送金蝶公共参数:客商、付款申请等统一使用),默认 WLTMS(运输TMS)
srcSys: ${BFI_SRC_SYS:WLTMS} srcSys: ${BFI_SRC_SYS:WLTMS}
# 项目编码真实化开关:开启后推送金蝶的项目编码取 blade_project_apply.project_code 真实值
# (前提:金蝶项目档案已存在且编码与 project_code 一致,否则该单推送失败回写单据可重推;未关联项目兜底 999)
projectRealCodeEnabled: ${BFI_PROJECT_REAL_CODE_ENABLED:false}
# 合同引用开关:开启后财务应付/应收送上游合同号(仅 kingdee_id 非空的已同步合同)、开票申请送合同三件套(contractdate 取申请日期)
contractRefEnabled: ${BFI_CONTRACT_REF_ENABLED:false}
# 金蝶黑名单查询(A801-5 客商提审拦截):禁止交易类(A)始终拦截; # 金蝶黑名单查询(A801-5 客商提审拦截):禁止交易类(A)始终拦截;
# 风险警示类(B)默认放行告警,开启后一并拦截 # 风险警示类(B)默认放行告警,开启后一并拦截
blacklist: blacklist:
+5
View File
@@ -64,6 +64,11 @@ thirdParty:
# 数据来源系统编码(推送金蝶公共参数:客商、付款申请等统一使用),默认 WLTMS(运输TMS) # 数据来源系统编码(推送金蝶公共参数:客商、付款申请等统一使用),默认 WLTMS(运输TMS)
srcSys: ${BFI_SRC_SYS:WLTMS} srcSys: ${BFI_SRC_SYS:WLTMS}
# 项目编码真实化开关:开启后推送金蝶的项目编码取 blade_project_apply.project_code 真实值
# (前提:金蝶项目档案已存在且编码与 project_code 一致,否则该单推送失败回写单据可重推;未关联项目兜底 999)
projectRealCodeEnabled: ${BFI_PROJECT_REAL_CODE_ENABLED:false}
# 合同引用开关:开启后财务应付/应收送上游合同号(仅 kingdee_id 非空的已同步合同)、开票申请送合同三件套(contractdate 取申请日期)
contractRefEnabled: ${BFI_CONTRACT_REF_ENABLED:false}
# 金蝶黑名单查询(A801-5 客商提审拦截):禁止交易类(A)始终拦截; # 金蝶黑名单查询(A801-5 客商提审拦截):禁止交易类(A)始终拦截;
# 风险警示类(B)默认放行告警,开启后一并拦截 # 风险警示类(B)默认放行告警,开启后一并拦截
blacklist: blacklist: