├── .gitignore ├── src ├── main │ ├── resources │ │ └── rule-dao.properties │ └── java │ │ └── com │ │ └── zhugw │ │ └── demo │ │ ├── App.java │ │ ├── template │ │ ├── model │ │ │ ├── Rule.java │ │ │ ├── RuleContext.java │ │ │ ├── FeeData.java │ │ │ └── ApplyInfo.java │ │ ├── Temp.java │ │ ├── MobileVerificationManager.java │ │ ├── NameIdCardVerificationManager.java │ │ ├── AbstractFeeDataManagerTemplate.java │ │ ├── FeeDataManagerFacade.java │ │ ├── AbstractFeeRuleProcessServiceTemplate.java │ │ ├── AbstractFeeRuleProcessServiceTemplate2.java │ │ ├── AbstractBatchFeeRuleProcessServiceTemplate.java │ │ ├── FeeDataManagerFacade2.java │ │ └── Main.java │ │ └── localdata │ │ ├── dao │ │ └── ApplyDAO.java │ │ ├── AppConfig.java │ │ └── service │ │ └── LocalDataQueryService.java └── test │ └── java │ └── com │ └── zhugw │ └── demo │ ├── AppTest.java │ └── localdata │ ├── LocalDataRuleServiceTest.java │ └── AppConfigTest.java ├── README.md └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | antifraud-design-demo.iml 3 | antifraud-design.iml 4 | target/ 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/rule-dao.properties: -------------------------------------------------------------------------------- 1 | 1=applyDAO#countApply#idcard,0 2 | 2=applyDAO#countRefusedApply#idcard,0 3 | 3=applyDAO#sumCreditAmount#idcard,0 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # antifraud-design-demo 2 | 风控系统设计demo 3 | 4 | 见 5 | 6 | https://segmentfault.com/a/1190000009151738 7 | 8 | https://segmentfault.com/a/1190000009192179 9 | -------------------------------------------------------------------------------- /src/main/java/com/zhugw/demo/App.java: -------------------------------------------------------------------------------- 1 | package com.zhugw.demo; 2 | 3 | /** 4 | * Hello world! 5 | * 6 | */ 7 | public class App 8 | { 9 | public static void main( String[] args ) 10 | { 11 | System.out.println( "Hello World!" ); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/zhugw/demo/template/model/Rule.java: -------------------------------------------------------------------------------- 1 | package com.zhugw.demo.template.model; 2 | 3 | /** 4 | * Created by zhuguowei on 4/21/17. 5 | */ 6 | public class Rule { 7 | public String getFeeDataCode() { 8 | return null; 9 | } 10 | 11 | public String getResult() { 12 | return null; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/zhugw/demo/template/Temp.java: -------------------------------------------------------------------------------- 1 | package com.zhugw.demo.template; 2 | 3 | /** 4 | * Created by zhuguowei on 4/25/17. 5 | */ 6 | public class Temp { 7 | public static void main(String[] args) { 8 | Object o = "0.11"; 9 | double d = Double.valueOf(o.toString()); 10 | System.out.println(d); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/zhugw/demo/template/model/RuleContext.java: -------------------------------------------------------------------------------- 1 | package com.zhugw.demo.template.model; 2 | 3 | /** 4 | * Created by zhuguowei on 4/21/17. 5 | */ 6 | public class RuleContext { 7 | public Rule getRule() { 8 | return new Rule(); 9 | } 10 | 11 | public void setResult(String refuse) { 12 | 13 | } 14 | 15 | public void setMessage(String format) { 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/zhugw/demo/localdata/dao/ApplyDAO.java: -------------------------------------------------------------------------------- 1 | package com.zhugw.demo.localdata.dao; 2 | 3 | 4 | import org.springframework.stereotype.Repository; 5 | 6 | /** 7 | * Created by zhuguowei on 4/25/17. 8 | */ 9 | @Repository 10 | public class ApplyDAO { 11 | public int countApply(String idCard,int daysAgo) { 12 | return 2; 13 | } 14 | public int countRefusedApply(String idcard, int daysAgo){ 15 | return 1; 16 | } 17 | public int sumCreditAmount(String idcard, int daysAgo){ 18 | return 1000; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/zhugw/demo/template/model/FeeData.java: -------------------------------------------------------------------------------- 1 | package com.zhugw.demo.template.model; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * Created by zhuguowei on 4/21/17. 8 | */ 9 | public class FeeData { 10 | private HashMap extra; 11 | 12 | public boolean isPass() { 13 | return false; 14 | } 15 | 16 | public Map getExtra() { 17 | return new HashMap(); 18 | } 19 | 20 | public void setExtra(HashMap extra) { 21 | this.extra = extra; 22 | } 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/zhugw/demo/template/MobileVerificationManager.java: -------------------------------------------------------------------------------- 1 | package com.zhugw.demo.template; 2 | 3 | import com.zhugw.demo.template.model.FeeData; 4 | 5 | import java.util.Map; 6 | 7 | /** 8 | * 手机号码实名认证 9 | * Created by zhuguowei on 4/21/17. 10 | */ 11 | public class MobileVerificationManager extends AbstractFeeDataManagerTemplate { 12 | protected void buildParams(Map params) { 13 | params.put("code", "mobile_verification"); 14 | } 15 | 16 | protected FeeData resolveResponse(String response) { 17 | return null; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/zhugw/demo/template/NameIdCardVerificationManager.java: -------------------------------------------------------------------------------- 1 | package com.zhugw.demo.template; 2 | 3 | import com.zhugw.demo.template.model.FeeData; 4 | 5 | import java.util.Map; 6 | 7 | /** 8 | * 姓名身份证号码实名认证 9 | * Created by zhuguowei on 4/21/17. 10 | */ 11 | public class NameIdCardVerificationManager extends AbstractFeeDataManagerTemplate { 12 | 13 | 14 | protected void buildParams(Map params) { 15 | // 组装此接口特有且恒定入参 如 16 | params.put("code", "name_idcard_verfication"); 17 | 18 | } 19 | 20 | protected FeeData resolveResponse(String response) { 21 | return null; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/zhugw/demo/template/AbstractFeeDataManagerTemplate.java: -------------------------------------------------------------------------------- 1 | package com.zhugw.demo.template; 2 | 3 | import com.zhugw.demo.template.model.FeeData; 4 | 5 | import java.util.Map; 6 | 7 | /** 8 | * Created by zhuguowei on 4/21/17. 9 | */ 10 | public abstract class AbstractFeeDataManagerTemplate { 11 | protected abstract void buildParams(Map params); 12 | 13 | public FeeData getFeeData(Map params){ 14 | buildParams(params); 15 | String response = sendRequest(params); 16 | return resolveResponse(response); 17 | } 18 | 19 | protected abstract FeeData resolveResponse(String response); 20 | 21 | private String sendRequest(Map params) { 22 | return ""; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/zhugw/demo/template/FeeDataManagerFacade.java: -------------------------------------------------------------------------------- 1 | package com.zhugw.demo.template; 2 | 3 | import com.zhugw.demo.template.model.FeeData; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | /** 9 | * 收费数据门面模式 10 | * Created by zhuguowei on 4/21/17. 11 | */ 12 | public class FeeDataManagerFacade { 13 | private static Map code2FeeDataManagerMap = new HashMap(); 14 | static{ 15 | code2FeeDataManagerMap.put("NAME_IDCARD_VERIFICATION", new NameIdCardVerificationManager()); 16 | //... 17 | } 18 | public FeeData getFeeData(String code, Map params){ 19 | return code2FeeDataManagerMap.get(code).getFeeData(params); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/com/zhugw/demo/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.zhugw.demo; 2 | 3 | import junit.framework.Test; 4 | import junit.framework.TestCase; 5 | import junit.framework.TestSuite; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | extends TestCase 12 | { 13 | /** 14 | * Create the test case 15 | * 16 | * @param testName name of the test case 17 | */ 18 | public AppTest( String testName ) 19 | { 20 | super( testName ); 21 | } 22 | 23 | /** 24 | * @return the suite of tests being tested 25 | */ 26 | public static Test suite() 27 | { 28 | return new TestSuite( AppTest.class ); 29 | } 30 | 31 | /** 32 | * Rigourous Test :-) 33 | */ 34 | public void testApp() 35 | { 36 | assertTrue( true ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/zhugw/demo/localdata/AppConfig.java: -------------------------------------------------------------------------------- 1 | package com.zhugw.demo.localdata; 2 | 3 | import org.springframework.beans.factory.config.PropertiesFactoryBean; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.ComponentScan; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.core.io.ClassPathResource; 8 | 9 | /** 10 | * Created by zhuguowei on 4/25/17. 11 | */ 12 | @Configuration 13 | @ComponentScan(basePackages = "com.zhugw.demo.localdata") 14 | public class AppConfig { 15 | 16 | @Bean(name = "ruleDaoProperties") 17 | public PropertiesFactoryBean mapper() { 18 | PropertiesFactoryBean bean = new PropertiesFactoryBean(); 19 | bean.setLocation(new ClassPathResource("rule-dao.properties")); 20 | return bean; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/zhugw/demo/template/model/ApplyInfo.java: -------------------------------------------------------------------------------- 1 | package com.zhugw.demo.template.model; 2 | 3 | /** 4 | * Created by zhuguowei on 4/25/17. 5 | */ 6 | public class ApplyInfo { 7 | private CharSequence residenceAddressProvinceName; 8 | private CharSequence residenceAddressCountyName; 9 | private Object residenceAddressCityName; 10 | private Object thirdBusinessAddress; 11 | private String idcard; 12 | 13 | public CharSequence getResidenceAddressProvinceName() { 14 | return residenceAddressProvinceName; 15 | } 16 | 17 | public CharSequence getResidenceAddressCountyName() { 18 | return residenceAddressCountyName; 19 | } 20 | 21 | public Object getResidenceAddressCityName() { 22 | return residenceAddressCityName; 23 | } 24 | 25 | public Object getThirdBusinessAddress() { 26 | return thirdBusinessAddress; 27 | } 28 | 29 | public void setIdcard(String idcard) { 30 | this.idcard = idcard; 31 | } 32 | 33 | public String getIdcard() { 34 | return idcard; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/zhugw/demo/template/AbstractFeeRuleProcessServiceTemplate.java: -------------------------------------------------------------------------------- 1 | package com.zhugw.demo.template; 2 | 3 | import com.zhugw.demo.template.model.FeeData; 4 | import com.zhugw.demo.template.model.RuleContext; 5 | 6 | import java.util.Map; 7 | 8 | /** 9 | * 通用收费规则处理模板 10 | * Created by zhuguowei on 4/21/17. 11 | */ 12 | public abstract class AbstractFeeRuleProcessServiceTemplate { 13 | private static FeeDataManagerFacade facade = new FeeDataManagerFacade(); 14 | public void process(Map params, RuleContext ruleContext){ 15 | try { 16 | FeeData feeData = facade.getFeeData(ruleContext.getRule().getFeeDataCode(), params); 17 | if(!feeData.isPass()){ 18 | // 校验未通过处理 19 | ruleContext.setResult(ruleContext.getRule().getResult()); // 设置决策结果:拒绝 20 | ruleContext.setMessage(buildMessage()); 21 | } 22 | } catch (Exception e) { 23 | // 接口调用异常 默认为人工复核 24 | ruleContext.setResult("REVIEW"); // 设置决策结果:人工复核 25 | ruleContext.setMessage(String.format("接口调用失败: %s",e.getMessage())); 26 | } 27 | 28 | } 29 | 30 | protected abstract String buildMessage(); 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/com/zhugw/demo/localdata/LocalDataRuleServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.zhugw.demo.localdata; 2 | 3 | import com.zhugw.demo.localdata.service.LocalDataQueryService; 4 | import com.zhugw.demo.template.model.ApplyInfo; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.test.context.ContextConfiguration; 9 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 10 | 11 | import java.util.Map; 12 | 13 | import static com.google.common.collect.Lists.newArrayList; 14 | import static org.junit.Assert.assertEquals; 15 | 16 | /** 17 | * Created by zhuguowei on 4/25/17. 18 | */ 19 | @ContextConfiguration(classes = AppConfig.class) 20 | @RunWith(SpringJUnit4ClassRunner.class) 21 | public class LocalDataRuleServiceTest { 22 | @Autowired 23 | private LocalDataQueryService localDataRuleService; 24 | @Test 25 | public void batchQueryLocalData() throws Exception { 26 | ApplyInfo applyInfo = new ApplyInfo(); 27 | applyInfo.setIdcard("123456199001011233"); 28 | Map map = localDataRuleService.batchQueryLocalData(applyInfo, newArrayList(1,2,3)); 29 | assertEquals(3, map.size()); 30 | System.out.println(map); 31 | } 32 | 33 | } -------------------------------------------------------------------------------- /src/main/java/com/zhugw/demo/template/AbstractFeeRuleProcessServiceTemplate2.java: -------------------------------------------------------------------------------- 1 | package com.zhugw.demo.template; 2 | 3 | import com.zhugw.demo.template.model.FeeData; 4 | import com.zhugw.demo.template.model.RuleContext; 5 | 6 | import java.util.Map; 7 | 8 | /** 9 | * 通用收费规则处理模板 10 | * Created by zhuguowei on 4/21/17. 11 | */ 12 | public abstract class AbstractFeeRuleProcessServiceTemplate2 { 13 | private static FeeDataManagerFacade facade = new FeeDataManagerFacade(); 14 | public void process(Map params, RuleContext ruleContext){ 15 | try { 16 | FeeData feeData = facade.getFeeData(ruleContext.getRule().getFeeDataCode(), params); 17 | if(!checkFeeData(feeData)){ 18 | // 校验未通过处理 19 | ruleContext.setResult(ruleContext.getRule().getResult()); // 设置决策结果:拒绝 20 | ruleContext.setMessage(buildMessage(feeData)); 21 | } 22 | } catch (Exception e) { 23 | // 接口调用异常 默认为人工复核 24 | ruleContext.setResult("REVIEW"); // 设置决策结果:人工复核 25 | ruleContext.setMessage(String.format("接口调用失败: %s",e.getMessage())); 26 | } 27 | 28 | } 29 | 30 | protected abstract boolean checkFeeData(FeeData feeData); 31 | 32 | protected abstract String buildMessage(FeeData feeData); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/com/zhugw/demo/localdata/AppConfigTest.java: -------------------------------------------------------------------------------- 1 | package com.zhugw.demo.localdata; 2 | 3 | import com.zhugw.demo.localdata.dao.ApplyDAO; 4 | import org.junit.Test; 5 | import org.junit.runner.RunWith; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.context.ApplicationContext; 8 | import org.springframework.test.context.ContextConfiguration; 9 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 10 | 11 | import javax.annotation.Resource; 12 | import java.util.Map; 13 | import java.util.Properties; 14 | 15 | import static junit.framework.Assert.assertEquals; 16 | import static junit.framework.Assert.assertNotNull; 17 | 18 | /** 19 | * Created by zhuguowei on 4/25/17. 20 | */ 21 | @ContextConfiguration(classes = AppConfig.class) 22 | @RunWith(SpringJUnit4ClassRunner.class) 23 | public class AppConfigTest { 24 | // private ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); 25 | @Autowired 26 | private ApplicationContext context; 27 | 28 | @Resource(name = "ruleDaoProperties") 29 | private Map rule2DaoMap; 30 | 31 | @Test 32 | public void test_component_scan(){ 33 | 34 | ApplyDAO applyDAO = (ApplyDAO) context.getBean("applyDAO"); 35 | assertNotNull(applyDAO); 36 | } 37 | @Test 38 | public void test_get_bean(){ 39 | Properties ruleDaoProperties = (Properties) context.getBean("ruleDaoProperties"); 40 | System.out.println(ruleDaoProperties); 41 | } 42 | @Test 43 | public void test_properties_2_map(){ 44 | assertEquals(3, rule2DaoMap.size()); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/zhugw/demo/template/AbstractBatchFeeRuleProcessServiceTemplate.java: -------------------------------------------------------------------------------- 1 | package com.zhugw.demo.template; 2 | 3 | import com.zhugw.demo.template.model.FeeData; 4 | import com.zhugw.demo.template.model.RuleContext; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | /** 10 | * 通用批量收费规则处理模板 11 | * Created by zhuguowei on 4/21/17. 12 | */ 13 | public abstract class AbstractBatchFeeRuleProcessServiceTemplate { 14 | private static final FeeDataManagerFacade facade = new FeeDataManagerFacade(); 15 | public void process(List params, RuleContext ruleContext){ 16 | try { 17 | String feeDataCode = ruleContext.getRule().getFeeDataCode(); 18 | String[] codes = feeDataCode.split(","); 19 | for (int i = 0; i < codes.length; i++) { 20 | FeeData feeData = facade.getFeeData(codes[i], params.get(i)); 21 | if(!checkFeeData(feeData)){ 22 | if(i < codes.length - 1){ 23 | // 校验未通过 继续往下执行 24 | continue; 25 | } 26 | // 所有校验均未通过处理 27 | ruleContext.setResult(ruleContext.getRule().getResult()); // 设置决策结果:拒绝 28 | ruleContext.setMessage(buildMessage(feeData)); 29 | 30 | } 31 | // 任一校验通过 直接返回 32 | return ; 33 | 34 | } 35 | 36 | } catch (Exception e) { 37 | // 接口调用异常 默认为人工复核 38 | ruleContext.setResult("REVIEW"); // 设置决策结果:人工复核 39 | ruleContext.setMessage(String.format("接口调用失败: %s",e.getMessage())); 40 | } 41 | 42 | } 43 | 44 | protected abstract boolean checkFeeData(FeeData feeData); 45 | 46 | protected abstract String buildMessage(FeeData feeData); 47 | 48 | } 49 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.zhugw.demo 6 | antifraud-design 7 | 1.0-SNAPSHOT 8 | jar 9 | 10 | antifraud-design-demo 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 16 | 17 | 18 | 19 | 20 | org.springframework 21 | spring-test 22 | 4.3.8.RELEASE 23 | 24 | 25 | io.springside 26 | springside-utils 27 | 5.0.0-RC1 28 | 29 | 30 | 31 | 32 | org.springframework 33 | spring-context 34 | 4.3.8.RELEASE 35 | 36 | 37 | 38 | com.google.guava 39 | guava 40 | 21.0 41 | 42 | 43 | 44 | org.springframework 45 | spring-expression 46 | 4.3.8.RELEASE 47 | 48 | 49 | junit 50 | junit 51 | 4.12 52 | test 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/main/java/com/zhugw/demo/localdata/service/LocalDataQueryService.java: -------------------------------------------------------------------------------- 1 | package com.zhugw.demo.localdata.service; 2 | 3 | import com.zhugw.demo.template.model.ApplyInfo; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.context.ApplicationContext; 6 | import org.springframework.expression.Expression; 7 | import org.springframework.expression.ExpressionParser; 8 | import org.springframework.expression.spel.standard.SpelExpressionParser; 9 | import org.springframework.stereotype.Service; 10 | import org.springside.modules.utils.reflect.ReflectionUtil; 11 | 12 | import javax.annotation.Resource; 13 | import java.util.ArrayList; 14 | import java.util.HashMap; 15 | import java.util.List; 16 | import java.util.Map; 17 | 18 | /** 19 | * 本地数据源查询 20 | * Created by zhuguowei on 4/25/17. 21 | */ 22 | @Service 23 | public class LocalDataQueryService { 24 | 25 | @Resource(name = "ruleDaoProperties") 26 | private Map rule2DaoMap; 27 | 28 | @Autowired 29 | private ApplicationContext context; 30 | 31 | private static final ExpressionParser expressionParser = new SpelExpressionParser(); 32 | 33 | public Map batchQueryLocalData(ApplyInfo applyInfo,List ruleIdList){ 34 | Map id2LocalDataMap = new HashMap<>(); 35 | for (Integer ruleId : ruleIdList) { 36 | // 找到该规则对应的配置 1=applyDAO#countApply#idcard,0 37 | String[] split = rule2DaoMap.get(ruleId.toString()).split("#"); 38 | String daoBean = split[0]; 39 | String method = split[1]; 40 | List paramList = new ArrayList<>(); 41 | if(split.length == 3) { 42 | String args = split[2]; 43 | // 解析参数 44 | resolveParamValue(applyInfo, paramList, args); 45 | } 46 | Object bean = context.getBean(daoBean); 47 | // 反射调用 48 | Object result = ReflectionUtil.invokeMethod(bean, method, paramList.toArray(new Object[]{paramList.size()})); 49 | id2LocalDataMap.put(ruleId, result); 50 | } 51 | 52 | return id2LocalDataMap; 53 | } 54 | 55 | private void resolveParamValue(ApplyInfo applyInfo, List paramList, String args) { 56 | String[] argArray = args.split(","); 57 | for (String arg : argArray) { 58 | Expression expression = expressionParser.parseExpression(arg); 59 | Object value = expression.getValue(applyInfo); 60 | paramList.add(value); 61 | } 62 | } 63 | 64 | public Map getRule2DaoMap() { 65 | return rule2DaoMap; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/zhugw/demo/template/FeeDataManagerFacade2.java: -------------------------------------------------------------------------------- 1 | package com.zhugw.demo.template; 2 | 3 | import com.zhugw.demo.template.model.FeeData; 4 | import org.springframework.expression.Expression; 5 | import org.springframework.expression.ExpressionParser; 6 | import org.springframework.expression.spel.standard.SpelExpressionParser; 7 | 8 | import java.util.*; 9 | 10 | /** 11 | * 收费数据门面模式 12 | * Created by zhuguowei on 4/21/17. 13 | */ 14 | public class FeeDataManagerFacade2 { 15 | private static Map code2FeeDataManagerMap = new HashMap(); 16 | static{ 17 | code2FeeDataManagerMap.put("NAME_IDCARD_VERIFICATION", new NameIdCardVerificationManager()); 18 | //... 19 | } 20 | private static final ExpressionParser expressionParser = new SpelExpressionParser(); 21 | public FeeData getFeeData(String code, Map params){ 22 | if("BATCH_QUERY_FEEDATA".equals(code)){ // 批量查询 23 | List> paramList = (List>) params.get("paramList"); 24 | List feeDataList = new ArrayList(); 25 | FeeData previous = null; 26 | for (Map param : paramList) { 27 | String realCode = (String) param.get("code"); // 实际接口编码 28 | Objects.requireNonNull(realCode,"接口编码不可为空"); 29 | // 若输入参数依赖前一查询结果 30 | for (Map.Entry entry : param.entrySet()) { 31 | String value = entry.getValue().toString(); 32 | if(value.startsWith("#{")){ 33 | // 表示动态变量 需要解析 34 | String el = value.replaceFirst("#\\{(.+)}", "$1"); 35 | Expression expression = expressionParser.parseExpression(el); 36 | Object resolvedValue = expression.getValue(previous); 37 | entry.setValue(resolvedValue); // 实际值替换动态变量 38 | } 39 | } 40 | FeeData feeData = code2FeeDataManagerMap.get(realCode).getFeeData(params); 41 | feeDataList.add(feeData); 42 | previous = feeData; 43 | } 44 | FeeData result = new FeeData(); 45 | result.setExtra(newHashMap("feeDataList",feeDataList)); 46 | return result; 47 | } 48 | // 单个查询 49 | return code2FeeDataManagerMap.get(code).getFeeData(params); 50 | } 51 | 52 | private HashMap newHashMap(String key, Object value) { 53 | HashMap extra = new HashMap(); 54 | extra.put(key, value); 55 | return extra; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/zhugw/demo/template/Main.java: -------------------------------------------------------------------------------- 1 | package com.zhugw.demo.template; 2 | 3 | import com.zhugw.demo.template.model.ApplyInfo; 4 | import com.zhugw.demo.template.model.FeeData; 5 | import com.zhugw.demo.template.model.RuleContext; 6 | 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | import static com.google.common.collect.Lists.newArrayList; 12 | 13 | /** 14 | * Created by zhuguowei on 4/21/17. 15 | */ 16 | public class Main { 17 | public static void main(String[] args) { 18 | //执行规则一 -- 申请人姓名身份证号实名验证 19 | FeeDataManagerFacade feeDataManagerFacade = new FeeDataManagerFacade(); 20 | 21 | RuleContext ruleContext = new RuleContext(); 22 | String code = ruleContext.getRule().getFeeDataCode(); 23 | 24 | final Map params = new HashMap(); 25 | params.put("name", "张三"); 26 | params.put("idcard", "123456199001011233"); 27 | 28 | final ApplyInfo applyInfo = new ApplyInfo(); 29 | 30 | // try { 31 | // FeeData feeData = feeDataManagerFacade.getFeeData(code, params); 32 | // if(!feeData.isPass()){ 33 | // // 校验未通过处理 34 | // ruleContext.setResult(ruleContext.getRule().getResult()); // 设置决策结果:拒绝 35 | // ruleContext.setMessage(String.format("申请人姓名: %s 身份证号: %s 实名验证失败",params.get("name"),params.get("idcard"))); 36 | // } 37 | // } catch (Exception e) { 38 | // // 接口调用异常 默认为人工复核 39 | // ruleContext.setResult("REVIEW"); // 设置决策结果:人工复核 40 | // ruleContext.setMessage(String.format("接口调用失败: %s",e.getMessage())); 41 | // } 42 | 43 | // new AbstractFeeRuleProcessServiceTemplate(){ 44 | // @Override 45 | // protected String buildMessage() { 46 | // return String.format("申请人姓名: %s 身份证号: %s 实名验证失败",params.get("name"),params.get("idcard")); 47 | // } 48 | // }.process(params,ruleContext); 49 | 50 | new AbstractFeeRuleProcessServiceTemplate2(){ 51 | 52 | @Override 53 | protected boolean checkFeeData(FeeData feeData) { 54 | return feeData.isPass(); 55 | } 56 | 57 | @Override 58 | protected String buildMessage(FeeData feeData) { 59 | return String.format("申请人姓名: %s 身份证号: %s 实名验证失败",params.get("name"),params.get("idcard")); 60 | } 61 | }.process(params,ruleContext); 62 | 63 | // 规则6--户籍地址与身份证号归属地比对 64 | new AbstractFeeRuleProcessServiceTemplate2(){ 65 | @Override 66 | protected boolean checkFeeData(FeeData feeData) { 67 | // 如 河北省 邯郸市 临漳县 、重庆市綦江县 68 | String location = (String) feeData.getExtra().get("location"); 69 | if (location.contains(applyInfo.getResidenceAddressProvinceName()) || location.contains(applyInfo.getResidenceAddressCountyName())) { 70 | return true; 71 | } 72 | return false; 73 | } 74 | 75 | @Override 76 | protected String buildMessage(FeeData feeData) { 77 | String message = String.format("自述户籍地址:%s %s %s 与身份证归属地:%s 不一致", 78 | applyInfo.getResidenceAddressProvinceName(),applyInfo.getResidenceAddressCityName() 79 | ,applyInfo.getResidenceAddressCountyName(),feeData.getExtra().get("location")); 80 | return message; 81 | } 82 | }.process(params,ruleContext); 83 | 84 | // 注册手机号码归属地与申请人身份证号归属地、现居住地、单位地址、家庭地址、户籍地址的交叉验证 85 | 86 | Map param1 = newHashMap("code", "MOBILE_LOCATION_QUERY", "mobile", "13800138000"); 87 | Map param2 = newHashMap("code", "IDCARD_LOCATION_QUERY", "idcard", "123456199001011233"); 88 | Map param = newHashMap("paramList", newArrayList(param1, param2)); 89 | new AbstractFeeRuleProcessServiceTemplate2(){ 90 | @Override 91 | protected boolean checkFeeData(FeeData feeData) { 92 | List feeDataList = (List) feeData.getExtra().get("feeDataList"); 93 | String mobileLocation = (String) feeDataList.get(0).getExtra().get("location"); 94 | String idcardLocation = (String) feeDataList.get(1).getExtra().get("location"); 95 | // ... 规则校验 96 | return false; 97 | } 98 | @Override 99 | protected String buildMessage(FeeData feeData) { 100 | //... 组装提示信息 101 | // String message = "注册手机号码归属城市:%s ,注册手机号码归属地城市与申请人一系列地址城市都不一致"; 102 | return null; 103 | } 104 | }.process(param,ruleContext); 105 | 106 | // IP地址与三级商户地址的交叉验证 107 | param1 = newHashMap("code", "IP_ADDRESS_QUERY", "ip", "222.128.42.13"); 108 | param2 = newHashMap("code", "ADDRESSES_DISTANCE_QUERY", "startAddress", applyInfo.getThirdBusinessAddress(),"endAddress","#{extra['address']}"); 109 | param = newHashMap("paramList", newArrayList(param1, param2)); 110 | 111 | new AbstractFeeRuleProcessServiceTemplate2(){ 112 | 113 | @Override 114 | protected boolean checkFeeData(FeeData feeData) { 115 | List feeDataList = (List) feeData.getExtra().get("feeDataList"); 116 | double distance = Double.valueOf(feeDataList.get(1).getExtra().get("distance").toString()); 117 | // 规则校验 ... 118 | return false; 119 | } 120 | 121 | @Override 122 | protected String buildMessage(FeeData feeData) { 123 | return null; 124 | } 125 | }.process(param,ruleContext); 126 | 127 | } 128 | 129 | private static Map newHashMap(String k1, Object v1, String k2, Object v2) { 130 | Map param1 = new HashMap(); 131 | param1.put(k2, v2); 132 | param1.put(k1, v1); 133 | return param1; 134 | } 135 | private static Map newHashMap(String k1, Object v1, String k2, Object v2, String k3, Object v3) { 136 | Map param1 = new HashMap(); 137 | param1.put(k2, v2); 138 | param1.put(k1, v1); 139 | param1.put(k3, v3); 140 | return param1; 141 | } 142 | private static Map newHashMap(String k1, Object v1) { 143 | Map param1 = new HashMap(); 144 | param1.put(k1, v1); 145 | return param1; 146 | } 147 | } 148 | --------------------------------------------------------------------------------