diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/ModelInvokeDTO.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/ModelInvokeDTO.java index 9a0348c..37fdb51 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/ModelInvokeDTO.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/ModelInvokeDTO.java @@ -150,4 +150,9 @@ public class ModelInvokeDTO { */ private String idType; + /** + * 证件号码(非必填) + */ + private String idNum; + } diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/LoanPricingModelService.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/LoanPricingModelService.java index a2b96c6..471531a 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/LoanPricingModelService.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/LoanPricingModelService.java @@ -39,12 +39,25 @@ public class LoanPricingModelService { @Resource private ModelCorpOutputFieldsMapper modelCorpOutputFieldsMapper; + @Resource + private SensitiveFieldCryptoService sensitiveFieldCryptoService; + public void invokeModelAsync(Long workflowId) { LoanPricingWorkflow loanPricingWorkflow = loanPricingWorkflowMapper.selectById(workflowId); if (Objects.isNull(loanPricingWorkflow)){ log.error("未找到对应的流程信息,未调用模型服务"); return; } + try + { + loanPricingWorkflow.setCustName(sensitiveFieldCryptoService.decrypt(loanPricingWorkflow.getCustName())); + loanPricingWorkflow.setIdNum(sensitiveFieldCryptoService.decrypt(loanPricingWorkflow.getIdNum())); + } + catch (RuntimeException ex) + { + log.error("贷款定价模型调用前敏感字段解密失败", ex); + throw ex; + } ModelInvokeDTO modelInvokeDTO = new ModelInvokeDTO(); BeanUtils.copyProperties(loanPricingWorkflow, modelInvokeDTO); JSONObject response = modelService.invokeModel(modelInvokeDTO); diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImpl.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImpl.java index 88a98f0..6bf51e1 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImpl.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImpl.java @@ -160,6 +160,10 @@ public class LoanPricingWorkflowServiceImpl implements ILoanPricingWorkflowServi LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(LoanPricingWorkflow::getSerialNum, serialNum); LoanPricingWorkflow loanPricingWorkflow = loanPricingWorkflowMapper.selectOne(wrapper); + String plainCustName = sensitiveFieldCryptoService.decrypt(loanPricingWorkflow.getCustName()); + String plainIdNum = sensitiveFieldCryptoService.decrypt(loanPricingWorkflow.getIdNum()); + loanPricingWorkflow.setCustName(loanPricingSensitiveDisplayService.maskCustName(plainCustName)); + loanPricingWorkflow.setIdNum(loanPricingSensitiveDisplayService.maskIdNum(plainIdNum)); loanPricingWorkflowVO.setLoanPricingWorkflow(loanPricingWorkflow); if (Objects.nonNull(loanPricingWorkflow.getModelOutputId())){ diff --git a/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/LoanPricingModelServiceTest.java b/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/LoanPricingModelServiceTest.java new file mode 100644 index 0000000..bd2ef6d --- /dev/null +++ b/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/LoanPricingModelServiceTest.java @@ -0,0 +1,66 @@ +package com.ruoyi.loanpricing.service; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.alibaba.fastjson2.JSONObject; +import com.ruoyi.loanpricing.domain.dto.ModelInvokeDTO; +import com.ruoyi.loanpricing.domain.entity.LoanPricingWorkflow; +import com.ruoyi.loanpricing.mapper.LoanPricingWorkflowMapper; +import com.ruoyi.loanpricing.mapper.ModelCorpOutputFieldsMapper; +import com.ruoyi.loanpricing.mapper.ModelRetailOutputFieldsMapper; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Objects; + +@ExtendWith(MockitoExtension.class) +class LoanPricingModelServiceTest +{ + @Mock + private ModelService modelService; + + @Mock + private LoanPricingWorkflowMapper loanPricingWorkflowMapper; + + @Mock + private ModelRetailOutputFieldsMapper modelRetailOutputFieldsMapper; + + @Mock + private ModelCorpOutputFieldsMapper modelCorpOutputFieldsMapper; + + @Mock + private SensitiveFieldCryptoService sensitiveFieldCryptoService; + + @InjectMocks + private LoanPricingModelService loanPricingModelService; + + @Test + void shouldDecryptCustNameAndIdNumBeforeInvokeModel() + { + LoanPricingWorkflow workflow = new LoanPricingWorkflow(); + workflow.setId(1L); + workflow.setCustType("个人"); + workflow.setCustName("cipher-name"); + workflow.setIdNum("cipher-id"); + + JSONObject response = new JSONObject(); + response.put("calculateRate", "6.15"); + + when(loanPricingWorkflowMapper.selectById(1L)).thenReturn(workflow); + when(sensitiveFieldCryptoService.decrypt("cipher-name")).thenReturn("张三"); + when(sensitiveFieldCryptoService.decrypt("cipher-id")).thenReturn("110101199001011234"); + when(modelService.invokeModel(any())).thenReturn(response); + + loanPricingModelService.invokeModelAsync(1L); + + verify(modelService).invokeModel(argThat((ModelInvokeDTO dto) -> + Objects.equals("张三", dto.getCustName()) + && Objects.equals("110101199001011234", dto.getIdNum()))); + } +} diff --git a/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImplTest.java b/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImplTest.java index 8933b81..f8c9a34 100644 --- a/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImplTest.java +++ b/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImplTest.java @@ -154,6 +154,27 @@ class LoanPricingWorkflowServiceImplTest assertEquals("6.15", result.getModelRetailOutputFields().getCalculateRate()); } + @Test + void shouldMaskCustNameAndIdNumWhenReturningWorkflowDetail() + { + LoanPricingWorkflow workflow = new LoanPricingWorkflow(); + workflow.setSerialNum("P20260328001"); + workflow.setCustType("个人"); + workflow.setCustName("cipher-name"); + workflow.setIdNum("cipher-id"); + + when(loanPricingWorkflowMapper.selectOne(any())).thenReturn(workflow); + when(sensitiveFieldCryptoService.decrypt("cipher-name")).thenReturn("张三"); + when(sensitiveFieldCryptoService.decrypt("cipher-id")).thenReturn("110101199001011234"); + when(loanPricingSensitiveDisplayService.maskCustName("张三")).thenReturn("张*"); + when(loanPricingSensitiveDisplayService.maskIdNum("110101199001011234")).thenReturn("1101********1234"); + + LoanPricingWorkflowVO result = loanPricingWorkflowService.selectLoanPricingBySerialNum("P20260328001"); + + assertEquals("张*", result.getLoanPricingWorkflow().getCustName()); + assertEquals("1101********1234", result.getLoanPricingWorkflow().getIdNum()); + } + @Test void shouldUseCorporateModelOutputCalculateRateForWorkflowDetail() {