SpringBoot+使用过滤器链执行风控决策
风控流程
下单前进行风控校验
// 1.begin---风控处理---前置处理{黑白名单校验}
RiskControlRuleEnum controlRuleEnum = riskControlHandlerService.preHandle(mappingObj.getMerchantGoodsType(), thatUser);
if (controlRuleEnum != null) {
logger.error("风控处理进入--->{}", controlRuleEnum.getDesc());
Result error = Result.error(controlRuleEnum.getDesc());
error.setCode("WEB_RISK_CONTROL_" + controlRuleEnum.getCode());
return error;
}
下单后进行风控判断是否会进入
// 2.ending---风控限制后置处理|处理{黑白名单校验}
taskExecutor.execute(() -> riskControlHandlerService.afterBuyingTicketsHandle(mappingObj.getMerchantGoodsType(), user));
风控前置校验
/**
* 风控---前置校验
*
* @param user user
* @return
* @throws Exception
*/
public RiskControlRuleEnum preHandle(String merchantGoodsType, User user) {
// 风控规则校验---拒绝购买票的号码校验
List<RiskControlManager> managerList = riskControlManagerService.getByMerchantGoodsType(merchantGoodsType);
if (CollectionUtils.isNotEmpty(managerList)) {
for (RiskControlManager manager : managerList) {
// 拒绝号码购买----风控校验
String riskControlDesc = manager.getRiskControlDesc();
if (StringUtils.isNotBlank(riskControlDesc)) {
String[] splitPhone = riskControlDesc.split(",");
for (String thatLimitPhone : splitPhone) {
if (StringUtils.isNotBlank(user.getMobile()) && user.getMobile().startsWith(thatLimitPhone)) {
return RiskControlRuleEnum.TicketPurchaseProhibited;
}
}
}
}
}
RiskControlUsers riskControlUsers = new RiskControlUsers();
riskControlUsers.setPayerId(user.getMid());
riskControlUsers.setMerchantGoodsType(merchantGoodsType);
List<RiskControlUsers> riskControlUsers1 = riskControlUsersService.listAll(riskControlUsers);
if (CollectionUtils.isEmpty(riskControlUsers1)) {
return null;
}
// 如果有黑名单限制--黑名单限制
for (RiskControlUsers controlUsers : riskControlUsers1) {
if (controlUsers.getRiskControlLimitType().equals(RiskControlRuleEnum.TicketPurchaseProhibited.getCode())) {
return RiskControlRuleEnum.TicketPurchaseProhibited;
}
}
// 如果没有黑名单限制--灰名单限制
Integer riskControlLimitType = riskControlUsers1.get(0).getRiskControlLimitType();
RiskControlRuleEnum[] values = RiskControlRuleEnum.values();
for (RiskControlRuleEnum ruleEnum : values) {
if (ruleEnum.getCode().equals(riskControlLimitType)) {
return ruleEnum;
}
}
return null;
}
风控后置--决策
/**
* 风控----后置校验
*
* @param user user
* @return
* @throws Exception
*/
public void afterBuyingTicketsHandle(String merchantGoodsType, User user) {
// 商品维度的风控策略加载||已启用的加商品类型过滤+优先级排序
List<RiskControlManager> managerList = riskControlManagerService.getByMerchantGoodsType(merchantGoodsType);
if (CollectionUtils.isEmpty(managerList)) {
return;
}
RiskControlDecisionsFilterChain filterChain = RiskControlDecisionsFilterChain.getInstance();
// 获取用户风控信息{已经SQL的排序修改按照序列的--优先级排序}
for (RiskControlManager manager : managerList) {
Long mid = manager.getMid();
// 获取风控惩罚机制
RiskControlRestrictive riskControlRestrictive = new RiskControlRestrictive();
riskControlRestrictive.setRiskControlRuleId(mid);
List<RiskControlRestrictive> restrictives = riskControlRestrictiveService.listAll(riskControlRestrictive);
if (CollectionUtils.isEmpty(restrictives)) {
// 如果没有--风控策略
continue;
}
// 风控排序 -----最小条件满足优先{天--小时---分钟}
Comparator<RiskControlRestrictive> comparator = new Comparator<RiskControlRestrictive>() {
@Override
public int compare(RiskControlRestrictive o1, RiskControlRestrictive o2) {
// 时间间隔单位
Integer timeIntervalUnitV1 = o1.getTimeIntervalUnit();
Integer timeIntervalUnitV2 = o2.getTimeIntervalUnit();
return timeIntervalUnitV1 - timeIntervalUnitV2;
}
};
restrictives.sort(comparator);
// 校验用户风控策略满足条件{过滤器链路使用---用户封印{无法根据IP、身份证、电话号码封印}}
for (RiskControlRestrictive restrictive : restrictives) {
// 获取限制类型---下单的限定
if (restrictive.getOperationType().equals(RiskControlRestrictiveOperationEnum.PlaceAnOrder.getCode())) {
// 风控决策引擎--启动{决策目标风控行为:开启所有的风控链决策--使用 execute 方法}
boolean execute = filterChain.executeDefaultHandler(user, manager, restrictive, riskControlLimitAccountFilterChain);
if (execute) {
// 满足风控条件任意一项:黑白名单入库成功---------风控过滤链释放
return;
}
} else if (restrictive.getOperationType().equals(RiskControlRestrictiveOperationEnum.Refund.getCode())) {
// 获取限制类型---退款的限定--todo
}
}
}
}
风控决策引擎管理--总线
/**
* packageName com.cztech.platform.transaction.common.riskControl
*
* @author GuoTong
* @version JDK 8
* @className RiskControlDecisionsFilterChain
* @date 2024/5/9
* @description 风控决策引擎
*/
public class RiskControlDecisionsFilterChain {
private Logger log = LoggerFactory.getLogger(RiskControlDecisionsFilterChain.class);
/**
* 标识===过滤器所属限制类型
* 子类必须重写
*
* @return int
*/
protected int getThisRestrictiveType() {
return 0;
}
/**
* 风控决策过滤器链
*/
public static List<RiskControlDecisionsFilterChain> filterChains = new ArrayList<>();
private static RiskControlDecisionsFilterChain chain = null;
public static RiskControlDecisionsFilterChain getInstance() {
if (chain == null) {
synchronized (RiskControlDecisionsFilterChain.class) {
if (chain == null) {
chain = new RiskControlDecisionsFilterChain();
}
}
}
return chain;
}
/**
* 风控决策引擎执行入口
*
* @param user 用户ID
* @param manager 风控管理器
* @param restrictive 风控限制
* @author GuoTong
*/
public boolean execute(User user, RiskControlManager manager, RiskControlRestrictive restrictive) {
log.error("风控决策引擎执行-----进入执行---------");
for (RiskControlDecisionsFilterChain filterChain : filterChains) {
// 获取限制类型----只运行当前限制的决策事件
if (restrictive.getRestrictiveType().equals(filterChain.getThisRestrictiveType())) {
// 获取执行链路的结果
boolean respWasSuccess = filterChain.execute(user, manager, restrictive);
// 已经执行成功,则过滤器链终止
if (respWasSuccess) {
return true;
}
}
}
log.error("风控决策引擎执行-----执行结束---------");
return false;
}
protected int countRiskControlLimit(String startTime, String endTime, User user) {
return 0;
}
/**
* 保存用户--进入限制桶
* 子类必须重写
*
* @param riskControlUsers riskControlUsers
*/
protected void saveLimitUser(RiskControlUsers riskControlUsers) {
}
protected ReleaseTimeSetting getReleaseTimeSetting() {
return null;
}
/**
* 限制名单限定--决策----通用业务逻辑
*
* @param user userId
* @param manager manager
* @param restrictive restrictive
*/
protected boolean executeDefaultHandler(User user, RiskControlManager manager, RiskControlRestrictive restrictive, RiskControlDecisionsFilterChain targetFilterChain) {
// 获取时间间隔
Long timeInterval = restrictive.getTimeInterval();
// 获取时间间隔单位
Integer timeIntervalUnit = restrictive.getTimeIntervalUnit();
// 获取限制次数
Long quantity = restrictive.getQuantity();
// 计算限制区间:当前时间 -- 开始时间
LocalDateTime now = LocalDateTime.now();
String endTime = LocalDateTimeUtil.format(now, RuleCommonUtils.YYYY_MM_DD_HH_MM_SS);
String startTime = null;
if (timeIntervalUnit.equals(RiskControlRestrictiveTimeEnum.Minute.getCode())) {
// 如果是分钟
startTime = LocalDateTimeUtil.format(now.minusMinutes(timeInterval), RuleCommonUtils.YYYY_MM_DD_HH_MM_SS);
} else if (timeIntervalUnit.equals(RiskControlRestrictiveTimeEnum.Hours.getCode())) {
// 如果是小时
startTime = LocalDateTimeUtil.format(now.minusHours(timeInterval), RuleCommonUtils.YYYY_MM_DD_HH_MM_SS);
} else {
// 天
startTime = LocalDateTimeUtil.format(now.minusDays(timeInterval), RuleCommonUtils.YYYY_MM_DD_HH_MM_SS);
}
// 查询当前情况下的下单数量
int thatOrderNum = targetFilterChain.countRiskControlLimit(startTime, endTime, user);
if (thatOrderNum >= quantity) {
log.error("用户{}在{}到{}期间下单次数超过限制次数{}", user.getMid(), startTime, endTime, quantity);
// 封印该用户--todo{惩罚机制}
RiskControlUsers riskControlUsers = new RiskControlUsers();
riskControlUsers.setStateId(1);
riskControlUsers.setCreateTime(new Date());
riskControlUsers.setMerchantGoodsType(manager.getMerchantGoodsType());
riskControlUsers.setRiskControlDetailLimit(manager.getRiskControlDetailLimit());
riskControlUsers.setRiskControlLimitType(manager.getRiskControlRule());
ReleaseTimeSetting releaseTimeSetting = targetFilterChain.getReleaseTimeSetting();
if (releaseTimeSetting != null) {
riskControlUsers.setReleaseTimeDay(releaseTimeSetting.getNowDay());
} else {
riskControlUsers.setReleaseTimeDay(7);
}
riskControlUsers.setRiskControlCardType("身份证");
riskControlUsers.setIdCard(user.getIdentityNumber());
// 黑名单|白名单
riskControlUsers.setRiskControlTypeName(manager.getRiskControlRestrictive());
riskControlUsers.setUserName(user.getName());
riskControlUsers.setPhone(user.getMobile());
riskControlUsers.setIpAddres(user.getLastLoginIP());
riskControlUsers.setLimitTime(new Date());
riskControlUsers.setDescLimit(manager.getRiskControlName());
riskControlUsers.setPayerId(user.getMid());
log.error("风控----管控---用户信息------>:" + JSONObject.toJSONString(riskControlUsers));
targetFilterChain.saveLimitUser(riskControlUsers);
return true;
}
return false;
}
}
风控链----01风控决策引擎---限制账户
/**
* packageName com.cztech.platform.transaction.common.riskControl
*
* @author GuoTong
* @version JDK 8
* @className RiskControlDecisionsFilterChain
* @date 2024/5/9
* @description 风控决策引擎---限制账户
*/
@Component
public class RiskControlLimitAccountFilterChain extends RiskControlDecisionsFilterChain {
private Logger log = LoggerFactory.getLogger(RiskControlLimitAccountFilterChain.class);
@Autowired
private RiskControlUsersService riskControlUsersService;
@Autowired
private OrderService orderService;
/**
* 标识===过滤器所属限制类型
* @return int
*/
@Override
protected int getThisRestrictiveType() {
return RiskControlRestrictiveEnum.LimitAccount.getCode();
}
/**
* 保存用户--进入限制桶
* 子类必须重写
* @param riskControlUsers riskControlUsers
*/
protected void saveLimitUser(RiskControlUsers riskControlUsers) {
riskControlUsersService.save(riskControlUsers);
}
/**
* 构造函数---注册到过滤器链
*/
public RiskControlLimitAccountFilterChain() {
filterChains.add(this);
}
/**
* 风控决策引擎执行入口--限制账户
*
* @param user, 用户ID
* @param manager 风控管理器
* @param restrictive 风控限制
* @author GuoTong
*/
@Override
public boolean execute(User user, RiskControlManager manager, RiskControlRestrictive restrictive) {
boolean restrictiveFlag = false;
try {
restrictiveFlag = super.executeDefaultHandler(user, manager, restrictive,this);
} catch (Exception e) {
log.error("RiskControlLimitAccountFilterChain execute error:", e);
}
return restrictiveFlag;
}
@Override
protected int countRiskControlLimit(String startTime, String endTime, User user) {
return orderService.countRiskControlLimit(startTime, endTime, user.getMid());
}
@Override
protected ReleaseTimeSetting getReleaseTimeSetting() {
return riskControlUsersService.selectReleaseTimeData();
}
}
风控链----02风控决策引擎---限制身份证
/**
* packageName com.cztech.platform.transaction.common.riskControl
*
* @author GuoTong
* @version JDK 8
* @className RiskControlDecisionsFilterChain
* @date 2024/5/9
* @description 风控决策引擎---限制身份证
*/
@Component
public class RiskControlLimitIdCardFilterChain extends RiskControlDecisionsFilterChain {
private Logger log = LoggerFactory.getLogger(RiskControlLimitIdCardFilterChain.class);
@Autowired
private RiskControlUsersService riskControlUsersService;
@Autowired
private OrderService orderService;
/**
* 标识===过滤器所属限制类型
* @return int
*/
@Override
protected int getThisRestrictiveType() {
return RiskControlRestrictiveEnum.LimitIdCard.getCode();
}
/**
* 构造函数---注册到过滤器链
*/
public RiskControlLimitIdCardFilterChain() {
filterChains.add(this);
}
/**
* 风控决策引擎执行入口--限制身份证
*
* @param user, 用户ID
* @param manager 风控管理器
* @param restrictive 风控限制
* @author GuoTong
*/
@Override
public boolean execute(User user, RiskControlManager manager, RiskControlRestrictive restrictive) {
boolean restrictiveFlag = false;
try {
restrictiveFlag = super.executeDefaultHandler(user, manager, restrictive,this);
} catch (Exception e) {
log.error("RiskControlLimitAccountFilterChain execute error:", e);
}
return restrictiveFlag;
}
@Override
protected int countRiskControlLimit(String startTime, String endTime, User user) {
String identityNumber = user.getIdentityNumber();
if (StringUtils.isBlank(identityNumber)) {
return 0;
}
return orderService.countRiskControlFiledLimit(startTime, endTime, identityNumber);
}
/**
* 保存用户--进入限制桶
* 子类必须重写
* @param riskControlUsers riskControlUsers
*/
protected void saveLimitUser(RiskControlUsers riskControlUsers) {
riskControlUsersService.save(riskControlUsers);
}
@Override
protected ReleaseTimeSetting getReleaseTimeSetting() {
return riskControlUsersService.selectReleaseTimeData();
}
}
风控链----03风控决策引擎---限制账IP
/**
* packageName com.cztech.platform.transaction.common.riskControl
*
* @author GuoTong
* @version JDK 8
* @className RiskControlDecisionsFilterChain
* @date 2024/5/9
* @description 风控决策引擎---限制IP
*/
@Component
public class RiskControlLimitIpFilterChain extends RiskControlDecisionsFilterChain {
private Logger log = LoggerFactory.getLogger(RiskControlLimitIpFilterChain.class);
@Autowired
private RiskControlUsersService riskControlUsersService;
@Autowired
private OrderService orderService;
/**
* 构造函数---注册到过滤器链
*/
public RiskControlLimitIpFilterChain() {
filterChains.add(this);
}
/**
* 标识===过滤器所属限制类型
* @return int
*/
@Override
protected int getThisRestrictiveType() {
return RiskControlRestrictiveEnum.LimitIp.getCode();
}
/**
* 风控决策引擎执行入口--限制IP
*
* @param user, 用户ID
* @param manager 风控管理器
* @param restrictive 风控限制
* @author GuoTong
*/
@Override
public boolean execute(User user, RiskControlManager manager, RiskControlRestrictive restrictive) {
boolean restrictiveFlag = false;
try {
restrictiveFlag = super.executeDefaultHandler(user, manager, restrictive,this);
} catch (Exception e) {
log.error("RiskControlLimitAccountFilterChain execute error:", e);
}
return restrictiveFlag;
}
@Override
protected int countRiskControlLimit(String startTime, String endTime, User user) {
String lastLoginIP = user.getLastLoginIP();
if (StringUtils.isBlank(lastLoginIP)) {
return 0;
}
return orderService.countRiskControlIPLimit(startTime, endTime, lastLoginIP);
}
/**
* 保存用户--进入限制桶
* 子类必须重写
* @param riskControlUsers riskControlUsers
*/
protected void saveLimitUser(RiskControlUsers riskControlUsers) {
riskControlUsersService.save(riskControlUsers);
}
@Override
protected ReleaseTimeSetting getReleaseTimeSetting() {
return riskControlUsersService.selectReleaseTimeData();
}
}
风控链----04风控决策引擎---限制手机
/**
* packageName com.cztech.platform.transaction.common.riskControl
*
* @author GuoTong
* @version JDK 8
* @className RiskControlDecisionsFilterChain
* @date 2024/5/9
* @description 风控决策引擎---限制手机号
*/
@Component
public class RiskControlLimitPhoneFilterChain extends RiskControlDecisionsFilterChain {
private Logger log = LoggerFactory.getLogger(RiskControlLimitPhoneFilterChain.class);
@Autowired
private RiskControlUsersService riskControlUsersService;
@Autowired
private OrderService orderService;
/**
* 标识===过滤器所属限制类型
* @return int
*/
@Override
protected int getThisRestrictiveType() {
return RiskControlRestrictiveEnum.LimitPhone.getCode();
}
/**
* 构造函数---注册到过滤器链
*/
public RiskControlLimitPhoneFilterChain() {
filterChains.add(this);
}
/**
* 风控决策引擎执行入口--限制手机号
*
* @param user, 用户ID
* @param manager 风控管理器
* @param restrictive 风控限制
* @author GuoTong
*/
@Override
public boolean execute(User user, RiskControlManager manager, RiskControlRestrictive restrictive) {
boolean restrictiveFlag = false;
try {
restrictiveFlag = super.executeDefaultHandler(user, manager, restrictive,this);
} catch (Exception e) {
log.error("RiskControlLimitAccountFilterChain execute error:", e);
}
return restrictiveFlag;
}
@Override
protected int countRiskControlLimit(String startTime, String endTime, User user) {
String mobile = user.getMobile();
if (StringUtils.isBlank(mobile)) {
return 0;
}
return orderService.countRiskControlPhoneLimit(startTime, endTime, mobile);
}
/**
* 保存用户--进入限制桶
* 子类必须重写
* @param riskControlUsers riskControlUsers
*/
protected void saveLimitUser(RiskControlUsers riskControlUsers) {
riskControlUsersService.save(riskControlUsers);
}
@Override
protected ReleaseTimeSetting getReleaseTimeSetting() {
return riskControlUsersService.selectReleaseTimeData();
}
}
作者:隔壁老郭
个性签名:独学而无友,则孤陋而寡闻。做一个灵魂有趣的人!
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!
Java入门到入坟
万水千山总是情,打赏一分行不行,所以如果你心情还比较高兴,也是可以扫码打赏博主,哈哈哈(っ•̀ω•́)っ✎⁾⁾!