ソースを参照

Merge branch 'package' of GameCenter/game-center into dev

zhimo 6 日 前
コミット
11aed2798c

+ 1 - 1
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/SDKApplication.java

@@ -25,7 +25,7 @@ public class SDKApplication {
 
     public static void main(String[] args) {
         SpringApplication.run(SDKApplication.class, args);
-        System.out.println("赞象SDK服务启动成功 <玩家角色上报信息, 优化判断> ( ´・・)ノ(._.`) \n" +
+        System.out.println("赞象SDK服务启动成功 <角色信息更新优化> ( ´・・)ノ(._.`) \n" +
                 " ___________ _   __\n" +
                 "/  ___|  _  \\ | / /\n" +
                 "\\ `--.| | | | |/ / \n" +

+ 2 - 1
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/IAgentService.java

@@ -27,9 +27,10 @@ public interface IAgentService extends IService<Agent> {
      *
      * @param game     游戏数据
      * @param userData 用户数据
+     * @param openId   用户openId
      * @return {@link Tuple3}<{@link Long}, {@link Map}<{@link String}, {@link String}>, {@link String}>
      */
-    Tuple3<Long, Map<String, String>, String> getUserAgentId(Game game, UserData userData);
+    Tuple3<Long, Map<String, String>, String> getUserAgentId(Game game, UserData userData, String openId);
 
     /**
      * 根据channel解析获取渠道信息

+ 39 - 3
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/AgentServiceImpl.java

@@ -8,6 +8,7 @@ import com.github.sd4324530.jtuple.Tuple2;
 import com.zanxiang.game.back.base.ServerInfo;
 import com.zanxiang.game.back.base.pojo.dto.TencentAppApiUserAgentQueryRpcDTO;
 import com.zanxiang.game.back.base.rpc.ITencentAppApiBackRpc;
+import com.zanxiang.game.back.base.rpc.ITencentMiniGameBackRpc;
 import com.zanxiang.game.module.base.pojo.enums.GameCategoryEnum;
 import com.zanxiang.game.module.mybatis.entity.*;
 import com.zanxiang.game.module.mybatis.mapper.AgentMapper;
@@ -37,6 +38,9 @@ public class AgentServiceImpl extends ServiceImpl<AgentMapper, Agent> implements
     @DubboReference(providedBy = ServerInfo.SERVER_DUBBO_NAME)
     private ITencentAppApiBackRpc tencentAppApiBackRpc;
 
+    @DubboReference(providedBy = ServerInfo.SERVER_DUBBO_NAME)
+    private ITencentMiniGameBackRpc tencentMiniGameBackRpc;
+
     @Autowired
     private IUserService userService;
 
@@ -89,7 +93,7 @@ public class AgentServiceImpl extends ServiceImpl<AgentMapper, Agent> implements
             //30天未登录, 更新渠道
             Game game = gameService.getById(user.getGameId());
             //渠道id, 链接参数, 分享人id
-            Tuple3<Long, Map<String, String>, String> tuple3 = this.getUserAgentId(game, userData);
+            Tuple3<Long, Map<String, String>, String> tuple3 = this.getUserAgentId(game, userData, user.getOpenId());
             //查询渠道
             Agent agent = super.getById(tuple3.getT1());
             if (agent == null) {
@@ -120,11 +124,22 @@ public class AgentServiceImpl extends ServiceImpl<AgentMapper, Agent> implements
     }
 
     @Override
-    public Tuple3<Long, Map<String, String>, String> getUserAgentId(Game game, UserData userData) {
+    public Tuple3<Long, Map<String, String>, String> getUserAgentId(Game game, UserData userData, String openId) {
         try {
             //微信小游戏解析
             if (Objects.equals(game.getCategory(), GameCategoryEnum.CATEGORY_WX_APPLET.getId())) {
-                return this.appletChannelTransform(userData.getChannel());
+                Tuple3<Long, Map<String, String>, String> tuple3 = this.appletChannelTransform(userData.getChannel());
+                //非自然量, 或者不存在openId, 直接返回结束
+                if (!Objects.equals(tuple3.getT1(), 0L) || Strings.isBlank(openId)) {
+                    return tuple3;
+                }
+                //自然量, 做监测链接匹配补偿归因
+                Tuple2<Long, Map<String, String>> tuple2 = this.getChannelByOpenId(game.getId(), openId);
+                if (tuple2 == null) {
+                    return tuple3;
+                }
+                userData.setChannel(JsonUtil.toString(tuple2.second));
+                return Tuples.of(tuple2.first, tuple2.second, tuple3.getT3());
             }
             //APP解析
             if (Objects.equals(game.getCategory(), GameCategoryEnum.CATEGORY_APP.getId())) {
@@ -142,6 +157,27 @@ public class AgentServiceImpl extends ServiceImpl<AgentMapper, Agent> implements
         return Tuples.of(0L, Collections.emptyMap(), Strings.EMPTY);
     }
 
+    private Tuple2<Long, Map<String, String>> getChannelByOpenId(Long gameId, String openId) {
+        try {
+            Map<String, Object> callBackMap = tencentMiniGameBackRpc.getCallBackByOpenId(gameId, openId).getData();
+            if (CollectionUtils.isEmpty(callBackMap) || !callBackMap.containsKey("agentKey")) {
+                return null;
+            }
+            Agent agent = super.getOne(new LambdaQueryWrapper<Agent>().eq(Agent::getAgentKey, callBackMap.get("agentKey")));
+            if (agent == null) {
+                return null;
+            }
+            Map<String, String> channelMap = new HashMap<>(3);
+            callBackMap.put("weixinadinfo", callBackMap.get("adgroupId") + "." + callBackMap.get("impressionId"));
+            callBackMap.put("gdt_vid", callBackMap.get("impressionId").toString());
+            callBackMap.put("callBack", JsonUtil.toString(callBackMap));
+            return Tuple2.with(agent.getId(), channelMap);
+        } catch (Exception e) {
+            log.error("微信小游戏补偿匹配监测链接异常, gameId : {}, openId : {}, e : {}", gameId, openId, e.getMessage(), e);
+        }
+        return null;
+    }
+
     private Tuple3<Long, Map<String, String>, String> appletChannelTransform(String channel) {
         //链接参数
         if (Strings.isBlank(channel)) {

+ 4 - 4
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/CpPushDataServiceImpl.java

@@ -508,7 +508,7 @@ public class CpPushDataServiceImpl implements ICpPushDataService {
                         .last("limit 1"));
                 user = this.transform(gameId, shareUser, param);
             } else {
-                Tuple3<Long, Map<String, String>, String> tuple3 = this.getUserAgentChannel(game, userData);
+                Tuple3<Long, Map<String, String>, String> tuple3 = this.getUserAgentChannel(game, userData, param.getOpenId());
                 user = this.transform(gameId, tuple3, param);
                 channelMap = tuple3.getT2();
             }
@@ -548,7 +548,7 @@ public class CpPushDataServiceImpl implements ICpPushDataService {
             return Collections.emptyMap();
         }
         //渠道id, 链接参数
-        Tuple3<Long, Map<String, String>, String> tuple3 = this.getUserAgentChannel(game, userData);
+        Tuple3<Long, Map<String, String>, String> tuple3 = this.getUserAgentChannel(game, userData, param.getOpenId());
         //查询渠道
         Agent agent = agentService.getById(tuple3.getT1());
         if (agent == null) {
@@ -571,7 +571,7 @@ public class CpPushDataServiceImpl implements ICpPushDataService {
         return tuple3.getT2();
     }
 
-    private Tuple3<Long, Map<String, String>, String> getUserAgentChannel(Game game, UserData userData) {
+    private Tuple3<Long, Map<String, String>, String> getUserAgentChannel(Game game, UserData userData, String openId) {
         //解析渠道信息
         String channel = new String(Base64.getDecoder().decode(userData.getChannel()));
         userData.setChannel(channel);
@@ -586,7 +586,7 @@ public class CpPushDataServiceImpl implements ICpPushDataService {
             return Tuples.of(0L, Collections.emptyMap(), channel);
         }
         //渠道id, 链接参数, 分享人id
-        Tuple3<Long, Map<String, String>, String> tuple3 = agentService.getUserAgentId(game, userData);
+        Tuple3<Long, Map<String, String>, String> tuple3 = agentService.getUserAgentId(game, userData, openId);
         //返回渠道id, 渠道参数
         return Tuples.of(tuple3.getT1(), tuple3.getT2(), channel);
     }

+ 7 - 18
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/GameUserRoleServiceImpl.java

@@ -176,27 +176,16 @@ public class GameUserRoleServiceImpl extends ServiceImpl<GameUserRoleMapper, Gam
                 + "_" + param.getRoleId(), 0L, 20L, TimeUnit.SECONDS)) {
             return Boolean.TRUE;
         }
-        //判断是否等级变更
-        boolean updateRoleLevel = param.getRoleLevel() > gameUserRole.getRoleLevel();
-        //玩家信息
-        GameUser gameUser = gameUserService.getOne(new LambdaQueryWrapper<GameUser>()
-                .eq(GameUser::getGameId, userData.getGameId())
-                .eq(GameUser::getUserId, userData.getUserId()));
-        //玩家角色信息更新
-        if (gameUserRole.getServerId() == null) {
-            gameUserRole.setServerId(param.getServerId());
-        }
+        //角色vip等级
         if (param.getRoleVipLevel() != null) {
             gameUserRole.setRoleVipLevel(param.getRoleVipLevel());
         }
-        if (param.getRolePower() != null) {
+        //角色战力和帮派信息
+        if (param.getRolePower() != null && param.getRolePower() > 0L) {
             gameUserRole.setRolePower(param.getRolePower());
-        }
-        if (param.getExtra() != null && Strings.isNotBlank(JsonUtil.toString(param.getExtra()))) {
-            gameUserRole.setExtra(JsonUtil.toString(param.getExtra()));
-        }
-        if (gameUser != null) {
-            gameUserRole.setGameUserId(gameUser.getId());
+            if (param.getExtra() != null && Strings.isNotBlank(JsonUtil.toString(param.getExtra()))) {
+                gameUserRole.setExtra(JsonUtil.toString(param.getExtra()));
+            }
         }
         gameUserRole.setRoleName(param.getRoleName());
         gameUserRole.setRoleLevel(param.getRoleLevel());
@@ -204,7 +193,7 @@ public class GameUserRoleServiceImpl extends ServiceImpl<GameUserRoleMapper, Gam
         gameUserRole.setUpdateTime(LocalDateTime.now());
         boolean result = super.updateById(gameUserRole);
         //等级变更
-        if (updateRoleLevel) {
+        if (param.getRoleLevel() > gameUserRole.getRoleLevel()) {
             //用户创角回传
             callBackService.roleCallBack(gameUserRole);
             //玩家消息推送

+ 60 - 5
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/LoginServiceImpl.java

@@ -5,10 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.zanxiang.game.module.base.pojo.enums.BanStatusEnum;
 import com.zanxiang.game.module.base.pojo.enums.GameCategoryEnum;
 import com.zanxiang.game.module.base.pojo.enums.HttpStatusEnum;
-import com.zanxiang.game.module.mybatis.entity.Game;
-import com.zanxiang.game.module.mybatis.entity.GameExt;
-import com.zanxiang.game.module.mybatis.entity.User;
-import com.zanxiang.game.module.mybatis.entity.UserCard;
+import com.zanxiang.game.module.mybatis.entity.*;
 import com.zanxiang.game.module.sdk.constant.RedisKeyConstant;
 import com.zanxiang.game.module.sdk.enums.KafkaEventTrackEnum;
 import com.zanxiang.game.module.sdk.enums.LoginTypeEnum;
@@ -29,6 +26,7 @@ import com.zanxiang.module.util.JsonUtil;
 import com.zanxiang.module.util.exception.BaseException;
 import com.zanxiang.module.util.pojo.ResultVO;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.logging.log4j.util.Strings;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -115,6 +113,9 @@ public class LoginServiceImpl implements IRegisterLoginService {
     @Autowired
     private IDistributedLockComponent distributedLockComponent;
 
+    @Autowired
+    private IUserEventService userEventService;
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public ResultVO<UserLoginVO> loginWxCode(LoginVxCodeParam param, UserData userData, HttpServletRequest request) {
@@ -212,6 +213,8 @@ public class LoginServiceImpl implements IRegisterLoginService {
             //返回登录信息
             return ResultVO.ok(userLoginVO);
         }
+        //设备账号数量检测
+        this.accountCheck(username, userData);
         //用户注册, 用户名密码校验
         HttpStatusEnum checkRegisterEnum = this.checkRegister(userData.getGameId(), username, password);
         if (!Objects.equals(checkRegisterEnum, HttpStatusEnum.SUCCESS)) {
@@ -260,6 +263,8 @@ public class LoginServiceImpl implements IRegisterLoginService {
             //返回登录信息
             return ResultVO.ok(userLoginVO);
         }
+        //设备账号数量检测
+        this.accountCheck(mobile, userData);
         //用户注册
         user = userCreateSave(userData, mobile, null, mobile, null, null);
         //返回登录信息
@@ -267,6 +272,56 @@ public class LoginServiceImpl implements IRegisterLoginService {
         return ResultVO.ok(userLoginVO);
     }
 
+    private void accountCheck(String userName, UserData userData) {
+        //非安卓设备, 无法限制
+        if (Strings.isBlank(userData.getAndroidId())) {
+            return;
+        }
+        Game game = gameService.getById(userData.getGameId());
+        //仙剑游戏限制注册账号数量, 其他游戏直接过
+        if (game == null || !Objects.equals(game.getSuperGameId(), 12L)) {
+            return;
+        }
+        //内部账号, 不受监控
+        if (userEventService.count(new LambdaQueryWrapper<UserEvent>()
+                .eq(UserEvent::getGameId, userData.getGameId())
+                .and(qw -> qw.eq(UserEvent::getUsername, userName)
+                        .or().eq(UserEvent::getMobile, userName)
+                        .or().eq(UserEvent::getIp, userData.getIp()))
+        ) > 0) {
+            return;
+        }
+        //判断安卓设备已经注册过2个账号
+        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<User>()
+                .eq(User::getGameId, userData.getGameId());
+        //条件匹配
+        queryWrapper.and(qw -> {
+            boolean hasCondition = false;
+            //安卓id匹配
+            if (StringUtils.isNoneBlank(userData.getAndroidId())) {
+                qw.or().eq(User::getAndroidId, userData.getAndroidId());
+                hasCondition = true;
+            }
+            //oaid匹配
+            if (StringUtils.isNoneBlank(userData.getOaid())) {
+                qw.or().eq(User::getOaid, userData.getOaid());
+                hasCondition = true;
+            }
+            //imei匹配
+            if (StringUtils.isNoneBlank(userData.getImei())) {
+                qw.or().eq(User::getImei, userData.getImei());
+                hasCondition = true;
+            }
+            // 避免无条件的OR查询
+            if (!hasCondition) {
+                qw.or().apply("1=0");
+            }
+        });
+        if (userService.count(queryWrapper) >= 2) {
+            throw new BaseException("注册异常,请勿重复申请注册账号!");
+        }
+    }
+
     private Tuple2<Boolean, Long> userGuideCheck(User user) {
         //非导量用户
         if (user.getRelationUserId() == null) {
@@ -297,7 +352,7 @@ public class LoginServiceImpl implements IRegisterLoginService {
         //获取游戏信息
         Game game = gameService.getById(userData.getGameId());
         //渠道id, 链接参数, 分享人id
-        Tuple3<Long, Map<String, String>, String> tuple3 = agentService.getUserAgentId(game, userData);
+        Tuple3<Long, Map<String, String>, String> tuple3 = agentService.getUserAgentId(game, userData, openId);
         //分享人id
         Long shareUserId = Strings.isBlank(tuple3.getT3()) ? null : Long.valueOf(tuple3.getT3());
         //用户参数补充