Ver código fonte

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

zhimo 11 meses atrás
pai
commit
a2d144a02f

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

@@ -23,7 +23,7 @@ public class SDKApplication {
 
     public static void main(String[] args) {
         SpringApplication.run(SDKApplication.class, args);
-        System.out.println("赞象SDK服务启动成功 <删除调试日志> ( ´・・)ノ(._.`) \n" +
+        System.out.println("赞象SDK服务启动成功 <头条投放虚拟游戏兼容H5和APP> ( ´・・)ノ(._.`) \n" +
                 " ___________ _   __\n" +
                 "/  ___|  _  \\ | / /\n" +
                 "\\ `--.| | | | |/ / \n" +

+ 6 - 4
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/IAgentService.java

@@ -2,6 +2,7 @@ package com.zanxiang.game.module.sdk.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.zanxiang.game.module.mybatis.entity.Agent;
+import com.zanxiang.game.module.mybatis.entity.Game;
 import com.zanxiang.game.module.mybatis.entity.User;
 import com.zanxiang.game.module.sdk.pojo.param.UserData;
 import reactor.util.function.Tuple3;
@@ -16,18 +17,19 @@ public interface IAgentService extends IService<Agent> {
     /**
      * 用户渠道更新
      *
-     * @param user    用户
-     * @param channel 通道
+     * @param user     用户
+     * @param userData 用户数据
      */
-    void userAgentUpdate(User user, String channel);
+    void userAgentUpdate(User user, UserData userData);
 
     /**
      * 根据前端参数获取渠道信息
      *
+     * @param game     游戏数据
      * @param userData 用户数据
      * @return {@link Tuple3}<{@link Long}, {@link Map}<{@link String}, {@link String}>, {@link String}>
      */
-    Tuple3<Long, Map<String, String>, String> getUserAgentId(UserData userData);
+    Tuple3<Long, Map<String, String>, String> getUserAgentId(Game game, UserData userData);
 
     /**
      * channel解析

+ 12 - 0
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/IUserAppletService.java

@@ -0,0 +1,12 @@
+package com.zanxiang.game.module.sdk.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zanxiang.game.module.mybatis.entity.UserApplet;
+
+/**
+ * @author : lingfeng
+ * @time : 2024-04-29
+ * @description : 投放小程序用户信息
+ */
+public interface IUserAppletService extends IService<UserApplet> {
+}

+ 109 - 31
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/AgentServiceImpl.java

@@ -2,7 +2,6 @@ package com.zanxiang.game.module.sdk.service.impl;
 
 import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.zanxiang.game.module.base.pojo.enums.GameCategoryEnum;
@@ -54,10 +53,13 @@ public class AgentServiceImpl extends ServiceImpl<AgentMapper, Agent> implements
     @Autowired
     private IKafkaService kafkaService;
 
+    @Autowired
+    private IUserAppletService userAppletService;
+
     @Override
-    public void userAgentUpdate(User user, String channel) {
-        log.error("用户登录接收到的渠道参数 userId : {}, channel : {}", user.getId(), channel);
+    public void userAgentUpdate(User user, UserData userData) {
         try {
+            String channel = userData.getChannel();
             //渠道参数为空
             if (Strings.isBlank(channel)) {
                 return;
@@ -77,54 +79,66 @@ public class AgentServiceImpl extends ServiceImpl<AgentMapper, Agent> implements
                 return;
             }
             //30天未登录, 更新渠道
-            Map<String, String> urlParamMap = this.channelTransform(channel);
+            Game game = gameService.getById(user.getGameId());
+            //渠道id, 链接参数, 分享人id
+            Tuple3<Long, Map<String, String>, String> tuple3 = this.getUserAgentId(game, userData);
             //查询渠道
-            Agent agent = this.getAgentByKey(urlParamMap);
+            Agent agent = super.getById(tuple3.getT1());
             if (agent == null) {
                 return;
             }
-            LocalDateTime localDateTime = LocalDateTime.now();
             //更新用户信息
-            userService.update(new LambdaUpdateWrapper<User>()
-                    .set(User::getAgentId, agent.getId())
-                    .set(User::getChannel, channel)
-                    .set(User::getUpdateTime, localDateTime)
-                    .eq(User::getId, user.getId()));
+            user.setAgentId(agent.getId());
+            user.setUpdateTime(LocalDateTime.now());
+            //App的渠道保存解析后的参数, 因为涉及到时间判断
+            if (Objects.equals(game.getCategory(), GameCategoryEnum.CATEGORY_APP.getId())) {
+                user.setChannel(JsonUtil.toString(tuple3.getT2()));
+            } else {
+                user.setChannel(channel);
+            }
+            userService.updateById(user);
             //添加渠道变更记录
             userAgentLogService.agentUpdateLog(user, agent.getId(), channel);
             //回传用户信息
-            user.setAgentId(agent.getId());
-            user.setChannel(channel);
-            user.setUpdateTime(localDateTime);
-            callBackService.userCallBack(user, urlParamMap);
+            callBackService.userCallBack(user, tuple3.getT2());
             //注册信息埋点数据发送到卡夫卡
             kafkaService.eventTrack(KafkaEventTrackEnum.KAFKA_EVENT_TRACK_AGENT_UPDATE, JsonUtil.toString(user));
         } catch (Exception e) {
-            log.error("用户渠道更新异常, userId : {}, channel : {}, e : {}", user.getId(), channel, e.getMessage());
+            log.error("用户渠道更新异常, user : {}, userData : {}, e : {}", JsonUtil.toString(user),
+                    JsonUtil.toString(userData), e.getMessage(), e);
         }
     }
 
     @Override
-    public Tuple3<Long, Map<String, String>, String> getUserAgentId(UserData userData) {
-        log.error("用户注册接收到的渠道参数 userData : {}", JsonUtil.toString(userData));
-        //获取游戏信息
-        GameExt gameExt = gameExtService.getByGameId(userData.getGameId());
-        Game game = gameService.getById(userData.getGameId());
-        //不投放得APP游戏按ip和ua进行渠道匹配
-        if (Objects.equals(game.getCategory(), GameCategoryEnum.CATEGORY_APP.getId())
-                && !Objects.equals(gameExt.getAdCallBackSwitch(), Boolean.TRUE)) {
-            UserVisitLog userVisitLog = this.getUserVisitLog(userData);
-            if (userVisitLog == null) {
-                return Tuples.of(0L, Collections.emptyMap(), Strings.EMPTY);
+    public Tuple3<Long, Map<String, String>, String> getUserAgentId(Game game, UserData userData) {
+        try {
+            //微信小游戏解析
+            if (Objects.equals(game.getCategory(), GameCategoryEnum.CATEGORY_WX_APPLET.getId())) {
+                return this.appletChannelTransform(userData.getChannel());
+            }
+            //APP解析
+            if (Objects.equals(game.getCategory(), GameCategoryEnum.CATEGORY_APP.getId())) {
+                return this.appChannelTransform(game, userData);
             }
-            return Tuples.of(userVisitLog.getAgentId(), Collections.emptyMap(), Strings.EMPTY);
+            //H5解析
+            if (Objects.equals(game.getCategory(), GameCategoryEnum.CATEGORY_H5.getId())) {
+                return this.h5ChannelTransform(userData.getChannel());
+            }
+        } catch (Exception e) {
+            log.error("用户渠道解析异常, game : {}, userData : {}, e : {}", JsonUtil.toString(game),
+                    JsonUtil.toString(userData), e.getMessage(), e);
         }
+        //默认返回自然量
+        return Tuples.of(0L, Collections.emptyMap(), Strings.EMPTY);
+    }
+
+    private Tuple3<Long, Map<String, String>, String> appletChannelTransform(String channel) {
         //链接参数
-        if (Strings.isBlank(userData.getChannel())) {
+        if (Strings.isBlank(channel)) {
             return Tuples.of(0L, Collections.emptyMap(), Strings.EMPTY);
         }
         //数据解析
-        Map<String, String> urlParamMap = this.channelTransform(userData.getChannel());
+        Map<String, String> urlParamMap = this.channelTransform(channel);
         String shareUserId = urlParamMap.get("shareUserId");
         //查询渠道
         Agent agent = null;
@@ -142,6 +156,48 @@ public class AgentServiceImpl extends ServiceImpl<AgentMapper, Agent> implements
         return Tuples.of(agent.getId(), urlParamMap, Strings.isBlank(shareUserId) ? Strings.EMPTY : shareUserId);
     }
 
+    private Tuple3<Long, Map<String, String>, String> appChannelTransform(Game game, UserData userData) {
+        //游戏拓展信息
+        GameExt gameExt = gameExtService.getByGameId(userData.getGameId());
+        //不投放, 不回传, 只归因渠道, -- 不投放, 且回传只存在于导量情况, 导量无注册行为
+        if (Objects.equals(game.getIsPut(), Boolean.FALSE) && Objects.equals(gameExt.getAdCallBackSwitch(), Boolean.FALSE)) {
+            //查询访问记录
+            UserVisitLog userVisitLog = this.getUserVisitLog(userData);
+            //返回渠道信息
+            return Tuples.of(userVisitLog == null ? 0L : userVisitLog.getAgentId(), Collections.emptyMap(), Strings.EMPTY);
+        }
+        //投放, 且回传 -- 投放, 且不回传这种情况不存在
+        if (Objects.equals(game.getIsPut(), Boolean.TRUE) && Objects.equals(gameExt.getAdCallBackSwitch(), Boolean.TRUE)) {
+            //查询访问记录
+            UserVisitLog userVisitLog = this.getUserVisitLog(userData);
+            if (userVisitLog == null) {
+                //未匹配到访问信息, 返回自然凉
+                return Tuples.of(0L, Collections.emptyMap(), Strings.EMPTY);
+            }
+            //解析访问记录中得请求参数
+            Map<String, String> urlParamMap = this.channelTransform(userVisitLog.getChannel());
+            //查询渠道
+            Agent agent = this.getAgentByKey(urlParamMap);
+            //返回渠道信息
+            return Tuples.of(agent == null ? 0L : agent.getId(), urlParamMap, Strings.EMPTY);
+        }
+        //默认返回自然量
+        return Tuples.of(0L, Collections.emptyMap(), Strings.EMPTY);
+    }
+
+    private Tuple3<Long, Map<String, String>, String> h5ChannelTransform(String channel) {
+        //链接参数
+        if (Strings.isBlank(channel)) {
+            return Tuples.of(0L, Collections.emptyMap(), Strings.EMPTY);
+        }
+        //数据解析
+        Map<String, String> urlParamMap = this.channelTransform(channel);
+        //查询渠道
+        Agent agent = this.getAgentByKey(urlParamMap);
+        //返回
+        return Tuples.of(agent == null ? 0L : agent.getId(), urlParamMap, Strings.EMPTY);
+    }
+
     private UserVisitLog getUserVisitLog(UserData userData) {
         //当前时间
         LocalDateTime regTime = LocalDateTime.now();
@@ -154,7 +210,7 @@ public class AgentServiceImpl extends ServiceImpl<AgentMapper, Agent> implements
         // 1. 策略一 : 根据 ip + ua 精准匹配用户
         userVisitLogList = userVisitLogService.list(new LambdaQueryWrapper<UserVisitLog>()
                 .eq(UserVisitLog::getIp, userData.getIp())
-                .eq(UserVisitLog::getUa, userData)
+                .eq(UserVisitLog::getUa, userData.getUa())
                 .le(UserVisitLog::getCreateTime, regTime));
         // 判断通过策略一是否拿到数据, 筛选出访问时间与注册时间最接近的
         if (CollectionUtils.isNotEmpty(userVisitLogList)) {
@@ -236,6 +292,28 @@ public class AgentServiceImpl extends ServiceImpl<AgentMapper, Agent> implements
 
     @Override
     public Map<String, String> channelTransform(String channel) {
+        if (Strings.isBlank(channel) || Strings.isBlank(channel.trim())) {
+            return Collections.emptyMap();
+        }
+        //渠道参数
+        Map<String, String> paramMap = this.channelToMap(channel);
+        //企业微信拼接字段名
+        String callState = "callState";
+        //判断是否包含转译参数
+        if (!paramMap.containsKey(callState)) {
+            return paramMap;
+        }
+        //小程序访问信息
+        UserApplet userApplet = userAppletService.getById(Integer.valueOf(paramMap.get(callState)));
+        if (userApplet != null && Strings.isNotBlank(userApplet.getChannel())) {
+            paramMap.putAll(this.channelToMap(userApplet.getChannel()));
+            paramMap.put("appId", userApplet.getAppId());
+            paramMap.put("openId", userApplet.getOpenId());
+        }
+        return paramMap;
+    }
+
+    private Map<String, String> channelToMap(String channel) {
         if (Strings.isBlank(channel) || Strings.isBlank(channel.trim())) {
             return Collections.emptyMap();
         }

+ 1 - 0
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/CallBackServiceImpl.java

@@ -267,6 +267,7 @@ public class CallBackServiceImpl implements ICallBackService {
                 .wechatOpenId(user.getOpenId())
                 .accountReport(ttAccountRpcDTO)
                 .agentKey(agent.getAgentKey())
+                .backPolicyId(agent.getBackPolicyId())
                 .activeTime(user.getCreateTime())
                 .clueToken(urlParamMap.get("clue_token"))
                 .projectId(Strings.isBlank(urlParamMap.get("project_id")) ? null : Long.valueOf(urlParamMap.get("project_id")))

+ 18 - 10
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/LoginServiceImpl.java

@@ -3,11 +3,9 @@ package com.zanxiang.game.module.sdk.service.impl;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 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.GameExt;
-import com.zanxiang.game.module.mybatis.entity.User;
-import com.zanxiang.game.module.mybatis.entity.UserCard;
-import com.zanxiang.game.module.mybatis.entity.UserShare;
+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;
@@ -95,6 +93,9 @@ public class LoginServiceImpl implements IRegisterLoginService {
     @Autowired
     private IKafkaService kafkaService;
 
+    @Autowired
+    private IGameService gameService;
+
     @Autowired
     private IGameAppletShellService gameAppletShellService;
 
@@ -137,7 +138,7 @@ public class LoginServiceImpl implements IRegisterLoginService {
                         .set(User::getSessionKey, sessionKey).eq(User::getId, user.getId()));
             }
             //渠道更新和回传判断
-            agentService.userAgentUpdate(user, userData.getChannel());
+            agentService.userAgentUpdate(user, userData);
             //返回登录信息
             UserLoginVO userLoginVO = this.createUserLoginVO(user, userData);
             userLoginVO.setAppletShellSwitch(gameAppletShellService.getUserShellSwitch(user, Boolean.FALSE, request));
@@ -191,7 +192,7 @@ public class LoginServiceImpl implements IRegisterLoginService {
                 return ResultVO.fail(HttpStatusEnum.USERNAME_OR_PASSWORD_ERR.getMsg());
             }
             //渠道更新和回传判断
-            agentService.userAgentUpdate(user, userData.getChannel());
+            agentService.userAgentUpdate(user, userData);
             //登录信息
             UserLoginVO userLoginVO = this.createUserLoginVO(user, userData);
             Tuple2<Boolean, Long> tuple2 = this.userGuideCheck(user);
@@ -237,7 +238,7 @@ public class LoginServiceImpl implements IRegisterLoginService {
                 return ResultVO.fail(HttpStatusEnum.ACCOUNT_HALT.getMsg());
             }
             //渠道更新和回传判断
-            agentService.userAgentUpdate(user, userData.getChannel());
+            agentService.userAgentUpdate(user, userData);
             UserLoginVO userLoginVO = this.createUserLoginVO(user, userData);
             //判断是否导量用户
             Tuple2<Boolean, Long> tuple2 = this.userGuideCheck(user);
@@ -282,18 +283,25 @@ public class LoginServiceImpl implements IRegisterLoginService {
         if (!distributedLockComponent.doLock(lockKey, 0L, 3L, TimeUnit.MINUTES)) {
             throw new BaseException("用户信息正在注册中, 请勿重复请求!");
         }
+        //获取游戏信息
+        Game game = gameService.getById(userData.getGameId());
         //渠道id, 链接参数, 分享人id
-        Tuple3<Long, Map<String, String>, String> tuple3 = agentService.getUserAgentId(userData);
+        Tuple3<Long, Map<String, String>, String> tuple3 = agentService.getUserAgentId(game, userData);
         //分享人id
         Long shareUserId = Strings.isBlank(tuple3.getT3()) ? null : Long.valueOf(tuple3.getT3());
         //用户参数补充
         User user = transform(userData, tuple3.getT1(), userName);
         user.setPassword(password);
         user.setMobile(mobile);
-        user.setOpenId(openId);
+        user.setOpenId(Strings.isNotBlank(openId) ? openId : tuple3.getT2().get("openId"));
         user.setSessionKey(sessionKey);
-        user.setChannel(userData.getChannel());
         user.setShareUserId(shareUserId);
+        //App的渠道保存解析后的参数, 因为涉及到时间判断
+        if (Objects.equals(game.getCategory(), GameCategoryEnum.CATEGORY_APP.getId())) {
+            user.setChannel(JsonUtil.toString(tuple3.getT2()));
+        } else {
+            user.setChannel(userData.getChannel());
+        }
         userService.save(user);
         gameUserService.createGameUser(user);
         userAgentLogService.regAgentLog(user);

+ 18 - 0
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/UserAppletServiceImpl.java

@@ -0,0 +1,18 @@
+package com.zanxiang.game.module.sdk.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.game.module.mybatis.entity.UserApplet;
+import com.zanxiang.game.module.mybatis.mapper.UserAppletMapper;
+import com.zanxiang.game.module.sdk.service.IUserAppletService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author : lingfeng
+ * @time : 2024-04-29
+ * @description : 投放小程序用户信息
+ */
+@Slf4j
+@Service
+public class UserAppletServiceImpl extends ServiceImpl<UserAppletMapper, UserApplet> implements IUserAppletService {
+}