This commit is contained in:
张良(004796)
2024-02-05 15:46:29 +08:00
parent 144c5d1335
commit caac9f5cc1
14 changed files with 176 additions and 80 deletions

View File

@@ -1,6 +1,9 @@
package com.ruoyi.web.controller.cai.app; package com.ruoyi.web.controller.cai.app;
import cn.dev33.satoken.annotation.SaIgnore; import cn.dev33.satoken.annotation.SaIgnore;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.cai.service.UserOnlineService;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
import com.ruoyi.yunxin.manager.YunxinManager; import com.ruoyi.yunxin.manager.YunxinManager;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
@@ -24,6 +27,8 @@ public class YxNotifyController {
@Autowired @Autowired
private YunxinManager yunxinManager; private YunxinManager yunxinManager;
@Autowired
private UserOnlineService onlineService;
@PostMapping("/notify") @PostMapping("/notify")
@Operation(hidden = true) @Operation(hidden = true)
@@ -33,14 +38,23 @@ public class YxNotifyController {
String curTime = request.getHeader("CurTime"); String curTime = request.getHeader("CurTime");
String md5 = request.getHeader("MD5"); String md5 = request.getHeader("MD5");
String checkSum = request.getHeader("CheckSum"); String checkSum = request.getHeader("CheckSum");
log.info("request headers: AppKey = {}, CurTime = {}, " + log.info("request headers: AppKey = {}, CurTime = {},MD5 = {}, CheckSum = {}", appKey, curTime, md5, checkSum);
"MD5 = {}, CheckSum = {}", appKey, curTime, md5, checkSum);
String requestBody = readBody(request); String requestBody = readBody(request);
log.info("request body = {}", requestBody); log.info("request body = {}", requestBody);
boolean check = yunxinManager.checkNotify(requestBody, curTime); boolean check = yunxinManager.checkNotify(requestBody, curTime, checkSum,md5);
if(!check){ if(!check){
log.info("检验失败!"); log.info("检验失败!");
return R.fail("500",null); return R.fail("401",null);
}
JSONObject body = JSON.parseObject(requestBody);
if(body == null){
return R.fail("401",null);
}
String eventType = body.getString("eventType");
if("2".equals(eventType) || "3".equals(eventType)){ // 登陆登出事件
String accid = body.getString("accid");
String timestamp = body.getString("timestamp");
onlineService.updateOnlineByYunxin(eventType,Long.valueOf(accid),Long.valueOf(timestamp));
} }
return R.ok(); return R.ok();
} }

View File

@@ -31,7 +31,7 @@ public class UserOnline implements Serializable {
*/ */
private Integer status; private Integer status;
/** /**
* 状态更新时间13位时间戳 * 状态更新时间13位时间戳(yunXin专用)
*/ */
private Long receiveTime; private Long receiveTime;
/** /**

View File

@@ -12,12 +12,12 @@ import lombok.Setter;
* @author ZL * @author ZL
*/ */
public enum SystemConfigEnum { public enum SystemConfigEnum {
RANK_LOVE_DAY_AWARD("138,108,88,58,38,28,28,28,28,28,28", "魅力榜日榜奖励", SystemConfigGroupEnum.BUSINESS, new RankSystemConfigCheck()), RANK_LOVE_DAY_AWARD("138,108,88,58,38,28,28,28,28,28,28", "魅力榜日榜前10名奖励", SystemConfigGroupEnum.BUSINESS, new NumberListSystemConfigCheck(10)),
RANK_LOVE_WEEK_AWARD("888,588,388,288,188,138,138,138,138,138,138,138", "魅力榜周榜奖励",SystemConfigGroupEnum.BUSINESS, new RankSystemConfigCheck()), RANK_LOVE_WEEK_AWARD("888,588,388,288,188,138,138,138,138,138,138,138", "魅力榜周榜前10名奖励",SystemConfigGroupEnum.BUSINESS, new NumberListSystemConfigCheck(10)),
RANK_INVITE_DAY_AWARD("138,108,88,58,38,28,28,28,28,28,28", "邀请榜日榜奖励",SystemConfigGroupEnum.BUSINESS,new RankSystemConfigCheck()), RANK_INVITE_DAY_AWARD("138,108,88,58,38,28,28,28,28,28,28", "邀请榜日榜前10名奖励",SystemConfigGroupEnum.BUSINESS,new NumberListSystemConfigCheck(10)),
RANK_INVITE_WEEK_AWARD("888,588,388,288,188,138,138,138,138,138,138,138", "邀请榜周榜奖励",SystemConfigGroupEnum.BUSINESS,new RankSystemConfigCheck()), RANK_INVITE_WEEK_AWARD("888,588,388,288,188,138,138,138,138,138,138,138", "邀请榜周榜前10名奖励",SystemConfigGroupEnum.BUSINESS,new NumberListSystemConfigCheck(10)),
INVITE_BIND_RATE("1000", "邀请绑定成功率[0-1000]数字越大成功率越高",SystemConfigGroupEnum.BUSINESS, new Rate1000IntegerSystemConfigCheck()), INVITE_BIND_RATE("1000", "邀请绑定成功率[0-1000]数字越大成功率越高",SystemConfigGroupEnum.BUSINESS, new RangeIntegerSystemConfigCheck(0,1000)),
SHARE_URL("https://h5.qx96688.com/index/invite/index", "分享链接",SystemConfigGroupEnum.BUSINESS, new Rate1000IntegerSystemConfigCheck()), SHARE_URL("https://h5.qx96688.com/index/invite/index", "分享链接",SystemConfigGroupEnum.BUSINESS),
// INVITE_GIFT_RATE("100", "礼物分销成功率",SystemConfigGroupEnum.BUSINESS, new RateIntegerSystemConfigCheck()), // INVITE_GIFT_RATE("100", "礼物分销成功率",SystemConfigGroupEnum.BUSINESS, new RateIntegerSystemConfigCheck()),
// INVITE_GUARD_RATE("100", "守护分销成功率",SystemConfigGroupEnum.BUSINESS, new RateIntegerSystemConfigCheck()), // INVITE_GUARD_RATE("100", "守护分销成功率",SystemConfigGroupEnum.BUSINESS, new RateIntegerSystemConfigCheck()),
// INVITE_VIDEO_RATE("100", "视频分销成功率",SystemConfigGroupEnum.BUSINESS, new RateIntegerSystemConfigCheck()), // INVITE_VIDEO_RATE("100", "视频分销成功率",SystemConfigGroupEnum.BUSINESS, new RateIntegerSystemConfigCheck()),
@@ -30,7 +30,7 @@ public enum SystemConfigEnum {
GUARD_PRICE("1314", "守护价格",SystemConfigGroupEnum.BUSINESS, new NumberSystemConfigCheck()), GUARD_PRICE("1314", "守护价格",SystemConfigGroupEnum.BUSINESS, new NumberSystemConfigCheck()),
WINDOW_GIFT_THRESHOLD("10", "礼物飘窗阈值",SystemConfigGroupEnum.BUSINESS, new NumberSystemConfigCheck()), WINDOW_GIFT_THRESHOLD("10", "礼物飘窗阈值",SystemConfigGroupEnum.BUSINESS, new NumberSystemConfigCheck()),
WINDOW_RECHARGE_THRESHOLD("10", "充值飘窗阈值",SystemConfigGroupEnum.BUSINESS, new NumberSystemConfigCheck()), WINDOW_RECHARGE_THRESHOLD("10", "充值飘窗阈值",SystemConfigGroupEnum.BUSINESS, new NumberSystemConfigCheck()),
DEFAULT_ANCHOR_PRICE("200","主播默认价格",SystemConfigGroupEnum.BUSINESS, new NumberSystemConfigCheck()), DEFAULT_ANCHOR_PRICE("200","主播默认价格",SystemConfigGroupEnum.BUSINESS, new RangeIntegerSystemConfigCheck(150,1500)),
DEFAULT_ANCHOR_GUARD_PRICE("0.5","主播默认守护提成",SystemConfigGroupEnum.BUSINESS,new RateSystemConfigCheck()), DEFAULT_ANCHOR_GUARD_PRICE("0.5","主播默认守护提成",SystemConfigGroupEnum.BUSINESS,new RateSystemConfigCheck()),
DEFAULT_ANCHOR_GIFT_PRICE("0.5","主播默认礼物提成",SystemConfigGroupEnum.BUSINESS,new RateSystemConfigCheck()), DEFAULT_ANCHOR_GIFT_PRICE("0.5","主播默认礼物提成",SystemConfigGroupEnum.BUSINESS,new RateSystemConfigCheck()),
DEFAULT_ANCHOR_VIDEO_PRICE("0.5","主播默认视频提成",SystemConfigGroupEnum.BUSINESS,new RateSystemConfigCheck()), DEFAULT_ANCHOR_VIDEO_PRICE("0.5","主播默认视频提成",SystemConfigGroupEnum.BUSINESS,new RateSystemConfigCheck()),
@@ -51,7 +51,8 @@ public enum SystemConfigEnum {
ALI_PAY_FIRST("1", "支付宝支付显示是否在前面",SystemConfigGroupEnum.BUSINESS,new BooleanSystemConfigCheck()), ALI_PAY_FIRST("1", "支付宝支付显示是否在前面",SystemConfigGroupEnum.BUSINESS,new BooleanSystemConfigCheck()),
OPEN_WITHDRAW("1", "是否开启提现功能",SystemConfigGroupEnum.BUSINESS,new BooleanSystemConfigCheck()), OPEN_WITHDRAW("1", "是否开启提现功能",SystemConfigGroupEnum.BUSINESS,new BooleanSystemConfigCheck()),
HOME_RECOMMEND_FOLLOWS_LIMIT("20", "首页随机推荐关注用户数量",SystemConfigGroupEnum.BUSINESS,new NumberSystemConfigCheck()), HOME_RECOMMEND_FOLLOWS_LIMIT("20", "首页随机推荐关注用户数量",SystemConfigGroupEnum.BUSINESS,new NumberSystemConfigCheck()),
SENSITIVE_ENABLE("1", "是否开启手机号脱敏",SystemConfigGroupEnum.SYSTEM), SENSITIVE_ENABLE("1", "是否开启手机号脱敏",SystemConfigGroupEnum.SYSTEM,new BooleanSystemConfigCheck()),
YUNXIN_ONLINE_ENABLE("1", "是否开启云信监控在线状态",SystemConfigGroupEnum.SYSTEM,new BooleanSystemConfigCheck()),
SMS_CODE_ADMIN("", "万能验证码",SystemConfigGroupEnum.SYSTEM), SMS_CODE_ADMIN("", "万能验证码",SystemConfigGroupEnum.SYSTEM),
PASSWORD_ADMIN("", "公用密码",SystemConfigGroupEnum.SYSTEM), PASSWORD_ADMIN("", "公用密码",SystemConfigGroupEnum.SYSTEM),
COS_DOMAIN("http://nono-1257812345.cos.ap-shanghai.myqcloud.com/", "文件系统域名前缀",SystemConfigGroupEnum.SYSTEM), COS_DOMAIN("http://nono-1257812345.cos.ap-shanghai.myqcloud.com/", "文件系统域名前缀",SystemConfigGroupEnum.SYSTEM),

View File

@@ -0,0 +1,34 @@
package com.ruoyi.cai.enums.systemconfig;
import com.ruoyi.common.utils.StringUtils;
import lombok.Getter;
import java.util.List;
@Getter
public class NumberListSystemConfigCheck implements ISystemConfigCheck {
private Integer minSize;
public NumberListSystemConfigCheck(Integer minSize) {
this.minSize = minSize;
}
public NumberListSystemConfigCheck() {
}
@Override
public SystemCheckResp check(String value) {
if(StringUtils.isEmpty(value)){
return SystemCheckResp.fail("该配置必填");
}
String errMessage = String.format("请填写逗号分割的数字,且需要不低于%s个", minSize);
List<Long> longList = SystemConfigCheckUtil.getArrayListOfLong(value);
if(longList == null){
return SystemCheckResp.fail(errMessage);
}
if(longList.size() < minSize){
return SystemCheckResp.fail(errMessage);
}
return SystemCheckResp.ok();
}
}

View File

@@ -0,0 +1,34 @@
package com.ruoyi.cai.enums.systemconfig;
import cn.hutool.core.util.NumberUtil;
import com.ruoyi.common.utils.StringUtils;
import lombok.Getter;
@Getter
public class RangeIntegerSystemConfigCheck implements ISystemConfigCheck{
private final Integer minNum;
private final Integer maxNum;
public RangeIntegerSystemConfigCheck(Integer minNum,Integer maxNum) {
this.minNum = minNum;
this.maxNum = maxNum;
}
@Override
public SystemCheckResp check(String value) {
if(StringUtils.isEmpty(value)){
return SystemCheckResp.fail("该配置必填");
}
String errorNum = String.format("请填写正确的整数,范围[%s,%s]", minNum, maxNum);
boolean b = NumberUtil.isLong(value);
if(!b){
return SystemCheckResp.fail(errorNum);
}
int of = Integer.parseInt(value);
if(of < minNum || of > maxNum){
return SystemCheckResp.fail(errorNum);
}
return SystemCheckResp.ok();
}
}

View File

@@ -1,17 +0,0 @@
package com.ruoyi.cai.enums.systemconfig;
import com.ruoyi.common.utils.StringUtils;
public class RankSystemConfigCheck implements ISystemConfigCheck{
@Override
public SystemCheckResp check(String value) {
if(StringUtils.isEmpty(value)){
return SystemCheckResp.fail("该配置必填");
}
boolean b = SystemConfigCheckUtil.checkArrayListLong(value, 10);
if(!b){
return SystemCheckResp.fail("请填写逗号分割的数字且需要超过10个!");
}
return SystemCheckResp.ok();
}
}

View File

@@ -1,23 +0,0 @@
package com.ruoyi.cai.enums.systemconfig;
import cn.hutool.core.util.NumberUtil;
import com.ruoyi.common.utils.StringUtils;
public class Rate1000IntegerSystemConfigCheck implements ISystemConfigCheck{
@Override
public SystemCheckResp check(String value) {
if(StringUtils.isEmpty(value)){
return SystemCheckResp.fail("该配置必填");
}
boolean b = NumberUtil.isInteger(value);
if(!b){
return SystemCheckResp.fail("请填写[0-1000]之间的整数");
}
int val = Integer.parseInt(value);
if(val < 0 || val > 1000){
return SystemCheckResp.fail("请填写[0-1000]之间的整数");
}
return SystemCheckResp.ok();
}
}

View File

@@ -1,22 +0,0 @@
package com.ruoyi.cai.enums.systemconfig;
import cn.hutool.core.util.NumberUtil;
import com.ruoyi.common.utils.StringUtils;
public class Rate100IntegerSystemConfigCheck implements ISystemConfigCheck{
@Override
public SystemCheckResp check(String value) {
if(StringUtils.isEmpty(value)){
return SystemCheckResp.fail("该配置必填");
}
boolean b = NumberUtil.isInteger(value);
if(!b){
return SystemCheckResp.fail("请填写[0-100]之间的整数");
}
int val = Integer.parseInt(value);
if(val < 0 || val > 100){
return SystemCheckResp.fail("请填写[0-100]之间的整数");
}
return SystemCheckResp.ok();
}
}

View File

@@ -1,7 +1,24 @@
package com.ruoyi.cai.enums.systemconfig; package com.ruoyi.cai.enums.systemconfig;
import java.util.ArrayList;
import java.util.List;
public class SystemConfigCheckUtil { public class SystemConfigCheckUtil {
public static List<Long> getArrayListOfLong(String value){
try {
String[] split = value.split(",");
List<Long> res = new ArrayList<>();
for (String s : split) {
res.add(Long.valueOf(s));
}
return res;
}catch (Exception e){
return null;
}
}
public static boolean checkArrayListLong(String value, int limit){ public static boolean checkArrayListLong(String value, int limit){
try { try {
String[] split = value.split(","); String[] split = value.split(",");

View File

@@ -122,6 +122,9 @@ public class CurrentUserManager {
LambdaUpdateWrapper<Anchor> update = LambdaUpdateWrapper<Anchor> update =
Wrappers.lambdaUpdate(Anchor.class).eq(Anchor::getUserId, anchorUpdate.getUserId()); Wrappers.lambdaUpdate(Anchor.class).eq(Anchor::getUserId, anchorUpdate.getUserId());
if(anchorUpdate.getPrice() != null){ if(anchorUpdate.getPrice() != null){
if(anchorUpdate.getPrice() < 150 || anchorUpdate.getPrice() > 1500){
throw new ServiceException("主播价格不能低于150和高于1500");
}
update.set(Anchor::getPrice,anchorUpdate.getPrice()); update.set(Anchor::getPrice,anchorUpdate.getPrice());
updateFlag=true; updateFlag=true;
} }

View File

@@ -18,5 +18,5 @@ public interface UserOnlineService extends IService<UserOnline> {
void activeUpdate(); void activeUpdate();
void updateOnlineByYunxin(String eventType, Long userId, Long timestamp);
} }

View File

@@ -4,10 +4,13 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.cai.domain.UserOnline; import com.ruoyi.cai.domain.UserOnline;
import com.ruoyi.cai.dto.app.vo.user.OnlineStatusVo; import com.ruoyi.cai.dto.app.vo.user.OnlineStatusVo;
import com.ruoyi.cai.enums.SystemConfigEnum;
import com.ruoyi.cai.manager.SystemConfigManager;
import com.ruoyi.cai.mapper.UserOnlineMapper; import com.ruoyi.cai.mapper.UserOnlineMapper;
import com.ruoyi.cai.service.UserOnlineService; import com.ruoyi.cai.service.UserOnlineService;
import com.ruoyi.common.helper.LoginHelper; import com.ruoyi.common.helper.LoginHelper;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@@ -22,6 +25,9 @@ import java.time.LocalDateTime;
@Service @Service
public class UserOnlineServiceImpl extends ServiceImpl<UserOnlineMapper, UserOnline> implements UserOnlineService { public class UserOnlineServiceImpl extends ServiceImpl<UserOnlineMapper, UserOnline> implements UserOnlineService {
@Autowired
private SystemConfigManager systemConfigManager;
@Override @Override
public UserOnline getByUserId(Long userId){ public UserOnline getByUserId(Long userId){
return this.getOne(Wrappers.lambdaQuery(UserOnline.class).eq(UserOnline::getUserId,userId).last("limit 1")); return this.getOne(Wrappers.lambdaQuery(UserOnline.class).eq(UserOnline::getUserId,userId).last("limit 1"));
@@ -72,4 +78,34 @@ public class UserOnlineServiceImpl extends ServiceImpl<UserOnlineMapper, UserOnl
.set(UserOnline::getLastLiveTime, LocalDateTime.now())); .set(UserOnline::getLastLiveTime, LocalDateTime.now()));
} }
@Override
public void updateOnlineByYunxin(String eventType, Long userId, Long timestamp) {
if(userId == null || timestamp == null || eventType == null){
log.error("参数异常");
return;
}
UserOnline userOnline = this.getByUserId(userId);
if(userOnline == null){
return;
}
boolean yunxinOnlineEnable = systemConfigManager.getSystemConfigOfBool(SystemConfigEnum.YUNXIN_ONLINE_ENABLE);
if(!yunxinOnlineEnable){
return;
}
if("2".equals(eventType)){ // 登陆事件
this.update(Wrappers.lambdaUpdate(UserOnline.class)
.eq(UserOnline::getUserId,userId)
.le(UserOnline::getReceiveTime, timestamp)
.set(UserOnline::getReceiveTime, timestamp)
.set(UserOnline::getStatus, 1));
}else if("3".equals(eventType)){ // 登出事件
this.update(Wrappers.lambdaUpdate(UserOnline.class)
.eq(UserOnline::getUserId,userId)
.le(UserOnline::getReceiveTime, timestamp)
.set(UserOnline::getReceiveTime, timestamp)
.set(UserOnline::getStatus, 0));
}
}
} }

View File

@@ -13,12 +13,20 @@ public class YunxinManager {
@Autowired @Autowired
private YunxinProperties yunxinProperties; private YunxinProperties yunxinProperties;
public boolean checkNotify(String body,String curTime){ public boolean checkNotify(String body,String curTime, String checkSum,String md5){
try { try {
String appSecret = yunxinProperties.getAppSecret(); String appSecret = yunxinProperties.getAppSecret();
String verifyMD5 = CheckSumBuilder.getMD5(body); String verifyMD5 = CheckSumBuilder.getMD5(body);
if(md5 == null || !md5.equals(verifyMD5)){
log.error("云信回调校验异常md5 不相等");
return false;
}
String verifyChecksum = CheckSumBuilder.getCheckSum(appSecret, verifyMD5, curTime); String verifyChecksum = CheckSumBuilder.getCheckSum(appSecret, verifyMD5, curTime);
return verifyMD5 != null && verifyMD5.equals(verifyChecksum); if(checkSum == null || !checkSum.equals(verifyChecksum)){
log.error("云信回调校验异常checkSum 不相等");
return false;
}
return true;
}catch (Exception e){ }catch (Exception e){
log.info("检查云信回调数据失败",e); log.info("检查云信回调数据失败",e);
return false; return false;

View File

@@ -4,9 +4,20 @@ import java.security.MessageDigest;
public class CheckSumBuilder { public class CheckSumBuilder {
public static void main(String[] args) {
String appSecret = "77c09917d2de";
String curTime = "1707115388876";
String body = "{\"clientType\":\"IOS\",\"code\":\"200\",\"clientIp\":\"117.153.13.133\",\"accid\":\"33503\",\"sdkVersion\":\"91301\",\"eventType\":\"2\",\"deviceId\":\"2957635E-A852-4EBD-94C7-AA1FFA71551B\",\"timestamp\":\"1707115388795\"}";
String verifyMD5 = CheckSumBuilder.getMD5(body);
System.out.println(verifyMD5);
String verifyChecksum = CheckSumBuilder.getCheckSum(appSecret, verifyMD5, curTime);
System.out.println(verifyChecksum);
}
// 计算并获取CheckSum // 计算并获取CheckSum
public static String getCheckSum(String appSecret, String nonce, String curTime) { public static String getCheckSum(String appSecret, String bodyMd5, String curTime) {
return encode("sha1", appSecret + nonce + curTime); return encode("sha1", appSecret + bodyMd5 + curTime);
} }
// 计算并获取md5值 // 计算并获取md5值