|
|
@@ -4,6 +4,10 @@ import cn.hutool.core.collection.CollUtil;
|
|
|
import cn.hutool.core.date.DateUtil;
|
|
|
import com.github.pagehelper.PageInfo;
|
|
|
import com.ytpm.advertise.enums.AdSourceTypeEnum;
|
|
|
+import com.ytpm.agent.enums.UserStatusEnum;
|
|
|
+import com.ytpm.agent.param.AuditCheckParam;
|
|
|
+import com.ytpm.agent.param.AuditUserParam;
|
|
|
+import com.ytpm.agent.view.AgentAuditCheckVO;
|
|
|
import com.ytpm.app.model.YtDyzAdRecord;
|
|
|
import com.ytpm.app.model.YtDyzLoginRecord;
|
|
|
import com.ytpm.app.model.YtDyzUser;
|
|
|
@@ -27,11 +31,17 @@ import com.ytpm.dao.qnjz.QNUserMapper;
|
|
|
import com.ytpm.dao.qnmjz.QnmAdRecordMapper;
|
|
|
import com.ytpm.dao.qnmjz.QnmLoginRecordMapper;
|
|
|
import com.ytpm.dao.qnmjz.QnmUserMapper;
|
|
|
+import com.ytpm.feign.RiskFeign;
|
|
|
import com.ytpm.general.RepMessage;
|
|
|
import com.ytpm.general.Result;
|
|
|
import com.ytpm.general.ResultTable;
|
|
|
import com.ytpm.risk.enums.BannedTypeEnum;
|
|
|
+import com.ytpm.risk.view.RiskConfigView;
|
|
|
+import com.ytpm.risk.view.RiskTemplateView;
|
|
|
+import com.ytpm.util.RedisService;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.beans.factory.annotation.Qualifier;
|
|
|
import org.springframework.web.bind.annotation.GetMapping;
|
|
|
import org.springframework.web.bind.annotation.PostMapping;
|
|
|
import org.springframework.web.bind.annotation.RequestBody;
|
|
|
@@ -85,6 +95,11 @@ public class UserController {
|
|
|
private QuestionMapper questionMapper;
|
|
|
|
|
|
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
|
+ @Qualifier("com.ytpm.feign.RiskFeign")
|
|
|
+ @Autowired
|
|
|
+ private RiskFeign riskFeign;
|
|
|
+ @Autowired
|
|
|
+ private RedisService redisService;
|
|
|
|
|
|
/**
|
|
|
* 查询app 所有玩家
|
|
|
@@ -382,4 +397,100 @@ public class UserController {
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 批量审核用户是否满足风控规则
|
|
|
+ * 不满足风控规则的审核通过后直接封禁指定天数
|
|
|
+ */
|
|
|
+ @PostMapping("/batchAudit")
|
|
|
+ public void batchAudit(@RequestBody AuditCheckParam checkParam){
|
|
|
+ AuditUserParam auditParam = checkParam.getAuditParam();
|
|
|
+ RiskTemplateView ecpmLimit = checkParam.getEcpmLimit();
|
|
|
+ RiskTemplateView revenueLimit = checkParam.getRevenueLimit();
|
|
|
+ //查询用户,指定应用激励视频的广告记录
|
|
|
+ List<AgentAuditCheckVO> auditList = new ArrayList<>();
|
|
|
+ List<AgentAuditCheckVO> auditCheckList = appUserMapper.queryTodayUserAd(auditParam);
|
|
|
+ if(CollUtil.isNotEmpty(auditCheckList)){auditList.addAll(auditCheckList);}
|
|
|
+ List<AgentAuditCheckVO> qnAuditCheckList = qnUserMapper.queryTodayUserAd(auditParam);
|
|
|
+ if(CollUtil.isNotEmpty(qnAuditCheckList)){auditList.addAll(qnAuditCheckList);}
|
|
|
+ List<AgentAuditCheckVO> nfAuditCheckList = nfUserMapper.queryTodayUserAd(auditParam);
|
|
|
+ if(CollUtil.isNotEmpty(nfAuditCheckList)){auditList.addAll(nfAuditCheckList);}
|
|
|
+ List<AgentAuditCheckVO> qnmAuditCheckList = qnmUserMapper.queryTodayUserAd(auditParam);
|
|
|
+ if(CollUtil.isNotEmpty(qnmAuditCheckList)){auditList.addAll(qnmAuditCheckList);}
|
|
|
+
|
|
|
+ Map<String, List<YtDyzAdRecord>> adRecordMap = auditList.stream().collect(
|
|
|
+ Collectors.toMap(AgentAuditCheckVO::getUserId, AgentAuditCheckVO::getAdRecordList));
|
|
|
+ checkRisk742(ecpmLimit,adRecordMap,auditParam);
|
|
|
+ checkRisk746(revenueLimit,adRecordMap,auditParam);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 校验默认风控规则742
|
|
|
+ */
|
|
|
+ private void checkRisk742(RiskTemplateView ecpmLimit,Map<String, List<YtDyzAdRecord>> adRecordMap,AuditUserParam auditParam) {
|
|
|
+ if(ecpmLimit.getEnabled()!=1)return;
|
|
|
+ Map<String, String> limitMap = ecpmLimit.getConfigList().stream().collect(
|
|
|
+ Collectors.toMap(RiskConfigView::getFieldName, RiskConfigView::getConfigVal));
|
|
|
+ int adCount = 0;
|
|
|
+ for (Map.Entry<String, List<YtDyzAdRecord>> entry : adRecordMap.entrySet()) {
|
|
|
+ adCount = CollUtil.isEmpty(entry.getValue())?adCount:entry.getValue().size();
|
|
|
+ ++adCount;
|
|
|
+ //判断当日观看视频数已经达到风控条件预设的视频数
|
|
|
+ int firstAdCount = Integer.parseInt(limitMap.get("firstAdCount"));
|
|
|
+ if(adCount>=firstAdCount){
|
|
|
+ //过滤出ecpm值小于预设值的视频数
|
|
|
+ int ecpm = Integer.parseInt(limitMap.get("ecpm"));
|
|
|
+ long count = entry.getValue().stream().filter(
|
|
|
+ s -> Objects.nonNull(s.getEcpm())&&(s.getEcpm().compareTo(BigDecimal.valueOf(ecpm))) < 0).count();
|
|
|
+ int exact = Math.toIntExact(count);
|
|
|
+ //判断小于预设值的视频数超出预设次数
|
|
|
+ int haveCount = Integer.parseInt(limitMap.get("haveCount"));
|
|
|
+ if(exact>haveCount){//把风控不满足的用户记录redis 进行封禁
|
|
|
+ checkLock(entry,auditParam);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 用户锁定操作
|
|
|
+ */
|
|
|
+ private void checkLock(Map.Entry<String, List<YtDyzAdRecord>> entry, AuditUserParam auditParam) {
|
|
|
+ log.error("执行对低价值用户{}的定时风控操作", entry.getKey());
|
|
|
+ if(auditParam.getEffectTime() == 0){ //立即锁定
|
|
|
+ lockUser(entry.getKey(), UserStatusEnum.RISK.getCode());
|
|
|
+ redisService.setTimeOutHoursStr("unlock_"+entry.getKey(),auditParam.getAppId(), auditParam.getBannedLimit()*24L);
|
|
|
+ }else{//延迟锁定
|
|
|
+ redisService.setTimeOutHoursStr("lock_"+entry.getKey(), auditParam.getAppId(), auditParam.getEffectTime());
|
|
|
+ redisService.setTimeOutHoursStr("unlock_"+entry.getKey(),auditParam.getAppId(),
|
|
|
+ auditParam.getBannedLimit()*24L + auditParam.getEffectTime());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 校验默认风控规则746
|
|
|
+ */
|
|
|
+ private void checkRisk746(RiskTemplateView revenueLimit,Map<String, List<YtDyzAdRecord>> adRecordMap,AuditUserParam auditParam) {
|
|
|
+ if(revenueLimit.getEnabled()!=1)return;
|
|
|
+ Map<String, String> revenueMap = revenueLimit.getConfigList().stream().collect(
|
|
|
+ Collectors.toMap(RiskConfigView::getFieldName, RiskConfigView::getConfigVal));
|
|
|
+ for (Map.Entry<String, List<YtDyzAdRecord>> entry : adRecordMap.entrySet()) {
|
|
|
+ List<YtDyzAdRecord> revenues = entry.getValue().stream().filter(
|
|
|
+ s -> Objects.nonNull(s.getRevenue())&&(s.getRevenue().compareTo(BigDecimal.ZERO)) > 0).collect(Collectors.toList());
|
|
|
+ int incomeCount = 0;
|
|
|
+ incomeCount = CollUtil.isEmpty(revenues)?incomeCount:entry.getValue().size();
|
|
|
+ //判断当日获得收益的广告达到预设数值,触发风控规则
|
|
|
+ int rewardCount = Integer.parseInt(revenueMap.get("rewardCount"));
|
|
|
+ if(incomeCount>=rewardCount){
|
|
|
+ BigDecimal income = new BigDecimal(revenueMap.get("income"));
|
|
|
+ //获取最先的两条
|
|
|
+ BigDecimal reduce = revenues.stream().map(YtDyzAdRecord::getRevenue).reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+ if(reduce.compareTo(income)<0){
|
|
|
+ checkLock(entry,auditParam);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
}
|