Explorar el Código

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

zhimo hace 1 año
padre
commit
e931d9468b
Se han modificado 32 ficheros con 588 adiciones y 406 borrados
  1. 24 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/RoleRechargeRankingDTO.java
  2. 4 15
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/vo/FlowMonitorVO.java
  3. 97 100
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/GameDataServiceImpl.java
  4. 3 3
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/PitcherDataServiceImpl.java
  5. 59 3
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/RoleManageServiceImpl.java
  6. 5 5
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/controller/KfMsgController.java
  7. 25 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/dto/KfWebSocketMsgDTO.java
  8. 1 3
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/IKfMsgService.java
  9. 3 2
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/IKfRoomService.java
  10. 9 6
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/KfAppletMsgServiceImpl.java
  11. 2 5
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/KfMsgServiceImpl.java
  12. 33 11
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/KfRoomMsgServiceImpl.java
  13. 12 9
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/KfRoomServiceImpl.java
  14. 11 1
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/websocket/KfMsgRedisListener.java
  15. 22 11
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/websocket/KfMsgWebsocketHandler.java
  16. 0 42
      game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/entity/KfLink.java
  17. 0 83
      game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/entity/KfMsgContent.java
  18. 0 1
      game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/entity/KfRoomMsg.java
  19. 0 12
      game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/mapper/KfLinkMapper.java
  20. 0 12
      game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/mapper/KfMsgContentMapper.java
  21. 1 1
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/SDKApplication.java
  22. 5 0
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/constant/RedisKeyConstant.java
  23. 49 0
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/enums/KafkaEventTrackEnum.java
  24. 2 2
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/enums/TokenCheckEnum.java
  25. 8 0
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/listener/OrderPaySuccessListener.java
  26. 6 0
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/pojo/dto/PlatformOrderDTO.java
  27. 29 0
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/IKafkaService.java
  28. 76 73
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/GameUserRoleServiceImpl.java
  29. 65 0
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/KafkaServiceImpl.java
  30. 10 1
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/LoginServiceImpl.java
  31. 21 5
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/OrderPayServiceImpl.java
  32. 6 0
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/OrderServiceImpl.java

+ 24 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/RoleRechargeRankingDTO.java

@@ -201,4 +201,28 @@ public class RoleRechargeRankingDTO extends BasePage {
     @ApiModelProperty(notes = "玩家操作系统筛选:windows;mac;ios;devtools;android")
     private String os;
 
+
+    /**
+     * 创角24小时内单笔充值金额
+     */
+    @ApiModelProperty(value = "创角24小时内单笔充值金额")
+    private Long rechargeAmountWithin24h;
+
+    /**
+     * 创角24小时内单笔充值金额范围单位
+     */
+    @ApiModelProperty(value = "创角24小时内单笔充值金额范围单位(>=,<=,=,<,>)")
+    private String rechargeAmountWithin24hUnit = ">=";
+
+    /**
+     * 创角24小时以内累计充值金额
+     */
+    @ApiModelProperty(value = "创角24小时以内累计充值金额")
+    private Long rechargeTotalAmountWithin24h;
+
+    /**
+     * 创角24小时以内累计充值金额范围单位
+     */
+    @ApiModelProperty(value = "创角24小时以内累计充值金额范围单位(>=,<=,=,<,>)")
+    private String rechargeTotalAmountWithin24hUnit = ">=";
 }

+ 4 - 15
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/vo/FlowMonitorVO.java

@@ -20,11 +20,7 @@ public class FlowMonitorVO implements Serializable {
      */
     @ApiModelProperty(value = "SDK类型")
     private String sourceSystem;
-    /**
-     * 投手名称
-     */
-    @ApiModelProperty(value = "投手名称")
-    private String pitcherName;
+
 
     /**
      * 消耗开始时间
@@ -112,15 +108,8 @@ public class FlowMonitorVO implements Serializable {
     private Double costCount = 0.0;
 
     /**
-     * 游戏名称
+     * 昨日充值总数
      */
-    @ApiModelProperty(value = "游戏名称")
-    private String gameName;
-
-    /**
-     * 渠道名称
-     */
-    @ApiModelProperty(value = "渠道名称")
-    private String agentName;
-
+    @ApiModelProperty(value = "yesterday_amount")
+    private Double yesterdayAmount = 0.0;
 }

+ 97 - 100
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/GameDataServiceImpl.java

@@ -5325,112 +5325,109 @@ public class GameDataServiceImpl implements IGameDataService {
      */
     public String flowMonitorSql(FlowMonitorDTO dto, Criteria cri, Criteria criCost, String costTable, String orderTable) {
         String gameColumn = "game_id  ";
-        String gameNameColumn = "game_name ";
         if (dto.getGameDimension() != 1) {
             gameColumn = "parent_game_id ";
-            gameNameColumn = "parent_game_name ";
         }
 
         String sql =
-                """
-                        SELECT 
-                              s.source_system,-- SDK类型
-                              s.minDay cost_begin_date, -- 消耗开始时间
-                              s.maxDay cost_end_date, -- 消耗结束时间
-                              s.day as order_date, -- 订单时间
-                              s.ten_amount, -- 10点充值
-                              s.ten_rate, -- 10点环比
-                              IFNULL(s.ten_recovery,0), -- 10点回报率
-                              s.fourteen_amount,  -- 14点充值
-                              s.fourteen_rate, -- 14点环比
-                              IFNULL(s.fourteen_recovery,0), -- 14点回报率  
-                              s.seventeen_amount, -- 17点充值
-                              s.seventeen_rate, -- 17点环比
-                              IFNULL(s.seventeen_recovery,0), -- 17点回报率
-                              s.twentyfour_amount, -- 24点充值
-                              s.twentyfour_rate, -- 24点环比
-                              IFNULL(s.twentyfour_recovery,0), -- 24点回报率
-                              IFNULL(s.costCount,0) as cost_count , -- 消耗总计
-                              s.pitcher_id, -- 投手id
-                              s.pitcher_name, -- 投手名称
-                              s.agent_id,
-                              s.account_id,
-                              s.agent_name,
-                              s. """ + gameNameColumn +
-                        """
-                              , s. """ + gameColumn +
-                        """
-                                      -- 游戏id
-                                     
-                                from (          
-                                     SELECT
-                                          a.source_system,
-                                          b.minDay,
-                                          b.maxDay,
-                                          a.day,
-                                          a.ten_amount, 
-                                          ROUND(a.ten_rate,2)*100 as ten_rate,  -- 10点环比
-                                          ROUND(IF(ten_amount>0,ten_amount/b.costCount,ten_amount),2)*100 as ten_recovery, -- 10点回报率(充值/消耗)
-                                          a.fourteen_amount, -- 14点充值
-                                          ROUND(a.fourteen_rate,2)*100 as fourteen_rate,  -- 14点环比
-                                          ROUND(IF(fourteen_amount>0,fourteen_amount/b.costCount,fourteen_amount),2)*100 as fourteen_recovery, -- 14点回报率
-                                          a.seventeen_amount, -- 17点充值
-                                          ROUND(a.seventeen_rate,2)*100 as seventeen_rate,  -- 17点环比
-                                          ROUND(IF(seventeen_amount>0,seventeen_amount/b.costCount,seventeen_amount),2)*100 as seventeen_recovery, -- 17点回报率
-                                          a.twentyfour_amount, -- 24点充值
-                                          ROUND(a.twentyfour_rate,2)*100 as twentyfour_rate,  -- 24点环比
-                                          ROUND(IF(twentyfour_amount>0,twentyfour_amount/b.costCount,twentyfour_amount),2)*100 as twentyfour_recovery, -- 24点回报率
-                                          b.costCount,
-                                          a.pitcher_id, -- 投手id
-                                          a.pitcher_name, -- 投手名称
-                                          a.agent_id,
-                                          a.account_id,
-                                          a.agent_name,
-                                          a.
-                                          """ + gameNameColumn + """
-                                          , a. """ + gameColumn + """
+             """
+                 select
+                        cost_begin_date, -- 消耗开始时间
+                        cost_end_date, -- 消耗结束时间
+                        order_date,
+                        source_system,
+                        ten_amount, -- 10点充值金额
+                        ROUND(IF(ten_amount>0,ten_amount/cost_count,cost_count),2)*100 as ten_recovery, -- 10点回报率(充值/消耗)
+                        ROUND(IF(cost_count>0,ten_amount/yesterday_amount,cost_count),2)*100 as ten_rate, -- 10点环比(前一天充值总额/消耗)
+                        fourteen_amount, -- 14点充值金额
+                        ROUND(IF(cost_count>0,fourteen_amount/cost_count,cost_count),2)*100 as fourteen_recovery, -- 14点回报率(充值/消耗)
+                        ROUND(IF(cost_count>0,fourteen_amount/yesterday_amount,cost_count),2)*100 as fourteen_rate, -- 14点环比(前一天充值总额/消耗)
+                        seventeen_amount, -- 17点充值金额
+                        ROUND(IF(cost_count>0,seventeen_amount/cost_count,cost_count),2)*100 as seventeen_recovery, -- 17点回报率(充值/消耗)
+                        ROUND(IF(cost_count>0,seventeen_amount/yesterday_amount,cost_count),2)*100 as seventeen_rate, -- 17点环比(前一天充值总额/消耗)
+                        twentyfour_amount, -- 24点充值金额
+                        ROUND(IF(cost_count>0,twentyfour_amount/cost_count,cost_count),2)*100 as twentyfour_recovery, -- 24点回报率(充值/消耗)
+                        ROUND(IF(cost_count>0,twentyfour_amount/yesterday_amount,cost_count),2)*100 as twentyfour_rate, -- 17点环比(前一天充值总额/消耗)
+                        cost_count, -- 消耗总计
+                        yesterday_amount -- 昨日充值总额
+                  from (
+                               SELECT
+                                      order_date,
+                                      ANY_VALUE(cost_begin_date) cost_begin_date , -- 消耗开始时间
+                                      ANY_VALUE(cost_end_date) cost_end_date, -- 消耗结束时间
+                                      sum(ten_amount) ten_amount,
+                                      sum(fourteen_amount) fourteen_amount ,
+                                      sum(seventeen_amount) seventeen_amount,
+                                      sum(twentyfour_amount) twentyfour_amount,
+                                      any_value(cost_count) cost_count,
+                                      any_value(source_system) source_system,
+                                      sum(yesterday_amount) yesterday_amount
+                                from (
+                                           SELECT
+                                                 s.source_system,-- SDK类型
+                                                 s.minDay cost_begin_date, -- 消耗开始时间
+                                                 s.maxDay cost_end_date, -- 消耗结束时间
+                                                 s.day as order_date, -- 订单时间
+                                                 s.ten_amount, -- 10点充值
+                                                 s.fourteen_amount,  -- 14点充值
+                                                 s.seventeen_amount, -- 17点充值
+                                                 s.twentyfour_amount, -- 24点充值
+                                                 IFNULL(s.costCount,0) as cost_count , -- 消耗总计
+                                                 s.yesterday_amount   -- 昨日充值总额
+                                           from (
+                                                    SELECT
+                                                            a.source_system,
+                                                            b.minDay,
+                                                            b.maxDay,
+                                                            a.day,
+                                                            a.ten_amount,
+                                                            a.fourteen_amount, -- 14点充值
+                                                            a.seventeen_amount, -- 17点充值
+                                                            a.twentyfour_amount, -- 24点充值
+                                                            b.costCount,
+                                                            a.pitcher_id, -- 投手id
+                                                            a.agent_id,
+                                                            a.account_id,
+                                                            a.yesterday_amount,
+                                                            a.""" + gameColumn + """
                                                  
-                        FROM
-                        		(
-                        			SELECT
-                        				day,
-                        				source_system,
-                        				ten_amount,
-                                        fourteen_amount,
-                                        seventeen_amount,
-                                        twentyfour_amount,
-                                        ten_rate,
-                                        fourteen_rate,
-                                        seventeen_rate,
-                                        twentyfour_rate,
-                                        pitcher_id,
-                                        pitcher_name,   
-                                        agent_id,
-                                        account_id,
-                                        agent_name,
-                                        """ + gameNameColumn +"""
-                         , """
-                        + gameColumn +
-                        """
-                                    FROM      
-                                """ + orderTable +
-                        """
-                                	) a
-                                LEFT JOIN (
-                                	SELECT
-                                		source_system,
-                                		sum(cost) costCount,
-                                		max(day) maxDay,
-                                		min(day) minDay
-                                	FROM  
-                                	""" + costTable +
-                        """
-                                """ + criCost +
-                        """
-                                            		GROUP BY source_system
-                                            	) b on a.source_system = b.source_system
-                                )s   
-                                """ + cri;
+                                                       FROM
+                                                      (
+                                                       SELECT
+                                                         day,
+                                                         source_system,
+                                                         ten_amount,
+                                                         fourteen_amount,
+                                                         seventeen_amount,
+                                                         twentyfour_amount,
+                                                         ten_rate,
+                                                         fourteen_rate,
+                                                         seventeen_rate,
+                                                         twentyfour_rate,
+                                                         pitcher_id,
+                                                         agent_id,
+                                                         account_id,
+                                                         yesterday_amount,
+                                                         """ + gameColumn + """
+                                                       FROM
+                                                         """ + orderTable + """
+                                                       ) a
+                                                             LEFT JOIN (
+                                                                    SELECT
+                                                                        source_system,
+                                                                        sum(cost) costCount,
+                                                                        max(day) maxDay,
+                                                                        min(day) minDay
+                                                                     FROM  
+                                                                        """ + costTable + """
+                                                                        """ + criCost + """
+                                                                        GROUP BY source_system
+                                            	                        ) b on a.source_system = b.source_system
+                                           )s""" + cri + """
+                                )a    group by order_date
+                                 
+                  )  aa  ORDER BY order_date DESC
+               """;
         return sql;
     }
 

+ 3 - 3
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/PitcherDataServiceImpl.java

@@ -264,7 +264,7 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
         List<PitcherDataDayVO> list = tempList.stream().map(vo -> {
             Long[] usersID = ArrayUtils.EMPTY_LONG_OBJECT_ARRAY;
             //将pitcherId和需要查询的注册时间拼接
-            String pitcherIdDate = vo.getPitcherId() + "/" + dto.getBeginDate();
+            String pitcherIdDate = vo.getPitcherId() + "/" + vo.getDt();
             //取出所有usersId
             if (map.containsKey(pitcherIdDate)) {
                 //string[] -> Long[]
@@ -325,7 +325,7 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
         findUsersCri.where().andNotEquals("reg_agent_id", 0);
         Sql findUsersIdSql;
         Criteria groupByCri = Cnd.cri();
-        groupByCri.getGroupBy().groupBy("pitcher_id", "DATE(reg_user_time)");
+        groupByCri.getGroupBy().groupBy("pitcher_id", "DATE(dt)");
         findUsersIdSql = Sqls.create(findUsersIdSql(findUsersCri, groupByCri));
         //自定义回传
         findUsersIdSql.setCallback((connection, resultSet, sql) -> {
@@ -349,7 +349,7 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
     private String findUsersIdSql(Criteria cri, Criteria groupByCri) {
         return """
                 SELECT
-                    CONCAT(pitcher_id,'/',DATE(reg_user_time)) as game_id_date,
+                    CONCAT(pitcher_id,'/',DATE(dt)) as game_id_date,
                     GROUP_CONCAT(CONVERT (player_id, varchar), "/") as amount_users_id
                 FROM
                     game_ads.ads_player_recharge_ranking

+ 59 - 3
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/RoleManageServiceImpl.java

@@ -58,6 +58,15 @@ public class RoleManageServiceImpl implements IRoleManageService {
             //角色注册子游戏
             criA.where().andInList("role_reg_game_id", dto.getGameId());
         }
+
+        //拼接24内充值金额条件
+        if(dto.getRechargeAmountWithin24h()!=null){
+            criA = spliceRechargeAmountWithin24h(dto, criA);
+        }
+        if(dto.getRechargeTotalAmountWithin24h()!=null){
+            criA = spliceRechargeTotalAmountWithin24h(dto, criA);
+        }
+
         if (CollectionUtils.isNotEmpty(dto.getParentGameIds())) {
             //角色注册父游戏
             criA.where().andInList("role_reg_parent_game_id", dto.getParentGameIds());
@@ -216,7 +225,7 @@ public class RoleManageServiceImpl implements IRoleManageService {
         sql.setPager(pager);
         dao.execute(sql);
         List<Map> list = sql.getList(Map.class).stream().map(map -> {
-            getNameById(map);
+             getNameById(map);
             //去除‘null’字符串
             if ("null".equals(map.get("add_corp_user_id"))) {
                 map.put("add_corp_user_id", null);
@@ -240,6 +249,34 @@ public class RoleManageServiceImpl implements IRoleManageService {
         return new Page<>(list, pager);
     }
 
+    private Criteria spliceRechargeTotalAmountWithin24h(RoleRechargeRankingDTO dto, Criteria criA) {
+        switch (dto.getRechargeTotalAmountWithin24hUnit()) {
+            case ">" -> criA.where().andGT("role_total_amount", dto.getRechargeTotalAmountWithin24h());
+            case ">=" -> criA.where().andGTE("role_total_amount", dto.getRechargeTotalAmountWithin24h());
+            case "=" -> criA.where().andEquals("role_total_amount", dto.getRechargeTotalAmountWithin24h());
+            case "<" -> criA.where().andLT("role_total_amount", dto.getRechargeTotalAmountWithin24h());
+            case "<=" -> criA.where().andLTE("role_total_amount", dto.getRechargeTotalAmountWithin24h());
+            default -> {
+                criA.where().andGTE("role_total_amount", dto.getRechargeTotalAmountWithin24h());
+            }
+        }
+        return criA;
+    }
+
+    private Criteria spliceRechargeAmountWithin24h(RoleRechargeRankingDTO dto, Criteria criA) {
+        switch (dto.getRechargeAmountWithin24hUnit()) {
+            case ">" -> criA.where().andGT("max_amount", dto.getRechargeAmountWithin24h());
+            case ">=" -> criA.where().andGTE("max_amount", dto.getRechargeAmountWithin24h());
+            case "=" -> criA.where().andEquals("max_amount", dto.getRechargeAmountWithin24h());
+            case "<" -> criA.where().andLT("max_amount", dto.getRechargeAmountWithin24h());
+            case "<=" -> criA.where().andLTE("max_amount", dto.getRechargeAmountWithin24h());
+            default -> {
+                criA.where().andGTE("max_amount", dto.getRechargeAmountWithin24h());
+            }
+        }
+        return criA;
+    }
+
     /**
      * 角色战力排行榜
      * @param dto RoleCombatRankingDTO
@@ -928,7 +965,9 @@ public class RoleManageServiceImpl implements IRoleManageService {
                 		j.create_by as create_by, -- 创建者
                 		j.update_time as update_time, -- 更新时间
                 		j.update_by as update_by, -- 更新者
-                		j.is_delete as is_delete -- 是否删除 1-删除;0-正常
+                		j.is_delete as is_delete, -- 是否删除 1-删除;0-正常
+                		ara.role_total_amount as role_total_amount, -- 创角24小时内总充值金额
+                		ara.max_amount as max_amount -- 创角24小时内单笔最大充值金额
                 	FROM
                 	(
                 		SELECT
@@ -953,6 +992,13 @@ public class RoleManageServiceImpl implements IRoleManageService {
                 		) a
                 		WHERE num = 1
                 	) a
+                	left join(
+                	    SELECT source_system,
+                	    role_id,
+                	    role_total_amount,
+                	    array_max(role_amount) max_amount 
+                	FROM game_ads.ads_role_amount 
+                	) ara on a.role_id = ara.role_id and a.source_system = ara.source_system
                 	LEFT JOIN (
                 		SELECT
                 			-- 角色等级、角色攻击力(取最新的信息)
@@ -1328,7 +1374,9 @@ public class RoleManageServiceImpl implements IRoleManageService {
                         j.create_by as create_by, -- 创建者
                         j.update_time as update_time, -- 更新时间
                         j.update_by as update_by, -- 更新者
-                        j.is_delete as is_delete -- 是否删除 1-删除;0-正常
+                        j.is_delete as is_delete, -- 是否删除 1-删除;0-正常
+                        ara.role_total_amount as role_total_amount, -- 创角24小时内总充值金额
+                		ara.max_amount as max_amount -- 创角24小时内单笔最大充值金额
                     FROM
                     (
                         SELECT
@@ -1353,6 +1401,14 @@ public class RoleManageServiceImpl implements IRoleManageService {
                         ) a
                         WHERE num = 1
                     ) a
+                    left join(
+                	    SELECT 
+                	        source_system,
+                	        role_id,
+                	        role_total_amount,
+                	        array_max(role_amount) max_amount 
+                	    FROM game_ads.ads_role_amount 
+                	) ara on a.role_id = ara.role_id and a.source_system = ara.source_system
                     LEFT JOIN (
                         SELECT
                             -- 角色等级、角色攻击力(取最新的信息)

+ 5 - 5
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/controller/KfMsgController.java

@@ -4,7 +4,7 @@ import com.zanxiang.erp.security.annotation.PreAuthorize;
 import com.zanxiang.game.module.manage.pojo.params.KfApiParam;
 import com.zanxiang.game.module.manage.pojo.params.KfUserUpdateParam;
 import com.zanxiang.game.module.manage.pojo.vo.KfGameVO;
-import com.zanxiang.game.module.manage.service.IKfMsgContentService;
+import com.zanxiang.game.module.manage.service.IKfMsgService;
 import com.zanxiang.game.module.manage.service.IKfUserService;
 import com.zanxiang.module.util.JsonUtil;
 import com.zanxiang.module.util.pojo.ResultVO;
@@ -33,7 +33,7 @@ import java.util.List;
 public class KfMsgController {
 
     @Autowired
-    private IKfMsgContentService kfMsgContentService;
+    private IKfMsgService kfMsgService;
 
     @Autowired
     private IKfUserService kfUserService;
@@ -43,7 +43,7 @@ public class KfMsgController {
     @PreAuthorize(permissionKey = "manage:kf:uploadMsg")
     @ApiResponses(value = {@ApiResponse(code = 200, message = "成功", response = Tuple2.class)})
     public ResultVO<Tuple2<String, String>> uploadMsg(String param, MultipartFile files) {
-        return ResultVO.ok(kfMsgContentService.uploadMsg(JsonUtil.toObj(param, KfApiParam.class), files));
+        return ResultVO.ok(kfMsgService.uploadMsg(JsonUtil.toObj(param, KfApiParam.class), files));
     }
 
     @ApiOperation(value = "小游戏列表查询")
@@ -51,7 +51,7 @@ public class KfMsgController {
     @PreAuthorize(permissionKey = "manage:kf:gameList")
     @ApiResponses(value = {@ApiResponse(code = 200, message = "成功", response = KfGameVO.class)})
     public ResultVO<List<KfGameVO>> list() {
-        return ResultVO.ok(kfMsgContentService.getKfGameList());
+        return ResultVO.ok(kfMsgService.getKfGameList());
     }
 
     @ApiOperation(value = "客服接口通用api")
@@ -59,7 +59,7 @@ public class KfMsgController {
     @PreAuthorize(permissionKey = "manage:kf:commApi")
     @ApiResponses(value = {@ApiResponse(code = 200, message = "成功", response = String.class)})
     public ResultVO<String> list(@Validated @RequestBody KfApiParam param) {
-        return ResultVO.ok(kfMsgContentService.kfApi(param));
+        return ResultVO.ok(kfMsgService.kfApi(param));
     }
 
     @ApiOperation(value = "获取小游戏授权码")

+ 25 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/dto/KfWebSocketMsgDTO.java

@@ -198,6 +198,11 @@ public class KfWebSocketMsgDTO {
          * 最后充值时间
          */
         private LocalDateTime lastPayTime;
+
+        /**
+         * 是否添加企微
+         */
+        private Boolean addCorpWechat;
     }
 
     @Data
@@ -370,6 +375,11 @@ public class KfWebSocketMsgDTO {
          * 开始等待时间
          */
         private LocalDateTime waitStartTime;
+
+        /**
+         * 是否添加企微
+         */
+        private Boolean addCorpWechat;
     }
 
     @Data
@@ -462,6 +472,11 @@ public class KfWebSocketMsgDTO {
          * 未读消息总数
          */
         private Integer unReadMsgCount;
+
+        /**
+         * 是否添加企微
+         */
+        private Boolean addCorpWechat;
     }
 
     @Data
@@ -497,6 +512,16 @@ public class KfWebSocketMsgDTO {
          */
         private Boolean readStatus;
 
+        /**
+         * 客服id, 当消息归属于客服得时候有值
+         */
+        private Long kfUserId;
+
+        /**
+         * 客服名称, 当消息归属于客服得时候有值
+         */
+        private String kfUserName;
+
         /**
          * 消息归属
          */

+ 1 - 3
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/IKfMsgContentService.java → game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/IKfMsgService.java

@@ -1,9 +1,7 @@
 package com.zanxiang.game.module.manage.service;
 
-import com.baomidou.mybatisplus.extension.service.IService;
 import com.zanxiang.game.module.manage.pojo.params.KfApiParam;
 import com.zanxiang.game.module.manage.pojo.vo.KfGameVO;
-import com.zanxiang.game.module.mybatis.entity.KfMsgContent;
 import org.springframework.web.multipart.MultipartFile;
 import reactor.util.function.Tuple2;
 
@@ -14,7 +12,7 @@ import java.util.List;
  * @time : 2023-11-28
  * @description :
  */
-public interface IKfMsgContentService extends IService<KfMsgContent> {
+public interface IKfMsgService {
 
     /**
      * 消息上传

+ 3 - 2
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/IKfRoomService.java

@@ -43,10 +43,11 @@ public interface IKfRoomService extends IService<KfRoom> {
     /**
      * 根据游戏获取游戏信息
      *
-     * @param gameId : 游戏id
+     * @param gameId   : 游戏id
+     * @param kfUserId : 客服号id
      * @return : 返回游戏信息
      */
-    List<KfWebSocketMsgDTO.GameBean> getKfGameByGameId(Long gameId);
+    List<KfWebSocketMsgDTO.GameBean> getKfGameByGameId(Long gameId, Long kfUserId);
 
     /**
      * 待接入房间列表

+ 9 - 6
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/KfAppletMsgServiceImpl.java

@@ -196,8 +196,6 @@ public class KfAppletMsgServiceImpl implements IKfAppletMsgService {
                 .gameId(gameId)
                 .roomId(kfRoom == null ? null : kfRoom.getId())
                 .build();
-        //游戏列表
-        kfWebSocketMsgDTO.setGameList(kfRoomService.getKfGameByGameId(gameId));
         //待接入消息
         if (Objects.equals(kfWebSocketMsgEnum, KfWebSocketMsgEnum.WEBSOCKET_MSG_WAIT_LIST)) {
             List<KfWebSocketMsgDTO.WaitUserBean> waitUserList = kfSessionUserService.getWaitUserList(gameId);
@@ -209,8 +207,11 @@ public class KfAppletMsgServiceImpl implements IKfAppletMsgService {
             KfWebSocketMsgDTO.RoomMsgBean roomMsgBean = BeanUtil.copy(kfRoomMsg, KfWebSocketMsgDTO.RoomMsgBean.class);
             roomMsgBean.setContent(msgContent);
             kfWebSocketMsgDTO.setRoomMsgList(Collections.singletonList(roomMsgBean));
-            //房间, 空指针警告只是逻辑警告, kfRoom为空不会走到这里, 走上面的 if 条件
-            kfWebSocketMsgDTO.setRoomList(kfRoomService.getRoomByRoomId(kfRoom.getId()));
+            //设置房间列表和游戏列表
+            if (kfRoom != null) {
+                kfWebSocketMsgDTO.setGameList(kfRoomService.getKfGameByGameId(gameId, kfRoom.getKfUserId()));
+                kfWebSocketMsgDTO.setRoomList(kfRoomService.getRoomByRoomId(kfRoom.getId()));
+            }
         }
         return kfWebSocketMsgDTO;
     }
@@ -246,8 +247,8 @@ public class KfAppletMsgServiceImpl implements IKfAppletMsgService {
                 .gameId(gameApplet.getGameId())
                 .userId(user == null ? null : user.getId())
                 .isWait(Boolean.FALSE)
-                .lastRoleId(gameUserRole == null ? "0" : gameUserRole.getRoleId())
-                .lastRoleName(gameUserRole == null ? kfAppletMsgDTO.getFromUserName() : gameUserRole.getRoleName())
+                .lastRoleId(gameUserRole == null ? null : gameUserRole.getRoleId())
+                .lastRoleName(gameUserRole == null ? "神秘人[未创角]" : gameUserRole.getRoleName())
                 .serverId(gameUserRole == null ? null : gameUserRole.getServerId())
                 .serverName(gameUserRole == null ? null : gameUserRole.getServerName())
                 .createTime(LocalDateTime.now())
@@ -262,6 +263,7 @@ public class KfAppletMsgServiceImpl implements IKfAppletMsgService {
                 .msgType(kfAppletMsgDTO.getMsgType())
                 .gameId(gameApplet.getGameId())
                 .openId(kfAppletMsgDTO.getFromUserName())
+                .userId(kfRoom == null ? null : kfRoom.getUserId())
                 .readStatus(Boolean.FALSE)
                 .roomId(kfRoom == null ? null : kfRoom.getId())
                 .kfUserId(kfRoom == null ? null : kfRoom.getKfUserId())
@@ -343,6 +345,7 @@ public class KfAppletMsgServiceImpl implements IKfAppletMsgService {
                 .msgType(KfRoomMsgTypeEnum.KF_MSG_TYPE_LINK.getValue())
                 .gameId(gameId)
                 .openId(openId)
+                .userId(kfRoom == null ? null : kfRoom.getUserId())
                 .readStatus(kfRoom != null)
                 .roomId(kfRoom == null ? null : kfRoom.getId())
                 .kfUserId(kfRoom == null ? null : kfRoom.getKfUserId())

+ 2 - 5
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/KfMsgContentServiceImpl.java → game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/KfMsgServiceImpl.java

@@ -2,7 +2,6 @@ package com.zanxiang.game.module.manage.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.zanxiang.erp.security.util.SecurityUtil;
 import com.zanxiang.game.module.manage.enums.KfActionEnum;
 import com.zanxiang.game.module.manage.enums.KfApiEnum;
@@ -11,13 +10,11 @@ import com.zanxiang.game.module.manage.pojo.params.KfApiParam;
 import com.zanxiang.game.module.manage.pojo.vo.KfGameVO;
 import com.zanxiang.game.module.manage.service.IGameAppletService;
 import com.zanxiang.game.module.manage.service.IGameAuthService;
-import com.zanxiang.game.module.manage.service.IKfMsgContentService;
+import com.zanxiang.game.module.manage.service.IKfMsgService;
 import com.zanxiang.game.module.manage.service.IKfUserService;
 import com.zanxiang.game.module.mybatis.entity.GameApplet;
 import com.zanxiang.game.module.mybatis.entity.GameAuth;
-import com.zanxiang.game.module.mybatis.entity.KfMsgContent;
 import com.zanxiang.game.module.mybatis.entity.KfUser;
-import com.zanxiang.game.module.mybatis.mapper.KfMsgContentMapper;
 import com.zanxiang.module.util.JsonUtil;
 import com.zanxiang.module.util.URIUtil;
 import com.zanxiang.module.util.bean.BeanUtil;
@@ -48,7 +45,7 @@ import java.util.stream.Collectors;
  */
 @Slf4j
 @Service
-public class KfMsgContentServiceImpl extends ServiceImpl<KfMsgContentMapper, KfMsgContent> implements IKfMsgContentService {
+public class KfMsgServiceImpl implements IKfMsgService {
 
     @Autowired
     private RestTemplate restTemplate;

+ 33 - 11
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/KfRoomMsgServiceImpl.java

@@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.erp.base.ErpServer;
+import com.zanxiang.erp.base.rpc.ISysUserRpc;
 import com.zanxiang.game.module.manage.enums.KfRoomMsgOwnerEnum;
 import com.zanxiang.game.module.manage.enums.KfRoomMsgTypeEnum;
 import com.zanxiang.game.module.manage.pojo.dto.KfWebSocketMsgDTO;
@@ -16,14 +18,13 @@ import com.zanxiang.module.util.JsonUtil;
 import com.zanxiang.module.util.bean.BeanUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.CollectionUtils;
+import org.apache.dubbo.config.annotation.DubboReference;
 import org.springframework.stereotype.Service;
 import reactor.util.function.Tuple2;
 import reactor.util.function.Tuples;
 
 import java.time.LocalDateTime;
-import java.util.List;
-import java.util.Objects;
-import java.util.UUID;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -35,6 +36,9 @@ import java.util.stream.Collectors;
 @Service
 public class KfRoomMsgServiceImpl extends ServiceImpl<KfRoomMsgMapper, KfRoomMsg> implements IKfRoomMsgService {
 
+    @DubboReference(providedBy = ErpServer.SERVER_DUBBO_NAME)
+    private ISysUserRpc sysUserRpc;
+
     @Override
     public Tuple2<KfWebSocketMsgDTO.PageBean, List<KfWebSocketMsgDTO.RoomMsgBean>> msgRoomHistory(Long roomId, KfWebSocketMsgParam.PageBean pageBean) {
         Page<KfRoomMsg> kfRoomMsgPage = super.page(new Page<>(pageBean.getPageNum(), pageBean.getPageSize()),
@@ -42,15 +46,18 @@ public class KfRoomMsgServiceImpl extends ServiceImpl<KfRoomMsgMapper, KfRoomMsg
                         .eq(KfRoomMsg::getRoomId, roomId)
                         .orderByDesc(KfRoomMsg::getCreateTime)
         );
+        //客服名字列表
+        Map<Long, String> kfUserNameMap = this.getKfUserNameMap(kfRoomMsgPage.getRecords());
         //构造消息列表
         List<KfWebSocketMsgDTO.RoomMsgBean> roomMsgBeanList = kfRoomMsgPage.getRecords().stream()
-                .map(this::transform).collect(Collectors.toList());
-        //更新消息已读状态
-        List<String> msgIdList = roomMsgBeanList.stream()
-                .filter(msg -> Objects.equals(msg.getReadStatus(), Boolean.FALSE))
-                .map(KfWebSocketMsgDTO.RoomMsgBean::getMsgId)
-                .collect(Collectors.toList());
-        if (CollectionUtils.isNotEmpty(msgIdList)) {
+                .map(roomMsgBean -> this.transform(roomMsgBean, kfUserNameMap)).collect(Collectors.toList());
+        //消息列表不为空
+        if (CollectionUtils.isNotEmpty(roomMsgBeanList)) {
+            //更新消息已读状态
+            List<String> msgIdList = roomMsgBeanList.stream()
+                    .filter(msg -> Objects.equals(msg.getReadStatus(), Boolean.FALSE))
+                    .map(KfWebSocketMsgDTO.RoomMsgBean::getMsgId)
+                    .collect(Collectors.toList());
             super.update(new LambdaUpdateWrapper<KfRoomMsg>()
                     .set(KfRoomMsg::getReadStatus, Boolean.TRUE)
                     .set(KfRoomMsg::getUpdateTime, LocalDateTime.now())
@@ -60,13 +67,16 @@ public class KfRoomMsgServiceImpl extends ServiceImpl<KfRoomMsgMapper, KfRoomMsg
         return Tuples.of(KfWebSocketMsgDTO.transformPage(kfRoomMsgPage), roomMsgBeanList);
     }
 
-    private KfWebSocketMsgDTO.RoomMsgBean transform(KfRoomMsg kfRoomMsg) {
+    private KfWebSocketMsgDTO.RoomMsgBean transform(KfRoomMsg kfRoomMsg, Map<Long, String> kfUserNameMap) {
         if (kfRoomMsg == null) {
             return null;
         }
         KfWebSocketMsgDTO.RoomMsgBean roomMsgBean = BeanUtil.copy(kfRoomMsg, KfWebSocketMsgDTO.RoomMsgBean.class);
         roomMsgBean.setMsgType(KfRoomMsgTypeEnum.getMsgTypeEnum(kfRoomMsg.getMsgType()));
         roomMsgBean.setContent(JsonUtil.toObj(kfRoomMsg.getContent(), KfWebSocketMsgDTO.MsgContentBean.class));
+        //客服消息, 设置客服名字
+        String kfUserName = kfUserNameMap.get(roomMsgBean.getKfUserId());
+        roomMsgBean.setKfUserName(kfUserName == null ? "查询erp客服名字异常" : kfUserName);
         return roomMsgBean;
     }
 
@@ -88,4 +98,16 @@ public class KfRoomMsgServiceImpl extends ServiceImpl<KfRoomMsgMapper, KfRoomMsg
                 .updateTime(LocalDateTime.now())
                 .build());
     }
+
+    private Map<Long, String> getKfUserNameMap(List<KfRoomMsg> roomMsgList) {
+        List<Long> kfUserIdList = roomMsgList.stream().map(KfRoomMsg::getKfUserId).collect(Collectors.toList());
+        Map<Long, String> kfUserNameMap;
+        try {
+            kfUserNameMap = sysUserRpc.getUserNameByIds(kfUserIdList).getData();
+        } catch (Exception e) {
+            log.error("获取erp客服名字异常, kfUserIdList : {}, e : {}", JsonUtil.toString(kfUserIdList), e.getMessage());
+            kfUserNameMap = Collections.emptyMap();
+        }
+        return kfUserNameMap;
+    }
 }

+ 12 - 9
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/KfRoomServiceImpl.java

@@ -73,15 +73,14 @@ public class KfRoomServiceImpl extends ServiceImpl<KfRoomMapper, KfRoom> impleme
 
     @Override
     public Long userJoinRoom(String openId, Long gameId) {
-        KfRoom kfRoom = super.getOne(new LambdaQueryWrapper<KfRoom>()
-                .eq(KfRoom::getOpenId, openId)
-                .eq(KfRoom::getKfUserId, SecurityUtil.getUserId()));
+        KfRoom kfRoom = super.getOne(new LambdaQueryWrapper<KfRoom>().eq(KfRoom::getOpenId, openId));
         if (kfRoom == null) {
             kfRoom = this.transform(openId, gameId);
             super.save(kfRoom);
             return kfRoom.getId();
         }
         super.update(new LambdaUpdateWrapper<KfRoom>()
+                .set(KfRoom::getKfUserId, SecurityUtil.getUserId())
                 .set(KfRoom::getOnline, Boolean.TRUE)
                 .set(KfRoom::getUpdateTime, LocalDateTime.now())
                 .eq(KfRoom::getId, kfRoom.getId())
@@ -106,8 +105,9 @@ public class KfRoomServiceImpl extends ServiceImpl<KfRoomMapper, KfRoom> impleme
 
     @Override
     public List<KfWebSocketMsgDTO.GameBean> getKfGameList() {
+        Long kfUserId = SecurityUtil.getUserId();
         List<GameAuth> gameAuthList = gameAuthService.list(new LambdaQueryWrapper<GameAuth>()
-                .eq(!SecurityUtil.isAdmin(), GameAuth::getUserId, SecurityUtil.getUserId()));
+                .eq(!SecurityUtil.isAdmin(), GameAuth::getUserId, kfUserId));
         if (!SecurityUtil.isAdmin() && CollectionUtils.isEmpty(gameAuthList)) {
             return Collections.emptyList();
         }
@@ -115,26 +115,29 @@ public class KfRoomServiceImpl extends ServiceImpl<KfRoomMapper, KfRoom> impleme
                 .in(!SecurityUtil.isAdmin(), GameApplet::getGameId,
                         gameAuthList.stream().map(GameAuth::getGameId).collect(Collectors.toSet()))
                 .eq(GameApplet::getType, 1)
-        ).stream().map(this::transform).collect(Collectors.toList());
+        ).stream().map(gameApplet -> this.transform(gameApplet, kfUserId)).collect(Collectors.toList());
     }
 
     @Override
-    public List<KfWebSocketMsgDTO.GameBean> getKfGameByGameId(Long gameId) {
+    public List<KfWebSocketMsgDTO.GameBean> getKfGameByGameId(Long gameId, Long kfUserId) {
         GameApplet gameApplet = gameAppletService.getOne(new LambdaQueryWrapper<GameApplet>()
                 .eq(GameApplet::getGameId, gameId));
         if (gameApplet == null) {
             return Collections.emptyList();
         }
-        return Collections.singletonList(this.transform(gameApplet));
+        return Collections.singletonList(this.transform(gameApplet, kfUserId));
     }
 
-    private KfWebSocketMsgDTO.GameBean transform(GameApplet gameApplet) {
+    private KfWebSocketMsgDTO.GameBean transform(GameApplet gameApplet, Long kfUserId) {
         if (gameApplet == null) {
             return null;
         }
         int unReadMsgCount = kfRoomMsgService.count(new LambdaQueryWrapper<KfRoomMsg>()
                 .eq(KfRoomMsg::getGameId, gameApplet.getGameId())
                 .eq(KfRoomMsg::getReadStatus, Boolean.FALSE)
+                .and(qw -> qw.eq(KfRoomMsg::getKfUserId, kfUserId)
+                        .or().isNull(KfRoomMsg::getRoomId)
+                )
                 .ne(KfRoomMsg::getMsgOwner, KfRoomMsgOwnerEnum.KF_MSG_OWNER_SYSTEM.getValue()));
         KfWebSocketMsgDTO.GameBean gameBean = BeanUtil.copy(gameApplet, KfWebSocketMsgDTO.GameBean.class);
         gameBean.setUnReadMsgCount(unReadMsgCount);
@@ -175,7 +178,7 @@ public class KfRoomServiceImpl extends ServiceImpl<KfRoomMapper, KfRoom> impleme
         int unReadMsgCount = kfRoomMsgService.count(new LambdaQueryWrapper<KfRoomMsg>()
                 .eq(KfRoomMsg::getRoomId, kfRoom.getId())
                 .eq(KfRoomMsg::getReadStatus, Boolean.FALSE)
-                .ne(KfRoomMsg::getMsgOwner, KfRoomMsgOwnerEnum.KF_MSG_OWNER_SYSTEM.getValue()));
+                .eq(KfRoomMsg::getMsgOwner, KfRoomMsgOwnerEnum.KF_MSG_OWNER_USER.getValue()));
         roomBean.setUnReadMsgCount(unReadMsgCount);
         //最后一条消息
         KfRoomMsg kfRoomMsg = kfRoomMsgService.getOne(new LambdaQueryWrapper<KfRoomMsg>()

+ 11 - 1
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/websocket/KfMsgRedisListener.java

@@ -1,6 +1,8 @@
 package com.zanxiang.game.module.manage.websocket;
 
+import com.zanxiang.game.module.manage.enums.KfWebSocketMsgEnum;
 import com.zanxiang.game.module.manage.pojo.dto.KfWebSocketMsgDTO;
+import com.zanxiang.game.module.manage.service.IKfRoomService;
 import com.zanxiang.module.util.JsonUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -10,8 +12,8 @@ import org.springframework.stereotype.Component;
 import org.springframework.web.socket.TextMessage;
 import org.springframework.web.socket.WebSocketSession;
 
-import java.io.IOException;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * @author : lingfeng
@@ -25,6 +27,9 @@ public class KfMsgRedisListener implements MessageListener {
     @Autowired
     private KfMsgWebSocketSessionRegistry kfMsgWebSocketSessionRegistry;
 
+    @Autowired
+    private IKfRoomService kfRoomService;
+
     @Override
     public void onMessage(Message message, byte[] pattern) {
         //从redis中拿到的消息
@@ -53,6 +58,11 @@ public class KfMsgRedisListener implements MessageListener {
         openSessions.forEach(session -> {
             if (session != null && session.isOpen()) {
                 try {
+                    //待接入的游戏消息, 设置个人游戏列表
+                    if (Objects.equals(kfWebSocketMsgDTO.getWebSocketMsgType(), KfWebSocketMsgEnum.WEBSOCKET_MSG_WAIT_LIST)) {
+                        Long finalKfUserId = Long.valueOf(session.getAttributes().get("kfUserId").toString());
+                        kfWebSocketMsgDTO.setGameList(kfRoomService.getKfGameByGameId(kfWebSocketMsgDTO.getGameId(), finalKfUserId));
+                    }
                     session.sendMessage(new TextMessage(JsonUtil.toString(kfWebSocketMsgDTO)));
                 } catch (Exception e) {
                     log.error("发送消息给所有客服异常, kfUserId : {}, kfWebSocketMsgDTO : {}, e : {}",

+ 22 - 11
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/websocket/KfMsgWebsocketHandler.java

@@ -300,11 +300,21 @@ public class KfMsgWebsocketHandler implements WebSocketHandler {
     }
 
     private void kfFinishSession(WebSocketSession session, KfWebSocketMsgEnum webSocketMsgType, Long gameId, Long roomId) {
+        //查询房间信息
+        KfRoom kfRoom = kfRoomService.getById(roomId);
+        if (kfRoom == null) {
+            this.sendMessage(session, KfWebSocketMsgDTO.fail(webSocketMsgType, "参数错误,房间信息不存在"));
+            return;
+        }
         //房间在线状态更新
         kfRoomService.update(new LambdaUpdateWrapper<KfRoom>()
                 .set(KfRoom::getOnline, Boolean.FALSE)
                 .set(KfRoom::getUpdateTime, LocalDateTime.now())
                 .eq(KfRoom::getId, roomId));
+        //玩家信息更新
+        kfSessionUserService.update(new LambdaUpdateWrapper<KfSessionUser>()
+                .set(KfSessionUser::getUpdateTime, LocalDateTime.now())
+                .eq(KfSessionUser::getOpenId, kfRoom.getOpenId()));
         //推送完整的已链接房间列表
         List<KfWebSocketMsgDTO.RoomBean> onlineRoomList = kfRoomService.getOnlineRoomList(gameId);
         this.sendMessage(session, KfWebSocketMsgDTO.builder()
@@ -339,7 +349,7 @@ public class KfMsgWebsocketHandler implements WebSocketHandler {
         //房间信息设置
         List<KfWebSocketMsgDTO.RoomBean> roomList = kfRoomService.getRoomByRoomId(param.getRoomId());
         //游戏列表
-        List<KfWebSocketMsgDTO.GameBean> gameList = kfRoomService.getKfGameByGameId(param.getGameId());
+        List<KfWebSocketMsgDTO.GameBean> gameList = kfRoomService.getKfGameByGameId(param.getGameId(), SecurityUtil.getUserId());
         //发送消息
         this.sendMessage(session, KfWebSocketMsgDTO.builder()
                 .webSocketMsgType(param.getWebSocketMsgType())
@@ -361,25 +371,26 @@ public class KfMsgWebsocketHandler implements WebSocketHandler {
         }
         //触发玩家接入线程锁
         if (!distributedLockComponent.doLock(RedisKeyConstant.KF_MSG_USER_CONNECT_JOIN + param.getOpenId(),
-                0L, 1L, TimeUnit.MINUTES)) {
-            this.sendMessage(session, KfWebSocketMsgDTO.fail(param.getWebSocketMsgType(),
-                    "玩家已被其他客服接入, param : " + JsonUtil.toString(param)));
+                0L, 5L, TimeUnit.MINUTES)) {
+            this.sendMessage(session, KfWebSocketMsgDTO.fail(param.getWebSocketMsgType(), "玩家已被其他客服接入"));
             return;
         }
-        //玩家更新
+        //玩家信息, 判断玩家是否已经被接入
+        KfSessionUser kfSessionUser = kfSessionUserService.getById(param.getOpenId());
+        if (!kfSessionUser.getIsWait()) {
+            this.sendMessage(session, KfWebSocketMsgDTO.fail(param.getWebSocketMsgType(), "玩家已被其他客服接入"));
+            return;
+        }
+        //玩家更新为已接入
         kfSessionUserService.update(new LambdaUpdateWrapper<KfSessionUser>()
                 .set(KfSessionUser::getIsWait, Boolean.FALSE)
                 .set(KfSessionUser::getUpdateTime, LocalDateTime.now())
-                .eq(KfSessionUser::getOpenId, param.getOpenId())
-        );
-        //玩家信息
-        KfSessionUser kfSessionUser = kfSessionUserService.getById(param.getOpenId());
+                .eq(KfSessionUser::getOpenId, param.getOpenId()));
         //房间更新
         Long roomId = kfRoomService.userJoinRoom(param.getOpenId(), param.getGameId());
-        //玩家未读消息更新到房间
+        //玩家未读消息, 系统消息更新到房间
         kfRoomMsgService.update(new LambdaUpdateWrapper<KfRoomMsg>()
                 .set(KfRoomMsg::getRoomId, roomId)
-                .set(KfRoomMsg::getUserId, kfSessionUser == null ? null : kfSessionUser.getUserId())
                 .set(KfRoomMsg::getKfUserId, SecurityUtil.getUserId())
                 .set(KfRoomMsg::getUpdateTime, LocalDateTime.now())
                 .eq(KfRoomMsg::getOpenId, param.getOpenId())

+ 0 - 42
game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/entity/KfLink.java

@@ -1,42 +0,0 @@
-package com.zanxiang.game.module.mybatis.entity;
-
-import com.baomidou.mybatisplus.annotation.TableName;
-import lombok.*;
-
-import java.time.LocalDateTime;
-
-/**
- * @author : lingfeng
- * @time : 2023-12-06
- * @description : 客服链接
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@ToString
-@Builder
-@TableName("t_kf_link")
-public class KfLink {
-
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 应用id
-     */
-    private String appId;
-
-    /**
-     * 第三方客服链接
-     */
-    private String customLink;
-
-    /**
-     * 创建时间
-     */
-    private LocalDateTime createTime;
-
-    /**
-     * 更新时间
-     */
-    private LocalDateTime updateTime;
-}

+ 0 - 83
game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/entity/KfMsgContent.java

@@ -1,83 +0,0 @@
-package com.zanxiang.game.module.mybatis.entity;
-
-import com.baomidou.mybatisplus.annotation.TableName;
-import lombok.*;
-
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
-/**
- * @author : lingfeng
- * @time : 2023-11-27
- * @description : 客服消息记录
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@ToString
-@Builder
-@TableName("t_kf_msg_content")
-public class KfMsgContent implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 消息id
-     */
-    private String msgId;
-
-    /**
-     * 消息类型
-     */
-    private Integer msgType;
-
-    /**
-     * 房间id
-     */
-    private String roomId;
-
-    /**
-     * 消息内容
-     */
-    private String msgKfContent;
-
-    /**
-     * 拓展信息
-     */
-    private String extraInfo;
-
-    /**
-     * 发送账号(客服消息才有值)
-     */
-    private String sendOpenAccount;
-
-    /**
-     * 发送者openid
-     */
-    private String sendOpenid;
-
-    /**
-     * 发送场景
-     */
-    private Integer sendScene;
-
-    /**
-     * session
-     */
-    private String sessionId;
-
-    /**
-     * 是否删除
-     */
-    private Integer isDelete;
-
-    /**
-     * 创建时间
-     */
-    private LocalDateTime createTime;
-
-    /**
-     * 更新时间
-     */
-    private LocalDateTime updateTime;
-}

+ 0 - 1
game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/entity/KfRoomMsg.java

@@ -48,7 +48,6 @@ public class KfRoomMsg {
      */
     private Long userId;
 
-
     /**
      * 客服id
      */

+ 0 - 12
game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/mapper/KfLinkMapper.java

@@ -1,12 +0,0 @@
-package com.zanxiang.game.module.mybatis.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.zanxiang.game.module.mybatis.entity.KfLink;
-
-/**
- * @author : lingfeng
- * @time : 2023-12-06
- * @description :  ${description}
- */
-public interface KfLinkMapper extends BaseMapper<KfLink> {
-}

+ 0 - 12
game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/mapper/KfMsgContentMapper.java

@@ -1,12 +0,0 @@
-package com.zanxiang.game.module.mybatis.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.zanxiang.game.module.mybatis.entity.KfMsgContent;
-
-/**
- * @author : lingfeng
- * @time : 2023-11-27
- * @description :  ${description}
- */
-public interface KfMsgContentMapper extends BaseMapper<KfMsgContent> {
-}

+ 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服务启动成功 <一大波修改> ( ´・・)ノ(._.`) \n" +
                 " ___________ _   __\n" +
                 "/  ___|  _  \\ | / /\n" +
                 "\\ `--.| | | | |/ / \n" +

+ 5 - 0
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/constant/RedisKeyConstant.java

@@ -62,4 +62,9 @@ public class RedisKeyConstant {
      */
     public static final String GAME_CUSTOM_PAY_SIGN = "game_sdk_manage_custom_pay_sign_";
 
+    /**
+     * 获取支付参数锁
+     */
+    public static final String GET_PAY_PARAM_LOCK = RedisKeyConstant.REDIS_PREFIX + "get_pay_param_lock_";
+
 }

+ 49 - 0
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/enums/KafkaEventTrackEnum.java

@@ -0,0 +1,49 @@
+package com.zanxiang.game.module.sdk.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author : lingfeng
+ * @time : 2024-03-07
+ * @description : 卡夫卡数据埋点类型
+ */
+@Getter
+@AllArgsConstructor
+public enum KafkaEventTrackEnum {
+
+    /**
+     * 注册
+     */
+    KAFKA_EVENT_TRACK_REG("KAFKA_EVENT_TRACK_REG"),
+
+    /**
+     * 登录
+     */
+    KAFKA_EVENT_TRACK_LOGIN("KAFKA_EVENT_TRACK_LOGIN"),
+
+    /**
+     * 下单
+     */
+    KAFKA_EVENT_TRACK_ORDER_CREATE("KAFKA_EVENT_TRACK_ORDER_CREATE"),
+
+    /**
+     * 支付
+     */
+    KAFKA_EVENT_TRACK_ORDER_PAY("KAFKA_EVENT_TRACK_ORDER_PAY"),
+
+    /**
+     * 创角
+     */
+    KAFKA_EVENT_TRACK_ROLE_CREATE("KAFKA_EVENT_TRACK_ROLE_CREATE"),
+
+    /**
+     * 角色更新
+     */
+    KAFKA_EVENT_TRACK_ROLE_UPDATE("KAFKA_EVENT_TRACK_ROLE_UPDATE");
+
+    /**
+     * 数据埋点类型
+     */
+    private String value;
+}

+ 2 - 2
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/enums/TokenCheckEnum.java

@@ -30,10 +30,10 @@ public enum TokenCheckEnum {
     /**
      * 支付方式
      */
-    private final Integer code;
+    private Integer code;
 
     /**
      * 支付类前缀
      */
-    private final String msg;
+    private String msg;
 }

+ 8 - 0
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/listener/OrderPaySuccessListener.java

@@ -1,10 +1,13 @@
 package com.zanxiang.game.module.sdk.listener;
 
 import com.zanxiang.game.module.base.pojo.enums.PayDeviceEnum;
+import com.zanxiang.game.module.sdk.enums.KafkaEventTrackEnum;
 import com.zanxiang.game.module.sdk.pojo.dto.PlatformOrderDTO;
 import com.zanxiang.game.module.sdk.service.ICallBackService;
+import com.zanxiang.game.module.sdk.service.IKafkaService;
 import com.zanxiang.game.module.sdk.service.IOrderService;
 import com.zanxiang.game.module.sdk.service.IPerformOrderService;
+import com.zanxiang.module.util.JsonUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.logging.log4j.util.Strings;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -27,6 +30,9 @@ import java.util.Objects;
 @Slf4j
 public class OrderPaySuccessListener {
 
+    @Autowired
+    private IKafkaService kafkaService;
+
     @Resource
     private IOrderService orderService;
 
@@ -69,6 +75,8 @@ public class OrderPaySuccessListener {
         }
         //订单回传
         callBackService.orderCallBack(platformOrderDTO);
+        //订单支付埋点数据发送到卡夫卡
+        kafkaService.eventTrack(KafkaEventTrackEnum.KAFKA_EVENT_TRACK_ORDER_PAY, JsonUtil.toString(platformOrderDTO));
         log.info("订单:{} 支付成功履约监听逻辑 ------end---------", event.getOrderId());
     }
 }

+ 6 - 0
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/pojo/dto/PlatformOrderDTO.java

@@ -121,6 +121,12 @@ public class PlatformOrderDTO {
      */
     private String merchantOrderNo;
 
+    /**
+     * 米大师商户订单号
+     * PS : 微信和支付宝都是以业务订单号作为商户订单号, 只有米大师个狗东西不一样, 独有字段
+     */
+    private String miPayMerchantNo;
+
     /**
      * 收款商户号
      */

+ 29 - 0
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/IKafkaService.java

@@ -0,0 +1,29 @@
+package com.zanxiang.game.module.sdk.service;
+
+import com.zanxiang.game.module.sdk.enums.KafkaEventTrackEnum;
+import com.zanxiang.game.module.sdk.pojo.param.GameRoleActiveCallParam;
+import com.zanxiang.game.module.sdk.pojo.param.UserData;
+
+/**
+ * @author : lingfeng
+ * @time : 2024-03-07
+ * @description : 卡夫卡队列
+ */
+public interface IKafkaService {
+
+    /**
+     * 埋点数据发送到卡夫卡
+     *
+     * @param eventTrackEnum : 埋点类型key
+     * @param data           : 数据
+     */
+    void eventTrack(KafkaEventTrackEnum eventTrackEnum, String data);
+
+    /**
+     * 角色活跃信息发送到卡夫卡
+     *
+     * @param userData : 用户信息
+     * @param param    : 提交参数
+     */
+    void roleActiveTrack(UserData userData, GameRoleActiveCallParam param);
+}

+ 76 - 73
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/GameUserRoleServiceImpl.java

@@ -10,20 +10,16 @@ import com.zanxiang.game.module.mybatis.entity.User;
 import com.zanxiang.game.module.mybatis.mapper.GameUserRoleMapper;
 import com.zanxiang.game.module.sdk.constant.RedisKeyConstant;
 import com.zanxiang.game.module.sdk.enums.DataTypeEnum;
+import com.zanxiang.game.module.sdk.enums.KafkaEventTrackEnum;
 import com.zanxiang.game.module.sdk.enums.LoginTypeEnum;
 import com.zanxiang.game.module.sdk.pojo.param.GameRoleActiveCallParam;
 import com.zanxiang.game.module.sdk.pojo.param.GameUserRoleUpdateParam;
 import com.zanxiang.game.module.sdk.pojo.param.UserData;
 import com.zanxiang.game.module.sdk.service.*;
 import com.zanxiang.module.redis.service.IDistributedLockComponent;
-import com.zanxiang.module.util.DateUtil;
 import com.zanxiang.module.util.JsonUtil;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.kafka.clients.producer.Producer;
-import org.apache.kafka.clients.producer.ProducerRecord;
-import org.apache.logging.log4j.util.Strings;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -41,36 +37,32 @@ import java.util.concurrent.TimeUnit;
 @Service
 public class GameUserRoleServiceImpl extends ServiceImpl<GameUserRoleMapper, GameUserRole> implements IGameUserRoleService {
 
-    @Autowired
-    private RestTemplate restTemplate;
-
-    @Autowired
-    private IGameUserService gameUserService;
+    @Value("${server.domain}")
+    private String serverUrl;
 
     @Autowired
     private IUserService userService;
 
     @Autowired
-    private IUserLoginLogService userLoginLogService;
+    private IKafkaService kafkaService;
 
     @Autowired
-    private IDistributedLockComponent distributedLockComponent;
+    private RestTemplate restTemplate;
 
     @Autowired
-    private IUserTokenService userTokenService;
+    private IGameUserService gameUserService;
 
     @Autowired
     private ICallBackService callBackService;
 
-    @Value("${spring.kafka.game-sdk.gameRoleActiveTopic}")
-    private String gameRoleActiveTopic;
+    @Autowired
+    private IUserTokenService userTokenService;
 
-    @Value("${server.domain}")
-    private String serverUrl;
+    @Autowired
+    private IUserLoginLogService userLoginLogService;
 
     @Autowired
-    @Qualifier("gameSdkKafkaProducer")
-    private Producer<String, String> kafkaProducer;
+    private IDistributedLockComponent distributedLockComponent;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -84,7 +76,7 @@ public class GameUserRoleServiceImpl extends ServiceImpl<GameUserRoleMapper, Gam
         //创建角色
         if (Objects.equals(dataType, DataTypeEnum.TYPE_CREATE_ROLE.getDateType())) {
             //新建游戏角色
-            this.createRoleUpdate(param, userData);
+            this.gameRoleCreate(param, userData);
             //插入用户登录记录
             return userLoginLogService.createRoleLoginLog(userData, param.getRoleId(), param.getRoleName(), LoginTypeEnum.LOGIN_IN.getLoginType());
         }
@@ -96,7 +88,11 @@ public class GameUserRoleServiceImpl extends ServiceImpl<GameUserRoleMapper, Gam
         //逻辑兜底, 万一角色未创建成功, 补充创建
         if (gameUserRole == null) {
             //新建游戏角色
-            this.createRoleUpdate(param, userData);
+            this.gameRoleCreate(param, userData);
+            //刚创建的角色, 如果是更新请求, 则不需要执行
+            if (Objects.equals(dataType, DataTypeEnum.TYPE_LEVEL_UP.getDateType())) {
+                return Boolean.TRUE;
+            }
         }
         //进入游戏
         if (Objects.equals(dataType, DataTypeEnum.TYPE_ENTER_GAME.getDateType())) {
@@ -105,22 +101,7 @@ public class GameUserRoleServiceImpl extends ServiceImpl<GameUserRoleMapper, Gam
         }
         //等级提升更新
         if (Objects.equals(dataType, DataTypeEnum.TYPE_LEVEL_UP.getDateType())) {
-            //更新频率限制, 20秒更新一次, 避免游戏实时战力高频上报
-            if (!distributedLockComponent.doLock(RedisKeyConstant.ROLE_LEVEL_UP + userData.getUserId(), 0L, 20L, TimeUnit.SECONDS)) {
-                return Boolean.TRUE;
-            }
-            return super.update(new LambdaUpdateWrapper<GameUserRole>()
-                    .set(GameUserRole::getRoleName, param.getRoleName())
-                    .set(GameUserRole::getRoleLevel, param.getRoleLevel())
-                    .set(gameUserRole == null || Strings.isBlank(gameUserRole.getServerId()), GameUserRole::getServerId, param.getServerId())
-                    .set(GameUserRole::getServerName, param.getServerName())
-                    .set(param.getRoleVipLevel() != null, GameUserRole::getRoleVipLevel, param.getRoleVipLevel())
-                    .set(param.getRolePower() != null, GameUserRole::getRolePower, param.getRolePower())
-                    .set(GameUserRole::getUpdateTime, param.getRoleGradeUpdateTime() == null || param.getRoleGradeUpdateTime() <= 0 ? LocalDateTime.now() : DateUtil.secondToLocalDateTime(param.getRoleGradeUpdateTime()))
-                    .set(param.getExtra() != null, GameUserRole::getExtra, JsonUtil.toString(param.getExtra()))
-                    .eq(GameUserRole::getUserId, userData.getUserId())
-                    .eq(GameUserRole::getGameId, userData.getGameId())
-                    .eq(GameUserRole::getRoleId, param.getRoleId()));
+            return this.gameRoleUpdate(param, gameUserRole, userData);
         }
         //退出游戏
         if (Objects.equals(dataType, DataTypeEnum.TYPE_EXIT_GAME.getDateType())) {
@@ -130,7 +111,35 @@ public class GameUserRoleServiceImpl extends ServiceImpl<GameUserRoleMapper, Gam
         return Boolean.FALSE;
     }
 
-    private void createRoleUpdate(GameUserRoleUpdateParam param, UserData userData) {
+    private boolean gameRoleUpdate(GameUserRoleUpdateParam param, GameUserRole gameUserRole, UserData userData) {
+        //更新频率限制, 20秒更新一次, 避免游戏实时战力高频上报
+        if (!distributedLockComponent.doLock(RedisKeyConstant.ROLE_LEVEL_UP + userData.getUserId(), 0L, 20L, TimeUnit.SECONDS)) {
+            return Boolean.TRUE;
+        }
+        //玩家角色信息更新
+        if (gameUserRole.getServerId() == null) {
+            gameUserRole.setServerId(param.getServerId());
+        }
+        if (param.getRoleVipLevel() != null) {
+            gameUserRole.setRoleVipLevel(param.getRoleVipLevel());
+        }
+        if (param.getRolePower() != null) {
+            gameUserRole.setRolePower(param.getRolePower());
+        }
+        if (param.getExtra() != null) {
+            gameUserRole.setExtra(JsonUtil.toString(param.getExtra()));
+        }
+        gameUserRole.setRoleName(param.getRoleName());
+        gameUserRole.setRoleLevel(param.getRoleLevel());
+        gameUserRole.setServerName(param.getServerName());
+        gameUserRole.setUpdateTime(LocalDateTime.now());
+        boolean result = super.updateById(gameUserRole);
+        //角色更新数据埋点发送到卡夫卡
+        kafkaService.eventTrack(KafkaEventTrackEnum.KAFKA_EVENT_TRACK_ROLE_UPDATE, JsonUtil.toString(gameUserRole));
+        return result;
+    }
+
+    private void gameRoleCreate(GameUserRoleUpdateParam param, UserData userData) {
         //上锁
         if (!distributedLockComponent.doLock(RedisKeyConstant.ROLE_UPDATE_KEY + "_" + userData.getUserId(), 0L, 1L, TimeUnit.MINUTES)) {
             return;
@@ -148,7 +157,28 @@ public class GameUserRoleServiceImpl extends ServiceImpl<GameUserRoleMapper, Gam
             return;
         }
         User user = userService.getById(userData.getUserId());
-        userRole = GameUserRole.builder()
+        userRole = this.transform(param, userData, gameUser, user);
+        super.save(userRole);
+        //更新玩家创角数
+        gameUserService.update(new LambdaUpdateWrapper<GameUser>()
+                .setSql("role_count=role_count+" + 1)
+                .set(GameUser::getUpdateTime, LocalDateTime.now())
+                .eq(GameUser::getId, gameUser.getId()));
+        //更新用户创角数
+        userService.update(new LambdaUpdateWrapper<User>()
+                .setSql("role_count=role_count+" + 1)
+                .set(User::getUpdateTime, LocalDateTime.now())
+                .eq(User::getId, gameUser.getUserId()));
+        //用户创角回传
+        callBackService.roleCallBack(userRole, userData);
+        //用户创角埋点数据发送到卡夫卡
+        kafkaService.eventTrack(KafkaEventTrackEnum.KAFKA_EVENT_TRACK_ROLE_CREATE, JsonUtil.toString(userRole));
+        //释放锁
+        distributedLockComponent.unlock(RedisKeyConstant.ROLE_UPDATE_KEY + "_" + userData.getUserId());
+    }
+
+    private GameUserRole transform(GameUserRoleUpdateParam param, UserData userData, GameUser gameUser, User user) {
+        return GameUserRole.builder()
                 .userId(userData.getUserId())
                 .gameUserId(gameUser.getId())
                 .gameId(userData.getGameId())
@@ -161,26 +191,11 @@ public class GameUserRoleServiceImpl extends ServiceImpl<GameUserRoleMapper, Gam
                 .rolePower(param.getRolePower())
                 .os(userData.getDeviceSystem())
                 .regTime(user == null ? null : user.getCreateTime())
-                .createTime(param.getRoleGradeUpdateTime() == null || param.getRoleGradeUpdateTime() <= 0 ? LocalDateTime.now() : DateUtil.secondToLocalDateTime(param.getRoleGradeUpdateTime()))
+                .createTime(LocalDateTime.now())
                 .updateTime(LocalDateTime.now())
                 .lastLoginTime(LocalDateTime.now())
                 .extra(param.getExtra() == null ? null : JsonUtil.toString(param.getExtra()))
                 .build();
-        super.save(userRole);
-        //更新玩家创角数
-        gameUserService.update(new LambdaUpdateWrapper<GameUser>()
-                .setSql("role_count=role_count+" + 1)
-                .set(GameUser::getUpdateTime, LocalDateTime.now())
-                .eq(GameUser::getId, gameUser.getId()));
-        //更新用户创角数
-        userService.update(new LambdaUpdateWrapper<User>()
-                .setSql("role_count=role_count+" + 1)
-                .set(User::getUpdateTime, LocalDateTime.now())
-                .eq(User::getId, gameUser.getUserId()));
-        //用户创角回传
-        callBackService.roleCallBack(userRole, userData);
-        //释放锁
-        distributedLockComponent.unlock(RedisKeyConstant.ROLE_UPDATE_KEY + "_" + userData.getUserId());
     }
 
     @Override
@@ -255,29 +270,17 @@ public class GameUserRoleServiceImpl extends ServiceImpl<GameUserRoleMapper, Gam
 
     @Override
     public boolean gameRoleActiveCall(UserData userData, GameRoleActiveCallParam param) {
-        //token临期失效判断
-        try {
-            userTokenService.userTokenUpdateCheck(userData);
-        } catch (Exception ignored) {
-        }
-        //测试环境不使用kafka
+        //测试不执行
         if (this.serverUrl.contains("test")) {
             return Boolean.TRUE;
         }
-        //活跃提交
-        Map<String, Object> activeParamMap = new HashMap<>(6);
-        activeParamMap.put("userId", userData.getUserId());
-        activeParamMap.put("gameId", userData.getGameId());
-        activeParamMap.put("serverId", param.getServerId());
-        activeParamMap.put("roleId", param.getRoleId());
-        activeParamMap.put("roleLevel", param.getRoleLevel());
-        activeParamMap.put("activeTime", System.currentTimeMillis());
+        //token临期失效判断
         try {
-            kafkaProducer.send(new ProducerRecord<>(gameRoleActiveTopic, userData.getUserId().toString(), JsonUtil.toString(activeParamMap)));
-        } catch (Exception e) {
-            log.error("用户角色活跃信息发送到 Kafka 异常!, activeParamMap : {}, e : {}", JsonUtil.toString(activeParamMap), e.getMessage());
-            return Boolean.FALSE;
+            userTokenService.userTokenUpdateCheck(userData);
+        } catch (Exception ignored) {
         }
+        //活跃信息发送到卡夫卡
+        kafkaService.roleActiveTrack(userData, param);
         return Boolean.TRUE;
     }
 }

+ 65 - 0
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/KafkaServiceImpl.java

@@ -0,0 +1,65 @@
+package com.zanxiang.game.module.sdk.service.impl;
+
+import com.zanxiang.game.module.sdk.enums.KafkaEventTrackEnum;
+import com.zanxiang.game.module.sdk.pojo.param.GameRoleActiveCallParam;
+import com.zanxiang.game.module.sdk.pojo.param.UserData;
+import com.zanxiang.game.module.sdk.service.IKafkaService;
+import com.zanxiang.module.util.JsonUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.kafka.clients.producer.Producer;
+import org.apache.kafka.clients.producer.ProducerRecord;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author : lingfeng
+ * @time : 2024-03-07
+ * @description : 卡夫卡队列
+ */
+@Slf4j
+@Service
+public class KafkaServiceImpl implements IKafkaService {
+
+    @Value("${spring.kafka.game-sdk.gameRoleActiveTopic}")
+    private String gameRoleActiveTopic;
+
+    @Value("${spring.kafka.game-sdk.gameEventTrackTopic}")
+    private String gameEventTrackTopic;
+
+    @Autowired
+    @Qualifier("gameSdkKafkaProducer")
+    private Producer<String, String> kafkaProducer;
+
+    @Override
+    public void eventTrack(KafkaEventTrackEnum eventTrackEnum, String data) {
+        try {
+            kafkaProducer.send(new ProducerRecord<>(this.gameEventTrackTopic, eventTrackEnum.getValue(), data));
+        } catch (Exception e) {
+            log.error("玩家数据埋点发送到 Kafka 异常!, eventTrackTopic : {}, eventTrackEnum : {}, data : {}, e : {}",
+                    this.gameEventTrackTopic, eventTrackEnum.getValue(), data, e.getMessage());
+        }
+    }
+
+    @Override
+    public void roleActiveTrack(UserData userData, GameRoleActiveCallParam param) {
+        //活跃提交
+        Map<String, Object> activeParamMap = new HashMap<>(6);
+        activeParamMap.put("userId", userData.getUserId());
+        activeParamMap.put("gameId", userData.getGameId());
+        activeParamMap.put("serverId", param.getServerId());
+        activeParamMap.put("roleId", param.getRoleId());
+        activeParamMap.put("roleLevel", param.getRoleLevel());
+        activeParamMap.put("activeTime", System.currentTimeMillis());
+        try {
+            kafkaProducer.send(new ProducerRecord<>(this.gameRoleActiveTopic, userData.getUserId().toString(), JsonUtil.toString(activeParamMap)));
+        } catch (Exception e) {
+            log.error("玩家角色活跃信息发送到 Kafka 异常!, eventTrackTopic : {}, data : {}, e : {}",
+                    this.gameRoleActiveTopic, JsonUtil.toString(activeParamMap), e.getMessage());
+        }
+    }
+}

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

@@ -9,6 +9,7 @@ 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.sdk.constant.RedisKeyConstant;
+import com.zanxiang.game.module.sdk.enums.KafkaEventTrackEnum;
 import com.zanxiang.game.module.sdk.enums.LoginTypeEnum;
 import com.zanxiang.game.module.sdk.enums.SmsTypeEnum;
 import com.zanxiang.game.module.sdk.pojo.dto.GameAppletDTO;
@@ -91,6 +92,9 @@ public class LoginServiceImpl implements IRegisterLoginService {
     @Autowired
     private IAgentService agentService;
 
+    @Autowired
+    private IKafkaService kafkaService;
+
     @Autowired
     private IGameAppletShellService gameAppletShellService;
 
@@ -306,6 +310,8 @@ public class LoginServiceImpl implements IRegisterLoginService {
                 .createTime(LocalDateTime.now())
                 .updateTime(LocalDateTime.now())
                 .build());
+        //注册信息埋点数据发送到卡夫卡
+        kafkaService.eventTrack(KafkaEventTrackEnum.KAFKA_EVENT_TRACK_REG, JsonUtil.toString(user));
         //释放锁
         distributedLockComponent.unlock(lockKey);
         return user;
@@ -332,9 +338,12 @@ public class LoginServiceImpl implements IRegisterLoginService {
     }
 
     private UserLoginVO createUserLoginVO(User user, UserData userData) {
-        //补全 userData 中的用户id
+        //注册, 补全 userData 中的用户id
         if (userData.getUserId() == null) {
             userData.setUserId(user.getId());
+        } else {
+            //登录, 发送登录埋点数据到卡夫卡
+            kafkaService.eventTrack(KafkaEventTrackEnum.KAFKA_EVENT_TRACK_LOGIN, JsonUtil.toString(user));
         }
         //获取token
         String userToken = userTokenService.getUserToken(user.getId(), userData.getDeviceType());

+ 21 - 5
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/OrderPayServiceImpl.java

@@ -20,6 +20,7 @@ import com.zanxiang.game.module.sdk.service.*;
 import com.zanxiang.game.module.sdk.service.pay.PayBaseService;
 import com.zanxiang.game.module.sdk.util.RedisUtil;
 import com.zanxiang.game.module.sdk.util.SpringUtils;
+import com.zanxiang.module.redis.service.IDistributedLockComponent;
 import com.zanxiang.module.util.JsonUtil;
 import com.zanxiang.module.util.bean.BeanUtil;
 import com.zanxiang.module.util.exception.BaseException;
@@ -36,6 +37,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.concurrent.TimeUnit;
 
 /**
  * @author : lingfeng
@@ -64,6 +66,9 @@ public class OrderPayServiceImpl implements IOrderPayService {
     @Autowired
     private RedisUtil<String> redisUtil;
 
+    @Autowired
+    private IDistributedLockComponent distributedLockComponent;
+
     @Value("${payConfig.wxPay.customH5Url}")
     private String customH5Url;
 
@@ -83,11 +88,7 @@ public class OrderPayServiceImpl implements IOrderPayService {
             return BeanUtil.copy(orderPayParam, PayParamVO.class);
         }
         //创建支付参数
-        ProductPayParamDTO productPayParamDTO = this.transform(order, code, openId, IpUtil.getRealIp(request));
-        //调起支付
-        PayTypeEnum payTypeEnum = PayTypeEnum.getByPayType(productPayParamDTO.getPayWay().intValue());
-        PayBaseService service = SpringUtils.getBean(payTypeEnum.getClazz());
-        service.payCreate(productPayParamDTO);
+        this.payParamCreate(code, openId, order, request);
         //重新查询
         orderPayParam = orderPayParamService.getOne(new LambdaQueryWrapper<OrderPayParam>()
                 .eq(OrderPayParam::getOrderId, order.getOrderId()));
@@ -99,6 +100,21 @@ public class OrderPayServiceImpl implements IOrderPayService {
         return BeanUtil.copy(orderPayParam, PayParamVO.class);
     }
 
+    private void payParamCreate(String code, String openId, Order order, HttpServletRequest request) {
+        //上锁
+        if (!distributedLockComponent.doLock(RedisKeyConstant.GET_PAY_PARAM_LOCK + order.getOrderId(), 0L, 1L, TimeUnit.MINUTES)) {
+            return;
+        }
+        //创建支付参数
+        ProductPayParamDTO productPayParamDTO = this.transform(order, code, openId, IpUtil.getRealIp(request));
+        //调起支付
+        PayTypeEnum payTypeEnum = PayTypeEnum.getByPayType(productPayParamDTO.getPayWay().intValue());
+        PayBaseService service = SpringUtils.getBean(payTypeEnum.getClazz());
+        service.payCreate(productPayParamDTO);
+        //释放锁
+        distributedLockComponent.unlock(RedisKeyConstant.GET_PAY_PARAM_LOCK + order.getOrderId());
+    }
+
     private ProductPayParamDTO transform(Order order, String code, String openId, String ip) {
         return ProductPayParamDTO.builder()
                 .gameId(order.getGameId())

+ 6 - 0
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/OrderServiceImpl.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.zanxiang.game.back.base.pojo.enums.OrderStatusEnum;
 import com.zanxiang.game.module.mybatis.entity.*;
 import com.zanxiang.game.module.mybatis.mapper.OrderMapper;
+import com.zanxiang.game.module.sdk.enums.KafkaEventTrackEnum;
 import com.zanxiang.game.module.sdk.pojo.dto.GamePayWayDTO;
 import com.zanxiang.game.module.sdk.pojo.dto.PlatformOrderDTO;
 import com.zanxiang.game.module.sdk.pojo.param.ProductPayParam;
@@ -35,6 +36,9 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
     @Autowired
     private IGameService gameService;
 
+    @Autowired
+    private IKafkaService kafkaService;
+
     @Autowired
     private IGameUserService gameUserService;
 
@@ -78,6 +82,8 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
         payParam.setOrderId(orderNum);
         //订单回传
         callBackService.orderCallBack(BeanUtil.copy(order, PlatformOrderDTO.class));
+        //下单数据埋点发送到卡夫卡
+        kafkaService.eventTrack(KafkaEventTrackEnum.KAFKA_EVENT_TRACK_ORDER_CREATE, JsonUtil.toString(order));
         //返回
         return Boolean.TRUE;
     }