|
|
@@ -16,41 +16,29 @@ import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.BeanUtils;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
-import org.springframework.context.annotation.Lazy;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
-import org.springframework.transaction.annotation.Transactional;
|
|
|
import org.springframework.util.StringUtils;
|
|
|
import shop.alien.config.properties.RiskControlProperties;
|
|
|
import shop.alien.entity.SecondVideoTask;
|
|
|
import shop.alien.entity.second.*;
|
|
|
-import shop.alien.entity.second.SecondTradeRecord;
|
|
|
+import shop.alien.entity.second.enums.SecondGoodsStatusEnum;
|
|
|
import shop.alien.entity.second.vo.*;
|
|
|
-import shop.alien.entity.second.vo.SecondGoodsDetailVo;
|
|
|
import shop.alien.entity.store.*;
|
|
|
import shop.alien.entity.store.vo.LifeUserVo;
|
|
|
import shop.alien.entity.store.vo.WebSocketVo;
|
|
|
import shop.alien.mapper.*;
|
|
|
-import shop.alien.mapper.second.SecondGoodsAuditMapper;
|
|
|
-import shop.alien.mapper.second.SecondGoodsMapper;
|
|
|
-import shop.alien.mapper.second.SecondGoodsRecordMapper;
|
|
|
-import shop.alien.mapper.second.SecondTradeRecordMapper;
|
|
|
+import shop.alien.mapper.second.*;
|
|
|
import shop.alien.second.feign.AlienStoreFeign;
|
|
|
import shop.alien.second.service.PlatformSecondTradeService;
|
|
|
+import shop.alien.second.service.RiskControlService;
|
|
|
import shop.alien.second.service.SecondGoodsService;
|
|
|
import shop.alien.second.service.VideoModerationService;
|
|
|
import shop.alien.util.common.Constants;
|
|
|
-import shop.alien.entity.second.enums.SecondGoodsStatusEnum;
|
|
|
import shop.alien.util.common.VideoUtils;
|
|
|
import shop.alien.util.common.safe.*;
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
-import java.util.ArrayList;
|
|
|
-import java.util.Arrays;
|
|
|
-import java.util.Collections;
|
|
|
-import java.util.Date;
|
|
|
-import java.util.HashMap;
|
|
|
-import java.util.List;
|
|
|
-import java.util.Map;
|
|
|
+import java.util.*;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
|
@@ -154,6 +142,11 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
|
|
|
|
|
|
@Autowired
|
|
|
private RiskControlProperties riskControlProperties;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 风控服务
|
|
|
+ */
|
|
|
+ private final RiskControlService riskControlService;
|
|
|
|
|
|
@Override
|
|
|
public SecondGoodsRecordDetailVo getAdminGoodsRecordDetail(Integer recordId) {
|
|
|
@@ -560,7 +553,7 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
|
|
|
// TODO 插入风控记录
|
|
|
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// 检查用户是否在24小时内发布同类商品超过阈值
|
|
|
if (!checkUserPublishSameCategoryLimit(goods)) {
|
|
|
log.warn("用户 {} 在24小时内发布同类商品次数超过限制", goodsDTO.getUserId());
|
|
|
@@ -613,15 +606,17 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
|
|
|
private boolean checkUserPublishLimit(SecondGoods goods) {
|
|
|
// 获取配置的阈值
|
|
|
int publishLimit = riskControlProperties.getTradeFraud().getPublishCount24h();
|
|
|
+ // 时间窗口(小时)
|
|
|
+ int timeWindowHours = riskControlProperties.getTradeFraud().getTimeWindowHours();
|
|
|
|
|
|
- // 计算24小时前的时间
|
|
|
- Date twentyFourHoursAgo = new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000L);
|
|
|
+ // 计算时间窗口前的时间
|
|
|
+ Date timeWindowStart = new Date(System.currentTimeMillis() - timeWindowHours * 60 * 60 * 1000L);
|
|
|
|
|
|
// 查询用户在24小时内发布的商品数量
|
|
|
LambdaQueryWrapper<SecondGoodsRecord> queryWrapper = new LambdaQueryWrapper<>();
|
|
|
queryWrapper.eq(SecondGoodsRecord::getUserId, goods.getUserId())
|
|
|
.eq(SecondGoodsRecord::getId, goods.getId())
|
|
|
- .ge(SecondGoodsRecord::getReleaseTime, twentyFourHoursAgo)
|
|
|
+ .ge(SecondGoodsRecord::getReleaseTime, timeWindowStart)
|
|
|
.in(SecondGoodsRecord::getGoodsStatus,
|
|
|
SecondGoodsStatusEnum.LISTED.getCode(),
|
|
|
SecondGoodsStatusEnum.SOLD.getCode());
|
|
|
@@ -633,33 +628,46 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 检查用户在24小时内发布同类商品的数量是否超过限制
|
|
|
+ * 检查用户在指定时间窗口内发布同类商品的数量是否超过限制
|
|
|
* @param goods 商品信息
|
|
|
* @return 是否未超过限制
|
|
|
*/
|
|
|
private boolean checkUserPublishSameCategoryLimit(SecondGoods goods) {
|
|
|
// 获取配置的阈值
|
|
|
int sameCategoryLimit = riskControlProperties.getAbnormalPublish().getSameCategoryCount24h();
|
|
|
+ int timeWindowHours = riskControlProperties.getAbnormalPublish().getTimeWindowHours();
|
|
|
|
|
|
- // 计算24小时前的时间
|
|
|
- Date twentyFourHoursAgo = new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000L);
|
|
|
+ // 计算时间窗口前的时间
|
|
|
+ Date timeWindowStart = new Date(System.currentTimeMillis() - timeWindowHours * 60 * 60 * 1000L);
|
|
|
|
|
|
- // 查询用户在24小时内发布同类商品的数量
|
|
|
- LambdaQueryWrapper<SecondGoodsRecord> queryWrapper = new LambdaQueryWrapper<>();
|
|
|
- queryWrapper.eq(SecondGoodsRecord::getUserId, goods.getUserId())
|
|
|
- .eq(SecondGoodsRecord::getCategoryOneId, goods.getCategoryOneId())
|
|
|
- .eq(SecondGoodsRecord::getCategoryTwoId, goods.getCategoryTwoId())
|
|
|
- .ge(SecondGoodsRecord::getReleaseTime, twentyFourHoursAgo)
|
|
|
- .in(SecondGoodsRecord::getGoodsStatus,
|
|
|
+ // 查询用户在时间窗口内发布同类商品的数量
|
|
|
+ LambdaQueryWrapper<SecondGoods> queryWrapper = new LambdaQueryWrapper<>();
|
|
|
+ queryWrapper.eq(SecondGoods::getUserId, goods.getUserId())
|
|
|
+ .eq(SecondGoods::getCategoryOneId, goods.getCategoryOneId())
|
|
|
+ .eq(SecondGoods::getCategoryTwoId, goods.getCategoryTwoId())
|
|
|
+ .ge(SecondGoods::getReleaseTime, timeWindowStart)
|
|
|
+ .in(SecondGoods::getGoodsStatus,
|
|
|
SecondGoodsStatusEnum.LISTED.getCode(),
|
|
|
SecondGoodsStatusEnum.SOLD.getCode());
|
|
|
-
|
|
|
- int sameCategoryCount = secondGoodsRecordMapper.selectCount(queryWrapper);
|
|
|
-
|
|
|
- // 如果发布数量超过限制,返回false
|
|
|
- return sameCategoryCount < sameCategoryLimit;
|
|
|
+
|
|
|
+ // 获取发布
|
|
|
+ List<SecondGoods> secondGoodsList = list(queryWrapper);
|
|
|
+ // 提取商品id集合
|
|
|
+ List<Integer> secondGoodsIds = secondGoodsList.stream().map(SecondGoods::getId).collect(Collectors.toList());
|
|
|
+ // 转成json
|
|
|
+ String json = JSON.toJSONString(secondGoodsIds);
|
|
|
+ // 获取实际发布数量
|
|
|
+ int sameCategoryCount = secondGoodsList.size();
|
|
|
+ // 如果发布数量超过限制,记录风控数据
|
|
|
+ if (sameCategoryCount >= sameCategoryLimit) {
|
|
|
+ riskControlService.recordRiskControlData(goods.getUserId(), 4, "异常发布-同类商品发布频率", goods.getId(),json);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* 执行内容审核
|
|
|
* @param goodsDTO 商品信息
|