Kaynağa Gözat

风控体系代码提交

zjy 1 ay önce
ebeveyn
işleme
0b928ae06b

+ 0 - 3
alien-entity/src/main/java/shop/alien/entity/second/SecondUserCreditRecord.java

@@ -30,9 +30,6 @@ public class SecondUserCreditRecord implements Serializable {
     @TableField("points_type")
     private Integer pointsType;
 
-    @TableField("user_points")
-    private Integer userPoints;
-
     @TableField("delete_flag")
     private Integer deleteFlag;
 

+ 36 - 0
alien-entity/src/main/java/shop/alien/entity/second/vo/SecondRiskControlRecordVo.java

@@ -0,0 +1,36 @@
+package shop.alien.entity.second.vo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import shop.alien.entity.second.SecondRiskControlRecord;
+
+import java.util.Date;
+
+@Data
+@JsonInclude
+@TableName("second_risk_control_record")
+public class SecondRiskControlRecordVo extends SecondRiskControlRecord {
+    private static final long serialVersionUID = 1L;
+
+    @TableField("rule_risk")
+    @ApiModelProperty(value = "风险等级")
+    private String ruleRisk;
+
+    @TableField("rule_name")
+    @ApiModelProperty(value = "规则名称")
+    private String ruleName;
+
+    @ApiModelProperty(value = "触发次数")
+    private String UserPhone;
+
+    @ApiModelProperty(value = "规则名称")
+    private String ruleTypeName;
+
+    @ApiModelProperty(value = "规则名称")
+    private String riskStatusName;
+
+}

+ 10 - 0
alien-entity/src/main/java/shop/alien/mapper/LifeUserMapper.java

@@ -54,4 +54,14 @@ public interface LifeUserMapper extends BaseMapper<LifeUser> {
     @Select("SELECT * " +
             "FROM life_user ${ew.customSqlSegment}")
     List<LifeUserVo> getUserByIds(@Param(Constants.WRAPPER) QueryWrapper<LifeUserVo> queryWrapper);
+
+    /**
+     * 根据id集合查询用户信息
+     *
+     * @param queryWrapper 查询条件
+     * @return 用户信息
+     */
+    @Select("SELECT * " +
+            "FROM life_user ${ew.customSqlSegment}")
+    LifeUserVo getUserById(@Param(Constants.WRAPPER) QueryWrapper<LifeUserVo> queryWrapper);
 }

+ 27 - 0
alien-entity/src/main/java/shop/alien/mapper/second/LifeUserLogMapper.java

@@ -0,0 +1,27 @@
+package shop.alien.mapper.second;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import shop.alien.entity.second.LifeUserLog;
+
+import java.util.List;
+
+@Mapper
+public interface LifeUserLogMapper extends BaseMapper<LifeUserLog> {
+
+    /**
+     * 查询时间段内同一个macip地址的登录记录
+     *
+     * @param starDate 开始日期
+     * @param endDate 结束日期
+     * @return 同一个macip地址的登录记录
+     */
+    @Select(" SELECT user_id, user_name, mac_ip FROM life_user_log " +
+            " WHERE created_time BETWEEN DATE_FORMAT(#{starDate}, '%Y-%m-%d %H:%i:%s') " +
+            " AND DATE_FORMAT(#{endDate}, '%Y-%m-%d %H:%i:%s') AND mac_ip = #{macIp} " +
+            " GROUP BY user_id, user_name, mac_ip ")
+    List<LifeUserLog> getLifeUserLogByDate(@Param("starDate") String starDate, @Param("endDate") String endDate, @Param("macIp") String macIp);
+
+}

+ 3 - 5
alien-gateway/src/main/java/shop/alien/gateway/service/LifeUserService.java

@@ -90,6 +90,8 @@ public class LifeUserService extends ServiceImpl<LifeUserMapper, LifeUser> {
                 baseRedisService.setString("user_" + phoneNum, userVo.getToken());
                 // 二手平台登录log,同一个macip登录多账号记录
                 addLifeUserLogInfo(user2, macIp);
+                // 第一次登录,添加用户基础积分
+                secondServiceFeign.createPointsRecord(user2.getId(), 300, 1);
                 return userVo;
             } else {
                 return null;
@@ -135,16 +137,12 @@ public class LifeUserService extends ServiceImpl<LifeUserMapper, LifeUser> {
             String endDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
             List<LifeUserLog> lsit = lifeUserLogMapper.getLifeUserLogByDate(startDate, endDate, macIp);
 
-            secondServiceFeign.recordRiskControlData(1, 2, "账号异常","1", "测试");
-
             if (lsit.size() > regCount24h) {
                 String detailInfo = lsit.stream()
                         .map(row -> row.getUserId().toString())
                         .collect(Collectors.joining(","));
-                secondServiceFeign.recordRiskControlData(null, 2, "账号异常", "1", detailInfo);
+                secondServiceFeign.recordRiskControlData(null, 2, "账号异常", macIp, detailInfo);
             }
-
-            secondServiceFeign.createPointsRecord(user.getId(), 300, 1);
         } catch (Exception e) {
             log.error("用户登录log存放异常:{}");
         }

+ 12 - 0
alien-second/src/main/java/shop/alien/second/controller/RiskControlController.java

@@ -31,4 +31,16 @@ public class RiskControlController {
                                       @RequestParam("detailInfo") String detailInfo) {
         riskControlService.recordRiskControlData(userId, ruleType, ruleName, businessId, detailInfo);
     }
+
+    /**
+     * 记录风控数据
+     *
+     * @param page     页码
+     * @param size   条数
+     */
+    @PostMapping("/queryRiskControlRecords")
+    public void queryRiskControlRecords(@RequestParam("page") Integer page,
+                                      @RequestParam("size") Integer size) {
+        riskControlService.queryRiskControlRecords(page,  size);
+    }
 }

+ 10 - 0
alien-second/src/main/java/shop/alien/second/service/RiskControlService.java

@@ -2,6 +2,7 @@ package shop.alien.second.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import shop.alien.entity.second.SecondRiskControlRecord;
+import shop.alien.entity.second.vo.SecondRiskControlRecordVo;
 
 import java.util.List;
 
@@ -33,4 +34,13 @@ public interface RiskControlService extends IService<SecondRiskControlRecord> {
      * @return 相同类型的风控数据列表
      */
     List<SecondRiskControlRecord> getSameTypeRiskControlRecords(Integer ruleType, String businessId);
+
+    /**
+     * 获取相同类型的风控数据
+     *
+     * @param page   页码
+     * @param size 条数
+     * @return 查询风控列表
+     */
+    List<SecondRiskControlRecordVo> queryRiskControlRecords(Integer page, Integer size);
 }

+ 79 - 0
alien-second/src/main/java/shop/alien/second/service/impl/RiskControlServiceImpl.java

@@ -1,16 +1,29 @@
 package shop.alien.second.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import shop.alien.entity.second.SecondRiskControlRecord;
+import shop.alien.entity.second.vo.SecondRiskControlRecordVo;
+import shop.alien.entity.store.LifeBrandedCard;
+import shop.alien.entity.store.LifeClassManage;
+import shop.alien.entity.store.LifeUser;
+import shop.alien.entity.store.vo.LifeUserVo;
+import shop.alien.mapper.LifeUserMapper;
 import shop.alien.mapper.second.SecondRiskControlRecordMapper;
 import shop.alien.second.service.RiskControlService;
+import shop.alien.util.common.Constants;
 
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * 风控服务实现类
@@ -22,6 +35,8 @@ public class RiskControlServiceImpl extends ServiceImpl<SecondRiskControlRecordM
 
     private final SecondRiskControlRecordMapper secondRiskControlRecordMapper;
 
+    private final LifeUserMapper lifeUserMapper;
+
     /**
      * 记录风控数据
      *
@@ -72,4 +87,68 @@ public class RiskControlServiceImpl extends ServiceImpl<SecondRiskControlRecordM
         log.info("查询条件: {}", queryWrapper.getSqlSegment());
         return secondRiskControlRecordMapper.selectList(queryWrapper);
     }
+
+    @Override
+    public List<SecondRiskControlRecordVo> queryRiskControlRecords(Integer page, Integer size) {
+        try {
+            List<SecondRiskControlRecordVo> list = new ArrayList<>();
+            IPage<SecondRiskControlRecord> brandedPage = new Page<>(page, size);
+
+            // 获取风险管控信息
+            QueryWrapper<SecondRiskControlRecord> queryWrapper = new QueryWrapper<>();
+            queryWrapper.eq("delete_flag", Constants.DeleteFlag.NOT_DELETED);
+            queryWrapper.orderByDesc("created_time");
+            IPage<SecondRiskControlRecord> brandedCards = secondRiskControlRecordMapper.selectPage(brandedPage, queryWrapper);
+
+            for (SecondRiskControlRecord card : brandedCards.getRecords()) {
+                SecondRiskControlRecordVo vo = new SecondRiskControlRecordVo();
+                if (1 == card.getRuleType()) {
+                    vo.setRuleTypeName("洗钱嫌疑");
+                    vo.setRuleName("高频高价交易");
+                    vo.setRuleRisk("中风险");
+                    vo.setCreatedTime(card.getCreatedTime());
+                } else if (2 == card.getRuleType()) {
+                    vo.setRuleTypeName("账号异常");
+                    vo.setRuleName("同一设备/mac 24小时内注册超过3个账号");
+                    vo.setRuleRisk("中风险");
+                    vo.setCreatedTime(card.getCreatedTime());
+                } else if (3 == card.getRuleType()) {
+                    vo.setRuleTypeName("交易欺诈");
+                    vo.setRuleName("用户频繁修改商品价格");
+                    vo.setRuleRisk("高风险");
+                    vo.setCreatedTime(card.getCreatedTime());
+                } else if (4 == card.getRuleType()) {
+                    vo.setRuleTypeName("异常发布");
+                    vo.setRuleName("短时间大量发布同类商品");
+                    vo.setRuleRisk("高风险");
+                    vo.setCreatedTime(card.getCreatedTime());
+                }
+
+                if ( 2 != card.getRuleType()) {
+                    // 根据ID查询用户信息
+                    QueryWrapper<LifeUserVo> queryWrapperUser = new QueryWrapper<>();
+                    queryWrapper.eq("delete_flag", Constants.DeleteFlag.NOT_DELETED)
+                            .eq("id", card.getUserId());
+                    LifeUserVo userInfoList = lifeUserMapper.getUserById(queryWrapperUser);
+                    // 用户手机号
+                    vo.setUserPhone(userInfoList.getUserPhone());
+                }
+
+                // 处理结果
+                if (card.getRiskStatus().equals(0)) {
+                    vo.setRiskStatusName("待处理");
+                } else if (card.getRiskStatus().equals(1)) {
+                    vo.setRiskStatusName("已处理");
+                } else if (card.getRiskStatus().equals(2)) {
+                    vo.setRiskStatusName("已忽略");
+                }
+                list.add(vo);
+            }
+            return list;
+        } catch (Exception e) {
+            log.error("记录风控数据时发生异常: 用户ID={}, 规则类型={},业务id={}", e);
+            return null;
+        }
+    }
+
 }

+ 1 - 1
alien-store/src/main/java/shop/alien/store/AlienStoreApplication.java

@@ -8,7 +8,7 @@ import org.springframework.cloud.openfeign.EnableFeignClients;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.scheduling.annotation.EnableScheduling;
 
-@ComponentScan({"shop.alien.store.*","shop.alien.util.*","shop.alien.config.http"})
+@ComponentScan({"shop.alien.store.*","shop.alien.util.*","shop.alien.config.http","shop.alien.config.properties"})
 @EnableSwaggerBootstrapUI
 @MapperScan({"shop.alien.mapper"})
 @SpringBootApplication

+ 3 - 2
alien-store/src/main/java/shop/alien/store/controller/LifeUserController.java

@@ -44,9 +44,10 @@ public class LifeUserController {
     @ApiImplicitParams({@ApiImplicitParam(name = "phoneNum", value = "手机号", dataType = "String", paramType = "query", required = true),
                         @ApiImplicitParam(name = "inviteCode", value = "邀请码", dataType = "String", paramType = "query", required = false)})
     @GetMapping("/userLogin")
-    public R<LifeUserVo> userLogin(@RequestParam("phoneNum") String phoneNum,  @RequestParam(required = false) String inviteCode) {
+    public R<LifeUserVo> userLogin(@RequestParam("phoneNum") String phoneNum,  @RequestParam(required = false) String inviteCode,
+                                   @RequestParam(value = "macIp",required = false) String macIp) {
         log.info("LifeUserController.userLogin?phoneNum={}", phoneNum);
-        LifeUserVo userVo = service.userLogin(phoneNum, inviteCode);
+        LifeUserVo userVo = service.userLogin(phoneNum, inviteCode, macIp);
         if (null == userVo) {
             return R.fail("登录失败");
         }

+ 25 - 1
alien-store/src/main/java/shop/alien/store/service/LifeUserService.java

@@ -12,25 +12,33 @@ import lombok.RequiredArgsConstructor;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Triple;
 import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
+import shop.alien.config.properties.RiskControlProperties;
+import shop.alien.entity.second.LifeUserLog;
+import shop.alien.entity.result.R;
 import shop.alien.entity.store.LifeFans;
 import shop.alien.entity.store.LifeNotice;
 import shop.alien.entity.store.LifeUser;
 import shop.alien.entity.store.vo.LifeMessageVo;
 import shop.alien.entity.store.vo.LifeUserVo;
 import shop.alien.entity.store.vo.WebSocketVo;
+import shop.alien.mapper.second.LifeUserLogMapper;
 import shop.alien.store.config.BaseRedisService;
 import shop.alien.mapper.LifeFansMapper;
 import shop.alien.mapper.LifeMessageMapper;
 import shop.alien.mapper.LifeNoticeMapper;
 import shop.alien.mapper.LifeUserMapper;
 import shop.alien.store.config.WebSocketProcess;
+import shop.alien.store.feign.SecondServiceFeign;
 import shop.alien.store.util.FunctionMagic;
 import shop.alien.util.common.JwtUtil;
 
 import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -55,6 +63,13 @@ public class LifeUserService extends ServiceImpl<LifeUserMapper, LifeUser> {
 
     private final ActivityInviteConfigService activityInviteConfigService;
 
+    private final LifeUserLogMapper lifeUserLogMapper;
+
+    private final SecondServiceFeign alienSecondFeign;
+
+    @Autowired
+    private RiskControlProperties riskControlProperties;
+
     @Value("${jwt.expiration-time}")
     private String effectiveTime;
 
@@ -138,7 +153,7 @@ public class LifeUserService extends ServiceImpl<LifeUserMapper, LifeUser> {
         return voList;
     }
 
-    public LifeUserVo userLogin(String phoneNum, String inviteCode) {
+    public LifeUserVo userLogin(String phoneNum, String inviteCode, String macIp) {
         LifeUser user = getUserByPhone(phoneNum);
         if (user == null) {
             LifeUser lifeUser = new LifeUser();
@@ -165,6 +180,12 @@ public class LifeUserService extends ServiceImpl<LifeUserMapper, LifeUser> {
                 if(StringUtils.isNotEmpty(inviteCode)){
                     activityInviteConfigService.bindInviteCode(lifeUser.getId(), inviteCode);
                 }
+
+                // 二手平台登录log,同一个macip登录多账号记录
+                addLifeUserLogInfo(user2, macIp);
+                // 第一次登录,添加用户基础积分
+                alienSecondFeign.createPointsRecord(user2.getId(), 300, 1);
+
                 return userVo;
             } else {
                 return null;
@@ -185,6 +206,9 @@ public class LifeUserService extends ServiceImpl<LifeUserMapper, LifeUser> {
                 activityInviteConfigService.bindInviteCode(user.getId(), inviteCode);
             }
 
+            // 二手平台登录log,同一个macip登录多账号记录
+            addLifeUserLogInfo(user, macIp);
+
             return userVo;
         }
     }