Browse Source

增加游客登录模式

marxjaw 2 months ago
parent
commit
716a362bee

+ 5 - 0
yt-adage/adage-feign/src/main/java/com/ytpm/adage/feign/AdageFeign.java

@@ -30,6 +30,11 @@ import java.util.Map;
 
 @FeignClient(name = "adage-service")
 public interface AdageFeign {
+    @GetMapping("/getLoginDitchCount")
+    int getLoginDitchCount(@RequestParam("deviceId")String deviceId,@RequestParam("hours")Integer hours);
+    @GetMapping("/getDitchCount")
+    int getDitchCount(@RequestParam("deviceId")String deviceId,@RequestParam("hours")Integer hours);
+
     @GetMapping("/user/getMonthRegistryUser")
     List<YtDyzUser> getMonthRegistryUser(@RequestParam("appIds")String appIds,@RequestParam("type")Integer type);
     @PostMapping("/user/queryAll")

+ 43 - 12
yt-adage/adage-service/src/main/java/com/ytpm/adage/controller/VisitorController.java

@@ -1,5 +1,6 @@
 package com.ytpm.adage.controller;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.RandomUtil;
 import cn.hutool.core.util.StrUtil;
@@ -23,9 +24,11 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.cloud.context.config.annotation.RefreshScope;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.servlet.http.HttpServletRequest;
@@ -61,30 +64,55 @@ public class VisitorController {
     @Transactional(rollbackFor = Exception.class)
     public Result<YtDyzUser> visitorLogin(@RequestBody WxLoginParam param, HttpServletRequest request) {
         param.setLoginIp(getClientIp(request));
-        YtDyzUser old = appUserMapper.getByDeviceAndDitch(param.getDeviceId(),param.getDitchId());
-        //当前设备在该渠道未曾注册
-        if(Objects.isNull(old)){
+        //获取该设备最后一次注册的用户信息
+        YtDyzUser registryUser = appUserMapper.getLastRegistryUser(param.getDeviceId());
+        //该设备未注册过用户
+        YtDyzUser old;
+        if(Objects.isNull(registryUser)) {
             old = new YtDyzUser();
             registerUser(param, old);
         }else{
-            //当前设备已注册该渠道
-            if(!old.getUserStatus().equals(UserStatusEnum.NORMAL.getCode())){
-                return new Result<>(StatusCode.ACCESS_ERR,getTipsMsg());
+            //查询当前设备当前渠道是否存在该用户
+            old = appUserMapper.getByDeviceAndDitch(param.getDeviceId(), param.getDitchId());
+            //不存在则说明该渠道为新注册用户,需要风控校验注册是否在规则允许范围内
+            if(Objects.isNull(old)) {
+                Result<?> result = riskFeign.checkRegRisk(registryUser);
+                if(result.getCode()!=200){
+                    return new Result<>(StatusCode.ACCESS_ERR,result.getMessage());
+                }
+                old = new YtDyzUser();
+                registerUser(param, old);
+            }else{//当前渠道已有用户,校验用户是否处于风控中 & 更新用户信息
+                if(!old.getUserStatus().equals(UserStatusEnum.NORMAL.getCode())){
+                    return new Result<>(StatusCode.ACCESS_ERR,getTipsMsg());
+                }
+                deadWithUserCrud(old,param);
             }
-            deadWithUserCrud(old,param);
         }
         //设置最后一次答题问题ID、今日答题数、历史答题数
         setExtInfo(old);
-        // 添加用户登录记录
-        addLoginRecord(param,old.getUserId());
-        //校验游客风控
+        //校验指定时间内登录的渠道数
         Result<?> result = riskFeign.checkLoginRisk(old);
         if(result.getCode()!=200){
-            return new Result<>(StatusCode.ACCESS_ERR,result.getMessage());
-        }
+        // 添加用户登录记录
+        addLoginRecord(param,old.getUserId());
+        return new Result<>(StatusCode.ACCESS_ERR,result.getMessage());
+    }
         return Result.resultObjOk(old);
     }
 
+    @ApiOperation("设备在指定时间内注册的渠道")
+    @GetMapping("/getDitchCount")
+    public int getDitchCount(@RequestParam("deviceId")String deviceId,@RequestParam("hours")Integer hours) {
+        return appUserMapper.countDitch(deviceId,hours);
+    }
+
+    @ApiOperation("设备在指定时间内注册的渠道")
+    @GetMapping("/getLoginDitchCount")
+    public int getLoginDitchCount(@RequestParam("deviceId")String deviceId,@RequestParam("hours")Integer hours) {
+        return appUserMapper.countLoginDitch(deviceId,hours);
+    }
+
     /**
      * 注册用户
      */
@@ -109,6 +137,9 @@ public class VisitorController {
         old.setSignDays(0);
         old.setAppId(param.getAppId());
         old.setUserStatus(UserStatusEnum.NORMAL.getCode());
+        String platformId = appUserMapper.getPlatformByDeviceId(param.getDeviceId());
+        old.setPlatformId(StrUtil.isBlank(platformId)?
+                (StrConstant.PLATFORM_ID_PREFIX + IdUtil.getSnowflakeNextIdStr()):platformId);
         appUserMapper.addOne(old);
         return old;
     }

+ 13 - 1
yt-adage/adage-service/src/main/java/com/ytpm/adage/dao/AppUserMapper.java

@@ -100,6 +100,8 @@ public interface AppUserMapper {
      */
     String getByDeviceId(@Param("deviceId")String deviceId,@Param("openid")String openid);
 
+    String getPlatformByDeviceId(@Param("deviceId")String deviceId);
+
     /**
      * 保存应用配置
      */
@@ -192,5 +194,15 @@ public interface AppUserMapper {
     /**
      * 查询设备指定天数内注册的渠道数
      */
-    int countDitch(@Param("deviceId")String deviceId,@Param("days")int days);
+    int countDitch(@Param("deviceId")String deviceId,@Param("hours")int hours);
+
+    /**
+     * 查询设备指定时间内登录的用户和渠道
+     */
+    int countLoginDitch(@Param("deviceId")String deviceId,@Param("hours")int hours);
+
+    /**
+     * 查询设备最新注册的用户
+     */
+    YtDyzUser getLastRegistryUser(@Param("deviceId")String deviceId);
 }

+ 22 - 2
yt-adage/adage-service/src/main/resources/mapper/AppUserMapper.xml

@@ -390,6 +390,13 @@
         and wx_open_id = #{openid}
         limit 1
     </select>
+    <select id="getPlatformByDeviceId" resultType="java.lang.String">
+        select
+            platform_id
+        from yt_dyz_user
+        where device_id = #{deviceId}
+        limit 1
+    </select>
     <select id="getConfigByIds" resultType="com.ytpm.app.view.WxDefaultConfig">
         select
             config_id, config_name, open_id, secret, app_id, app_key, app_type,user_path,login_path,ad_path,answer_path,power_path
@@ -646,8 +653,21 @@
             count( distinct ditch_id)
         from yt_dyz_user
         where device_id = #{deviceId}
-        and registry_time > DATE_SUB(CURRENT_DATE(), INTERVAL #{days} DAY)
-        and registry_time <![CDATA[<=]]> CURRENT_DATE()
+        and registry_time > (NOW() - INTERVAL #{hours} HOUR )
+    </select>
+    <select id="countLoginDitch" resultType="java.lang.Integer">
+        select
+            count( distinct ditch_id)
+        from yt_dyz_user
+        where device_id = #{deviceId}
+          and last_login_time > (NOW() - INTERVAL #{hours} HOUR )
+    </select>
+    <select id="getLastRegistryUser" resultType="com.ytpm.app.model.YtDyzUser">
+        select
+            user_id, head_img, nick_name, registry_time, last_login_time, last_login_ip, login_days, total_video, total_income, red_packet_balance, red_packet_amount, points_balance, points_total, withdraw_total, sign_days, user_status, risk_reason, wx_open_id, ditch_id, app_id, platform_id, power, phone, device_id, phone_json
+        from yt_dyz_user
+        where user_status = 1 and device_id = #{deviceId}
+        order by registry_time desc limit 1
     </select>
     <update id="unlockUser">
         update yt_dyz_user

+ 2 - 0
yt-common/src/main/java/com/ytpm/general/RepMessage.java

@@ -10,6 +10,7 @@ public class RepMessage {
     public static final String ADD_SUCCESS = "增加成功";
     public static final String SAVE_SUCCESS = "保存成功";
     public static final String PROCESS_SUCCESS = "处理成功";
+    public static final String RISK_SUCCESS = "风控校验通过";
     public static final String DELETE_SUCCESS = "删除成功";
     public static final String RELATIVE_SUCCESS = "关联成功";
     public static final String LOGOUT_SUCCESS = "已退出登录";
@@ -30,6 +31,7 @@ public class RepMessage {
     public static final String UUID_EMPTY = "验证码生成失败! UUID:";
     public static final String OBJECT_ALREADY_EXIST = "查询对象已存在";
     public static final String LOCK_FAIL = "锁定用户失败!";
+    public static final String DITCH_REG_LIMIT = "小时内注册渠道已达上限!";
 
     public static final String COLLECTION_EMPTY = "集合数据不能为空";
     public static final String PAYMENT_ATTACH_EMPTY = "缴费凭证不能为空";

+ 3 - 1
yt-risk/risk-feign/src/main/java/com/ytpm/feign/RiskFeign.java

@@ -17,6 +17,8 @@ public interface RiskFeign {
     Result<?> checkAdRisk(@RequestBody YtDyzUser ytDyzUser);
     @GetMapping("/public/addDeblockingRecord")
     void addBlockingRecord(@RequestParam("userId")String userId);
+    @PostMapping("/public/checkRegRisk")
+    Result<?> checkRegRisk(@RequestBody YtDyzUser ytDyzUser);
     @PostMapping("/public/checkLoginRisk")
-    Result<?> checkLoginRisk(@RequestBody YtDyzUser ytDyzUser);
+    Result<?> checkLoginRisk(YtDyzUser old);
 }

+ 10 - 0
yt-risk/risk-feign/src/main/java/com/ytpm/feign/fallback/RiskFeignFallBack.java

@@ -22,4 +22,14 @@ public abstract class RiskFeignFallBack implements RiskFeign {
     public Result<?> checkAdRisk(@RequestBody YtDyzUser ytDyzUser) {
         return new Result<>(StatusCode.ACCESS_ERR, RepMessage.TOKEN_EXPIRE);
     }
+
+    @Override
+    public Result<?> checkRegRisk(@RequestBody YtDyzUser ytDyzUser) {
+        return new Result<>(StatusCode.ACCESS_ERR, RepMessage.TOKEN_EXPIRE);
+    }
+
+    @Override
+    public Result<?> checkLoginRisk(@RequestBody YtDyzUser ytDyzUser) {
+        return new Result<>(StatusCode.ACCESS_ERR, RepMessage.TOKEN_EXPIRE);
+    }
 }

+ 6 - 0
yt-risk/risk-manage/src/main/java/com/ytpm/controller/PublicApiController.java

@@ -81,6 +81,12 @@ public class PublicApiController {
         riskService.addDeblockingRecord(userId);
     }
 
+    @ApiOperation("校验注册风控配置")
+    @PostMapping("/checkRegRisk")
+    public Result<?> checkRegRisk(@RequestBody YtDyzUser dyzUser){
+        return riskService.checkRegRisk(dyzUser);
+    }
+
     @ApiOperation("校验登录风控配置")
     @PostMapping("/checkLoginRisk")
     public Result<?> checkLoginRisk(@RequestBody YtDyzUser dyzUser){

+ 8 - 0
yt-risk/risk-manage/src/main/java/com/ytpm/service/RiskService.java

@@ -120,5 +120,13 @@ public interface RiskService {
      */
     List<RiskTemplateView> getRiskTemplate(String appId);
 
+    /**
+     * 校验注册风控规则
+     */
+    Result<?> checkRegRisk(YtDyzUser dyzUser);
+
+    /**
+     * 校验登录风控配置
+     */
     Result<?> checkLoginRisk(YtDyzUser dyzUser);
 }

+ 58 - 1
yt-risk/risk-manage/src/main/java/com/ytpm/service/impl/RiskServiceImpl.java

@@ -911,12 +911,69 @@ public class RiskServiceImpl implements RiskService {
         return configMapper.getTemplateByAppId(appId);
     }
 
+    /**
+     * 校验注册风控规则
+     */
+    @Override
+    public Result<?> checkRegRisk(YtDyzUser dyzUser) {
+        RiskTemplateView view= configMapper.getByCode(dyzUser.getAppId()+"-333");
+        return checkReg333(dyzUser,view);
+    }
+
     /**
      * 校验登录风控规则
      */
     @Override
     public Result<?> checkLoginRisk(YtDyzUser dyzUser) {
+        RiskTemplateView view= configMapper.getByCode(dyzUser.getAppId()+"-323");
+        checkVisitor323(dyzUser,view);
+        return Result.resultOk(RepMessage.RISK_SUCCESS);
+    }
+
+    /**
+     * 校验游客登录323规则
+     */
+    private void checkVisitor323(YtDyzUser dyzUser, RiskTemplateView view) {
+        List<RiskConfigView> configList = view.getConfigList();
+        Map<String, String> configMap = configList.stream().collect(
+                Collectors.toMap(RiskConfigView::getFieldName, RiskConfigView::getConfigVal));
+        //判断同应用 UID生成数如果不小于配置数则触发规则校验
+        int uidCount = Integer.parseInt(configMap.get("uidCount"));
+        int hours = Integer.parseInt(configMap.get("hours"));
+        //根据用户所属应用查询该应用母包openid查询用户信息
+        YtApp ytApp = appMapper.selectRiskApp(dyzUser.getAppId());
+        YtPlatformUserApp userApp =  appMapper.selectParentApp(ytApp.getSuperiorId());
+        Object o = feignInvoker.invoke(userApp.getServiceName(),"getLoginDitchCount",dyzUser.getDeviceId(),hours);
+        int ditchCount = (int)o;
+        //三天内注册的渠道数小于预设的渠道数通过校验,否则风控锁定用户
+        if(ditchCount<uidCount)return;
+        riskLockUser(dyzUser,"323",hours+"小时内登录渠道已达上限",getTipsMsg());
+    }
+
+    /**
+     * 333 注册风控可配置
+     *  需求要求改为小时控制
+     * @param dyzUser 该设备同应用的最新一条注册用户信息
+     * @param view 当前校验的设备登录的应用风控配置
+     */
+    private Result<?> checkReg333(YtDyzUser dyzUser, RiskTemplateView view) {
+        //根据用户所属应用查询该应用母包openid查询用户信息
+        List<RiskConfigView> configList = view.getConfigList();
+        Map<String, String> configMap = configList.stream().collect(
+                Collectors.toMap(RiskConfigView::getFieldName, RiskConfigView::getConfigVal));
+        //得到配置的注册数
+        int uidCount = Integer.parseInt(configMap.get("uidCount"));
+        //得到配置的时间间隔
+        int hours = Integer.parseInt(configMap.get("hours"));
 
-        return null;
+        //根据用户所属应用查询该应用母包openid查询用户信息
+        YtApp ytApp = appMapper.selectRiskApp(dyzUser.getAppId());
+        YtPlatformUserApp userApp =  appMapper.selectParentApp(ytApp.getSuperiorId());
+        Object o = feignInvoker.invoke(userApp.getServiceName(),"getDitchCount",dyzUser.getDeviceId(),hours);
+        int regCount = (int) o;
+        if(regCount<uidCount){
+            return Result.resultOk(RepMessage.RISK_SUCCESS);
+        }
+        return Result.resultErr(hours+RepMessage.DITCH_REG_LIMIT);
     }
 }