mirror of
https://gitee.com/freshday/radar.git
synced 2026-03-22 04:37:16 +08:00
1
.gitignore
vendored
1
.gitignore
vendored
@@ -21,3 +21,4 @@ webapp/node_modules/
|
||||
.settings
|
||||
.classpath
|
||||
.factorypath
|
||||
/radar-kafka-demo/target/
|
||||
|
||||
74
README_en.md
Normal file
74
README_en.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# Risk Engine(Radar)
|
||||
## Introduction
|
||||
|
||||
A real-time risk analysis engine,which can update risk rule in real-time and make it effective immediately.
|
||||
It applies to the anti-fraud application perfectly.
|
||||
The project code called Radar, like the code, monitor the transaction at the back.
|
||||
|
||||
## FEATURE
|
||||
|
||||
* real-time
|
||||
* visual rule editor
|
||||
* plugin design
|
||||
* nosql, easy extended
|
||||
* simple configuration
|
||||
* out-of-the-box
|
||||
|
||||
## Relation Site
|
||||
Gitee: https://gitee.com/freshday/radar
|
||||
Github: https://github.com/wfh45678/radar
|
||||
Official Site: https://www.91risk.com
|
||||
Wiki: https://gitee.com/freshday/radar/wikis/home
|
||||
|
||||
|
||||
## Architecture
|
||||
|
||||
|
||||
Server-end: SpringBoot + Mybatis + tkMapper + Mysql + MongoDB + Redis + Groovy + ES + Swagger
|
||||
|
||||
Front-end: React(SPA)
|
||||
|
||||
### System Component Diagram
|
||||

|
||||
|
||||
## Technology stack
|
||||
* Springboot:base spring boot 2.x framework.
|
||||
|
||||
* Mybatis + tkMapper: data persistence layer framework.
|
||||
|
||||
* Mysql : model meta data storage.
|
||||
|
||||
* MongoDB: for event data storage.
|
||||
|
||||
* ES: risk result data analysis.
|
||||
|
||||
* Redis: cache, pub sub when model meta data change.
|
||||
|
||||
* Groovy: rule engine.
|
||||
|
||||
* Swagger: Rest API.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## [manual](https://gitee.com/freshday/radar/wikis/manual)
|
||||
https://gitee.com/freshday/radar/wikis/manual
|
||||
|
||||
|
||||
## Demo site
|
||||
[Demo URL:](http://121.36.168.6:6580/) http://121.36.168.6:6580/
|
||||
|
||||
## wiki
|
||||
[WIKI:](https://gitee.com/freshday/radar/wikis/home?sort_id=1637444) https://gitee.com/freshday/radar/wikis/home?sort_id=1637444
|
||||
|
||||
|
||||
|
||||
## Thanks
|
||||
|
||||
千面怪, 烈日下的从容, DerekDingLu, king, sanying2012, 紫泉夜, 玄梦
|
||||
成书平, 徐帅,郭锐, 王成,马兆永...
|
||||
|
||||
|
||||
|
||||
## Statement
|
||||
Copyright © 2019-2021 WangFeiHu
|
||||
2
pom.xml
2
pom.xml
@@ -20,7 +20,7 @@
|
||||
</parent>
|
||||
<groupId>com.pgmmers</groupId>
|
||||
<artifactId>radar</artifactId>
|
||||
<version>1.0.7-SNAPSHOT</version>
|
||||
<version>1.0.8-SNAPSHOT</version>
|
||||
<name>radar</name>
|
||||
<description>Demo project for Spring Boot</description>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>radar</artifactId>
|
||||
<groupId>com.pgmmers</groupId>
|
||||
<version>1.0.7-SNAPSHOT</version>
|
||||
<version>1.0.8-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>radar-admin</artifactId>
|
||||
|
||||
@@ -77,7 +77,7 @@ public class ActivationApiController {
|
||||
return activationService.query(query);
|
||||
}
|
||||
|
||||
@GetMapping("/datacolumns/{modelId}")
|
||||
@GetMapping("/feature/columns/{modelId}")
|
||||
public CommonResult getDataColumns(@PathVariable Long modelId) {
|
||||
List<DataColumnInfo> list = new ArrayList<DataColumnInfo>();
|
||||
// 1、Data
|
||||
@@ -124,7 +124,7 @@ public class ActivationApiController {
|
||||
return result;
|
||||
}
|
||||
|
||||
@GetMapping("/absColumns/{modelId}")
|
||||
@GetMapping("/abstraction/columns/{modelId}")
|
||||
public CommonResult getAbstractionColumns(@PathVariable Long modelId) {
|
||||
CommonResult result = new CommonResult();
|
||||
result.setSuccess(true);
|
||||
@@ -140,7 +140,7 @@ public class ActivationApiController {
|
||||
return result;
|
||||
}
|
||||
|
||||
@GetMapping("/rulecolumns/{modelId}")
|
||||
@GetMapping("/rule/columns/{modelId}")
|
||||
public CommonResult getRuleColumns(@PathVariable Long modelId) {
|
||||
List<DataColumnInfo> list = new ArrayList<>();
|
||||
List<ActivationVO> listActivation=activationService.listActivation(modelId);
|
||||
@@ -185,4 +185,14 @@ public class ActivationApiController {
|
||||
}
|
||||
ds.addChildren(preItem.getLabel(), preItem.getDestField(), children);
|
||||
}
|
||||
|
||||
@PostMapping("/disable/{activationId}")
|
||||
public CommonResult disable(@PathVariable Long activationId) {
|
||||
return activationService.updateStatus(activationId, 0);
|
||||
}
|
||||
|
||||
@PostMapping("/enable/{activationId}")
|
||||
public CommonResult enable(@PathVariable Long activationId) {
|
||||
return activationService.updateStatus(activationId, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,13 +56,7 @@ public class ModelApiController {
|
||||
|
||||
@GetMapping("/list")
|
||||
public CommonResult list(HttpServletRequest request) {
|
||||
// HttpSession session = request.getSession();
|
||||
// UserVO user = (UserVO) session.getAttribute("user");
|
||||
CommonResult result = new CommonResult();
|
||||
// if (user == null) {
|
||||
// result.setMsg("session已过期");
|
||||
// return result;
|
||||
// }
|
||||
result.setSuccess(true);
|
||||
result.getData().put("modelList", modelService.listModel(contextHolder.getContext().getCode(), null));
|
||||
return result;
|
||||
@@ -79,14 +73,6 @@ public class ModelApiController {
|
||||
@PostMapping
|
||||
public CommonResult query(@RequestBody ModelQuery query, HttpServletRequest request) {
|
||||
CommonResult result = new CommonResult();
|
||||
|
||||
// HttpSession session = request.getSession();
|
||||
// UserVO user = (UserVO) session.getAttribute("user");
|
||||
// if (user == null) {
|
||||
// result.setMsg("session已过期");
|
||||
// return result;
|
||||
// }
|
||||
// query.setMerchantCode(user.getCode());
|
||||
query.setMerchantCode(contextHolder.getContext().getCode());
|
||||
return modelService.query(query);
|
||||
}
|
||||
@@ -94,9 +80,6 @@ public class ModelApiController {
|
||||
|
||||
@PutMapping
|
||||
public CommonResult save(@RequestBody ModelVO model, HttpServletRequest request) {
|
||||
// HttpSession session = request.getSession();
|
||||
// UserVO user = (UserVO) session.getAttribute("user");
|
||||
// model.setCode(user.getCode());
|
||||
model.setCode(contextHolder.getContext().getCode());
|
||||
return modelService.save(model);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ public class RuleApiController {
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
public CommonResult save(@RequestBody RuleVO rule, HttpServletRequest request) {
|
||||
public CommonResult save(@RequestBody RuleVO rule) {
|
||||
return ruleService.save(rule, contextHolder.getContext().getUsername());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<!doctype html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <title>风控引擎管理平台</title> <link rel="shortcut icon" href="/images/anquan.png"> <!--[if lt IE 10]>
|
||||
<script src="https://as.alipayobjects.com/g/component/??console-polyfill/0.2.2/index.js,es5-shim/4.5.7/es5-shim.min.js,es5-shim/4.5.7/es5-sham.min.js,html5shiv/3.7.2/html5shiv.min.js,media-match/2.0.2/media.match.min.js"></script>
|
||||
<![endif]--> <link href="./index.fd241aec-1.css" rel="stylesheet"><link href="./index.fd241aec-2.css" rel="stylesheet"><link href="./index.fd241aec-3.css" rel="stylesheet"></head> <body> <div id="react-content"></div> <script type="text/javascript" src="./main.fd241aec.js"></script></body> </html>
|
||||
<![endif]--> <link href="./index.da6b2009-1.css" rel="stylesheet"><link href="./index.da6b2009-2.css" rel="stylesheet"><link href="./index.da6b2009-3.css" rel="stylesheet"></head> <body> <div id="react-content"></div> <script type="text/javascript" src="./main.da6b2009.js"></script></body> </html>
|
||||
File diff suppressed because one or more lines are too long
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<artifactId>radar</artifactId>
|
||||
<groupId>com.pgmmers</groupId>
|
||||
<version>1.0.7-SNAPSHOT</version>
|
||||
<version>1.0.8-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -12,17 +12,17 @@ import java.security.SecureRandom;
|
||||
public class CryptUtils {
|
||||
|
||||
private final static String DES = "DES";
|
||||
//private final static String MD5 = "MD5";
|
||||
private final static String MD5 = "MD5";
|
||||
private final static String SHA = "SHA1";
|
||||
|
||||
public static void main(String args[]){
|
||||
// System.out.println( md5("123") );
|
||||
System.out.println( md5("123") );
|
||||
System.out.println( sha("222222") );
|
||||
}
|
||||
//
|
||||
// public static String md5(String source) {
|
||||
// return encryption(source, MD5);
|
||||
// }
|
||||
|
||||
public static String md5(String source) {
|
||||
return encryption(source, MD5);
|
||||
}
|
||||
|
||||
public static String sha(String source) {
|
||||
return encryption(source, SHA);
|
||||
|
||||
@@ -29,12 +29,12 @@ public class GroovyScriptUtil {
|
||||
* 2016年8月2日
|
||||
*/
|
||||
public static GroovyObject loadScript(String script) {
|
||||
GroovyObject groovyObject = passedClassMap.get(script.hashCode() + "");
|
||||
GroovyObject groovyObject = passedClassMap.get(CryptUtils.md5(script));
|
||||
if (groovyObject == null) {
|
||||
Class groovyClass = groovyClassLoader.parseClass(script);
|
||||
try {
|
||||
groovyObject = (GroovyObject) groovyClass.newInstance();
|
||||
passedClassMap.put(script.hashCode() + "", groovyObject);
|
||||
passedClassMap.put(CryptUtils.md5(script), groovyObject);
|
||||
} catch (InstantiationException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
@@ -62,6 +62,6 @@ public class GroovyScriptUtil {
|
||||
* 删除不在使用的脚本关联的groovy object, 不然内存有溢出风险。
|
||||
*/
|
||||
public static void removeInactiveScript(String script){
|
||||
passedClassMap.remove(script.hashCode() + "");
|
||||
passedClassMap.remove(CryptUtils.md5(script));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>radar</artifactId>
|
||||
<groupId>com.pgmmers</groupId>
|
||||
<version>1.0.7-SNAPSHOT</version>
|
||||
<version>1.0.8-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ public interface ModelDal {
|
||||
|
||||
List<ModelVO> listModel(String merchantCode,Integer status);
|
||||
|
||||
List<ModelVO> listModel(String merchantCode,Integer status, Boolean isTemplate);
|
||||
List<ModelVO> listModel(String code,Integer status, Boolean isTemplate);
|
||||
|
||||
List<ModelVO> listModel(Integer status);
|
||||
|
||||
|
||||
@@ -445,12 +445,12 @@ public class ModelDalImpl implements ModelDal {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ModelVO> listModel(String merchantCode, Integer status,
|
||||
public List<ModelVO> listModel(String code, Integer status,
|
||||
Boolean isTemplate) {
|
||||
Example example = new Example(ModelPO.class);
|
||||
Example.Criteria criteria = example.createCriteria();
|
||||
if (!StringUtils.isEmpty(merchantCode)) {
|
||||
criteria.andEqualTo("code", merchantCode);
|
||||
if (!StringUtils.isEmpty(code)) {
|
||||
criteria.andEqualTo("code", code);
|
||||
}
|
||||
if (status != null) {
|
||||
criteria.andEqualTo("status", status);
|
||||
|
||||
@@ -46,6 +46,11 @@ public class RuleVO implements Serializable{
|
||||
|
||||
private Integer rate;
|
||||
|
||||
/**
|
||||
* 最大得分值.
|
||||
*/
|
||||
private Integer max;
|
||||
|
||||
@JsonProperty
|
||||
private JsonNode ruleDefinition;
|
||||
|
||||
@@ -197,6 +202,12 @@ public class RuleVO implements Serializable{
|
||||
public void setLabel(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Integer getMax() {
|
||||
return max;
|
||||
}
|
||||
|
||||
public void setMax(Integer max) {
|
||||
this.max = max;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>radar</artifactId>
|
||||
<groupId>com.pgmmers</groupId>
|
||||
<version>1.0.7-SNAPSHOT</version>
|
||||
<version>1.0.8-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>radar-dao</artifactId>
|
||||
@@ -44,7 +44,7 @@
|
||||
<plugin>
|
||||
<groupId>org.mybatis.generator</groupId>
|
||||
<artifactId>mybatis-generator-maven-plugin</artifactId>
|
||||
<version>1.3.6</version>
|
||||
<version>1.3.7</version>
|
||||
<configuration>
|
||||
<configurationFile>
|
||||
${basedir}/src/main/resources/generator/generatorConfig.xml
|
||||
|
||||
@@ -49,6 +49,9 @@ public class PreItemPO {
|
||||
@Column(name = "PLUGIN")
|
||||
private String plugin;
|
||||
|
||||
/**
|
||||
* 响应字段配置信息
|
||||
*/
|
||||
@Column(name = "CONFIG_JSON")
|
||||
private String configJson;
|
||||
|
||||
@@ -204,14 +207,18 @@ public class PreItemPO {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CONFIG_JSON
|
||||
* 获取响应字段配置信息
|
||||
*
|
||||
* @return CONFIG_JSON - 响应字段配置信息
|
||||
*/
|
||||
public String getConfigJson() {
|
||||
return configJson;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param configJson
|
||||
* 设置响应字段配置信息
|
||||
*
|
||||
* @param configJson 响应字段配置信息
|
||||
*/
|
||||
public void setConfigJson(String configJson) {
|
||||
this.configJson = configJson;
|
||||
|
||||
@@ -70,6 +70,12 @@ public class RulePO {
|
||||
@Column(name = "RATE")
|
||||
private Integer rate;
|
||||
|
||||
/**
|
||||
* 最大值
|
||||
*/
|
||||
@Column(name = "MAX")
|
||||
private Integer max;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
@@ -279,6 +285,24 @@ public class RulePO {
|
||||
this.rate = rate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最大值
|
||||
*
|
||||
* @return MAX - 最大值
|
||||
*/
|
||||
public Integer getMax() {
|
||||
return max;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置最大值
|
||||
*
|
||||
* @param max 最大值
|
||||
*/
|
||||
public void setMax(Integer max) {
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取状态
|
||||
*
|
||||
|
||||
@@ -5,6 +5,9 @@ import javax.persistence.*;
|
||||
|
||||
@Table(name = "users")
|
||||
public class UserPO {
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@Id
|
||||
@Column(name = "ID")
|
||||
@GeneratedValue(generator = "JDBC")
|
||||
@@ -41,14 +44,18 @@ public class UserPO {
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* @return ID
|
||||
* 获取主键
|
||||
*
|
||||
* @return ID - 主键
|
||||
*/
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id
|
||||
* 设置主键
|
||||
*
|
||||
* @param id 主键
|
||||
*/
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
jdbc.driverClass=com.mysql.jdbc.Driver
|
||||
jdbc.driverClass=com.mysql.cj.jdbc.Driver
|
||||
jdbc.url=jdbc:mysql://localhost:3306/radar?characterEncoding=UTF-8&useSSL=false
|
||||
jdbc.user=root
|
||||
jdbc.password=456132
|
||||
@@ -25,6 +25,8 @@
|
||||
connectionURL="${jdbc.url}"
|
||||
userId="${jdbc.user}"
|
||||
password="${jdbc.password}">
|
||||
<property name="serverTimezone" value="Asia/Shanghai"/>
|
||||
<property name="nullCatalogMeansCurrent" value="true"/>
|
||||
</jdbcConnection>
|
||||
|
||||
<javaModelGenerator targetPackage="com.pgmmers.radar.model"
|
||||
@@ -38,7 +40,7 @@
|
||||
type="XMLMAPPER"/>
|
||||
|
||||
|
||||
<table tableName="USERS" domainObjectName="User">
|
||||
<table tableName="radar.USERS" domainObjectName="User">
|
||||
<generatedKey column="ID" sqlStatement="JDBC"/>
|
||||
</table>
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
<result column="OPERATOR" jdbcType="VARCHAR" property="operator" />
|
||||
<result column="ABSTRACTION_NAME" jdbcType="VARCHAR" property="abstractionName" />
|
||||
<result column="RATE" jdbcType="INTEGER" property="rate" />
|
||||
<result column="MAX" jdbcType="INTEGER" property="max" />
|
||||
<result column="STATUS" jdbcType="INTEGER" property="status" />
|
||||
<result column="RULE_DEFINITION" jdbcType="VARCHAR" property="ruleDefinition" />
|
||||
<result column="CREATE_TIME" jdbcType="TIMESTAMP" property="createTime" />
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>radar</artifactId>
|
||||
<groupId>com.pgmmers</groupId>
|
||||
<version>1.0.7-SNAPSHOT</version>
|
||||
<version>1.0.8-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.pgmmers.radar.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 事件信息。
|
||||
* @author feihu.wang
|
||||
*/
|
||||
public class EventRequest {
|
||||
@ApiModelProperty(value = "模型guid")
|
||||
@NotBlank(message = "guid 不能为空")
|
||||
private String guid;
|
||||
|
||||
@ApiModelProperty(value = "请求流水号")
|
||||
@NotBlank(message = "reqId 不能为空")
|
||||
private String reqId;
|
||||
|
||||
@ApiModelProperty(value = "事件内容")
|
||||
@NotNull(message = "jsonInfo 不能为空")
|
||||
private JSONObject jsonInfo;
|
||||
|
||||
public String getGuid() {
|
||||
return guid;
|
||||
}
|
||||
|
||||
public void setGuid(String guid) {
|
||||
this.guid = guid;
|
||||
}
|
||||
|
||||
public String getReqId() {
|
||||
return reqId;
|
||||
}
|
||||
|
||||
public void setReqId(String reqId) {
|
||||
this.reqId = reqId;
|
||||
}
|
||||
|
||||
public JSONObject getJsonInfo() {
|
||||
return jsonInfo;
|
||||
}
|
||||
|
||||
public void setJsonInfo(JSONObject jsonInfo) {
|
||||
this.jsonInfo = jsonInfo;
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@ import io.swagger.annotations.ApiParam;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/services/v1")
|
||||
@Api(value = "RiskApi", description = "接受用户事件数据,实时进行分析并返回分析结果。", tags = {"风险分析API(引擎端)"})
|
||||
@@ -28,6 +30,7 @@ public class MainController {
|
||||
private RiskAnalysisEngineService engineApi;
|
||||
|
||||
|
||||
@Deprecated
|
||||
@PostMapping("/uploadInfo")
|
||||
@ApiOperation(value = "事件数据提交接口")
|
||||
public CommonResult upload(@RequestParam @ApiParam(name="modelGuid", value="模型Guid", required=true) String modelGuid,
|
||||
@@ -44,4 +47,11 @@ public class MainController {
|
||||
CommonResult result = engineApi.getScore(modelGuid, reqId);
|
||||
return result;
|
||||
}
|
||||
|
||||
@PostMapping("/upload")
|
||||
@ApiOperation(value = "事件数据提交接口")
|
||||
public CommonResult upload(@Valid @RequestBody EventRequest request) {
|
||||
CommonResult result = engineApi.uploadInfo(request.getGuid(), request.getReqId(), request.getJsonInfo());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.pgmmers.radar.error;
|
||||
|
||||
import com.pgmmers.radar.service.common.CommonResult;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.converter.HttpMessageConversionException;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.ObjectError;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* global exception handle.
|
||||
* @author feihu.wang
|
||||
*/
|
||||
@ControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
|
||||
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
@ResponseBody
|
||||
public ResponseEntity handleMethodArgumentNotValidException(
|
||||
MethodArgumentNotValidException e) {
|
||||
logger.error("handleMethodArgumentNotValidException: ", e.getMessage());
|
||||
CommonResult result = handleBindingResult(e.getBindingResult());
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(result);
|
||||
}
|
||||
|
||||
@ExceptionHandler(RuntimeException.class)
|
||||
@ResponseBody
|
||||
public ResponseEntity handleRuntimeException(RuntimeException e) {
|
||||
logger.error("handleRuntimeException: ", e);
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(HttpMessageConversionException.class)
|
||||
@ResponseBody
|
||||
public ResponseEntity handleHttpMessageConversionException(HttpMessageConversionException e) {
|
||||
logger.error("handleHttpMessageConversionException: ", e);
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
@ResponseBody
|
||||
public ResponseEntity handleException(Exception e) {
|
||||
logger.error("Exception: ", e);
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
|
||||
}
|
||||
|
||||
private CommonResult handleBindingResult(BindingResult bindingResult) {
|
||||
CommonResult result = new CommonResult();
|
||||
List<String> errorList = new ArrayList<>();
|
||||
if (bindingResult.hasErrors()) {
|
||||
List<ObjectError> allErrors = bindingResult.getAllErrors();
|
||||
for (ObjectError objectError : allErrors) {
|
||||
String message = objectError.getDefaultMessage();
|
||||
errorList.add(message);
|
||||
}
|
||||
}
|
||||
result.getData().put("errList", errorList);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>radar</artifactId>
|
||||
<groupId>com.pgmmers</groupId>
|
||||
<version>1.0.7-SNAPSHOT</version>
|
||||
<version>1.0.8-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>radar</artifactId>
|
||||
<groupId>com.pgmmers</groupId>
|
||||
<version>1.0.7-SNAPSHOT</version>
|
||||
<version>1.0.8-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -58,13 +58,18 @@ public class RiskAnalysisEngineServiceImpl implements RiskAnalysisEngineService
|
||||
|
||||
@Override
|
||||
public CommonResult uploadInfo(String modelGuid, String reqId, String jsonInfo) {
|
||||
return uploadInfo(modelGuid, reqId, JSON.parseObject(jsonInfo));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult uploadInfo(String modelGuid, String reqId, JSONObject jsonInfo) {
|
||||
logger.info("req info:{},{},{}", modelGuid, reqId, jsonInfo);
|
||||
CommonResult result = new CommonResult();
|
||||
Map<String, Map<String, ?>> context = new HashMap<>();
|
||||
ModelVO model;
|
||||
try {
|
||||
// 1. check
|
||||
JSONObject eventJson = JSON.parseObject(jsonInfo);
|
||||
JSONObject eventJson = jsonInfo;
|
||||
|
||||
model = modelService.getModelByGuid(modelGuid);
|
||||
|
||||
@@ -110,8 +115,9 @@ public class RiskAnalysisEngineServiceImpl implements RiskAnalysisEngineService
|
||||
.formatDate(new Date(eventTimeMillis), "yyyy-MM-dd'T'HH:mm:ssZ");
|
||||
preItemMap.put("radar_ref_datetime", timeStr);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
result.setMsg("数据异常!");
|
||||
logger.error("process error", e);
|
||||
//result.setMsg("数据异常!" + e.getMessage());
|
||||
throw new RuntimeException("数据处理异常:" + e.getMessage());
|
||||
}
|
||||
|
||||
// 缓存分析结果
|
||||
@@ -135,4 +141,5 @@ public class RiskAnalysisEngineServiceImpl implements RiskAnalysisEngineService
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -323,6 +323,7 @@ public class AntiFraudEngineImpl implements AntiFraudEngine {
|
||||
BigDecimal base = new BigDecimal(rule.getBaseNum());
|
||||
BigDecimal extra = BigDecimal.ZERO;
|
||||
String by = rule.getAbstractionName();
|
||||
BigDecimal maxScore = new BigDecimal(rule.getMax());
|
||||
if (!StringUtils.isEmpty(by)) {
|
||||
if (by.indexOf(".") != -1) {
|
||||
//目前 被操作数 支持 基础字段和抽象字段。
|
||||
@@ -360,14 +361,20 @@ public class AntiFraudEngineImpl implements AntiFraudEngine {
|
||||
break;
|
||||
default:
|
||||
}
|
||||
BigDecimal account = initScore.add(extra);
|
||||
BigDecimal amount = initScore.add(extra);
|
||||
// 规则得分设置最大值.
|
||||
if (maxScore.compareTo(BigDecimal.ZERO) > 0 && amount.compareTo(maxScore) > 0) {
|
||||
amount = maxScore;
|
||||
}
|
||||
sum = sum.add(amount);
|
||||
|
||||
// hit detail
|
||||
HitObject hit = new HitObject();
|
||||
hit.setKey(rule.getId().toString());
|
||||
hit.setDesc(rule.getLabel());
|
||||
hit.setValue(account.setScale(2, 4).doubleValue());
|
||||
hit.setValue(amount.setScale(2, 4).doubleValue());
|
||||
result.getHitRulesMap().get(act.getActivationName()).add(hit);
|
||||
result.getHitRulesMap2().get(act.getActivationName()).put("rule_"+ hit.getKey(), hit);
|
||||
sum = sum.add(account);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -108,7 +108,20 @@ public class ActivationServiceImpl extends BaseLocalCacheService implements Acti
|
||||
return result;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
@Override
|
||||
public CommonResult updateStatus(Long activationId, Integer status) {
|
||||
CommonResult result = new CommonResult();
|
||||
ActivationVO activation = activationDal.get(activationId);
|
||||
if (activation == null) return result;
|
||||
activation = new ActivationVO();
|
||||
activation.setId(activationId);
|
||||
activation.setStatus(status);
|
||||
activationDal.save(activation);
|
||||
result.setSuccess(true);
|
||||
return result;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
cacheService.subscribeActivation(this);
|
||||
}
|
||||
|
||||
@@ -43,10 +43,6 @@ import org.springframework.stereotype.Service;
|
||||
public class ModelServiceImpl extends BaseLocalCacheService implements ModelService,
|
||||
SubscribeHandle {
|
||||
|
||||
@Override
|
||||
public Object query(Long modelId) {
|
||||
return modelDal.getModelById(modelId);
|
||||
}
|
||||
|
||||
public static Logger logger = LoggerFactory
|
||||
.getLogger(ModelServiceImpl.class);
|
||||
@@ -367,4 +363,9 @@ public class ModelServiceImpl extends BaseLocalCacheService implements ModelServ
|
||||
return modelDal.listModel(null, null, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object query(Long modelId) {
|
||||
return modelDal.getModelById(modelId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ public class RuleServiceImpl extends BaseLocalCacheService implements RuleServic
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult save(RuleVO rule,String merchantCode) {
|
||||
public CommonResult save(RuleVO rule,String userCode) {
|
||||
CommonResult result = new CommonResult();
|
||||
if (rule.getId() != null) {
|
||||
RuleVO oldRule = ruleDal.get(rule.getId());
|
||||
@@ -112,7 +112,7 @@ public class RuleServiceImpl extends BaseLocalCacheService implements RuleServic
|
||||
// 存储History
|
||||
RuleHistoryVO ruleHistoryVO=new RuleHistoryVO();
|
||||
ruleHistoryVO.setRuleId(rule.getId());
|
||||
ruleHistoryVO.setMerchantCode(merchantCode);
|
||||
ruleHistoryVO.setMerchantCode(userCode);
|
||||
ruleHistoryVO.setLabel(rule.getLabel());
|
||||
ruleHistoryVO.setInitScore(rule.getInitScore());
|
||||
ruleHistoryVO.setBaseNum(rule.getBaseNum());
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>radar</artifactId>
|
||||
<groupId>com.pgmmers</groupId>
|
||||
<version>1.0.7-SNAPSHOT</version>
|
||||
<version>1.0.8-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.pgmmers.radar.service;
|
||||
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.pgmmers.radar.service.common.CommonResult;
|
||||
|
||||
|
||||
@@ -24,9 +25,17 @@ public interface RiskAnalysisEngineService {
|
||||
* @author feihu.wang
|
||||
*
|
||||
*/
|
||||
CommonResult uploadInfo( String modelGuid,
|
||||
String reqId,
|
||||
String jsonInfo);
|
||||
CommonResult uploadInfo(String modelGuid, String reqId, String jsonInfo);
|
||||
|
||||
/**
|
||||
* 上传信息.
|
||||
* @param modelGuid
|
||||
* @param reqId
|
||||
* @param jsonInfo
|
||||
* @return
|
||||
* @see "uploadInfo(String modelGuid, String reqId, String jsonInfo)"
|
||||
*/
|
||||
CommonResult uploadInfo(String modelGuid, String reqId, JSONObject jsonInfo);
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -21,4 +21,14 @@ public interface ActivationService {
|
||||
|
||||
CommonResult updateOrder(Long activationId, String ruleOrder);
|
||||
|
||||
/**
|
||||
* update status of activation.
|
||||
* @param activationId
|
||||
* @param status
|
||||
* @return
|
||||
*
|
||||
* @author feihu.wang
|
||||
*/
|
||||
CommonResult updateStatus(Long activationId, Integer status);
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ public interface RuleService {
|
||||
|
||||
CommonResult query(RuleQuery query);
|
||||
|
||||
CommonResult save(RuleVO rule, String merchantCode);
|
||||
CommonResult save(RuleVO rule, String userCode);
|
||||
|
||||
CommonResult delete(Long[] id);
|
||||
|
||||
|
||||
2
sql/radar-1.0.8.sql
Normal file
2
sql/radar-1.0.8.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE `engine_rule`
|
||||
ADD COLUMN `MAX` int(11) NOT NULL DEFAULT 0 COMMENT '最大得分值' AFTER `RATE`;
|
||||
Reference in New Issue
Block a user