Browse Source

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

zhimo 10 months ago
parent
commit
3efd341639
100 changed files with 5580 additions and 479 deletions
  1. 113 0
      game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/dto/TencentOrderAppRpcDTO.java
  2. 84 0
      game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/dto/TencentRoleRegisterAppRpcDTO.java
  3. 82 0
      game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/dto/TencentUserAppRpcDTO.java
  4. 35 0
      game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/dto/TtAppOrderBackQueryRpcDTO.java
  5. 34 0
      game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/dto/TtAppRoleRegisterBackQueryRpcDTO.java
  6. 31 0
      game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/dto/TtAppUserBackQueryRpcDTO.java
  7. 92 0
      game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/dto/TtOrderAppRpcDTO.java
  8. 77 0
      game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/dto/TtRoleRegisterAppRpcDTO.java
  9. 73 0
      game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/dto/TtUserActiveAppRpcDTO.java
  10. 25 0
      game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/vo/OrderBackQueryRpcVO.java
  11. 21 0
      game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/rpc/ITencentAppBackRpc.java
  12. 44 0
      game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/rpc/ITtAppBackRpc.java
  13. 6 0
      game-back/game-back-serve/pom.xml
  14. 27 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/config/KafkaConfig.java
  15. 3 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/config/NacosDynamicParamConfig.java
  16. 33 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/controller/api/OceanengineCallbackApi.java
  17. 36 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/controller/api/TencentCallbackApi.java
  18. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameOceanengineAppBackLogMapper.java
  19. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameOceanengineAppCallbackMapper.java
  20. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameOceanengineAppOrderLogMapper.java
  21. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameOceanengineAppRoleRegisterLogMapper.java
  22. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameOceanengineAppUserLogMapper.java
  23. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameTencentAppBackLogMapper.java
  24. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameTencentAppCallbackMapper.java
  25. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameTencentAppOrderMapper.java
  26. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameTencentAppOrderSplitLogMapper.java
  27. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameTencentAppRoleRegisterMapper.java
  28. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameTencentAppUserMapper.java
  29. 218 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/dto/GameOceanengineAppCallbackDTO.java
  30. 185 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/dto/GameTencentAppCallbackDTO.java
  31. 90 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameOceanengineAppBackLog.java
  32. 239 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameOceanengineAppCallback.java
  33. 134 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameOceanengineAppOrderLog.java
  34. 100 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameOceanengineAppRoleRegisterLog.java
  35. 90 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameOceanengineAppUserLog.java
  36. 111 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentAppBackLog.java
  37. 204 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentAppCallback.java
  38. 161 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentAppOrder.java
  39. 84 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentAppOrderSplitLog.java
  40. 117 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentAppRoleRegister.java
  41. 117 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentAppUser.java
  42. 212 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/rpc/impl/TencentAppBackRpcImpl.java
  43. 258 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/rpc/impl/TtAppBackRpcImpl.java
  44. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameOceanengineAppBackLogService.java
  45. 10 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameOceanengineAppCallbackService.java
  46. 15 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameOceanengineAppOrderLogService.java
  47. 9 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameOceanengineAppRoleRegisterLogService.java
  48. 9 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameOceanengineAppUserLogService.java
  49. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentAppBackLogService.java
  50. 10 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentAppCallbackService.java
  51. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentAppOrderService.java
  52. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentAppOrderSplitLogService.java
  53. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentAppRoleRegisterService.java
  54. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentAppUserService.java
  55. 14 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameOceanengineAppBackLogServiceImpl.java
  56. 44 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameOceanengineAppCallbackServiceImpl.java
  57. 336 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameOceanengineAppOrderLogServiceImpl.java
  58. 100 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameOceanengineAppRoleRegisterLogServiceImpl.java
  59. 73 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameOceanengineAppUserLogServiceImpl.java
  60. 14 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentAppBackLogServiceImpl.java
  61. 65 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentAppCallbackServiceImpl.java
  62. 14 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentAppOrderServiceImpl.java
  63. 14 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentAppOrderSplitLogServiceImpl.java
  64. 14 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentAppRoleRegisterServiceImpl.java
  65. 178 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentAppUserServiceImpl.java
  66. 53 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/task/CallbackClearTask.java
  67. 3 4
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/controller/GameMonitorAlarmController.java
  68. 12 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/RoleRechargeRankingDTO.java
  69. 26 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/vo/GameDataTotalTotalVO.java
  70. 26 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/vo/GameDataTotalVO.java
  71. 4 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/vo/GameMonitorAlarmVO.java
  72. 6 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/vo/PitcherDataDayTotalVO.java
  73. 8 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/vo/PitcherDataDayVO.java
  74. 9 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/vo/PitcherDataTotalSumVO.java
  75. 13 3
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/vo/PitcherDataTotalVO.java
  76. 2 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/IGameMonitorAlarmService.java
  77. 8 6
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/AdsOrderDetailServiceImpl.java
  78. 680 399
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/GameDataServiceImpl.java
  79. 124 23
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/GameMonitorAlarmServiceImpl.java
  80. 9 9
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/OrderCostMonitorAlarmBySmsServiceImpl.java
  81. 29 17
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/PitcherDataServiceImpl.java
  82. 8 4
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/RoleManageServiceImpl.java
  83. 2 2
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/task/OrderCostMonitorAlarmTask.java
  84. 15 1
      game-gs-data/game-gs-data-serve/pom.xml
  85. 23 0
      game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/GameGsDataApplication.java
  86. 11 0
      game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/config/MybatisFlexConfig.java
  87. 2 2
      game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/config/SwaggerConfig.java
  88. 33 0
      game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/controller/GameParentController.java
  89. 19 0
      game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/dao/mapper/erp/SysUserMapper.java
  90. 19 0
      game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/dao/mapper/game/order/GameAuthGroupMapper.java
  91. 19 0
      game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/dao/mapper/game/order/GameAuthRoleGroupMapper.java
  92. 19 0
      game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/dao/mapper/game/order/GameMapper.java
  93. 19 0
      game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/dao/mapper/game/order/GameServerMapper.java
  94. 19 0
      game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/dao/mapper/game/order/RoleOperateMapper.java
  95. 19 0
      game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/dao/mapper/game/parent/AdsRoleAmountDataParentMapper.java
  96. 19 0
      game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/dao/mapper/game/parent/AdsRoleAmountDataTodayParentMapper.java
  97. 98 0
      game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/handler/GlobalExceptionHandler.java
  98. 0 9
      game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/pojo/BTable.java
  99. 22 0
      game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/pojo/dto/BaseListDTO.java
  100. 28 0
      game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/pojo/dto/BigRDTO.java

+ 113 - 0
game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/dto/TencentOrderAppRpcDTO.java

@@ -0,0 +1,113 @@
+package com.zanxiang.game.back.base.pojo.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class TencentOrderAppRpcDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+    /**
+     * 回传策略ID
+     */
+    private Long backPolicyId;
+    /**
+     * sdk 里面的用户 id(要求唯一)
+     */
+    private String userId;
+    /**
+     * 游戏ID
+     */
+    private Long gameId;
+
+    /**
+     * 广告账号ID
+     */
+    private Long adAccountId;
+
+    /**
+     * 注册时间
+     */
+    private LocalDateTime registerTime;
+
+    /**
+     * 关注时间
+     */
+    private LocalDateTime subscribeTime;
+
+    /**
+     * 充值金额(分)
+     */
+    private Long rechargeMoney;
+
+    /**
+     * 充值时间
+     */
+    private LocalDateTime rechargeTime;
+
+    /**
+     * 订单ID
+     */
+    private String orderId;
+
+    /**
+     * 渠道号
+     */
+    private String channel;
+
+    /**
+     * 支付状态,0 : 预下单, 1 : 待支付,2 : 支付成功,-1 : 已取消
+     */
+    private Integer orderStatus;
+
+    /**
+     * 支付时间
+     */
+    private LocalDateTime payTime;
+
+    private String roleId;
+
+    private String roleName;
+
+    /**
+     * 数据源ID
+     */
+    private Long userActionSetId;
+
+    /**
+     * 用户设备mac地址
+     */
+    private String mac;
+
+    /**
+     * 设备唯一编号IMEI
+     */
+    private String imei;
+
+    /**
+     * 设备OAID
+     */
+    private String oaid;
+
+    /**
+     * 安卓id, (仅安卓设备才有值)
+     */
+    private String androidId;
+
+    /**
+     * IOS设备IDFA
+     */
+    private String idfa;
+
+    /**
+     * IOS设备CAID
+     */
+    private String caid;
+}

+ 84 - 0
game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/dto/TencentRoleRegisterAppRpcDTO.java

@@ -0,0 +1,84 @@
+package com.zanxiang.game.back.base.pojo.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class TencentRoleRegisterAppRpcDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+
+    /**
+     * 回传策略ID
+     */
+    private Long backPolicyId;
+    /**
+     * sdk 里面的用户 id(要求唯一)
+     */
+    private String userId;
+    /**
+     * 游戏ID
+     */
+    private Long gameId;
+
+    /**
+     * 广告账号ID
+     */
+    private Long adAccountId;
+    /**
+     * 注册时间
+     */
+    private LocalDateTime registerTime;
+
+    /**
+     * 渠道号
+     */
+    private String channel;
+
+    private String roleId;
+
+    private String roleName;
+
+    /**
+     * 数据源ID
+     */
+    private Long userActionSetId;
+
+    /**
+     * 用户设备mac地址
+     */
+    private String mac;
+
+    /**
+     * 设备唯一编号IMEI
+     */
+    private String imei;
+
+    /**
+     * 设备OAID
+     */
+    private String oaid;
+
+    /**
+     * 安卓id, (仅安卓设备才有值)
+     */
+    private String androidId;
+
+    /**
+     * IOS设备IDFA
+     */
+    private String idfa;
+
+    /**
+     * IOS设备CAID
+     */
+    private String caid;
+}

+ 82 - 0
game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/dto/TencentUserAppRpcDTO.java

@@ -0,0 +1,82 @@
+package com.zanxiang.game.back.base.pojo.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class TencentUserAppRpcDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+    /**
+     * 回传策略ID
+     */
+    private Long backPolicyId;
+    /**
+     * sdk 里面的用户 id(要求唯一)
+     */
+    private String userId;
+    /**
+     * 游戏ID
+     */
+    private Long gameId;
+
+    /**
+     * 广告账号ID
+     */
+    private Long adAccountId;
+    /**
+     * 注册时间
+     */
+    private LocalDateTime registerTime;
+
+    /**
+     * 关注时间
+     */
+    private LocalDateTime subscribeTime;
+
+    /**
+     * 渠道号
+     */
+    private String channel;
+
+    /**
+     * 数据源ID
+     */
+    private Long userActionSetId;
+    /**
+     * 用户设备mac地址
+     */
+    private String mac;
+
+    /**
+     * 设备唯一编号IMEI
+     */
+    private String imei;
+
+    /**
+     * 设备OAID
+     */
+    private String oaid;
+
+    /**
+     * 安卓id, (仅安卓设备才有值)
+     */
+    private String androidId;
+
+    /**
+     * IOS设备IDFA
+     */
+    private String idfa;
+
+    /**
+     * IOS设备CAID
+     */
+    private String caid;
+}

+ 35 - 0
game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/dto/TtAppOrderBackQueryRpcDTO.java

@@ -0,0 +1,35 @@
+package com.zanxiang.game.back.base.pojo.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 创角是否回传
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class TtAppOrderBackQueryRpcDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+    /**
+     * 游戏 id
+     */
+    private Long gameId;
+    /**
+     * sdk 里面的用户 id(要求唯一)
+     */
+    private String userId;
+    /**
+     * 订单编号
+     */
+    private String orderId;
+    /**
+     * 渠道标识
+     */
+    private String agentKey;
+}

+ 34 - 0
game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/dto/TtAppRoleRegisterBackQueryRpcDTO.java

@@ -0,0 +1,34 @@
+package com.zanxiang.game.back.base.pojo.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 创角是否回传
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class TtAppRoleRegisterBackQueryRpcDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 游戏 id
+     */
+    private Long gameId;
+    /**
+     * sdk 里面的用户 id(要求唯一)
+     */
+    private String userId;
+    /**
+     * 渠道标识
+     */
+    private String agentKey;
+
+    private String roleId;
+}

+ 31 - 0
game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/dto/TtAppUserBackQueryRpcDTO.java

@@ -0,0 +1,31 @@
+package com.zanxiang.game.back.base.pojo.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 创角是否回传
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class TtAppUserBackQueryRpcDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+    /**
+     * 游戏 id
+     */
+    private Long gameId;
+    /**
+     * sdk 里面的用户 id(要求唯一)
+     */
+    private String userId;
+    /**
+     * 渠道标识
+     */
+    private String agentKey;
+}

+ 92 - 0
game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/dto/TtOrderAppRpcDTO.java

@@ -0,0 +1,92 @@
+package com.zanxiang.game.back.base.pojo.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class TtOrderAppRpcDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+    /**
+     * 游戏 id
+     */
+    private Long gameId;
+    /**
+     * 微信小游戏上报组件
+     */
+    private TtAccountRpcDTO accountReport;
+    /**
+     * sdk 里面的用户 id(要求唯一)
+     */
+    private String userId;
+    /**
+     * 订单编号
+     */
+    private String orderId;
+    /**
+     * 渠道标识
+     */
+    private String agentKey;
+    /**
+     * 回传策略 id
+     */
+    private Long backPolicyId;
+    /**
+     * 订单金额(分)
+     */
+    private Long rechargeMoney;
+    /**
+     * 支付状态,0 : 预下单, 1 : 待支付,2 : 支付成功,-1 : 已取消
+     */
+    private Integer orderStatus;
+
+    private LocalDateTime regTime;
+    /**
+     * 下单时间
+     */
+    private LocalDateTime createTime;
+    /**
+     * 支付时间
+     */
+    private LocalDateTime payTime;
+
+    private String roleId;
+
+    private String roleName;
+    /**
+     * 用户设备mac地址
+     */
+    private String mac;
+
+    /**
+     * 设备唯一编号IMEI
+     */
+    private String imei;
+
+    /**
+     * 设备OAID
+     */
+    private String oaid;
+
+    /**
+     * 安卓id, (仅安卓设备才有值)
+     */
+    private String androidId;
+
+    /**
+     * IOS设备IDFA
+     */
+    private String idfa;
+
+    /**
+     * IOS设备CAID
+     */
+    private String caid;
+}

+ 77 - 0
game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/dto/TtRoleRegisterAppRpcDTO.java

@@ -0,0 +1,77 @@
+package com.zanxiang.game.back.base.pojo.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class TtRoleRegisterAppRpcDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 游戏 id
+     */
+    private Long gameId;
+    /**
+     * sdk 里面的用户 id(要求唯一)
+     */
+    private String userId;
+
+
+    /**
+     * 回传策略ID
+     */
+    private Long backPolicyId;
+    /**
+     * 微信小游戏上报组件
+     */
+    private TtAccountRpcDTO accountReport;
+    /**
+     * 渠道标识
+     */
+    private String agentKey;
+
+    private String roleId;
+
+    private String roleName;
+    /**
+     * 激活/注册时间
+     */
+    private LocalDateTime registerTime;
+    /**
+     * 用户设备mac地址
+     */
+    private String mac;
+
+    /**
+     * 设备唯一编号IMEI
+     */
+    private String imei;
+
+    /**
+     * 设备OAID
+     */
+    private String oaid;
+
+    /**
+     * 安卓id, (仅安卓设备才有值)
+     */
+    private String androidId;
+
+    /**
+     * IOS设备IDFA
+     */
+    private String idfa;
+
+    /**
+     * IOS设备CAID
+     */
+    private String caid;
+}

+ 73 - 0
game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/dto/TtUserActiveAppRpcDTO.java

@@ -0,0 +1,73 @@
+package com.zanxiang.game.back.base.pojo.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class TtUserActiveAppRpcDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 游戏 id
+     */
+    private Long gameId;
+    /**
+     * 微信小游戏上报组件
+     */
+    private TtAccountRpcDTO accountReport;
+    /**
+     * 渠道标识
+     */
+    private String agentKey;
+    /**
+     * 激活/注册时间
+     */
+    private LocalDateTime activeTime;
+
+    /**
+     * 回传策略 id
+     */
+    private Long backPolicyId;
+    /**
+     * sdk 里面的用户 id(要求唯一)
+     */
+    private String userId;
+
+    /**
+     * 用户设备mac地址
+     */
+    private String mac;
+
+    /**
+     * 设备唯一编号IMEI
+     */
+    private String imei;
+
+    /**
+     * 设备OAID
+     */
+    private String oaid;
+
+    /**
+     * 安卓id, (仅安卓设备才有值)
+     */
+    private String androidId;
+
+    /**
+     * IOS设备IDFA
+     */
+    private String idfa;
+
+    /**
+     * IOS设备CAID
+     */
+    private String caid;
+}

+ 25 - 0
game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/vo/OrderBackQueryRpcVO.java

@@ -0,0 +1,25 @@
+package com.zanxiang.game.back.base.pojo.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class OrderBackQueryRpcVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private Boolean doBack;
+
+    private Long backMoney;
+
+    /**
+     * 回传信息
+     */
+    private String backMsg;
+}

+ 21 - 0
game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/rpc/ITencentAppBackRpc.java

@@ -0,0 +1,21 @@
+package com.zanxiang.game.back.base.rpc;
+
+import com.zanxiang.game.back.base.pojo.dto.*;
+import com.zanxiang.module.util.pojo.ResultVO;
+
+/**
+ * 腾讯数据源回传
+ */
+public interface ITencentAppBackRpc {
+    /**
+     * 订单回传
+     */
+    ResultVO<Boolean> backOrder(TencentOrderAppRpcDTO dto);
+
+    /**
+     * 用户回传
+     */
+    ResultVO<Boolean> backUser(TencentUserAppRpcDTO dto);
+
+    ResultVO<Boolean> backRoleRegister(TencentRoleRegisterAppRpcDTO dto);
+}

+ 44 - 0
game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/rpc/ITtAppBackRpc.java

@@ -0,0 +1,44 @@
+package com.zanxiang.game.back.base.rpc;
+
+import com.zanxiang.game.back.base.pojo.dto.*;
+import com.zanxiang.game.back.base.pojo.vo.OrderBackQueryRpcVO;
+import com.zanxiang.module.util.pojo.ResultVO;
+
+/**
+ * 微信小游戏头条上报
+ * 参考文档:https://bytedance.feishu.cn/docx/doxcnsCqXkvxoAg36GDzkRRRuAq
+ */
+public interface ITtAppBackRpc {
+
+    /**
+     * 用户激活、注册等上报
+     */
+    ResultVO<Boolean> userActiveReport(TtUserActiveAppRpcDTO dto);
+
+    /**
+     * 用户下单、支付上报
+     */
+    ResultVO<Boolean> orderReport(TtOrderAppRpcDTO dto);
+
+    /**
+     * 创角上报
+     */
+    ResultVO<Boolean> roleRegisterReport(TtRoleRegisterAppRpcDTO dto);
+
+
+
+    /**
+     * 用户是否回传
+     */
+    ResultVO<Boolean> userBackQuery(TtAppUserBackQueryRpcDTO dto);
+
+    /**
+     * 订单是否回传
+     */
+    ResultVO<OrderBackQueryRpcVO> orderBackQuery(TtAppOrderBackQueryRpcDTO dto);
+
+    /**
+     * 创角是否回传
+     */
+    ResultVO<Boolean> roleRegisterBackQuery(TtAppRoleRegisterBackQueryRpcDTO dto);
+}

+ 6 - 0
game-back/game-back-serve/pom.xml

@@ -70,6 +70,12 @@
             <groupId>com.alibaba.nacos</groupId>
             <artifactId>nacos-client</artifactId>
         </dependency>
+        <!-- kafka -->
+        <dependency>
+            <groupId>org.apache.kafka</groupId>
+            <artifactId>kafka-clients</artifactId>
+            <version>2.2.1</version>
+        </dependency>
         <dependency>
             <groupId>com.zanxiang.erp</groupId>
             <artifactId>erp-security</artifactId>

+ 27 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/config/KafkaConfig.java

@@ -0,0 +1,27 @@
+package com.zanxiang.game.back.serve.config;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.kafka.clients.producer.KafkaProducer;
+import org.apache.kafka.clients.producer.ProducerConfig;
+import org.apache.kafka.common.serialization.StringSerializer;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.Properties;
+
+@Slf4j
+@Configuration
+public class KafkaConfig {
+    @Value("${spring.kafka.bootstrap-servers}")
+    private String kafkaSevers;
+
+    @Bean
+    public KafkaProducer<String, String> gameKafkaProducer() {
+        Properties props = new Properties();
+        props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaSevers);
+        props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
+        props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
+        return new KafkaProducer<>(props);
+    }
+}

+ 3 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/config/NacosDynamicParamConfig.java

@@ -9,4 +9,7 @@ import org.springframework.stereotype.Component;
 @Component
 @RefreshScope
 public class NacosDynamicParamConfig {
+
+    @Value("${nacos.dynamic.callbackClearDay:15}")
+    private Integer callbackClearDay;
 }

+ 33 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/controller/api/OceanengineCallbackApi.java

@@ -0,0 +1,33 @@
+package com.zanxiang.game.back.serve.controller.api;
+
+import com.zanxiang.game.back.serve.pojo.dto.GameOceanengineAppCallbackDTO;
+import com.zanxiang.game.back.serve.service.IGameOceanengineAppCallbackService;
+import com.zanxiang.module.util.JsonUtil;
+import com.zanxiang.module.util.pojo.ResultVO;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 头条监测链接
+ */
+@Slf4j
+@RestController
+@RequestMapping("/api/oceanengineCallback")
+public class OceanengineCallbackApi {
+
+    @Autowired
+    private IGameOceanengineAppCallbackService gameOceanengineAppCallbackService;
+
+    // https://api.zanxiangwl.com/gameBack/api/oceanengineCallback/callback?promotionid=__PROMOTION_ID__&projectId=__PROJECT_ID__&mid1=__MID1__&mid2=__MID2__&mid3=__MID3__&mid4=__MID4__&mid5=__MID5__&mid6=__MID6__
+    // &aid=__AID__&cid=__CID__&campaignId=__CAMPAIGN_ID__&ctype=__CTYPE__&advertiserId=__ADVERTISER_ID__&csite=__CSITE__&convertId=__CONVERT_ID__&requestId=__REQUEST_ID__&trackId=__TRACK_ID__&sl=__SL__
+    // &imei=__imei__&idfa=__IDFA__&idfaMd5=__IDFA_MD5__&androidid=__ANDROIDID__&oaid=__OAID__&oaidMd5=__OAID_MD5__&os=__OS__&mac=__MAC__&mac1=MAC1&ipv4=__IPV4__&ipv6=__ipv6__&ip=__IP__
+    // &ua=__UA__&geo=__GEO__&ts=__TS__&callbackParam=__CALLBACK_PARAM__&callbackUrl=__CALLBACK_URL__&model=__MODEL__&unionSite=__UNION_SITE__&caid=__CAID__&productid=__PRODUCTID__&outerid=__OUTERID__
+    @GetMapping("/callback")
+    public ResultVO<Boolean> callback(GameOceanengineAppCallbackDTO dto) {
+        log.info("头条监测链接:{}", JsonUtil.toString(dto));
+        return ResultVO.ok(gameOceanengineAppCallbackService.callback(dto));
+    }
+}

+ 36 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/controller/api/TencentCallbackApi.java

@@ -0,0 +1,36 @@
+package com.zanxiang.game.back.serve.controller.api;
+
+import com.zanxiang.game.back.serve.pojo.dto.GameTencentAppCallbackDTO;
+import com.zanxiang.game.back.serve.service.IGameTencentAppCallbackService;
+import com.zanxiang.module.util.JsonUtil;
+import com.zanxiang.module.util.pojo.ResultVO;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 腾讯监测链接
+ */
+@Slf4j
+@RestController
+@RequestMapping("/api/tencentCallback")
+public class TencentCallbackApi {
+    @Autowired
+    private IGameTencentAppCallbackService gameTencentAppCallbackService;
+
+    // https://api.zanxiangwl.com/gameBack/api/tencentCallback/callback
+    // ?click_id=__CLICK_ID__&click_time=__CLICK_TIME__&impressionTime=__IMPRESSION_TIME__&adgroup_id=__ADGROUP_ID__
+    // &dynamicCreativeId=__DYNAMIC_CREATIVE_ID__&marketing_asset_id=__MARKETING_ASSET_ID__&material_package_id=__MATERIAL_PACKAGE_ID__
+    // &ad_platform_type=__AD_PLATFORM_TYPE__&account_id=__ACCOUNT_ID__&agency_id=__AGENCY_ID__&click_sku_id=__CLICK_SKU_ID__&device_os_type=__DEVICE_OS_TYPE__
+    // &process_time=__PROCESS_TIME__&promotedObjectId=__PROMOTED_OBJECT_ID__&request_id=__REQUEST_ID__&impressionId=__IMPRESSION_ID__&muid=__MUID__
+    // &hash_android_id=__HASH_ANDROID_ID__&ip=__IP__&userAgent=__USER_AGENT__&callback=__CALLBACK__&encryptedPositionId=__ENCRYPTED_POSITION_ID__
+    // &ipv6=__IPV6__&hash_oaid=__HASH_OAID__&&caid=__QAID_CAA__&model=__MODEL__&ipMd5=__IP_MD5__&ipv6Md5=__IPV6_MD5__
+    // &channelPackageId=__CHANNEL_PACKAGE_ID__&deviceOsVersion=__DEVICE_OS_VERSION__
+    @GetMapping("/callback")
+    public ResultVO<Boolean> callback(GameTencentAppCallbackDTO dto) {
+        log.info("腾讯监测链接:{}", JsonUtil.toString(dto));
+        return ResultVO.ok(gameTencentAppCallbackService.callback(dto));
+    }
+}

+ 7 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameOceanengineAppBackLogMapper.java

@@ -0,0 +1,7 @@
+package com.zanxiang.game.back.serve.dao.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineAppBackLog;
+
+public interface GameOceanengineAppBackLogMapper extends BaseMapper<GameOceanengineAppBackLog> {
+}

+ 7 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameOceanengineAppCallbackMapper.java

@@ -0,0 +1,7 @@
+package com.zanxiang.game.back.serve.dao.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineAppCallback;
+
+public interface GameOceanengineAppCallbackMapper extends BaseMapper<GameOceanengineAppCallback> {
+}

+ 7 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameOceanengineAppOrderLogMapper.java

@@ -0,0 +1,7 @@
+package com.zanxiang.game.back.serve.dao.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineAppOrderLog;
+
+public interface GameOceanengineAppOrderLogMapper extends BaseMapper<GameOceanengineAppOrderLog> {
+}

+ 7 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameOceanengineAppRoleRegisterLogMapper.java

@@ -0,0 +1,7 @@
+package com.zanxiang.game.back.serve.dao.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineAppRoleRegisterLog;
+
+public interface GameOceanengineAppRoleRegisterLogMapper extends BaseMapper<GameOceanengineAppRoleRegisterLog> {
+}

+ 7 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameOceanengineAppUserLogMapper.java

@@ -0,0 +1,7 @@
+package com.zanxiang.game.back.serve.dao.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineAppUserLog;
+
+public interface GameOceanengineAppUserLogMapper extends BaseMapper<GameOceanengineAppUserLog> {
+}

+ 7 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameTencentAppBackLogMapper.java

@@ -0,0 +1,7 @@
+package com.zanxiang.game.back.serve.dao.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentAppBackLog;
+
+public interface GameTencentAppBackLogMapper extends BaseMapper<GameTencentAppBackLog> {
+}

+ 7 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameTencentAppCallbackMapper.java

@@ -0,0 +1,7 @@
+package com.zanxiang.game.back.serve.dao.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentAppCallback;
+
+public interface GameTencentAppCallbackMapper extends BaseMapper<GameTencentAppCallback> {
+}

+ 7 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameTencentAppOrderMapper.java

@@ -0,0 +1,7 @@
+package com.zanxiang.game.back.serve.dao.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentAppOrder;
+
+public interface GameTencentAppOrderMapper extends BaseMapper<GameTencentAppOrder> {
+}

+ 7 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameTencentAppOrderSplitLogMapper.java

@@ -0,0 +1,7 @@
+package com.zanxiang.game.back.serve.dao.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentAppOrderSplitLog;
+
+public interface GameTencentAppOrderSplitLogMapper extends BaseMapper<GameTencentAppOrderSplitLog> {
+}

+ 7 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameTencentAppRoleRegisterMapper.java

@@ -0,0 +1,7 @@
+package com.zanxiang.game.back.serve.dao.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentAppRoleRegister;
+
+public interface GameTencentAppRoleRegisterMapper extends BaseMapper<GameTencentAppRoleRegister> {
+}

+ 7 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameTencentAppUserMapper.java

@@ -0,0 +1,7 @@
+package com.zanxiang.game.back.serve.dao.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentAppUser;
+
+public interface GameTencentAppUserMapper extends BaseMapper<GameTencentAppUser> {
+}

+ 218 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/dto/GameOceanengineAppCallbackDTO.java

@@ -0,0 +1,218 @@
+package com.zanxiang.game.back.serve.pojo.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 头条游戏 APP 监测链接回传数据(文档:https://open.oceanengine.com/labels/7/docs/1696710655781900)
+ * </p>
+ *
+ */
+@Data
+public class GameOceanengineAppCallbackDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 巨量广告体验版中特有的宏参,代表巨量广告体验版的广告ID, ex: ID: 7074140945750507528, 宏: PROMOTION_ID
+     */
+    private Long promotionId;
+
+    /**
+     * 巨量广告体验版中特有的宏参,代表巨量广告体验版的项目ID, ex: ID: 7074140945750507528, 宏: PROJECT_ID
+     */
+    private Long projectId;
+
+    /**
+     * 针对巨量广告体验版,图片素材宏参数(下发原始素材id), 宏: MID1
+     */
+    private String mid1;
+
+    /**
+     * 针对巨量广告体验版,标题素材宏参数(下发原始素材id), 宏: MID2
+     */
+    private String mid2;
+
+    /**
+     * 针对巨量广告体验版,视频素材宏参数(下发原始素材id), 宏: MID3
+     */
+    private String mid3;
+
+    /**
+     * 针对巨量广告体验版,搭配试玩素材宏参数(下发原始素材id), 宏: MID4
+     */
+    private String mid4;
+
+    /**
+     * 针对巨量广告体验版,落地页素材宏参数(下发原始素材id), 宏: MID5
+     */
+    private String mid5;
+
+    /**
+     * 针对巨量广告体验版,安卓下载详情页素材宏参数(下发原始素材id), 宏: MID6
+     */
+    private String mid6;
+
+    /**
+     * 广告计划id, ex: 1645988237525045, 宏: AID
+     */
+    private Long aid;
+
+    /**
+     * 广告创意 id, ex: 1650703686054530, 宏: CID
+     */
+    private Long cid;
+
+    /**
+     * 广告组 id, ex: 1651688272934434, 宏: CAMPAIGN_ID
+     */
+    private Long campaignId;
+
+    /**
+     * 创意样式, 2=小图模式、3=大图模式、4=组图模式、5=视频, 宏: CTYPE
+     */
+    private Integer ctype;
+
+    /**
+     * 广告主id, ex: 1631857582073864, 宏: ADVERTISER_ID
+     */
+    private Long advertiserId;
+
+    /**
+     * 广告投放位置, 今日头条:1-10000,80000-110001、西瓜视频:10001-10099、火山小视频:30001-30099、抖音:40001-40099、番茄小说:26001-26099、穿山甲开屏广告:800000000、穿山甲网盟非开屏广告:900000000、通投广告位:33013、搜索:38016, 宏: CSITE
+     */
+    private Integer csite;
+
+    /**
+     * 转化id, ex: 1681681272671401, 宏: CONVERT_ID
+     */
+    private Long convertId;
+
+    /**
+     * 请求下发的id, ex: 20191202180607010026077068090BA60A, 宏: REQUEST_ID
+     */
+    private String requestId;
+
+    /**
+     * 请求下发的id&创意id的md5,16位, ex: b2f97be5b363764d, 宏: TRACK_ID
+     */
+    private String trackId;
+
+    /**
+     * 这次请求的语言, ex: zh, 宏: SL
+     */
+    private String sl;
+
+    /**
+     * 安卓的设备 ID 的 md5 摘要,32位, 假设原始的 imei 是 868823031739689我们最终发送的是 imei 的 md5 摘要:0c2bd03c39f19845bf54ea0abafae70e,会存在部分无法获取imei的情况,则imei会回传空字符串或者0的md5摘要, 宏: IMEI
+     */
+    private String imei;
+
+    /**
+     * IOS 6+的设备id字段,32位, ex: 4FCFEFA1-096D-4176-B352-1870ED6DB777注意,一些例外00000000-0000-0000-0000-000000000000, 如果用户关闭里读取idfa的权限,会导致idfa全部是0, 宏: IDFA
+     */
+    private String idfa;
+
+    /**
+     * IOS 6+的设备id的md5摘要,32位, ex: 09c593c62a6074ae5f859e97a222c0e8,注意,用户关闭读取idfa权限,0值也会进行MD5加密, 宏: IDFA_MD5
+     */
+    private String idfaMd5;
+
+    /**
+     * 安卓id原值的md5,32位, ex: androidId的原值是: 7b5ca2d57178d2f1我们进行md5摘要,最终结果是:873541edf36da9170af47d5b69e82193, 宏: ANDROIDID
+     */
+    private String androidid;
+
+    /**
+     * Android Q及更高版本的设备号,32位, ex: 97e7ef3f-e5f2-d0b8-ccfc-f79bbeaf4841注意,一些例外如果无法获取oaid,oaid会传空字符串, 宏: OAID
+     */
+    private String oaid;
+
+    /**
+     * Android Q及更高版本的设备号的md5摘要,32位, ex: 87f8274c36eb73fabcbf143a10eca6a4,会存在部分无法获取oaid的情况,则该字段会回传空字符串, 宏: OAID_MD5
+     */
+    private String oaidMd5;
+
+    /**
+     * 操作系统平台, 安卓:0、IOS:1、其它:3, 宏: OS
+     */
+    private Integer os;
+
+    /**
+     * 移动设备mac地址,转换成大写字母,去掉“:”,并且取md5摘要后的结果, 假设原始的mac地址是34:d7:12:9b:3a:89去掉“:”后变成 34d7129b3a89变成大写字母34D7129B3A89取MD5摘要,最后变成如下结果:df97bc5021e14256e141b2f036df5a3c, 宏: MAC
+     */
+    private String mac;
+
+    /**
+     * 移动设备 mac 地址,转换成大写字母,并且取md5摘要后的结果,32位, 假设原始的mac地址是 34:d7:12:9b:3a:89变成大写字母: 34:D7:12:9B:3A:89进行MD5摘要,最后变成如下结果:4d0433eb614f5d5ad409a65395426cbe, 宏: MAC1
+     */
+    private String mac1;
+
+    /**
+     * 优先使用上报请求的对端 IP 地址。如果该IP为 IPv6, 则使用客户端获取的 client_ipv4 地址, ex: 61.168.146.195或为空, 宏: IPV4
+     */
+    private String ipv4;
+
+    /**
+     * 优先使用上报请求的对端 IP 地址。如果该IP为 IPv4, 则使用客户端获取的 client_ipv6 地址, ex: 240e:498:1c90:9d00:5513:b9c9:650a:d9d2或为空, 宏: IPV6
+     */
+    private String ipv6;
+
+    /**
+     * [下发逻辑修改 - 0727生效]正常情况下,全量下发IPv4地址。极少数情况如IPV4无法取数,则下发 IPv6, ex: 61.158.146.195或240e:398:1c90:9d00:5513:b9c9:650a:d9d2, 宏: IP
+     */
+    private String ip;
+
+    /**
+     * 用户代理(User Agent),一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。经过url encode, ex: News+7.4.5+rv%3A7.4.5.23%5C%28iPhone%3B+iOS+12.4.1%3B+zh_CN%5C%29Cronet, 宏: UA
+     */
+    private String ua;
+
+    /**
+     * 位置信息,包含三部分:latitude(纬度),longitude(经度)以及precise(确切信息,精度)十进制保留1位小数,西经南纬保留负数,用字母 x 分 割纬度与精度 (先纬后经,最后精度), ex: 35.7x122.4x100.0, 宏: GEO
+     */
+    private String geo;
+
+    /**
+     * 客户端发生广告点击事件的时间,以毫秒为单位时间戳, ex: 1575194434000, 宏: TS
+     */
+    private Long ts;
+
+    /**
+     * 一些跟广告信息相关的回调参数,内容是一个加密字符串,在调用事件回传接口的时候会用到, ex: EJiw267wvfQCGKf2g74ZIPD89-vIATAMOAFCIjIwMTkxMTI3MTQxMTEzMDEwMDI2MDc3MjE1MTUwNTczNTBIAQ==, 宏: CALLBACK_PARAM
+     */
+    private String callbackParam;
+
+    /**
+     * 直接把调用事件回传接口的url生成出来,广告主可以直接使用, ex: https://ad.toutiao.com/track/activate/?callback=EJiw267wvfQCGKf2g74ZIPD89-vIATAMOAFCIjIwMTkxMTI3MTQxMTEzMDEwMDI2MDc3MjE1MTUwNTczNTBIAQ==&os=0&muid=db94e6a60a9c6661e3e03a7d301c25b6, 宏: CALLBACK_URL
+     */
+    private String callbackUrl;
+
+    /**
+     * 手机型号, 包含多种格式, ex: iPhone12,2 (urlencode之后为iPhone12%2c2),iPhone X (urlencode之后为iPhone+X),SM-A750GN (urlencode之后为SM-A750GN), 宏: MODEL
+     */
+    private String model;
+
+    /**
+     * 对外广告位编码, ex: 2045891290, 宏: UNION_SITE
+     */
+    private String unionSite;
+
+    /**
+     * 中国广告协会互联网广告标识,包含最新两个版本的CAID和版本号,url encode之后的json字符串。(【CAID】和【CAID1、CAID2】的信息一致,使用一种即可;建议使用【CAID】,参数中包含多个信息,后续维护成本低), ex: %5B%7B%22version%22%3A%2220220111%22%2C%22caid%22%3A%22912ec803b2ce49e4a541068d495ab570%22%7D%2C%7B%22version%22%3A%2220211207%22%2C%22caid%22%3A%22e332a76c29654fcb7f6e6b31ced090c7%22%7D%5D, 宏: CAID
+     */
+    private String caid;
+
+    /**
+     * 商品id,仅支持站内(不支持穿山甲), 宏: PRODUCTID
+     */
+    private String productid;
+
+    /**
+     * 商品id,同时支持站内和穿山甲, 宏: OUTERID
+     */
+    private String outerid;
+
+
+}

+ 185 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/dto/GameTencentAppCallbackDTO.java

@@ -0,0 +1,185 @@
+package com.zanxiang.game.back.serve.pojo.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 腾讯游戏 APP 监测链接回传数据(文档:https://datanexus.qq.com/doc/develop/guider/interface/conversion/ad_track_click#5-%E5%AD%97%E6%AE%B5%E5%88%97%E8%A1%A8)
+ * </p>
+ *
+ * @author wcc
+ * @since 2024-06-27
+ */
+@Data
+public class GameTencentAppCallbackDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 点击id, ex: 24oi6xq2aaakvagnqu7a, 宏: __CLICK_ID__
+     */
+    private String clickId;
+
+    /**
+     * 点击时间, ex: 1586437362, 宏: __CLICK_TIME__
+     */
+    private Long clickTime;
+
+    /**
+     * 曝光时间, ex: 1586437361, ex: , 宏: __IMPRESSION_TIME__
+     */
+    private Long impressionTime;
+
+    /**
+     * 广告组id(实际为广告id), ex: 228691429, ex: , 宏: __ADGROUP_ID__
+     */
+    private Long adgroupId;
+
+    /**
+     * 创意 ID, ex: 654321, 宏: __DYNAMIC_CREATIVE_ID__
+     */
+    private Long dynamicCreativeId;
+
+    /**
+     * 营销资产ID, ex: 12345, 宏: __MARKETING_ASSET_ID__
+     */
+    private Long marketingAssetId;
+
+    /**
+     * 素材标签ID, 宏: __MATERIAL_PACKAGE_ID__
+     */
+    private String materialPackageId;
+
+    /**
+     * 广告投放平台, 1:GDT entrance、3:京东直投、5:经 wechat mp 投放的广告、6:京东运营、8:QQ 公众账号平台、9:移动联盟 SSP、10:58 运营、11:58 商户、12:易车运营、13:易车商户、14:融 360 运营、15:融 360 商户、16:点评运营、17:点评商户、18:来自 OMG 的广告主、19:京东外单, 宏: __AD_PLATFORM_TYPE__
+     */
+    private Integer adPlatformType;
+
+    /**
+     * 广告主id, ex: 9471147, 宏: __ACCOUNT_ID__
+     */
+    private Long accountId;
+
+    /**
+     * 代理商id, ex: 1050262, 宏: __AGENCY_ID__
+     */
+    private Long agencyId;
+
+    /**
+     * 点击sku, ex: 478c4a93a054f7c9087b4ecb1f03f8a1, 宏: __CLICK_SKU_ID__
+     */
+    private String clickSkuId;
+
+    /**
+     * 设备类型, ex: ios、android, 宏: __DEVICE_OS_TYPE__
+     */
+    private String deviceOsType;
+
+    /**
+     * 请求时间, ex: 1586437335, 宏: __PROCESS_TIME__
+     */
+    private Long processTime;
+
+    /**
+     * 应用id, ex: 1101072624、wx69618ae091cf2c76, 宏: __PROMOTED_OBJECT_ID__
+     */
+    private String promotedObjectId;
+
+    /**
+     * 请求id, ex: vqp7xdombqonw, 宏: __REQUEST_ID__
+     */
+    private String requestId;
+
+    /**
+     * 曝光id, ex: xkrx5et47h7g401, 宏: __IMPRESSION_ID__
+     */
+    private String impressionId;
+
+    /**
+     * 设备id(imei或idfa的加密值),对 IMEI 设备号转成小写,再进行md5编码,再小写,32位、对 IDFA 设备号保持大写,再进行 md5 编码,再小写,32位, 宏: __MUID__
+     */
+    private String muid;
+
+    /**
+     * 安卓id做md5加密后小写, ex: 797745b011e3286de9e1a1c59ba72c97, 宏: __HASH_ANDROID_ID__
+     */
+    private String hashAndroidId;
+
+    /**
+     * 媒体投放系统获取的用户终端的公共IPV4地址, ex: 183.226.102.120, 宏: __IP__
+     */
+    private String ip;
+
+    /**
+     * 用户代理(user_agent), ex: Dalvik%2F2.1.0+%28Linux%3B+U%3B+Android+8.0.0%3B+PIC-AL00+Build%2FHUAWEIPIC-AL00%29, 宏: __USER_AGENT__
+     */
+    private String userAgent;
+
+    /**
+     * 情况1:使用 DataNexus 配置,并与广告直接绑定(ex: 空值)、情况2:新版转化归因中的监测链接信息(使用 DataNexus 或直接填写监测链接)直接提供上报信息回传接口的 url,示例为url encode 编码原值,广告主需要 decode 作为 post 请求url回传至腾讯广告(ex: http%3A%2F%2Ftracking.e.qq.com%2Fconv%3Fcb%3DxXx%252BxXx%253D%26conv_id%3D123)、情况3:使用投放管理平台 - 工具(ex: http://tracking.e.qq.com/conv?cb=%s&&%s&&%s&&%s 其中%s代表的参数分别为 productId、productType、advertiserId、clickId), 宏: __CALLBACK__
+     */
+    private String callback;
+
+    /**
+     * 联盟广告位id, ex: 8144201, 宏: __ENCRYPTED_POSITION_ID__
+     */
+    private String encryptedPositionId;
+
+    /**
+     * 媒体投放系统获取的用户终端的公共IPV6地址, ex: 2409%3A8a55%3A4cc0%3A4050%3A2507%3A4922%3Abbe0%3A524b, 宏: __IPV6__
+     */
+    private String ipv6;
+
+    /**
+     * Android Q 及更高版本的设备号,64位及以下,取原值后做md5加密, ex: 9d271e4d04de7e4b0b4f1df20e79ce64, 宏: __HASH_OAID__
+     */
+    private String hashOaid;
+
+    /**
+     * URL Encode后的JSON数组;其中qaid为中广协ID(即CAID),hash_qaid为CAID原值MD5加密后的结果, version为腾讯版本号,支持两个版本同时下发(即最新版和上一版),腾讯版本号与中广协版本对应关系为:腾讯 1001 = 中广协 20200901;腾讯 1003 = 中广协 20201230; 腾讯1004 = 中广协 20211207;腾讯1005=中广协 20220111;腾讯1006=中广协 20230330, 宏: __QAID_CAA__
+     */
+    private String caid;
+
+    /**
+     * 机型, ex:  PCKM00、Redmi 7、iPhone 7..., 宏: __MODEL__
+     */
+    private String model;
+
+    /**
+     * 专用于网页类小程序转化规则的点击监测下发,其它类型不支持该字段下发。每个用户针对小程序应用会产生一个安全的OpenID,只针对当前的小程序有效, ex: ozWH25VK0aodxYMZrX0Lqj9HHhrg, 宏: __WECHAT_OPEN_ID__
+     */
+    private String wechatOpenid;
+
+    /**
+     * 媒体投放系统获取的用户终端的公共IPV4地址MD5加密后转小写,仅在新版转化里支持配置, 宏: __IP_MD5__
+     */
+    private String ipMd5;
+
+    /**
+     * 媒体投放系统获取的用户终端的公共IPV6地址MD5加密后转小写,仅在新版转化里支持配置, 宏: __IPV6_MD5__
+     */
+    private String ipv6Md5;
+
+    /**
+     * 渠道包id, 只 for Android 设备生效, 宏: __CHANNEL_PACKAGE_ID__
+     */
+    private String channelPackageId;
+
+    /**
+     * 操作系统版本, 只 for iOS 和 Android 设备生效, 宏: __DEVICE_OS_VERSION__
+     */
+    private String deviceOsVersion;
+
+    /**
+     * 行为类型, LANDING_PAGE_CLICK:点击跳转按钮,RESERVATION:表单预约, 宏: __ACT_TYPE__
+     */
+    private String actType;
+
+    /**
+     * 行为时间, ex: 1586437361, 宏: __ACT_TIME__
+     */
+    private Long actTime;
+
+
+}

+ 90 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameOceanengineAppBackLog.java

@@ -0,0 +1,90 @@
+package com.zanxiang.game.back.serve.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 头条订单上报日志
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@TableName("t_game_ocenaengine_app_back_log")
+public class GameOceanengineAppBackLog implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    private String userId;
+
+    /**
+     * 用户设备mac地址
+     */
+    private String mac;
+
+    /**
+     * 设备唯一编号IMEI
+     */
+    private String imei;
+
+    /**
+     * 设备OAID
+     */
+    private String oaid;
+
+    /**
+     * 安卓id, (仅安卓设备才有值)
+     */
+    private String androidId;
+
+    /**
+     * IOS设备IDFA
+     */
+    private String idfa;
+
+    /**
+     * IOS设备CAID
+     */
+    private String caid;
+    /**
+     * 游戏 id
+     */
+    private Long gameId;
+
+    private Long accountId;
+    /**
+     * 事件类型
+     */
+    private String eventType;
+    /**
+     * 触发回传的日志 id
+     */
+    private Long eventLogId;
+    /**
+     * 支付回传的支付金额
+     */
+    private Long payAmount;
+    /**
+     * 回传状态(0:成功、-1:失败)
+     */
+    private Integer backStatus;
+    /**
+     * 回传失败的错误日志
+     */
+    private String errMsg;
+    /**
+     * 回传时间
+     */
+    private LocalDateTime createTime;
+
+}

+ 239 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameOceanengineAppCallback.java

@@ -0,0 +1,239 @@
+package com.zanxiang.game.back.serve.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.time.LocalDate;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * <p>
+ * 头条游戏 APP 监测链接回传数据(文档:https://open.oceanengine.com/labels/7/docs/1696710655781900)
+ * </p>
+ *
+ * @author wcc
+ * @since 2024-06-27
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@TableName(GameOceanengineAppCallback.TABLE_NAME)
+public class GameOceanengineAppCallback implements Serializable {
+    private static final long serialVersionUID = 1L;
+    public static final String TABLE_NAME = "t_game_oceanengine_app_callback";
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 时间发生日期
+     */
+    private LocalDate day;
+
+    /**
+     * 巨量广告体验版中特有的宏参,代表巨量广告体验版的广告ID, ex: ID: 7074140945750507528, 宏: PROMOTION_ID
+     */
+    private Long promotionId;
+
+    /**
+     * 巨量广告体验版中特有的宏参,代表巨量广告体验版的项目ID, ex: ID: 7074140945750507528, 宏: PROJECT_ID
+     */
+    private Long projectId;
+
+    /**
+     * 针对巨量广告体验版,图片素材宏参数(下发原始素材id), 宏: MID1
+     */
+    private String mid1;
+
+    /**
+     * 针对巨量广告体验版,标题素材宏参数(下发原始素材id), 宏: MID2
+     */
+    private String mid2;
+
+    /**
+     * 针对巨量广告体验版,视频素材宏参数(下发原始素材id), 宏: MID3
+     */
+    private String mid3;
+
+    /**
+     * 针对巨量广告体验版,搭配试玩素材宏参数(下发原始素材id), 宏: MID4
+     */
+    private String mid4;
+
+    /**
+     * 针对巨量广告体验版,落地页素材宏参数(下发原始素材id), 宏: MID5
+     */
+    private String mid5;
+
+    /**
+     * 针对巨量广告体验版,安卓下载详情页素材宏参数(下发原始素材id), 宏: MID6
+     */
+    private String mid6;
+
+    /**
+     * 广告计划id, ex: 1645988237525045, 宏: AID
+     */
+    private Long aid;
+
+    /**
+     * 广告创意 id, ex: 1650703686054530, 宏: CID
+     */
+    private Long cid;
+
+    /**
+     * 广告组 id, ex: 1651688272934434, 宏: CAMPAIGN_ID
+     */
+    private Long campaignId;
+
+    /**
+     * 创意样式, 2=小图模式、3=大图模式、4=组图模式、5=视频, 宏: CTYPE
+     */
+    private Integer ctype;
+
+    /**
+     * 广告主id, ex: 1631857582073864, 宏: ADVERTISER_ID
+     */
+    private Long advertiserId;
+
+    /**
+     * 广告投放位置, 今日头条:1-10000,80000-110001、西瓜视频:10001-10099、火山小视频:30001-30099、抖音:40001-40099、番茄小说:26001-26099、穿山甲开屏广告:800000000、穿山甲网盟非开屏广告:900000000、通投广告位:33013、搜索:38016, 宏: CSITE
+     */
+    private Integer csite;
+
+    /**
+     * 转化id, ex: 1681681272671401, 宏: CONVERT_ID
+     */
+    private Long convertId;
+
+    /**
+     * 请求下发的id, ex: 20191202180607010026077068090BA60A, 宏: REQUEST_ID
+     */
+    private String requestId;
+
+    /**
+     * 请求下发的id&创意id的md5,16位, ex: b2f97be5b363764d, 宏: TRACK_ID
+     */
+    private String trackId;
+
+    /**
+     * 这次请求的语言, ex: zh, 宏: SL
+     */
+    private String sl;
+
+    /**
+     * 安卓的设备 ID 的 md5 摘要,32位, 假设原始的 imei 是 868823031739689我们最终发送的是 imei 的 md5 摘要:0c2bd03c39f19845bf54ea0abafae70e,会存在部分无法获取imei的情况,则imei会回传空字符串或者0的md5摘要, 宏: IMEI
+     */
+    private String imei;
+
+    /**
+     * IOS 6+的设备id字段,32位, ex: 4FCFEFA1-096D-4176-B352-1870ED6DB777注意,一些例外00000000-0000-0000-0000-000000000000, 如果用户关闭里读取idfa的权限,会导致idfa全部是0, 宏: IDFA
+     */
+    private String idfa;
+
+    /**
+     * IOS 6+的设备id的md5摘要,32位, ex: 09c593c62a6074ae5f859e97a222c0e8,注意,用户关闭读取idfa权限,0值也会进行MD5加密, 宏: IDFA_MD5
+     */
+    private String idfaMd5;
+
+    /**
+     * 安卓id原值的md5,32位, ex: androidId的原值是: 7b5ca2d57178d2f1我们进行md5摘要,最终结果是:873541edf36da9170af47d5b69e82193, 宏: ANDROIDID
+     */
+    private String androidid;
+
+    /**
+     * Android Q及更高版本的设备号,32位, ex: 97e7ef3f-e5f2-d0b8-ccfc-f79bbeaf4841注意,一些例外如果无法获取oaid,oaid会传空字符串, 宏: OAID
+     */
+    private String oaid;
+
+    /**
+     * Android Q及更高版本的设备号的md5摘要,32位, ex: 87f8274c36eb73fabcbf143a10eca6a4,会存在部分无法获取oaid的情况,则该字段会回传空字符串, 宏: OAID_MD5
+     */
+    private String oaidMd5;
+
+    /**
+     * 操作系统平台, 安卓:0、IOS:1、其它:3, 宏: OS
+     */
+    private Integer os;
+
+    /**
+     * 移动设备mac地址,转换成大写字母,去掉“:”,并且取md5摘要后的结果, 假设原始的mac地址是34:d7:12:9b:3a:89去掉“:”后变成 34d7129b3a89变成大写字母34D7129B3A89取MD5摘要,最后变成如下结果:df97bc5021e14256e141b2f036df5a3c, 宏: MAC
+     */
+    private String mac;
+
+    /**
+     * 移动设备 mac 地址,转换成大写字母,并且取md5摘要后的结果,32位, 假设原始的mac地址是 34:d7:12:9b:3a:89变成大写字母: 34:D7:12:9B:3A:89进行MD5摘要,最后变成如下结果:4d0433eb614f5d5ad409a65395426cbe, 宏: MAC1
+     */
+    private String mac1;
+
+    /**
+     * 优先使用上报请求的对端 IP 地址。如果该IP为 IPv6, 则使用客户端获取的 client_ipv4 地址, ex: 61.168.146.195或为空, 宏: IPV4
+     */
+    private String ipv4;
+
+    /**
+     * 优先使用上报请求的对端 IP 地址。如果该IP为 IPv4, 则使用客户端获取的 client_ipv6 地址, ex: 240e:498:1c90:9d00:5513:b9c9:650a:d9d2或为空, 宏: IPV6
+     */
+    private String ipv6;
+
+    /**
+     * [下发逻辑修改 - 0727生效]正常情况下,全量下发IPv4地址。极少数情况如IPV4无法取数,则下发 IPv6, ex: 61.158.146.195或240e:398:1c90:9d00:5513:b9c9:650a:d9d2, 宏: IP
+     */
+    private String ip;
+
+    /**
+     * 用户代理(User Agent),一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。经过url encode, ex: News+7.4.5+rv%3A7.4.5.23%5C%28iPhone%3B+iOS+12.4.1%3B+zh_CN%5C%29Cronet, 宏: UA
+     */
+    private String ua;
+
+    /**
+     * 位置信息,包含三部分:latitude(纬度),longitude(经度)以及precise(确切信息,精度)十进制保留1位小数,西经南纬保留负数,用字母 x 分 割纬度与精度 (先纬后经,最后精度), ex: 35.7x122.4x100.0, 宏: GEO
+     */
+    private String geo;
+
+    /**
+     * 客户端发生广告点击事件的时间,以毫秒为单位时间戳, ex: 1575194434000, 宏: TS
+     */
+    private Long ts;
+
+    /**
+     * 一些跟广告信息相关的回调参数,内容是一个加密字符串,在调用事件回传接口的时候会用到, ex: EJiw267wvfQCGKf2g74ZIPD89-vIATAMOAFCIjIwMTkxMTI3MTQxMTEzMDEwMDI2MDc3MjE1MTUwNTczNTBIAQ==, 宏: CALLBACK_PARAM
+     */
+    private String callbackParam;
+
+    /**
+     * 直接把调用事件回传接口的url生成出来,广告主可以直接使用, ex: https://ad.toutiao.com/track/activate/?callback=EJiw267wvfQCGKf2g74ZIPD89-vIATAMOAFCIjIwMTkxMTI3MTQxMTEzMDEwMDI2MDc3MjE1MTUwNTczNTBIAQ==&os=0&muid=db94e6a60a9c6661e3e03a7d301c25b6, 宏: CALLBACK_URL
+     */
+    private String callbackUrl;
+
+    /**
+     * 手机型号, 包含多种格式, ex: iPhone12,2 (urlencode之后为iPhone12%2c2),iPhone X (urlencode之后为iPhone+X),SM-A750GN (urlencode之后为SM-A750GN), 宏: MODEL
+     */
+    private String model;
+
+    /**
+     * 对外广告位编码, ex: 2045891290, 宏: UNION_SITE
+     */
+    private String unionSite;
+
+    /**
+     * 中国广告协会互联网广告标识,包含最新两个版本的CAID和版本号,url encode之后的json字符串。(【CAID】和【CAID1、CAID2】的信息一致,使用一种即可;建议使用【CAID】,参数中包含多个信息,后续维护成本低), ex: %5B%7B%22version%22%3A%2220220111%22%2C%22caid%22%3A%22912ec803b2ce49e4a541068d495ab570%22%7D%2C%7B%22version%22%3A%2220211207%22%2C%22caid%22%3A%22e332a76c29654fcb7f6e6b31ced090c7%22%7D%5D, 宏: CAID
+     */
+    private String caid;
+
+    /**
+     * 商品id,仅支持站内(不支持穿山甲), 宏: PRODUCTID
+     */
+    private String productid;
+
+    /**
+     * 商品id,同时支持站内和穿山甲, 宏: OUTERID
+     */
+    private String outerid;
+
+
+}

+ 134 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameOceanengineAppOrderLog.java

@@ -0,0 +1,134 @@
+package com.zanxiang.game.back.serve.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author wcc
+ * @since 2024-06-28
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@TableName(GameOceanengineAppOrderLog.TABLE_NAME)
+public class GameOceanengineAppOrderLog implements Serializable {
+    private static final long serialVersionUID = 1L;
+    public static final String TABLE_NAME = "t_game_oceanengine_app_order_log";
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    private String userId;
+
+    /**
+     * 用户设备mac地址
+     */
+    private String mac;
+
+    /**
+     * 设备唯一编号IMEI
+     */
+    private String imei;
+
+    /**
+     * 设备OAID
+     */
+    private String oaid;
+
+    /**
+     * 安卓id, (仅安卓设备才有值)
+     */
+    private String androidId;
+
+    /**
+     * IOS设备IDFA
+     */
+    private String idfa;
+
+    /**
+     * IOS设备CAID
+     */
+    private String caid;
+
+    /**
+     * 游戏 id
+     */
+    private Long gameId;
+
+    /**
+     * 广告账号_id
+     */
+    private Long accountId;
+
+    private Long backPolicyId;
+
+    /**
+     * 渠道标识
+     */
+    private String agentKey;
+
+    /**
+     * 订单编号
+     */
+    private String orderNo;
+
+    /**
+     * 订单金额(分)
+     */
+    private Long amount;
+
+    /**
+     * 支付状态,0 : 预下单, 1 : 待支付,2 : 支付成功,-1 : 已取消
+     */
+    private Integer orderStatus;
+
+    /**
+     * 下单时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 支付时间
+     */
+    private LocalDateTime payTime;
+
+    private Integer backStatus;
+
+    /**
+     * 注册时间
+     */
+    private LocalDateTime regTime;
+
+    private String roleId;
+
+    private String roleName;
+
+    /**
+     * 是否是首单
+     */
+    private Boolean isFirstOrder;
+
+    /**
+     * 回传金额
+     */
+    private Long backMoney;
+
+    /**
+     * 回传信息
+     */
+    private String backMsg;
+
+
+}

+ 100 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameOceanengineAppRoleRegisterLog.java

@@ -0,0 +1,100 @@
+package com.zanxiang.game.back.serve.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author wcc
+ * @since 2024-06-28
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@TableName(GameOceanengineAppRoleRegisterLog.TABLE_NAME)
+public class GameOceanengineAppRoleRegisterLog implements Serializable {
+    private static final long serialVersionUID = 1L;
+    public static final String TABLE_NAME = "t_game_oceanengine_app_role_register_log";
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    private String userId;
+
+    /**
+     * 用户设备mac地址
+     */
+    private String mac;
+
+    /**
+     * 设备唯一编号IMEI
+     */
+    private String imei;
+
+    /**
+     * 设备OAID
+     */
+    private String oaid;
+
+    /**
+     * 安卓id, (仅安卓设备才有值)
+     */
+    private String androidId;
+
+    /**
+     * IOS设备IDFA
+     */
+    private String idfa;
+
+    /**
+     * IOS设备CAID
+     */
+    private String caid;
+
+    /**
+     * 游戏 id
+     */
+    private Long gameId;
+
+    /**
+     * 广告账号_id
+     */
+    private Long accountId;
+
+    /**
+     * 渠道标识
+     */
+    private String agentKey;
+
+    /**
+     * 角色 id
+     */
+    private String roleId;
+
+    /**
+     * 角色名称
+     */
+    private String roleName;
+
+    /**
+     * 创角时间
+     */
+    private LocalDateTime registerTime;
+
+    private Integer backStatus;
+
+    private LocalDateTime createTime;
+
+
+}

+ 90 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameOceanengineAppUserLog.java

@@ -0,0 +1,90 @@
+package com.zanxiang.game.back.serve.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author wcc
+ * @since 2024-06-28
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@TableName(GameOceanengineAppUserLog.TABLE_NAME)
+public class GameOceanengineAppUserLog implements Serializable {
+    private static final long serialVersionUID = 1L;
+    public static final String TABLE_NAME = "t_game_oceanengine_app_user_log";
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    private String userId;
+
+    /**
+     * 用户设备mac地址
+     */
+    private String mac;
+
+    /**
+     * 设备唯一编号IMEI
+     */
+    private String imei;
+
+    /**
+     * 设备OAID
+     */
+    private String oaid;
+
+    /**
+     * 安卓id, (仅安卓设备才有值)
+     */
+    private String androidId;
+
+    /**
+     * IOS设备IDFA
+     */
+    private String idfa;
+
+    /**
+     * IOS设备CAID
+     */
+    private String caid;
+
+    /**
+     * 游戏 id
+     */
+    private Long gameId;
+
+    /**
+     * 广告账号_id
+     */
+    private Long accountId;
+
+    /**
+     * 渠道标识
+     */
+    private String agentKey;
+
+    /**
+     * 激活/注册时间
+     */
+    private LocalDateTime activeTime;
+
+    private Integer backStatus;
+
+    private LocalDateTime createTime;
+
+
+}

+ 111 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentAppBackLog.java

@@ -0,0 +1,111 @@
+package com.zanxiang.game.back.serve.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * <p>
+ * 腾讯 APP回传日志表
+ * </p>
+ *
+ * @author wcc
+ * @since 2024-06-28
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@TableName(GameTencentAppBackLog.TABLE_NAME)
+public class GameTencentAppBackLog implements Serializable {
+    private static final long serialVersionUID = 1L;
+    public static final String TABLE_NAME = "t_game_tencent_app_back_log";
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    private String userId;
+
+    /**
+     * 游戏id
+     */
+    private Long gameId;
+
+    /**
+     * 广告账号ID
+     */
+    private Long adAccountId;
+
+    /**
+     * 数据源ID
+     */
+    private Long userActionSetId;
+
+    /**
+     * 行为发生时,客户端的时间点
+     */
+    private LocalDateTime actionTime;
+
+    /**
+     * 用户设备mac地址
+     */
+    private String mac;
+
+    /**
+     * 设备唯一编号IMEI
+     */
+    private String imei;
+
+    /**
+     * 设备OAID
+     */
+    private String oaid;
+
+    /**
+     * 安卓id, (仅安卓设备才有值)
+     */
+    private String androidId;
+
+    /**
+     * IOS设备IDFA
+     */
+    private String idfa;
+
+    /**
+     * IOS设备CAID
+     */
+    private String caid;
+
+    /**
+     * 行为类型:(REGISTER/PURCHASE/COMPLETE_ORDER)
+     */
+    private String actionType;
+
+    /**
+     * 订单ID
+     */
+    private String orderId;
+
+    /**
+     * 回传时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 回传日志
+     */
+    private String backLog;
+
+    /**
+     * 行为参数
+     */
+    private String actionParam;
+
+
+}

+ 204 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentAppCallback.java

@@ -0,0 +1,204 @@
+package com.zanxiang.game.back.serve.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.time.LocalDate;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * <p>
+ * 腾讯游戏 APP 监测链接回传数据(文档:https://datanexus.qq.com/doc/develop/guider/interface/conversion/ad_track_click#5-%E5%AD%97%E6%AE%B5%E5%88%97%E8%A1%A8)
+ * </p>
+ *
+ * @author wcc
+ * @since 2024-06-27
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@TableName(GameTencentAppCallback.TABLE_NAME)
+public class GameTencentAppCallback implements Serializable {
+    private static final long serialVersionUID = 1L;
+    public static final String TABLE_NAME = "t_game_tencent_app_callback";
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 时间发生日期
+     */
+    private LocalDate day;
+
+    /**
+     * 点击id, ex: 24oi6xq2aaakvagnqu7a, 宏: __CLICK_ID__
+     */
+    private String clickId;
+
+    /**
+     * 点击时间, ex: 1586437362, 宏: __CLICK_TIME__
+     */
+    private Long clickTime;
+
+    /**
+     * 曝光时间, ex: 1586437361, ex: , 宏: __IMPRESSION_TIME__
+     */
+    private Long impressionTime;
+
+    /**
+     * 广告组id(实际为广告id), ex: 228691429, ex: , 宏: __ADGROUP_ID__
+     */
+    private Long adgroupId;
+
+    /**
+     * 创意 ID, ex: 654321, 宏: __DYNAMIC_CREATIVE_ID__
+     */
+    private Long dynamicCreativeId;
+
+    /**
+     * 营销资产ID, ex: 12345, 宏: __MARKETING_ASSET_ID__
+     */
+    private Long marketingAssetId;
+
+    /**
+     * 素材标签ID, 宏: __MATERIAL_PACKAGE_ID__
+     */
+    private String materialPackageId;
+
+    /**
+     * 广告投放平台, 1:GDT entrance、3:京东直投、5:经 wechat mp 投放的广告、6:京东运营、8:QQ 公众账号平台、9:移动联盟 SSP、10:58 运营、11:58 商户、12:易车运营、13:易车商户、14:融 360 运营、15:融 360 商户、16:点评运营、17:点评商户、18:来自 OMG 的广告主、19:京东外单, 宏: __AD_PLATFORM_TYPE__
+     */
+    private Integer adPlatformType;
+
+    /**
+     * 广告主id, ex: 9471147, 宏: __ACCOUNT_ID__
+     */
+    private Long accountId;
+
+    /**
+     * 代理商id, ex: 1050262, 宏: __AGENCY_ID__
+     */
+    private Long agencyId;
+
+    /**
+     * 点击sku, ex: 478c4a93a054f7c9087b4ecb1f03f8a1, 宏: __CLICK_SKU_ID__
+     */
+    private String clickSkuId;
+
+    /**
+     * 设备类型, ex: ios、android, 宏: __DEVICE_OS_TYPE__
+     */
+    private String deviceOsType;
+
+    /**
+     * 请求时间, ex: 1586437335, 宏: __PROCESS_TIME__
+     */
+    private Long processTime;
+
+    /**
+     * 应用id, ex: 1101072624、wx69618ae091cf2c76, 宏: __PROMOTED_OBJECT_ID__
+     */
+    private String promotedObjectId;
+
+    /**
+     * 请求id, ex: vqp7xdombqonw, 宏: __REQUEST_ID__
+     */
+    private String requestId;
+
+    /**
+     * 曝光id, ex: xkrx5et47h7g401, 宏: __IMPRESSION_ID__
+     */
+    private String impressionId;
+
+    /**
+     * 设备id(imei或idfa的加密值),对 IMEI 设备号转成小写,再进行md5编码,再小写,32位、对 IDFA 设备号保持大写,再进行 md5 编码,再小写,32位, 宏: __MUID__
+     */
+    private String muid;
+
+    /**
+     * 安卓id做md5加密后小写, ex: 797745b011e3286de9e1a1c59ba72c97, 宏: __HASH_ANDROID_ID__
+     */
+    private String hashAndroidId;
+
+    /**
+     * 媒体投放系统获取的用户终端的公共IPV4地址, ex: 183.226.102.120, 宏: __IP__
+     */
+    private String ip;
+
+    /**
+     * 用户代理(user_agent), ex: Dalvik%2F2.1.0+%28Linux%3B+U%3B+Android+8.0.0%3B+PIC-AL00+Build%2FHUAWEIPIC-AL00%29, 宏: __USER_AGENT__
+     */
+    private String userAgent;
+
+    /**
+     * 情况1:使用 DataNexus 配置,并与广告直接绑定(ex: 空值)、情况2:新版转化归因中的监测链接信息(使用 DataNexus 或直接填写监测链接)直接提供上报信息回传接口的 url,示例为url encode 编码原值,广告主需要 decode 作为 post 请求url回传至腾讯广告(ex: http%3A%2F%2Ftracking.e.qq.com%2Fconv%3Fcb%3DxXx%252BxXx%253D%26conv_id%3D123)、情况3:使用投放管理平台 - 工具(ex: http://tracking.e.qq.com/conv?cb=%s&&%s&&%s&&%s 其中%s代表的参数分别为 productId、productType、advertiserId、clickId), 宏: __CALLBACK__
+     */
+    private String callback;
+
+    /**
+     * 联盟广告位id, ex: 8144201, 宏: __ENCRYPTED_POSITION_ID__
+     */
+    private String encryptedPositionId;
+
+    /**
+     * 媒体投放系统获取的用户终端的公共IPV6地址, ex: 2409%3A8a55%3A4cc0%3A4050%3A2507%3A4922%3Abbe0%3A524b, 宏: __IPV6__
+     */
+    private String ipv6;
+
+    /**
+     * Android Q 及更高版本的设备号,64位及以下,取原值后做md5加密, ex: 9d271e4d04de7e4b0b4f1df20e79ce64, 宏: __HASH_OAID__
+     */
+    private String hashOaid;
+
+    /**
+     * URL Encode后的JSON数组;其中qaid为中广协ID(即CAID),hash_qaid为CAID原值MD5加密后的结果, version为腾讯版本号,支持两个版本同时下发(即最新版和上一版),腾讯版本号与中广协版本对应关系为:腾讯 1001 = 中广协 20200901;腾讯 1003 = 中广协 20201230; 腾讯1004 = 中广协 20211207;腾讯1005=中广协 20220111;腾讯1006=中广协 20230330, 宏: __QAID_CAA__
+     */
+    private String caid;
+
+    /**
+     * 机型, ex:  PCKM00、Redmi 7、iPhone 7..., 宏: __MODEL__
+     */
+    private String model;
+
+    /**
+     * 专用于网页类小程序转化规则的点击监测下发,其它类型不支持该字段下发。每个用户针对小程序应用会产生一个安全的OpenID,只针对当前的小程序有效, ex: ozWH25VK0aodxYMZrX0Lqj9HHhrg, 宏: __WECHAT_OPEN_ID__
+     */
+    private String wechatOpenid;
+
+    /**
+     * 媒体投放系统获取的用户终端的公共IPV4地址MD5加密后转小写,仅在新版转化里支持配置, 宏: __IP_MD5__
+     */
+    private String ipMd5;
+
+    /**
+     * 媒体投放系统获取的用户终端的公共IPV6地址MD5加密后转小写,仅在新版转化里支持配置, 宏: __IPV6_MD5__
+     */
+    private String ipv6Md5;
+
+    /**
+     * 渠道包id, 只 for Android 设备生效, 宏: __CHANNEL_PACKAGE_ID__
+     */
+    private String channelPackageId;
+
+    /**
+     * 操作系统版本, 只 for iOS 和 Android 设备生效, 宏: __DEVICE_OS_VERSION__
+     */
+    private String deviceOsVersion;
+
+    /**
+     * 行为类型, LANDING_PAGE_CLICK:点击跳转按钮,RESERVATION:表单预约, 宏: __ACT_TYPE__
+     */
+    private String actType;
+
+    /**
+     * 行为时间, ex: 1586437361, 宏: __ACT_TIME__
+     */
+    private Long actTime;
+
+
+}

+ 161 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentAppOrder.java

@@ -0,0 +1,161 @@
+package com.zanxiang.game.back.serve.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * <p>
+ * 游戏腾讯APP订单表
+ * </p>
+ *
+ * @author wcc
+ * @since 2024-06-28
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@TableName(GameTencentAppOrder.TABLE_NAME)
+public class GameTencentAppOrder implements Serializable {
+    private static final long serialVersionUID = 1L;
+    public static final String TABLE_NAME = "t_game_tencent_app_order";
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    private String userId;
+
+    /**
+     * 渠道号
+     */
+    private String channel;
+
+    /**
+     * 游戏ID
+     */
+    private Long gameId;
+
+    /**
+     * 广告账号ID
+     */
+    private Long adAccountId;
+
+    /**
+     * 注册时间
+     */
+    private LocalDateTime registerTime;
+
+    /**
+     * 关注时间
+     */
+    private LocalDateTime subscribeTime;
+
+    /**
+     * 充值金额(分)
+     */
+    private Long rechargeMoney;
+
+    /**
+     * 充值时间
+     */
+    private LocalDateTime rechargeTime;
+
+    /**
+     * 订单ID
+     */
+    private String orderId;
+
+    /**
+     * 用户设备mac地址
+     */
+    private String mac;
+
+    /**
+     * 设备唯一编号IMEI
+     */
+    private String imei;
+
+    /**
+     * 设备OAID
+     */
+    private String oaid;
+
+    /**
+     * 安卓id, (仅安卓设备才有值)
+     */
+    private String androidId;
+
+    /**
+     * IOS设备IDFA
+     */
+    private String idfa;
+
+    /**
+     * IOS设备CAID
+     */
+    private String caid;
+
+    /**
+     * 支付状态,0 : 预下单, 1 : 待支付,2 : 支付成功,-1 : 已取消
+     */
+    private Integer orderStatus;
+
+    /**
+     * 支付时间
+     */
+    private LocalDateTime payTime;
+
+    /**
+     * 0:未回传;1:回传
+     */
+    private Integer isBack;
+
+    private LocalDateTime createTime;
+
+    private LocalDateTime updateTime;
+
+    private Long updateBy;
+
+    /**
+     * 回传日志
+     */
+    private String backLog;
+
+    /**
+     * 回传策略id
+     */
+    private Long backPolicyId;
+
+    /**
+     * 数据源ID
+     */
+    private Long userActionSetId;
+
+    private String roleId;
+
+    private String roleName;
+
+    /**
+     * 是否是首单
+     */
+    private Boolean isFirstOrder;
+
+    /**
+     * 回传金额
+     */
+    private Long backMoney;
+
+    /**
+     * 回传信息
+     */
+    private String backMsg;
+
+
+}

+ 84 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentAppOrderSplitLog.java

@@ -0,0 +1,84 @@
+package com.zanxiang.game.back.serve.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author wcc
+ * @since 2024-06-28
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@TableName(GameTencentAppOrderSplitLog.TABLE_NAME)
+public class GameTencentAppOrderSplitLog implements Serializable {
+    private static final long serialVersionUID = 1L;
+    public static final String TABLE_NAME = "t_game_tencent_app_order_split_log";
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    private String userId;
+
+    /**
+     * 回传日期
+     */
+    private LocalDate backDay;
+
+    /**
+     * 订单编号
+     */
+    private String orderNo;
+
+    /**
+     * 回传序号
+     */
+    private Integer backIndex;
+
+    /**
+     * 总计拆成几单
+     */
+    private Integer backCount;
+
+    /**
+     * 拆分的回传金额
+     */
+    private Long splitMoney;
+
+    /**
+     * 回传时间
+     */
+    private LocalDateTime backTime;
+
+    /**
+     * 真实的回传时间
+     */
+    private LocalDateTime executeTime;
+
+    /**
+     * 回传状态
+     */
+    private Integer backStatus;
+
+    private LocalDateTime createTime;
+
+    /**
+     * 回传失败消息
+     */
+    private String backErrorMsg;
+
+
+}

+ 117 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentAppRoleRegister.java

@@ -0,0 +1,117 @@
+package com.zanxiang.game.back.serve.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * <p>
+ * 游戏腾讯APP角色创建表
+ * </p>
+ *
+ * @author wcc
+ * @since 2024-06-28
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@TableName(GameTencentAppRoleRegister.TABLE_NAME)
+public class GameTencentAppRoleRegister implements Serializable {
+    private static final long serialVersionUID = 1L;
+    public static final String TABLE_NAME = "t_game_tencent_app_role_register";
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    private String userId;
+
+    /**
+     * 渠道号
+     */
+    private String channel;
+
+    /**
+     * 游戏ID
+     */
+    private Long gameId;
+
+    /**
+     * 广告账号ID
+     */
+    private Long adAccountId;
+
+    /**
+     * 注册时间
+     */
+    private LocalDateTime registerTime;
+
+    /**
+     * 用户设备mac地址
+     */
+    private String mac;
+
+    /**
+     * 设备唯一编号IMEI
+     */
+    private String imei;
+
+    /**
+     * 设备OAID
+     */
+    private String oaid;
+
+    /**
+     * 安卓id, (仅安卓设备才有值)
+     */
+    private String androidId;
+
+    /**
+     * IOS设备IDFA
+     */
+    private String idfa;
+
+    /**
+     * IOS设备CAID
+     */
+    private String caid;
+
+    /**
+     * 0:未回传;1:回传
+     */
+    private Integer isBack;
+
+    private LocalDateTime createTime;
+
+    /**
+     * 回传日志
+     */
+    private String backLog;
+
+    /**
+     * 回传策略id
+     */
+    private Long backPolicyId;
+
+    /**
+     * 数据源ID
+     */
+    private Long userActionSetId;
+
+    private String roleId;
+
+    private String roleName;
+
+    /**
+     * 回传信息
+     */
+    private String backMsg;
+
+
+}

+ 117 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentAppUser.java

@@ -0,0 +1,117 @@
+package com.zanxiang.game.back.serve.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * <p>
+ * 游戏腾讯 APP用户表
+ * </p>
+ *
+ * @author wcc
+ * @since 2024-06-28
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@TableName(GameTencentAppUser.TABLE_NAME)
+public class GameTencentAppUser implements Serializable {
+    private static final long serialVersionUID = 1L;
+    public static final String TABLE_NAME = "t_game_tencent_app_user";
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    private String userId;
+
+    /**
+     * 渠道号
+     */
+    private String channel;
+
+    /**
+     * 游戏ID
+     */
+    private Long gameId;
+
+    /**
+     * 广告账号ID
+     */
+    private Long adAccountId;
+
+    /**
+     * 注册时间
+     */
+    private LocalDateTime registerTime;
+
+    /**
+     * 关注时间
+     */
+    private LocalDateTime subscribeTime;
+
+    /**
+     * 用户设备mac地址
+     */
+    private String mac;
+
+    /**
+     * 设备唯一编号IMEI
+     */
+    private String imei;
+
+    /**
+     * 设备OAID
+     */
+    private String oaid;
+
+    /**
+     * 安卓id, (仅安卓设备才有值)
+     */
+    private String androidId;
+
+    /**
+     * IOS设备IDFA
+     */
+    private String idfa;
+
+    /**
+     * IOS设备CAID
+     */
+    private String caid;
+
+    /**
+     * 0:未回传;1:回传;-1:回传失败
+     */
+    private Integer isBack;
+
+    private LocalDateTime createTime;
+
+    private LocalDateTime updateTime;
+
+    private Long updateBy;
+
+    /**
+     * 回传日志
+     */
+    private String backLog;
+
+    /**
+     * 回传策略id
+     */
+    private Long backPolicyId;
+
+    /**
+     * 数据源ID
+     */
+    private Long userActionSetId;
+
+
+}

+ 212 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/rpc/impl/TencentAppBackRpcImpl.java

@@ -0,0 +1,212 @@
+package com.zanxiang.game.back.serve.rpc.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.zanxiang.game.back.base.pojo.dto.*;
+import com.zanxiang.game.back.base.pojo.enums.OrderStatusEnum;
+import com.zanxiang.game.back.base.rpc.ITencentAppBackRpc;
+import com.zanxiang.game.back.serve.pojo.entity.*;
+import com.zanxiang.game.back.serve.pojo.enums.BackStatusEnum;
+import com.zanxiang.game.back.serve.service.IGameTencentAppOrderService;
+import com.zanxiang.game.back.serve.service.IGameTencentAppRoleRegisterService;
+import com.zanxiang.game.back.serve.service.IGameTencentAppUserService;
+import com.zanxiang.module.util.JsonUtil;
+import com.zanxiang.module.util.pojo.ResultVO;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.dubbo.config.annotation.DubboService;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.time.LocalDateTime;
+import java.util.Objects;
+
+@Slf4j
+@DubboService
+public class TencentAppBackRpcImpl implements ITencentAppBackRpc {
+    @Autowired
+    private IGameTencentAppUserService gameTencentAppUserService;
+    @Autowired
+    private IGameTencentAppRoleRegisterService gameTencentAppRoleRegisterService;
+    @Autowired
+    private IGameTencentAppOrderService gameTencentAppOrderService;
+
+    @Override
+    public ResultVO<Boolean> backUser(TencentUserAppRpcDTO dto) {
+        log.error("腾讯 APP用户回传收到:{}", JsonUtil.toString(dto));
+        if (StringUtils.isBlank(dto.getMac())) {
+            dto.setMac("");
+        }
+        if(StringUtils.isBlank(dto.getImei())) {
+            dto.setImei("");
+        }
+        if(StringUtils.isBlank(dto.getOaid())) {
+            dto.setOaid("");
+        }
+        if(StringUtils.isBlank(dto.getAndroidId())) {
+            dto.setAndroidId("");
+        }
+        if(StringUtils.isBlank(dto.getIdfa())) {
+            dto.setIdfa("");
+        }
+        if(StringUtils.isBlank(dto.getCaid())) {
+            dto.setCaid("");
+        }
+        if(StringUtils.isBlank(dto.getMac())
+                && StringUtils.isBlank(dto.getImei())
+                && StringUtils.isBlank(dto.getOaid())
+                && StringUtils.isBlank(dto.getAndroidId())
+                && StringUtils.isBlank(dto.getIdfa())
+                && StringUtils.isBlank(dto.getCaid())) {
+            return ResultVO.fail("找不到用户唯一标识");
+        }
+        GameTencentAppUser gameTencentUser = GameTencentAppUser.builder()
+                .adAccountId(dto.getAdAccountId())
+                .gameId(dto.getGameId())
+                .channel(dto.getChannel())
+                .subscribeTime(dto.getSubscribeTime())
+                .registerTime(dto.getRegisterTime())
+                .mac(dto.getMac())
+                .imei(dto.getImei())
+                .oaid(dto.getOaid())
+                .androidId(dto.getAndroidId())
+                .idfa(dto.getIdfa())
+                .caid(dto.getCaid())
+                .isBack(BackStatusEnum.NO.getBackStatus())
+                .userActionSetId(dto.getUserActionSetId())
+                .createTime(LocalDateTime.now())
+                .build();
+        gameTencentAppUserService.save(gameTencentUser);
+        return ResultVO.ok(true);
+        // 激活现在默认不回传了,等创角的时候一起回传
+        // return ResultVO.ok(gameTencentUserService.userBack(gameTencentUser, false));
+    }
+
+    @Override
+    public ResultVO<Boolean> backRoleRegister(TencentRoleRegisterAppRpcDTO dto) {
+        log.error("腾讯 APP创角回传收到:{}", JsonUtil.toString(dto));
+        if (StringUtils.isBlank(dto.getMac())) {
+            dto.setMac("");
+        }
+        if(StringUtils.isBlank(dto.getImei())) {
+            dto.setImei("");
+        }
+        if(StringUtils.isBlank(dto.getOaid())) {
+            dto.setOaid("");
+        }
+        if(StringUtils.isBlank(dto.getAndroidId())) {
+            dto.setAndroidId("");
+        }
+        if(StringUtils.isBlank(dto.getIdfa())) {
+            dto.setIdfa("");
+        }
+        if(StringUtils.isBlank(dto.getCaid())) {
+            dto.setCaid("");
+        }
+        if(StringUtils.isBlank(dto.getMac())
+                && StringUtils.isBlank(dto.getImei())
+                && StringUtils.isBlank(dto.getOaid())
+                && StringUtils.isBlank(dto.getAndroidId())
+                && StringUtils.isBlank(dto.getIdfa())
+                && StringUtils.isBlank(dto.getCaid())) {
+            return ResultVO.fail("找不到用户唯一标识");
+        }
+        GameTencentAppRoleRegister roleRegister = GameTencentAppRoleRegister.builder()
+                .backPolicyId(dto.getBackPolicyId())
+                .channel(dto.getChannel())
+                .gameId(dto.getGameId())
+                .adAccountId(dto.getAdAccountId())
+                .registerTime(dto.getRegisterTime())
+                .mac(dto.getMac())
+                .imei(dto.getImei())
+                .oaid(dto.getOaid())
+                .androidId(dto.getAndroidId())
+                .idfa(dto.getIdfa())
+                .caid(dto.getCaid())
+                .isBack(BackStatusEnum.NO.getBackStatus())
+                .userActionSetId(dto.getUserActionSetId())
+                .createTime(LocalDateTime.now())
+                .roleId(dto.getRoleId())
+                .roleName(dto.getRoleName())
+                .build();
+        gameTencentAppRoleRegisterService.save(roleRegister);
+        // return ResultVO.ok(gameTencentAppRoleRegisterService.roleRegisterBack(roleRegister));
+        return ResultVO.ok(true);
+    }
+
+    @Override
+    public ResultVO<Boolean> backOrder(TencentOrderAppRpcDTO dto) {
+        if (Objects.equals(OrderStatusEnum.SUCCESS_PAY.getValue(), dto.getOrderStatus())) {
+            log.error("腾讯 APP订单回传收到:{}。", JsonUtil.toString(dto));
+        } else {
+            log.error("腾讯H5订单回传收到:{}。订单未支付,直接过滤", JsonUtil.toString(dto));
+            return ResultVO.ok(true);
+        }
+        if (StringUtils.isBlank(dto.getMac())) {
+            dto.setMac("");
+        }
+        if(StringUtils.isBlank(dto.getImei())) {
+            dto.setImei("");
+        }
+        if(StringUtils.isBlank(dto.getOaid())) {
+            dto.setOaid("");
+        }
+        if(StringUtils.isBlank(dto.getAndroidId())) {
+            dto.setAndroidId("");
+        }
+        if(StringUtils.isBlank(dto.getIdfa())) {
+            dto.setIdfa("");
+        }
+        if(StringUtils.isBlank(dto.getCaid())) {
+            dto.setCaid("");
+        }
+        if(StringUtils.isBlank(dto.getMac())
+                && StringUtils.isBlank(dto.getImei())
+                && StringUtils.isBlank(dto.getOaid())
+                && StringUtils.isBlank(dto.getAndroidId())
+                && StringUtils.isBlank(dto.getIdfa())
+                && StringUtils.isBlank(dto.getCaid())) {
+            return ResultVO.fail("找不到用户唯一标识");
+        }
+        boolean isFirstOrder = gameTencentAppOrderService.getOne(new LambdaQueryWrapper<GameTencentAppOrder>()
+                .select(GameTencentAppOrder::getOrderId)
+                .eq(GameTencentAppOrder::getGameId, dto.getGameId())
+                .eq(GameTencentAppOrder::getAdAccountId, dto.getAdAccountId())
+                .eq(GameTencentAppOrder::getMac, dto.getMac())
+                .eq(GameTencentAppOrder::getImei, dto.getImei())
+                .eq(GameTencentAppOrder::getOaid, dto.getOaid())
+                .eq(GameTencentAppOrder::getAndroidId, dto.getAndroidId())
+                .eq(GameTencentAppOrder::getIdfa, dto.getIdfa())
+                .eq(GameTencentAppOrder::getCaid, dto.getCaid())
+                .eq(GameTencentAppOrder::getOrderStatus, OrderStatusEnum.SUCCESS_PAY.getValue())
+                .last("limit 1")
+        ) == null;
+        //订单保存
+        GameTencentAppOrder gameTencentOrder = GameTencentAppOrder.builder()
+                .adAccountId(dto.getAdAccountId())
+                .gameId(dto.getGameId())
+                .orderId(dto.getOrderId())
+                .channel(dto.getChannel())
+                .rechargeMoney(dto.getRechargeMoney())
+                .rechargeTime(dto.getRechargeTime())
+                .subscribeTime(dto.getSubscribeTime())
+                .registerTime(dto.getRegisterTime())
+                .mac(dto.getMac())
+                .imei(dto.getImei())
+                .oaid(dto.getOaid())
+                .androidId(dto.getAndroidId())
+                .idfa(dto.getIdfa())
+                .caid(dto.getCaid())
+                .orderStatus(dto.getOrderStatus())
+                .payTime(dto.getPayTime())
+                .createTime(LocalDateTime.now())
+                .isBack(BackStatusEnum.NO.getBackStatus())
+                .backPolicyId(dto.getBackPolicyId())
+                .userActionSetId(dto.getUserActionSetId())
+                .roleId(dto.getRoleId())
+                .roleName(dto.getRoleName())
+                .isFirstOrder(isFirstOrder)
+                .build();
+        gameTencentAppOrderService.save(gameTencentOrder);
+        return ResultVO.ok(true);
+        // return ResultVO.ok(gameTencentAppOrderService.orderBack(gameTencentOrder));
+    }
+}

+ 258 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/rpc/impl/TtAppBackRpcImpl.java

@@ -0,0 +1,258 @@
+package com.zanxiang.game.back.serve.rpc.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.zanxiang.game.back.base.pojo.dto.*;
+import com.zanxiang.game.back.base.pojo.enums.OrderStatusEnum;
+import com.zanxiang.game.back.base.pojo.vo.OrderBackQueryRpcVO;
+import com.zanxiang.game.back.base.rpc.ITtAppBackRpc;
+import com.zanxiang.game.back.serve.pojo.entity.*;
+import com.zanxiang.game.back.serve.pojo.enums.BackStatusEnum;
+import com.zanxiang.game.back.serve.service.IGameBackPolicyService;
+import com.zanxiang.game.back.serve.service.IGameOceanengineAppOrderLogService;
+import com.zanxiang.game.back.serve.service.IGameOceanengineAppRoleRegisterLogService;
+import com.zanxiang.game.back.serve.service.IGameOceanengineAppUserLogService;
+import com.zanxiang.game.module.base.ServerInfo;
+import com.zanxiang.game.module.base.rpc.IAgentRpc;
+import com.zanxiang.module.redis.service.IDistributedLockComponent;
+import com.zanxiang.module.util.JsonUtil;
+import com.zanxiang.module.util.pojo.ResultVO;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.apache.dubbo.config.annotation.DubboService;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.time.LocalDateTime;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+@Slf4j
+@DubboService
+public class TtAppBackRpcImpl implements ITtAppBackRpc {
+
+    @Autowired
+    private IGameBackPolicyService gameBackPolicyService;
+    @DubboReference(providedBy = ServerInfo.SERVER_DUBBO_NAME)
+    private IAgentRpc agentRpc;
+    @Autowired
+    private IGameOceanengineAppUserLogService gameOceanengineAppUserLogService;
+    @Autowired
+    private IGameOceanengineAppRoleRegisterLogService gameOceanengineAppRoleRegisterLogService;
+    @Autowired
+    private IGameOceanengineAppOrderLogService gameOceanengineAppOrderLogService;
+    @Autowired
+    private IDistributedLockComponent distributedLockComponent;
+
+    @Override
+    public ResultVO<Boolean> userActiveReport(TtUserActiveAppRpcDTO dto) {
+        log.error("头条 APP用户回传收到:{}", JsonUtil.toString(dto));
+        if (StringUtils.isBlank(dto.getMac())) {
+            dto.setMac("");
+        }
+        if(StringUtils.isBlank(dto.getImei())) {
+            dto.setImei("");
+        }
+        if(StringUtils.isBlank(dto.getOaid())) {
+            dto.setOaid("");
+        }
+        if(StringUtils.isBlank(dto.getAndroidId())) {
+            dto.setAndroidId("");
+        }
+        if(StringUtils.isBlank(dto.getIdfa())) {
+            dto.setIdfa("");
+        }
+        if(StringUtils.isBlank(dto.getCaid())) {
+            dto.setCaid("");
+        }
+        if(StringUtils.isBlank(dto.getUserId()) || (StringUtils.isBlank(dto.getMac())
+                && StringUtils.isBlank(dto.getImei())
+                && StringUtils.isBlank(dto.getOaid())
+                && StringUtils.isBlank(dto.getAndroidId())
+                && StringUtils.isBlank(dto.getIdfa())
+                && StringUtils.isBlank(dto.getCaid()))) {
+            return ResultVO.fail("找不到用户唯一标识");
+        }
+
+        GameOceanengineAppUserLog userLog = GameOceanengineAppUserLog.builder()
+                .userId(dto.getUserId())
+                .mac(dto.getMac())
+                .imei(dto.getImei())
+                .oaid(dto.getOaid())
+                .androidId(dto.getAndroidId())
+                .idfa(dto.getIdfa())
+                .caid(dto.getCaid())
+                .gameId(dto.getGameId())
+                .accountId(dto.getAccountReport().getAccountId())
+                .agentKey(dto.getAgentKey())
+                .activeTime(dto.getActiveTime())
+                .backStatus(BackStatusEnum.NO.getBackStatus())
+                .createTime(LocalDateTime.now())
+                .build();
+        gameOceanengineAppUserLogService.save(userLog);
+        return ResultVO.ok(gameOceanengineAppUserLogService.callback(userLog, Boolean.FALSE));
+    }
+
+    @Override
+    public ResultVO<Boolean> orderReport(TtOrderAppRpcDTO dto) {
+        if (Objects.equals(OrderStatusEnum.SUCCESS_PAY.getValue(), dto.getOrderStatus())) {
+            log.error("头条 APP订单回传收到:{}。", JsonUtil.toString(dto));
+        } else {
+            log.error("头条 APP订单回传收到:{}。订单未支付,直接过滤", JsonUtil.toString(dto));
+            return ResultVO.ok(true);
+        }
+        if (StringUtils.isBlank(dto.getMac())) {
+            dto.setMac("");
+        }
+        if(StringUtils.isBlank(dto.getImei())) {
+            dto.setImei("");
+        }
+        if(StringUtils.isBlank(dto.getOaid())) {
+            dto.setOaid("");
+        }
+        if(StringUtils.isBlank(dto.getAndroidId())) {
+            dto.setAndroidId("");
+        }
+        if(StringUtils.isBlank(dto.getIdfa())) {
+            dto.setIdfa("");
+        }
+        if(StringUtils.isBlank(dto.getCaid())) {
+            dto.setCaid("");
+        }
+        if(StringUtils.isBlank(dto.getUserId()) || (StringUtils.isBlank(dto.getMac())
+                && StringUtils.isBlank(dto.getImei())
+                && StringUtils.isBlank(dto.getOaid())
+                && StringUtils.isBlank(dto.getAndroidId())
+                && StringUtils.isBlank(dto.getIdfa())
+                && StringUtils.isBlank(dto.getCaid()))) {
+            return ResultVO.fail("找不到用户唯一标识");
+        }
+        // 此处加锁防止 cp 方调用过快,导致查询回传结果时判断逻辑没走完
+        String lockKey = com.zanxiang.game.back.base.ServerInfo.SERVER_NAME + ":TtAppOrderBack:" + dto.getGameId() + ":" + dto.getOrderId();
+        distributedLockComponent.doLock(lockKey, 0L, 60L, TimeUnit.SECONDS);
+        try {
+            GameOceanengineAppOrderLog orderLog = GameOceanengineAppOrderLog.builder()
+                    .userId(dto.getUserId())
+                    .mac(dto.getMac())
+                    .imei(dto.getImei())
+                    .oaid(dto.getOaid())
+                    .androidId(dto.getAndroidId())
+                    .idfa(dto.getIdfa())
+                    .caid(dto.getCaid())
+                    .gameId(dto.getGameId())
+                    .backPolicyId(dto.getBackPolicyId())
+                    .accountId(dto.getAccountReport().getAccountId())
+                    .agentKey(dto.getAgentKey())
+                    .regTime(dto.getRegTime())
+                    .orderNo(dto.getOrderId())
+                    .amount(dto.getRechargeMoney())
+                    .orderStatus(dto.getOrderStatus())
+                    .createTime(dto.getCreateTime())
+                    .payTime(dto.getPayTime())
+                    .backStatus(BackStatusEnum.NO.getBackStatus())
+                    .roleId(dto.getRoleId())
+                    .roleName(dto.getRoleName())
+                    .build();
+            boolean isFirstOrder = gameOceanengineAppOrderLogService.getOne(new LambdaQueryWrapper<GameOceanengineAppOrderLog>()
+                    .eq(GameOceanengineAppOrderLog::getGameId, orderLog.getGameId())
+                    .eq(GameOceanengineAppOrderLog::getUserId, orderLog.getUserId())
+                    .eq(GameOceanengineAppOrderLog::getAccountId, orderLog.getAccountId())
+                    .eq(GameOceanengineAppOrderLog::getOrderStatus, OrderStatusEnum.SUCCESS_PAY.getValue())
+                    .last("limit 1")
+            ) == null;
+            orderLog.setIsFirstOrder(isFirstOrder);
+            gameOceanengineAppOrderLogService.save(orderLog);
+            return ResultVO.ok(gameOceanengineAppOrderLogService.callback(orderLog));
+        } finally {
+            distributedLockComponent.unlock(lockKey);
+        }
+    }
+
+    @Override
+    public ResultVO<Boolean> roleRegisterReport(TtRoleRegisterAppRpcDTO dto) {
+        log.error("头条 APP创角回传收到:{}", JsonUtil.toString(dto));
+        if (StringUtils.isBlank(dto.getMac())) {
+            dto.setMac("");
+        }
+        if(StringUtils.isBlank(dto.getImei())) {
+            dto.setImei("");
+        }
+        if(StringUtils.isBlank(dto.getOaid())) {
+            dto.setOaid("");
+        }
+        if(StringUtils.isBlank(dto.getAndroidId())) {
+            dto.setAndroidId("");
+        }
+        if(StringUtils.isBlank(dto.getIdfa())) {
+            dto.setIdfa("");
+        }
+        if(StringUtils.isBlank(dto.getCaid())) {
+            dto.setCaid("");
+        }
+        if(StringUtils.isBlank(dto.getUserId()) || (StringUtils.isBlank(dto.getMac())
+                && StringUtils.isBlank(dto.getImei())
+                && StringUtils.isBlank(dto.getOaid())
+                && StringUtils.isBlank(dto.getAndroidId())
+                && StringUtils.isBlank(dto.getIdfa())
+                && StringUtils.isBlank(dto.getCaid()))) {
+            return ResultVO.fail("找不到用户唯一标识");
+        }
+        GameOceanengineAppRoleRegisterLog roleRegisterLog = GameOceanengineAppRoleRegisterLog.builder()
+                .userId(dto.getUserId())
+                .mac(dto.getMac())
+                .imei(dto.getImei())
+                .oaid(dto.getOaid())
+                .androidId(dto.getAndroidId())
+                .idfa(dto.getIdfa())
+                .caid(dto.getCaid())
+                .gameId(dto.getGameId())
+                .accountId(dto.getAccountReport().getAccountId())
+                .agentKey(dto.getAgentKey())
+                .roleId(dto.getRoleId())
+                .roleName(dto.getRoleName())
+                .registerTime(dto.getRegisterTime())
+                .backStatus(BackStatusEnum.NO.getBackStatus())
+                .createTime(LocalDateTime.now())
+                .build();
+        gameOceanengineAppRoleRegisterLogService.save(roleRegisterLog);
+        return ResultVO.ok(gameOceanengineAppRoleRegisterLogService.callback(roleRegisterLog));
+    }
+
+    @Override
+    public ResultVO<Boolean> userBackQuery(TtAppUserBackQueryRpcDTO dto) {
+        log.error("头条APP用户回传结果查询:{}", JsonUtil.toString(dto));
+        return ResultVO.ok(Boolean.TRUE);
+    }
+
+    @Override
+    public ResultVO<OrderBackQueryRpcVO> orderBackQuery(TtAppOrderBackQueryRpcDTO dto) {
+        log.error("头条APP订单回传结果查询:{}", JsonUtil.toString(dto));
+
+        // 加锁最大等待 60s
+        String lockKey = com.zanxiang.game.back.base.ServerInfo.SERVER_NAME + ":TtAppOrderBack:" + dto.getGameId() + ":" + dto.getOrderId();
+        distributedLockComponent.doLock(lockKey, 60, 1L, TimeUnit.SECONDS);
+
+        GameOceanengineAppOrderLog orderLog = gameOceanengineAppOrderLogService.getOne(new LambdaQueryWrapper<GameOceanengineAppOrderLog>()
+                .eq(GameOceanengineAppOrderLog::getOrderNo, dto.getOrderId())
+                .eq(GameOceanengineAppOrderLog::getGameId, dto.getGameId())
+                .eq(GameOceanengineAppOrderLog::getAgentKey, dto.getAgentKey())
+                .eq(GameOceanengineAppOrderLog::getUserId, dto.getUserId())
+        );
+        if  (orderLog == null) {
+            return ResultVO.ok(OrderBackQueryRpcVO.builder()
+                            .doBack(Boolean.FALSE)
+                            .backMsg("回传异常,找不到订单:" + dto.getOrderId())
+                    .build());
+        }
+        return ResultVO.ok(OrderBackQueryRpcVO.builder()
+                        .doBack(BackStatusEnum.getByValue(orderLog.getBackStatus()) ==  BackStatusEnum.SUCCESS)
+                        .backMoney(orderLog.getBackMoney())
+                        .backMsg(orderLog.getBackMsg())
+                .build());
+    }
+
+    @Override
+    public ResultVO<Boolean> roleRegisterBackQuery(TtAppRoleRegisterBackQueryRpcDTO dto) {
+        log.error("头条APP创角回传结果查询:{}", JsonUtil.toString(dto));
+        return ResultVO.ok(Boolean.TRUE);
+    }
+}

+ 7 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameOceanengineAppBackLogService.java

@@ -0,0 +1,7 @@
+package com.zanxiang.game.back.serve.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineAppBackLog;
+
+public interface IGameOceanengineAppBackLogService extends IService<GameOceanengineAppBackLog> {
+}

+ 10 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameOceanengineAppCallbackService.java

@@ -0,0 +1,10 @@
+package com.zanxiang.game.back.serve.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zanxiang.game.back.serve.pojo.dto.GameOceanengineAppCallbackDTO;
+import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineAppCallback;
+
+public interface IGameOceanengineAppCallbackService extends IService<GameOceanengineAppCallback> {
+
+    boolean callback(GameOceanengineAppCallbackDTO dto);
+}

+ 15 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameOceanengineAppOrderLogService.java

@@ -0,0 +1,15 @@
+package com.zanxiang.game.back.serve.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.github.sd4324530.jtuple.Tuple2;
+import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineAppOrderLog;
+import com.zanxiang.game.back.serve.pojo.enums.BackStatusEnum;
+
+import java.time.LocalDateTime;
+
+public interface IGameOceanengineAppOrderLogService extends IService<GameOceanengineAppOrderLog> {
+
+    boolean callback(GameOceanengineAppOrderLog orderLog);
+
+    Tuple2<BackStatusEnum, String> doCallback(GameOceanengineAppOrderLog orderLog, LocalDateTime backTime, Long backMoney);
+}

+ 9 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameOceanengineAppRoleRegisterLogService.java

@@ -0,0 +1,9 @@
+package com.zanxiang.game.back.serve.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineAppRoleRegisterLog;
+
+public interface IGameOceanengineAppRoleRegisterLogService extends IService<GameOceanengineAppRoleRegisterLog> {
+
+    boolean callback(GameOceanengineAppRoleRegisterLog roleRegisterLog);
+}

+ 9 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameOceanengineAppUserLogService.java

@@ -0,0 +1,9 @@
+package com.zanxiang.game.back.serve.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineAppUserLog;
+
+public interface IGameOceanengineAppUserLogService extends IService<GameOceanengineAppUserLog> {
+
+    boolean callback(GameOceanengineAppUserLog userLog, boolean mustBack);
+}

+ 7 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentAppBackLogService.java

@@ -0,0 +1,7 @@
+package com.zanxiang.game.back.serve.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentAppBackLog;
+
+public interface IGameTencentAppBackLogService extends IService<GameTencentAppBackLog> {
+}

+ 10 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentAppCallbackService.java

@@ -0,0 +1,10 @@
+package com.zanxiang.game.back.serve.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zanxiang.game.back.serve.pojo.dto.GameTencentAppCallbackDTO;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentAppCallback;
+
+public interface IGameTencentAppCallbackService extends IService<GameTencentAppCallback> {
+
+    boolean callback(GameTencentAppCallbackDTO dto);
+}

+ 7 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentAppOrderService.java

@@ -0,0 +1,7 @@
+package com.zanxiang.game.back.serve.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentAppOrder;
+
+public interface IGameTencentAppOrderService extends IService<GameTencentAppOrder> {
+}

+ 7 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentAppOrderSplitLogService.java

@@ -0,0 +1,7 @@
+package com.zanxiang.game.back.serve.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentAppOrderSplitLog;
+
+public interface IGameTencentAppOrderSplitLogService extends IService<GameTencentAppOrderSplitLog> {
+}

+ 7 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentAppRoleRegisterService.java

@@ -0,0 +1,7 @@
+package com.zanxiang.game.back.serve.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentAppRoleRegister;
+
+public interface IGameTencentAppRoleRegisterService extends IService<GameTencentAppRoleRegister> {
+}

+ 7 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentAppUserService.java

@@ -0,0 +1,7 @@
+package com.zanxiang.game.back.serve.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentAppUser;
+
+public interface IGameTencentAppUserService extends IService<GameTencentAppUser> {
+}

+ 14 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameOceanengineAppBackLogServiceImpl.java

@@ -0,0 +1,14 @@
+package com.zanxiang.game.back.serve.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.game.back.serve.dao.mapper.GameOceanengineAppBackLogMapper;
+import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineAppBackLog;
+import com.zanxiang.game.back.serve.service.IGameOceanengineAppBackLogService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+public class GameOceanengineAppBackLogServiceImpl extends ServiceImpl<GameOceanengineAppBackLogMapper, GameOceanengineAppBackLog>
+implements IGameOceanengineAppBackLogService {
+}

+ 44 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameOceanengineAppCallbackServiceImpl.java

@@ -0,0 +1,44 @@
+package com.zanxiang.game.back.serve.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.game.back.serve.dao.mapper.GameOceanengineAppCallbackMapper;
+import com.zanxiang.game.back.serve.pojo.dto.GameOceanengineAppCallbackDTO;
+import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineAppCallback;
+import com.zanxiang.game.back.serve.service.IGameOceanengineAppCallbackService;
+import com.zanxiang.module.util.DateUtil;
+import com.zanxiang.module.util.JsonUtil;
+import com.zanxiang.module.util.bean.BeanUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.kafka.clients.producer.KafkaProducer;
+import org.apache.kafka.clients.producer.ProducerRecord;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDate;
+
+@Slf4j
+@Service
+public class GameOceanengineAppCallbackServiceImpl extends ServiceImpl<GameOceanengineAppCallbackMapper, GameOceanengineAppCallback>
+implements IGameOceanengineAppCallbackService {
+
+    @Value("${spring.kafka.oceanengineAppCallbackTopic}")
+    private String oceanengineAppCallbackTopic;
+    @Autowired
+    private KafkaProducer<String, String> kafkaProducer;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean callback(GameOceanengineAppCallbackDTO dto) {
+        GameOceanengineAppCallback appCallback = BeanUtil.copy(dto, GameOceanengineAppCallback.class);
+        appCallback.setDay(dto.getTs() == null || dto.getTs() < 1000 ? LocalDate.now() : DateUtil.milliToLocalDateTime(dto.getTs()).toLocalDate());
+        save(appCallback);
+        try {
+            kafkaProducer.send(new ProducerRecord<>(oceanengineAppCallbackTopic, dto.getAdvertiserId().toString(), JsonUtil.toString(appCallback)));
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+        }
+        return true;
+    }
+}

+ 336 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameOceanengineAppOrderLogServiceImpl.java

@@ -0,0 +1,336 @@
+package com.zanxiang.game.back.serve.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.github.sd4324530.jtuple.Tuple2;
+import com.github.sd4324530.jtuple.Tuple3;
+import com.zanxiang.game.back.base.pojo.enums.OrderStatusEnum;
+import com.zanxiang.game.back.serve.dao.mapper.GameOceanengineAppOrderLogMapper;
+import com.zanxiang.game.back.serve.oceanengine.MiniGameCallback;
+import com.zanxiang.game.back.serve.pojo.entity.*;
+import com.zanxiang.game.back.serve.pojo.enums.BackStatusEnum;
+import com.zanxiang.game.back.serve.pojo.enums.BackUnitEnum;
+import com.zanxiang.game.back.serve.service.*;
+import com.zanxiang.game.back.serve.utils.BackPolicyUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+import java.util.*;
+
+@Slf4j
+@Service
+public class GameOceanengineAppOrderLogServiceImpl extends ServiceImpl<GameOceanengineAppOrderLogMapper, GameOceanengineAppOrderLog>
+implements IGameOceanengineAppOrderLogService {
+
+    @Autowired
+    private IGameBackPolicyService gameBackPolicyService;
+    @Autowired
+    private IGameOceanengineAppUserLogService gameOceanengineAppUserLogService;
+    @Autowired
+    private IGameOceanengineAppBackLogService gameOceanengineAppBackLogService;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean callback(GameOceanengineAppOrderLog orderLog) {
+        if (!Objects.equals(orderLog.getOrderStatus(), OrderStatusEnum.SUCCESS_PAY.getValue())) {
+            // 头条只要回传支付订单
+            return true;
+        }
+        GameOceanengineAppUserLog userLog = userLog(orderLog);
+        if (userLog == null) {
+            // 找不到用户
+            return update(new LambdaUpdateWrapper<GameOceanengineAppOrderLog>()
+                    .set(GameOceanengineAppOrderLog::getBackStatus, BackStatusEnum.NO.getBackStatus())
+                    .set(GameOceanengineAppOrderLog::getBackMoney, orderLog.getAmount())
+                    .set(GameOceanengineAppOrderLog::getBackMsg, "回传失败!找不到回传用户")
+                    .eq(GameOceanengineAppOrderLog::getId, orderLog.getId())
+            );
+        }
+
+        GameBackPolicy gameBackPolicy = gameBackPolicyService.getById(orderLog.getBackPolicyId());
+        Tuple3<Boolean, Long, String> backInfo = BackPolicyUtil.backOrder(orderLog.getOrderNo(), gameBackPolicy, orderLog.getAmount(),
+                orderLog.getIsFirstOrder(),
+                orderLog.getPayTime(),
+                // 此处使用用户最近一次的重新染色时间
+                userLog.getCreateTime(),
+                orderLog.getUserId(),
+                new OceanengineOrderBackPolicyCheck(this, userLog, orderLog, gameBackPolicy)
+        );
+        boolean doBack = backInfo.first;
+        Long backMoney = backInfo.second;
+        String backMsg = backInfo.third;
+
+        if (!doBack) {
+            // 不回传
+            return update(new LambdaUpdateWrapper<GameOceanengineAppOrderLog>()
+                    .set(GameOceanengineAppOrderLog::getBackStatus, BackStatusEnum.NO.getBackStatus())
+                    .set(GameOceanengineAppOrderLog::getBackMoney, backMoney)
+                    .set(GameOceanengineAppOrderLog::getBackMsg, backMsg)
+                    .eq(GameOceanengineAppOrderLog::getId, orderLog.getId())
+            );
+        }
+
+        Tuple2<BackStatusEnum, String> backResult = doCallback(orderLog, orderLog.getPayTime(), backMoney);
+        if (StringUtils.isNotBlank(backResult.second)) {
+            backMsg = backMsg + ("回传失败:" + backResult.second);
+        }
+        return update(new LambdaUpdateWrapper<GameOceanengineAppOrderLog>()
+                .set(GameOceanengineAppOrderLog::getBackStatus, backResult.first.getBackStatus())
+                .set(GameOceanengineAppOrderLog::getBackMoney, backMoney)
+                .set(GameOceanengineAppOrderLog::getBackMsg, backMsg)
+                .eq(GameOceanengineAppOrderLog::getId, orderLog.getId())
+        );
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Tuple2<BackStatusEnum, String> doCallback(GameOceanengineAppOrderLog orderLog, LocalDateTime backTime, Long backMoney) {
+        GameOceanengineAppUserLog userLog = userLog(orderLog);
+        if (userLog == null) {
+            gameOceanengineAppBackLogService.save(GameOceanengineAppBackLog.builder()
+                    .userId(orderLog.getUserId())
+                    .mac(orderLog.getMac())
+                    .imei(orderLog.getImei())
+                    .oaid(orderLog.getOaid())
+                    .androidId(orderLog.getAndroidId())
+                    .idfa(orderLog.getIdfa())
+                    .caid(orderLog.getCaid())
+                    .gameId(orderLog.getGameId())
+                    .accountId(orderLog.getAccountId())
+                    .eventType(String.valueOf(MiniGameCallback.EventType.ACTIVE_PAY.getEventType()))
+                    .eventLogId(orderLog.getId())
+                    .createTime(LocalDateTime.now())
+                    .payAmount(backMoney)
+                    .backStatus(BackStatusEnum.FAILED.getBackStatus())
+                    .errMsg("找不到用户注册信息")
+                    .build());
+            return Tuple2.with(BackStatusEnum.FAILED, "找不到用户注册信息");
+        }
+        Integer eventType = MiniGameCallback.EventType.ACTIVE_PAY.getEventType();
+        BackStatusEnum backStatus = BackStatusEnum.SUCCESS;
+        String errMsg = null;
+        gameOceanengineAppBackLogService.save(GameOceanengineAppBackLog.builder()
+                .userId(orderLog.getUserId())
+                .mac(orderLog.getMac())
+                .imei(orderLog.getImei())
+                .oaid(orderLog.getOaid())
+                .androidId(orderLog.getAndroidId())
+                .idfa(orderLog.getIdfa())
+                .caid(orderLog.getCaid())
+                .gameId(orderLog.getGameId())
+                .accountId(orderLog.getAccountId())
+                .eventType(String.valueOf(eventType))
+                .eventLogId(orderLog.getId())
+                .createTime(LocalDateTime.now())
+                .payAmount(backMoney)
+                .backStatus(backStatus.getBackStatus())
+                .errMsg(errMsg)
+                .build());
+        return Tuple2.with(backStatus, errMsg);
+    }
+
+    private GameOceanengineAppUserLog userLog(GameOceanengineAppOrderLog orderLog) {
+        return gameOceanengineAppUserLogService.getOne(new LambdaQueryWrapper<GameOceanengineAppUserLog>()
+                .eq(GameOceanengineAppUserLog::getGameId, orderLog.getGameId())
+                .eq(GameOceanengineAppUserLog::getUserId, orderLog.getUserId())
+                .eq(GameOceanengineAppUserLog::getAccountId, orderLog.getAccountId())
+                .orderByDesc(GameOceanengineAppUserLog::getCreateTime)
+                .last("limit 1")
+        );
+    }
+
+    public static class OceanengineOrderBackPolicyCheck implements BackPolicyUtil.IBackPolicyCheck {
+        private final IGameOceanengineAppOrderLogService gameOceanengineAppOrderLogService;
+        private final GameBackPolicy gameBackPolicy;
+        private final GameOceanengineAppUserLog userLog;
+        private final GameOceanengineAppOrderLog orderLog;
+
+        public OceanengineOrderBackPolicyCheck(IGameOceanengineAppOrderLogService gameOceanengineAppOrderLogService, GameOceanengineAppUserLog userLog, GameOceanengineAppOrderLog orderLog, GameBackPolicy gameBackPolicy) {
+            this.gameOceanengineAppOrderLogService = gameOceanengineAppOrderLogService;
+            this.gameBackPolicy = gameBackPolicy;
+            this.userLog = userLog;
+            this.orderLog = orderLog;
+        }
+
+        @Override
+        public long backCountForFixedRate(int numberOfRound, BackUnitEnum backUnit, Boolean firstPolicy) {
+            numberOfRound = numberOfRound - 1;
+            if (backUnit == BackUnitEnum.UNIT_ONCE) {
+                return gameOceanengineAppOrderLogService.list(new LambdaQueryWrapper<GameOceanengineAppOrderLog>()
+                        .eq(GameOceanengineAppOrderLog::getGameId, orderLog.getGameId())
+                        .eq(GameOceanengineAppOrderLog::getAccountId, orderLog.getAccountId())
+                        .eq(GameOceanengineAppOrderLog::getBackPolicyId, gameBackPolicy.getId())
+                        .eq(GameOceanengineAppOrderLog::getOrderStatus, OrderStatusEnum.SUCCESS_PAY.getValue())
+                        .eq(GameOceanengineAppOrderLog::getIsFirstOrder, firstPolicy)
+                        .ne(GameOceanengineAppOrderLog::getOrderNo, orderLog.getOrderNo())
+                        .orderByDesc(GameOceanengineAppOrderLog::getCreateTime)
+                        .last("limit " + numberOfRound)
+                ).stream().filter(log -> log.getBackStatus().equals(BackStatusEnum.SUCCESS.getBackStatus())).count();
+            } else if (backUnit == BackUnitEnum.UNIT_DAY) {
+                return gameOceanengineAppOrderLogService.list(new LambdaQueryWrapper<GameOceanengineAppOrderLog>()
+                        .eq(GameOceanengineAppOrderLog::getGameId, orderLog.getGameId())
+                        .eq(GameOceanengineAppOrderLog::getAccountId, orderLog.getAccountId())
+                        .eq(GameOceanengineAppOrderLog::getBackPolicyId, gameBackPolicy.getId())
+                        .eq(GameOceanengineAppOrderLog::getOrderStatus, OrderStatusEnum.SUCCESS_PAY.getValue())
+                        .apply(firstPolicy, "date(reg_time) = date(pay_time)")
+                        .apply(!firstPolicy, "date(reg_time) != date(pay_time)")
+                        .ne(GameOceanengineAppOrderLog::getOrderNo, orderLog.getOrderNo())
+                        .orderByDesc(GameOceanengineAppOrderLog::getCreateTime)
+                        .last("limit " + numberOfRound)
+                ).stream().filter(log -> log.getBackStatus().equals(BackStatusEnum.SUCCESS.getBackStatus())).count();
+            } else if (backUnit == BackUnitEnum.UNIT_TIME_DAY) {
+                return gameOceanengineAppOrderLogService.list(new LambdaQueryWrapper<GameOceanengineAppOrderLog>()
+                        .eq(GameOceanengineAppOrderLog::getGameId, orderLog.getGameId())
+                        .eq(GameOceanengineAppOrderLog::getAccountId, orderLog.getAccountId())
+                        .eq(GameOceanengineAppOrderLog::getBackPolicyId, gameBackPolicy.getId())
+                        .eq(GameOceanengineAppOrderLog::getOrderStatus, OrderStatusEnum.SUCCESS_PAY.getValue())
+                        .apply(firstPolicy, "TIMESTAMPDIFF(HOUR, reg_time, pay_time) < 24")
+                        .apply(!firstPolicy, "TIMESTAMPDIFF(HOUR, reg_time, pay_time) >= 24")
+                        .ne(GameOceanengineAppOrderLog::getOrderNo, orderLog.getOrderNo())
+                        .orderByDesc(GameOceanengineAppOrderLog::getCreateTime)
+                        .last("limit " + numberOfRound)
+                ).stream().filter(log -> log.getBackStatus().equals(BackStatusEnum.SUCCESS.getBackStatus())).count();
+            } else if (backUnit == BackUnitEnum.UNIT_TIME_2DAY) {
+                return gameOceanengineAppOrderLogService.list(new LambdaQueryWrapper<GameOceanengineAppOrderLog>()
+                        .eq(GameOceanengineAppOrderLog::getGameId, orderLog.getGameId())
+                        .eq(GameOceanengineAppOrderLog::getAccountId, orderLog.getAccountId())
+                        .eq(GameOceanengineAppOrderLog::getBackPolicyId, gameBackPolicy.getId())
+                        .eq(GameOceanengineAppOrderLog::getOrderStatus, OrderStatusEnum.SUCCESS_PAY.getValue())
+                        .apply(firstPolicy, "TIMESTAMPDIFF(HOUR, reg_time, pay_time) < 48")
+                        .apply(!firstPolicy, "TIMESTAMPDIFF(HOUR, reg_time, pay_time) >= 48")
+                        .ne(GameOceanengineAppOrderLog::getOrderNo, orderLog.getOrderNo())
+                        .orderByDesc(GameOceanengineAppOrderLog::getCreateTime)
+                        .last("limit " + numberOfRound)
+                ).stream().filter(log -> log.getBackStatus().equals(BackStatusEnum.SUCCESS.getBackStatus())).count();
+            } else if (backUnit == BackUnitEnum.LARGE_AMOUNT) {
+                return gameOceanengineAppOrderLogService.list(new LambdaQueryWrapper<GameOceanengineAppOrderLog>()
+                        .eq(GameOceanengineAppOrderLog::getGameId, orderLog.getGameId())
+                        .eq(GameOceanengineAppOrderLog::getAccountId, orderLog.getAccountId())
+                        .eq(GameOceanengineAppOrderLog::getBackPolicyId, gameBackPolicy.getId())
+                        .eq(GameOceanengineAppOrderLog::getOrderStatus, OrderStatusEnum.SUCCESS_PAY.getValue())
+                        .ne(GameOceanengineAppOrderLog::getOrderNo, orderLog.getOrderNo())
+                        .orderByDesc(GameOceanengineAppOrderLog::getCreateTime)
+                        .last("limit " + numberOfRound)
+                ).stream().filter(log -> log.getBackStatus().equals(BackStatusEnum.SUCCESS.getBackStatus())).count();
+            } else {
+                throw new RuntimeException("不支持的回传单位[" + backUnit.getValue() + "]");
+            }
+        }
+
+        @Override
+        public long backCountForUser(BackUnitEnum backUnit, String userId, Boolean firstPolicy) {
+            if (backUnit == BackUnitEnum.UNIT_ONCE) {
+                if (firstPolicy) {
+                    // 首单直接返回 0,必定回传
+                    return 0;
+                }
+                return gameOceanengineAppOrderLogService.count(new LambdaQueryWrapper<GameOceanengineAppOrderLog>()
+                        .eq(GameOceanengineAppOrderLog::getGameId, orderLog.getGameId())
+                        .eq(GameOceanengineAppOrderLog::getAccountId, orderLog.getAccountId())
+                        .eq(GameOceanengineAppOrderLog::getBackPolicyId, gameBackPolicy.getId())
+                        .eq(GameOceanengineAppOrderLog::getOrderStatus, OrderStatusEnum.SUCCESS_PAY.getValue())
+                        .eq(GameOceanengineAppOrderLog::getBackStatus, BackStatusEnum.SUCCESS.getBackStatus())
+                        .eq(GameOceanengineAppOrderLog::getUserId, userId)
+                        .eq(GameOceanengineAppOrderLog::getIsFirstOrder, firstPolicy)
+                        .ne(GameOceanengineAppOrderLog::getOrderNo, orderLog.getOrderNo())
+                );
+            } else if (backUnit == BackUnitEnum.UNIT_DAY) {
+                return gameOceanengineAppOrderLogService.count(new LambdaQueryWrapper<GameOceanengineAppOrderLog>()
+                        .eq(GameOceanengineAppOrderLog::getGameId, orderLog.getGameId())
+                        .eq(GameOceanengineAppOrderLog::getAccountId, orderLog.getAccountId())
+                        .eq(GameOceanengineAppOrderLog::getBackPolicyId, gameBackPolicy.getId())
+                        .eq(GameOceanengineAppOrderLog::getOrderStatus, OrderStatusEnum.SUCCESS_PAY.getValue())
+                        .eq(GameOceanengineAppOrderLog::getBackStatus, BackStatusEnum.SUCCESS.getBackStatus())
+                        .eq(GameOceanengineAppOrderLog::getUserId, userId)
+                        .apply(firstPolicy, "date(reg_time) = date(pay_time)")
+                        .apply(!firstPolicy, "date(reg_time) != date(pay_time)")
+                        .ne(GameOceanengineAppOrderLog::getOrderNo, orderLog.getOrderNo())
+                );
+            } else if (backUnit == BackUnitEnum.UNIT_TIME_DAY) {
+                return gameOceanengineAppOrderLogService.count(new LambdaQueryWrapper<GameOceanengineAppOrderLog>()
+                        .eq(GameOceanengineAppOrderLog::getGameId, orderLog.getGameId())
+                        .eq(GameOceanengineAppOrderLog::getAccountId, orderLog.getAccountId())
+                        .eq(GameOceanengineAppOrderLog::getBackPolicyId, gameBackPolicy.getId())
+                        .eq(GameOceanengineAppOrderLog::getOrderStatus, OrderStatusEnum.SUCCESS_PAY.getValue())
+                        .eq(GameOceanengineAppOrderLog::getBackStatus, BackStatusEnum.SUCCESS.getBackStatus())
+                        .eq(GameOceanengineAppOrderLog::getUserId, userId)
+                        .apply(firstPolicy, "TIMESTAMPDIFF(HOUR, reg_time, pay_time) < 24")
+                        .apply(!firstPolicy, "TIMESTAMPDIFF(HOUR, reg_time, pay_time) >= 24")
+                        .ne(GameOceanengineAppOrderLog::getOrderNo, orderLog.getOrderNo())
+                );
+            } else if (backUnit == BackUnitEnum.UNIT_TIME_2DAY) {
+                return gameOceanengineAppOrderLogService.count(new LambdaQueryWrapper<GameOceanengineAppOrderLog>()
+                        .eq(GameOceanengineAppOrderLog::getGameId, orderLog.getGameId())
+                        .eq(GameOceanengineAppOrderLog::getAccountId, orderLog.getAccountId())
+                        .eq(GameOceanengineAppOrderLog::getBackPolicyId, gameBackPolicy.getId())
+                        .eq(GameOceanengineAppOrderLog::getOrderStatus, OrderStatusEnum.SUCCESS_PAY.getValue())
+                        .eq(GameOceanengineAppOrderLog::getBackStatus, BackStatusEnum.SUCCESS.getBackStatus())
+                        .eq(GameOceanengineAppOrderLog::getUserId, userId)
+                        .apply(firstPolicy, "TIMESTAMPDIFF(HOUR, reg_time, pay_time) < 48")
+                        .apply(!firstPolicy, "TIMESTAMPDIFF(HOUR, reg_time, pay_time) >= 48")
+                        .ne(GameOceanengineAppOrderLog::getOrderNo, orderLog.getOrderNo())
+                );
+            } else if (backUnit == BackUnitEnum.LARGE_AMOUNT) {
+                return gameOceanengineAppOrderLogService.count(new LambdaQueryWrapper<GameOceanengineAppOrderLog>()
+                        .eq(GameOceanengineAppOrderLog::getGameId, orderLog.getGameId())
+                        .eq(GameOceanengineAppOrderLog::getAccountId, orderLog.getAccountId())
+                        .eq(GameOceanengineAppOrderLog::getBackPolicyId, gameBackPolicy.getId())
+                        .eq(GameOceanengineAppOrderLog::getOrderStatus, OrderStatusEnum.SUCCESS_PAY.getValue())
+                        .eq(GameOceanengineAppOrderLog::getBackStatus, BackStatusEnum.SUCCESS.getBackStatus())
+                        .eq(GameOceanengineAppOrderLog::getUserId, userId)
+                        .ne(GameOceanengineAppOrderLog::getOrderNo, orderLog.getOrderNo())
+                );
+            } else {
+                throw new RuntimeException("不支持的回传单位[" + backUnit.getValue() + "]");
+            }
+        }
+
+        @Override
+        public long markUpOfFixedRate(int numberOfRound, Long markUpTime) {
+            numberOfRound = numberOfRound - 1;
+            return gameOceanengineAppOrderLogService.list(new LambdaQueryWrapper<GameOceanengineAppOrderLog>()
+                    .eq(GameOceanengineAppOrderLog::getGameId, orderLog.getGameId())
+                    .eq(GameOceanengineAppOrderLog::getAccountId, orderLog.getAccountId())
+                    .eq(GameOceanengineAppOrderLog::getBackPolicyId, gameBackPolicy.getId())
+                    .eq(GameOceanengineAppOrderLog::getOrderStatus, OrderStatusEnum.SUCCESS_PAY.getValue())
+                    .apply("TIMESTAMPDIFF(MINUTE, reg_time, pay_time) > {0}", markUpTime)
+                    .ne(GameOceanengineAppOrderLog::getOrderNo, orderLog.getOrderNo())
+                    .orderByDesc(GameOceanengineAppOrderLog::getCreateTime)
+                    .last("limit " + numberOfRound)
+            ).stream().filter(log -> log.getBackStatus().equals(BackStatusEnum.SUCCESS.getBackStatus())).count();
+        }
+
+        @Override
+        public long markUpForUser(String userId, Long markUpTime) {
+            return gameOceanengineAppOrderLogService.count(new LambdaQueryWrapper<GameOceanengineAppOrderLog>()
+                    .eq(GameOceanengineAppOrderLog::getGameId, orderLog.getGameId())
+                    .eq(GameOceanengineAppOrderLog::getAccountId, orderLog.getAccountId())
+                    .eq(GameOceanengineAppOrderLog::getBackPolicyId, gameBackPolicy.getId())
+                    .eq(GameOceanengineAppOrderLog::getOrderStatus, OrderStatusEnum.SUCCESS_PAY.getValue())
+                    .eq(GameOceanengineAppOrderLog::getBackStatus, BackStatusEnum.SUCCESS.getBackStatus())
+                    .eq(GameOceanengineAppOrderLog::getUserId, userId)
+                    .apply("TIMESTAMPDIFF(MINUTE, reg_time, pay_time) > {0}", markUpTime)
+                    .ne(GameOceanengineAppOrderLog::getOrderNo, orderLog.getOrderNo())
+            );
+        }
+
+        @Override
+        public Long totalRechargeAmount() {
+            return gameOceanengineAppOrderLogService.getOne(new QueryWrapper<GameOceanengineAppOrderLog>()
+                    .select("ifnull(sum(amount), 0) as amount").lambda()
+                    .eq(GameOceanengineAppOrderLog::getGameId, orderLog.getGameId())
+                    .eq(GameOceanengineAppOrderLog::getAccountId, orderLog.getAccountId())
+                    .eq(GameOceanengineAppOrderLog::getBackPolicyId, gameBackPolicy.getId())
+                    .eq(GameOceanengineAppOrderLog::getOrderStatus, OrderStatusEnum.SUCCESS_PAY.getValue())
+                    .eq(GameOceanengineAppOrderLog::getUserId, userLog.getUserId())
+                    .ne(GameOceanengineAppOrderLog::getOrderNo, orderLog.getOrderNo())
+            ).getAmount();
+        }
+    }
+}

+ 100 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameOceanengineAppRoleRegisterLogServiceImpl.java

@@ -0,0 +1,100 @@
+package com.zanxiang.game.back.serve.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.game.back.serve.dao.mapper.GameOceanengineAppRoleRegisterLogMapper;
+import com.zanxiang.game.back.serve.oceanengine.MiniGameCallback;
+import com.zanxiang.game.back.serve.pojo.entity.*;
+import com.zanxiang.game.back.serve.pojo.enums.BackStatusEnum;
+import com.zanxiang.game.back.serve.service.*;
+import com.zanxiang.game.module.base.ServerInfo;
+import com.zanxiang.game.module.base.rpc.IAgentRpc;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+
+@Slf4j
+@Service
+public class GameOceanengineAppRoleRegisterLogServiceImpl extends ServiceImpl<GameOceanengineAppRoleRegisterLogMapper, GameOceanengineAppRoleRegisterLog>
+implements IGameOceanengineAppRoleRegisterLogService {
+    @Autowired
+    private IGameOceanengineAppUserLogService gameOceanengineAppUserLogService;
+    @Autowired
+    private IGameOceanengineAppBackLogService gameOceanengineAppBackLogService;
+    @DubboReference(providedBy = ServerInfo.SERVER_DUBBO_NAME)
+    private IAgentRpc agentRpc;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean callback(GameOceanengineAppRoleRegisterLog roleRegisterLog) {
+        BackStatusEnum backStatus = doCallback(roleRegisterLog);
+        return update(new LambdaUpdateWrapper<GameOceanengineAppRoleRegisterLog>()
+                .set(GameOceanengineAppRoleRegisterLog::getBackStatus, backStatus.getBackStatus())
+                .eq(GameOceanengineAppRoleRegisterLog::getId, roleRegisterLog.getId())
+        );
+    }
+
+    private BackStatusEnum doCallback(GameOceanengineAppRoleRegisterLog roleRegisterLog) {
+        GameOceanengineAppUserLog userLog = gameOceanengineAppUserLogService.getOne(new LambdaQueryWrapper<GameOceanengineAppUserLog>()
+                .eq(GameOceanengineAppUserLog::getGameId, roleRegisterLog.getGameId())
+                .eq(GameOceanengineAppUserLog::getUserId, roleRegisterLog.getUserId())
+                .eq(GameOceanengineAppUserLog::getAccountId, roleRegisterLog.getAccountId())
+                .orderByDesc(GameOceanengineAppUserLog::getCreateTime)
+                .last("limit 1")
+        );
+        if (userLog == null) {
+            gameOceanengineAppBackLogService.save(GameOceanengineAppBackLog.builder()
+                    .userId(roleRegisterLog.getUserId())
+                    .mac(roleRegisterLog.getMac())
+                    .imei(roleRegisterLog.getImei())
+                    .oaid(roleRegisterLog.getOaid())
+                    .androidId(roleRegisterLog.getAndroidId())
+                    .idfa(roleRegisterLog.getIdfa())
+                    .caid(roleRegisterLog.getCaid())
+                    .gameId(roleRegisterLog.getGameId())
+                    .accountId(roleRegisterLog.getAccountId())
+                    .eventType(String.valueOf(MiniGameCallback.EventType.ACTIVE_REGISTER.getEventType()))
+                    .eventLogId(roleRegisterLog.getId())
+                    .createTime(LocalDateTime.now())
+                    .backStatus(BackStatusEnum.FAILED.getBackStatus())
+                    .errMsg("找不到用户注册信息")
+                    .build());
+            return BackStatusEnum.FAILED;
+        }
+        //判断创角是否已回传
+        if (gameOceanengineAppBackLogService.count(new LambdaQueryWrapper<GameOceanengineAppBackLog>()
+                .eq(GameOceanengineAppBackLog::getGameId, userLog.getGameId())
+                .eq(GameOceanengineAppBackLog::getUserId, userLog.getUserId())
+                .eq(GameOceanengineAppBackLog::getAccountId, userLog.getAccountId())
+                .eq(GameOceanengineAppBackLog::getEventType, MiniGameCallback.EventType.ACTIVE_REGISTER.getEventType())
+                .eq(GameOceanengineAppBackLog::getBackStatus, BackStatusEnum.SUCCESS.getBackStatus())
+        ) > 0) {
+            //创角已回传
+            return BackStatusEnum.NO;
+        }
+        BackStatusEnum backStatus = BackStatusEnum.SUCCESS;
+        String errMsg = null;
+        gameOceanengineAppBackLogService.save(GameOceanengineAppBackLog.builder()
+                .userId(roleRegisterLog.getUserId())
+                .mac(roleRegisterLog.getMac())
+                .imei(roleRegisterLog.getImei())
+                .oaid(roleRegisterLog.getOaid())
+                .androidId(roleRegisterLog.getAndroidId())
+                .idfa(roleRegisterLog.getIdfa())
+                .caid(roleRegisterLog.getCaid())
+                .gameId(roleRegisterLog.getGameId())
+                .accountId(roleRegisterLog.getAccountId())
+                .eventType(String.valueOf(MiniGameCallback.EventType.ACTIVE_REGISTER.getEventType()))
+                .eventLogId(roleRegisterLog.getId())
+                .createTime(LocalDateTime.now())
+                .backStatus(backStatus.getBackStatus())
+                .errMsg(errMsg)
+                .build());
+        return backStatus;
+    }
+}

+ 73 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameOceanengineAppUserLogServiceImpl.java

@@ -0,0 +1,73 @@
+package com.zanxiang.game.back.serve.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.game.back.serve.dao.mapper.GameOceanengineAppUserLogMapper;
+import com.zanxiang.game.back.serve.oceanengine.MiniGameCallback;
+import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineAppBackLog;
+import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineAppUserLog;
+import com.zanxiang.game.back.serve.pojo.enums.BackStatusEnum;
+import com.zanxiang.game.back.serve.service.IGameOceanengineAppBackLogService;
+import com.zanxiang.game.back.serve.service.IGameOceanengineAppUserLogService;
+import com.zanxiang.game.module.base.ServerInfo;
+import com.zanxiang.game.module.base.rpc.IAgentRpc;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+
+@Slf4j
+@Service
+public class GameOceanengineAppUserLogServiceImpl extends ServiceImpl<GameOceanengineAppUserLogMapper, GameOceanengineAppUserLog>
+implements IGameOceanengineAppUserLogService {
+
+    @Autowired
+    private IGameOceanengineAppBackLogService gameOceanengineAppBackLogService;
+    @DubboReference(providedBy = ServerInfo.SERVER_DUBBO_NAME)
+    private IAgentRpc agentRpc;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean callback(GameOceanengineAppUserLog userLog, boolean mustBack) {
+        BackStatusEnum backStatus = doCallback(userLog, mustBack);
+        return update(new LambdaUpdateWrapper<GameOceanengineAppUserLog>()
+                .set(GameOceanengineAppUserLog::getBackStatus, backStatus.getBackStatus())
+                .eq(GameOceanengineAppUserLog::getId, userLog.getId())
+        );
+    }
+
+    private BackStatusEnum doCallback(GameOceanengineAppUserLog userLog, boolean mustBack) {
+        // 是否已经回传过
+        if (!mustBack && gameOceanengineAppBackLogService.count(new LambdaQueryWrapper<GameOceanengineAppBackLog>()
+                .eq(GameOceanengineAppBackLog::getGameId, userLog.getGameId())
+                .eq(GameOceanengineAppBackLog::getUserId, userLog.getUserId())
+                .eq(GameOceanengineAppBackLog::getAccountId, userLog.getAccountId())
+                .eq(GameOceanengineAppBackLog::getEventType, MiniGameCallback.EventType.ACTIVE.getEventType())
+                .eq(GameOceanengineAppBackLog::getBackStatus, BackStatusEnum.SUCCESS.getBackStatus())
+        ) > 0) {
+            return BackStatusEnum.NO;
+        }
+        BackStatusEnum backStatus = BackStatusEnum.SUCCESS;
+        gameOceanengineAppBackLogService.save(GameOceanengineAppBackLog.builder()
+                .userId(userLog.getUserId())
+                .mac(userLog.getMac())
+                .imei(userLog.getImei())
+                .oaid(userLog.getOaid())
+                .androidId(userLog.getAndroidId())
+                .idfa(userLog.getIdfa())
+                .caid(userLog.getCaid())
+                .gameId(userLog.getGameId())
+                .accountId(userLog.getAccountId())
+                .eventType(String.valueOf(MiniGameCallback.EventType.ACTIVE.getEventType()))
+                .eventLogId(userLog.getId())
+                .createTime(LocalDateTime.now())
+                .backStatus(backStatus.getBackStatus())
+                .errMsg(null)
+                .build());
+        return backStatus;
+    }
+}

+ 14 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentAppBackLogServiceImpl.java

@@ -0,0 +1,14 @@
+package com.zanxiang.game.back.serve.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.game.back.serve.dao.mapper.GameTencentAppBackLogMapper;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentAppBackLog;
+import com.zanxiang.game.back.serve.service.IGameTencentAppBackLogService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+public class GameTencentAppBackLogServiceImpl extends ServiceImpl<GameTencentAppBackLogMapper, GameTencentAppBackLog>
+implements IGameTencentAppBackLogService {
+}

+ 65 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentAppCallbackServiceImpl.java

@@ -0,0 +1,65 @@
+package com.zanxiang.game.back.serve.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.game.back.serve.dao.mapper.GameTencentAppCallbackMapper;
+import com.zanxiang.game.back.serve.pojo.dto.GameTencentAppCallbackDTO;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentAppCallback;
+import com.zanxiang.game.back.serve.service.IGameTencentAppCallbackService;
+import com.zanxiang.module.util.DateUtil;
+import com.zanxiang.module.util.JsonUtil;
+import com.zanxiang.module.util.bean.BeanUtil;
+import com.zanxiang.module.util.encryption.Md5Util;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.kafka.clients.producer.KafkaProducer;
+import org.apache.kafka.clients.producer.ProducerRecord;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDate;
+
+@Slf4j
+@Service
+public class GameTencentAppCallbackServiceImpl extends ServiceImpl<GameTencentAppCallbackMapper, GameTencentAppCallback>
+implements IGameTencentAppCallbackService {
+
+    @Value("${spring.kafka.tencentAppCallbackTopic}")
+    private String tencentAppCallbackTopic;
+    @Autowired
+    private KafkaProducer<String, String> kafkaProducer;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean callback(GameTencentAppCallbackDTO dto) {
+        GameTencentAppCallback appCallback = BeanUtil.copy(dto, GameTencentAppCallback.class);
+        appCallback.setDay(dto.getClickTime() == null || dto.getClickTime() < 1000 ? LocalDate.now() : DateUtil.milliToLocalDateTime(dto.getClickTime()).toLocalDate());
+        save(appCallback);
+        try {
+            kafkaProducer.send(new ProducerRecord<>(tencentAppCallbackTopic, dto.getAccountId().toString(), JsonUtil.toString(appCallback)));
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+        }
+        return true;
+    }
+
+    public GameTencentAppCallback getUserClickInfo(String imei, String oaid, String android, String idfa, String caid) {
+        LambdaQueryWrapper<GameTencentAppCallback> qw = new LambdaQueryWrapper<>();
+        if (StringUtils.isNoneBlank(imei)) {
+            qw.or().eq(GameTencentAppCallback::getMuid, Md5Util.encrypt32(imei.toLowerCase()).toLowerCase());
+        } else if (StringUtils.isNoneBlank(idfa)) {
+            qw.or().eq(GameTencentAppCallback::getMuid, Md5Util.encrypt32(idfa).toLowerCase());
+        }
+        if(StringUtils.isNoneBlank(android)) {
+            qw.or().eq(GameTencentAppCallback::getHashAndroidId, Md5Util.encrypt32(android).toLowerCase());
+        }
+        if(StringUtils.isNoneBlank(oaid)) {
+            qw.or().eq(GameTencentAppCallback::getHashOaid, Md5Util.encrypt32(oaid).toLowerCase());
+        }
+        qw.orderByDesc(GameTencentAppCallback::getClickTime)
+                .last("limit 1");
+        return getOne(qw);
+    }
+}

+ 14 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentAppOrderServiceImpl.java

@@ -0,0 +1,14 @@
+package com.zanxiang.game.back.serve.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.game.back.serve.dao.mapper.GameTencentAppOrderMapper;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentAppOrder;
+import com.zanxiang.game.back.serve.service.IGameTencentAppOrderService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+public class GameTencentAppOrderServiceImpl extends ServiceImpl<GameTencentAppOrderMapper, GameTencentAppOrder>
+implements IGameTencentAppOrderService {
+}

+ 14 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentAppOrderSplitLogServiceImpl.java

@@ -0,0 +1,14 @@
+package com.zanxiang.game.back.serve.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.game.back.serve.dao.mapper.GameTencentAppOrderSplitLogMapper;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentAppOrderSplitLog;
+import com.zanxiang.game.back.serve.service.IGameTencentAppOrderSplitLogService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+public class GameTencentAppOrderSplitLogServiceImpl extends ServiceImpl<GameTencentAppOrderSplitLogMapper, GameTencentAppOrderSplitLog>
+implements IGameTencentAppOrderSplitLogService {
+}

+ 14 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentAppRoleRegisterServiceImpl.java

@@ -0,0 +1,14 @@
+package com.zanxiang.game.back.serve.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.game.back.serve.dao.mapper.GameTencentAppRoleRegisterMapper;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentAppRoleRegister;
+import com.zanxiang.game.back.serve.service.IGameTencentAppRoleRegisterService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+public class GameTencentAppRoleRegisterServiceImpl extends ServiceImpl<GameTencentAppRoleRegisterMapper, GameTencentAppRoleRegister>
+implements IGameTencentAppRoleRegisterService {
+}

+ 178 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentAppUserServiceImpl.java

@@ -0,0 +1,178 @@
+package com.zanxiang.game.back.serve.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.advertising.tencent.base.AdvertisingTencentServer;
+import com.zanxiang.advertising.tencent.base.pojo.dto.DataReportOfAppIdRpcDTO;
+import com.zanxiang.advertising.tencent.base.pojo.dto.UserActionRpcDTO;
+import com.zanxiang.advertising.tencent.base.rpc.IUserActionSetRpc;
+import com.zanxiang.erp.base.ErpServer;
+import com.zanxiang.erp.base.rpc.ISysUserRpc;
+import com.zanxiang.game.back.serve.dao.mapper.GameTencentAppUserMapper;
+import com.zanxiang.game.back.serve.pojo.dto.GameTencentUserDTO;
+import com.zanxiang.game.back.serve.pojo.entity.*;
+import com.zanxiang.game.back.serve.pojo.enums.ActionTypeEnum;
+import com.zanxiang.game.back.serve.pojo.enums.BackStatusEnum;
+import com.zanxiang.game.back.serve.pojo.vo.GameTencentUserVO;
+import com.zanxiang.game.back.serve.service.IGameTencentAppBackLogService;
+import com.zanxiang.game.back.serve.service.IGameTencentAppCallbackService;
+import com.zanxiang.game.back.serve.service.IGameTencentAppUserService;
+import com.zanxiang.game.back.serve.service.IGameTencentBackLogService;
+import com.zanxiang.game.module.base.ServerInfo;
+import com.zanxiang.game.module.base.pojo.vo.AgentRpcVO;
+import com.zanxiang.game.module.base.rpc.IAgentRpc;
+import com.zanxiang.module.util.bean.BeanUtil;
+import com.zanxiang.module.util.pojo.ResultVO;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+public class GameTencentAppUserServiceImpl extends ServiceImpl<GameTencentAppUserMapper, GameTencentAppUser>
+implements IGameTencentAppUserService {
+    @DubboReference(providedBy = AdvertisingTencentServer.SERVER_DUBBO_NAME)
+    private IUserActionSetRpc userActionSetRpc;
+    @DubboReference(providedBy = ErpServer.SERVER_DUBBO_NAME)
+    private ISysUserRpc sysUserRpc;
+    @Autowired
+    private IGameTencentAppBackLogService gameTencentAppBackLogService;
+    @DubboReference(providedBy = ServerInfo.SERVER_DUBBO_NAME)
+    private IAgentRpc agentRpc;
+    @Autowired
+    private IGameTencentAppCallbackService gameTencentAppCallbackService;
+
+    /*@Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean userBack(GameTencentAppUser userLog, boolean mustBack) {
+        BackStatusEnum backStatus = doCallback(userLog, mustBack);
+        return update(new LambdaUpdateWrapper<GameTencentAppUser>()
+                .set(GameTencentAppUser::getIsBack, backStatus.getBackStatus())
+                .eq(GameTencentAppUser::getId, userLog.getId())
+        );
+    }
+
+
+    @Override
+    public IPage<GameTencentUserVO> tencentUserLogList(GameTencentUserDTO dto) {
+        IPage<GameTencentUser> page = page(dto.toPage(), new LambdaQueryWrapper<GameTencentUser>()
+                .eq(StringUtils.isNotBlank(dto.getChannel()), GameTencentUser::getChannel, dto.getChannel())
+                .ge(dto.getActiveTimeBegin() != null, GameTencentUser::getRegisterTime, dto.getActiveTimeBegin() == null ? null : LocalDateTime.of(dto.getActiveTimeBegin(), LocalTime.MIDNIGHT))
+                .le(dto.getActiveTimeEnd() != null, GameTencentUser::getRegisterTime, dto.getActiveTimeEnd() == null ? null : LocalDateTime.of(dto.getActiveTimeEnd(), LocalTime.MAX))
+                .eq(null != dto.getGameId(), GameTencentUser::getGameId, dto.getGameId())
+                .eq(null != dto.getAdAccountId(), GameTencentUser::getAdAccountId, dto.getAdAccountId())
+                .eq(StringUtils.isNotBlank(dto.getWechatAppId()), GameTencentUser::getWechatAppId, dto.getWechatAppId())
+                .eq(StringUtils.isNotBlank(dto.getWechatOpenid()), GameTencentUser::getWechatOpenid, dto.getWechatOpenid())
+                .eq(null != dto.getIsBack(), GameTencentUser::getIsBack, dto.getIsBack())
+                .orderByDesc(GameTencentUser::getCreateTime)
+        );
+
+        IPage<GameTencentUserVO> result = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
+        if (CollectionUtils.isEmpty(page.getRecords())) {
+            return result;
+        }
+        result.setRecords(toVOBatch(page.getRecords()));
+        return result;
+    }
+
+    @Override
+    public boolean tencentUserReport(List<Long> ids) {
+        listByIds(ids).forEach(userLog -> {
+            BackStatusEnum backStatus = doCallback(userLog, true);
+            update(new LambdaUpdateWrapper<GameTencentUser>()
+                    .set(GameTencentUser::getIsBack, backStatus.getBackStatus())
+                    .eq(GameTencentUser::getId, userLog.getId())
+            );
+        });
+        return true;
+    }
+
+    private List<GameTencentUserVO> toVOBatch(List<GameTencentUser> logList) {
+        if (CollectionUtils.isEmpty(logList)) {
+            return Collections.emptyList();
+        }
+        Set<String> agentKeys = logList.stream().map(GameTencentUser::getChannel).filter(StringUtils::isNotBlank).collect(Collectors.toSet());
+        Map<String, AgentRpcVO> agentMap = CollectionUtils.isEmpty(agentKeys) ? Collections.emptyMap() : agentRpc.getByAgentKeys(new ArrayList<>(agentKeys))
+                .getData().stream().collect(Collectors.toMap(AgentRpcVO::getAgentKey, Function.identity()));
+        return logList.stream().map(log -> {
+            GameTencentUserVO vo = BeanUtil.copy(log, GameTencentUserVO.class);
+            if (StringUtils.isNotBlank(log.getChannel())) {
+                AgentRpcVO agent = agentMap.get(log.getChannel());
+                if (agent != null) {
+                    vo.setAgentName(agent.getAgentName());
+                }
+            }
+            return vo;
+        }).collect(Collectors.toList());
+
+    }
+
+
+    private BackStatusEnum doCallback(GameTencentAppUser userLog, boolean mustBack) {
+        boolean isBack = mustBack ? false : gameTencentAppBackLogService.count(new LambdaQueryWrapper<GameTencentAppBackLog>()
+                .eq(GameTencentAppBackLog::getGameId, userLog.getGameId())
+                .eq(GameTencentAppBackLog::getMac, userLog.getMac())
+                .eq(GameTencentAppBackLog::getImei, userLog.getImei())
+                .eq(GameTencentAppBackLog::getOaid, userLog.getOaid())
+                .eq(GameTencentAppBackLog::getAndroidId, userLog.getAndroidId())
+                .eq(GameTencentAppBackLog::getIdfa, userLog.getIdfa())
+                .eq(GameTencentAppBackLog::getCaid, userLog.getCaid())
+                .eq(GameTencentAppBackLog::getAdAccountId, userLog.getAdAccountId())
+                .eq(GameTencentAppBackLog::getBackLog, "回传成功")
+        ) > 0;
+        if (isBack) {
+            return BackStatusEnum.NO;
+        }
+
+        Map<String, Object> actionParam = new HashMap<>(2);
+        actionParam.put("claim_type", 0);
+        DataReportOfAppIdRpcDTO dataReportOfAppIdRpcDTO = DataReportOfAppIdRpcDTO.builder()
+                .appId(userLog.getWechatAppId())
+                .userActionSetId(userLog.getUserActionSetId())
+                .action(UserActionRpcDTO.builder()
+                        .actionTime(userLog.getRegisterTime())
+                        .actionType(ActionTypeEnum.REGISTER.getActionType())
+                        .userId(UserActionRpcDTO.UserIdRpcDTO.builder()
+                                .wechatAppId(userLog.getWechatAppId())
+                                .wechatOpenid(userLog.getWechatOpenid())
+                                .build())
+                        .actionParam(actionParam)
+                        .build())
+                .build();
+
+        GameTencentBackLog gameTencentBackLog = GameTencentBackLog.builder()
+                .gameId(userLog.getGameId())
+                .adAccountId(userLog.getAdAccountId())
+                .actionTime(userLog.getRegisterTime())
+                .createTime(LocalDateTime.now())
+                .actionType(ActionTypeEnum.REGISTER.getActionType())
+                .wechatAppId(userLog.getWechatAppId())
+                .wechatOpenid(userLog.getWechatOpenid())
+                .userActionSetId(userLog.getUserActionSetId())
+                .actionParam(actionParam.toString())
+                .build();
+        ResultVO<Boolean> result = userActionSetRpc.reportByAppId(dataReportOfAppIdRpcDTO);
+        BackStatusEnum backStatus = BackStatusEnum.FAILED;
+        if (result.isSuccess()) {
+            backStatus = BackStatusEnum.SUCCESS;
+            gameTencentBackLog.setBackLog("回传成功");
+        } else {
+            gameTencentBackLog.setBackLog(result.getMsg());
+        }
+        gameTencentBackLogService.save(gameTencentBackLog);
+        return backStatus;
+    }*/
+}

+ 53 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/task/CallbackClearTask.java

@@ -0,0 +1,53 @@
+package com.zanxiang.game.back.serve.task;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.zanxiang.game.back.base.ServerInfo;
+import com.zanxiang.game.back.serve.config.NacosDynamicParamConfig;
+import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineAppCallback;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentAppCallback;
+import com.zanxiang.game.back.serve.service.IGameOceanengineAppCallbackService;
+import com.zanxiang.game.back.serve.service.IGameTencentAppCallbackService;
+import com.zanxiang.module.redis.service.IDistributedLockComponent;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDate;
+
+@Slf4j
+@Component
+public class CallbackClearTask {
+    private static final String CLEAR_KEY = ServerInfo.SERVER_NAME + ":CALLBACK_DATA_CLEAR";
+
+    @Autowired
+    private NacosDynamicParamConfig nacosDynamicParamConfig;
+    @Autowired
+    private IDistributedLockComponent distributedLockComponent;
+    @Autowired
+    private IGameOceanengineAppCallbackService gameOceanengineAppCallbackService;
+    @Autowired
+    private IGameTencentAppCallbackService gameTencentAppCallbackService;
+
+    /**
+     * 每天凌晨 2点清理一次 15天前的监测链接数据
+     */
+    @Scheduled(cron = "0 0 2 * * ?")
+    public void execute() {
+        log.error("开始清理监测链接的日志");
+        try {
+            gameOceanengineAppCallbackService.remove(new LambdaQueryWrapper<GameOceanengineAppCallback>()
+                    .lt(GameOceanengineAppCallback::getDay, LocalDate.now().minusDays(nacosDynamicParamConfig.getCallbackClearDay()))
+            );
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+        }
+        try {
+            gameTencentAppCallbackService.remove(new LambdaQueryWrapper<GameTencentAppCallback>()
+                    .lt(GameTencentAppCallback::getDay, LocalDate.now().minusDays(nacosDynamicParamConfig.getCallbackClearDay()))
+            );
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+        }
+    }
+}

+ 3 - 4
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/controller/GameMonitorAlarmController.java

@@ -39,13 +39,12 @@ public class GameMonitorAlarmController {
     }
 
 
+
+
     @ApiOperation(value = "测试")
     @PutMapping("/monitor")
     public ResultVO<Boolean> test() {
-        List<String> serverIdByGSId = gameServerService.getServerIdByGSId(120L);
-        serverIdByGSId.forEach(System.out::println);
-//        orderCostMonitorAlarmService.monitorTencentCostStatus();
-//        orderCostMonitorAlarmService.monitorDataStatus();
+        gameMonitorAlarmService.sendMsgToUserTest();
         return ResultVO.ok();
     }
 }

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

@@ -271,5 +271,17 @@ public class RoleRechargeRankingDTO extends BasePage {
     @ApiModelProperty(value = "玩家渠道id")
     private List<Long> agentIds;
 
+    /**
+     * 角色最近充值时间最小值
+     */
+    @ApiModelProperty(value = "角色最近充值时间最小值")
+    private LocalDate roleLastPayTimeMin;
+    /**
+     * 角色最近充值时间最大值
+     */
+    @ApiModelProperty(value = "角色最近充值时间最大值")
+    private LocalDate roleLastPayTimeMax;
+
+
 
 }

+ 26 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/vo/GameDataTotalTotalVO.java

@@ -121,6 +121,32 @@ public class GameDataTotalTotalVO {
     @ApiModelProperty(value = "新用户累计充值金额(总量)")
     private BigDecimal newUserTotalAmount;
 
+    /**
+     * 新用户充值金额(支付宝金额)(自然量)
+     */
+    @ApiModelProperty(value = "支付宝金额")
+    private BigDecimal alipayAmount;
+    /**
+     * 新用户充值金额(微信金额)(自然量)
+     */
+    @ApiModelProperty(value = "微信金额")
+    private BigDecimal wxAmount;
+    /**
+     * 新用户充值金额(米大师金额)(自然量)
+     */
+    @ApiModelProperty(value = "米大师金额")
+    private BigDecimal miMasterAmount;
+
+    @ApiModelProperty(value = "支付宝新用户累计充值金额(自然量)")
+    private BigDecimal natureNewUserTotalZfbAmount;
+
+    @ApiModelProperty(value = "微信新用户累计充值金额(自然量)")
+    private BigDecimal natureNewUserTotalWxAmount;
+
+    @ApiModelProperty(value = "米大师新用户累计充值金额(自然量)")
+    private BigDecimal natureNewUserTotalMdsAmount;
+
+
     /**
      * 首日Roi(总量)
      */

+ 26 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/vo/GameDataTotalVO.java

@@ -61,6 +61,32 @@ public class GameDataTotalVO {
     @ApiModelProperty(value = "新用户充值人数(总量)")
     private Long newUserAmountNum;
 
+    /**
+     * 新用户充值金额(支付宝金额)
+     */
+    @ApiModelProperty(value = "支付宝金额")
+    private BigDecimal alipayAmount;
+    /**
+     * 新用户充值金额(微信金额)
+     */
+    @ApiModelProperty(value = "微信金额")
+    private BigDecimal wxAmount;
+    /**
+     * 新用户充值金额(米大师金额)
+     */
+    @ApiModelProperty(value = "米大师金额")
+    private BigDecimal miMasterAmount;
+
+
+    @ApiModelProperty(value = "支付宝新用户累计充值金额(自然量)")
+    private BigDecimal natureNewUserTotalZfbAmount;
+
+    @ApiModelProperty(value = "微信新用户累计充值金额(自然量)")
+    private BigDecimal natureNewUserTotalWxAmount;
+
+    @ApiModelProperty(value = "米大师新用户累计充值金额(自然量)")
+    private BigDecimal natureNewUserTotalMdsAmount;
+
     /**
      * 新用户充值金额(总量)
      */

+ 4 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/vo/GameMonitorAlarmVO.java

@@ -93,6 +93,10 @@ public class GameMonitorAlarmVO {
      * 策略内容
      */
     private String configExplain;
+    /**
+     * 策略类型
+     */
+    private Integer configType;
 
     /**
      * 报警状态,0表示未报警,1标识已报警

+ 6 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/vo/PitcherDataDayTotalVO.java

@@ -121,6 +121,12 @@ public class PitcherDataDayTotalVO {
     @ApiModelProperty(value = "单日付费100+人数")
     private Long hundredUserNum;
 
+    /**
+     * 7日累充500+用户数
+     */
+    @ApiModelProperty(value = "7日累充500+用户数")
+    private Long totalFiveHundredUserCount;
+
     /**
      * 买量新用户累计充值金额
      */

+ 8 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/vo/PitcherDataDayVO.java

@@ -206,6 +206,12 @@ public class PitcherDataDayVO {
     @ApiModelProperty(value = "买量回收率")
     private BigDecimal buyRoi;
 
+    /**
+     * 7日累充500+用户数
+     */
+    @ApiModelProperty(value = "7日累充500+用户数")
+    private Long totalFiveHundredUserCount;
+
     /**
      * 当日回收率
      */
@@ -2154,4 +2160,6 @@ public class PitcherDataDayVO {
     @ApiModelProperty(value = "da1的用户详情")
     private FirstNewUserAgainTrendVO userDetails;
 
+
+
 }

+ 9 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/vo/PitcherDataTotalSumVO.java

@@ -222,6 +222,15 @@ public class PitcherDataTotalSumVO {
     @ApiModelProperty(value = "单日付费100+成本")
     private BigDecimal hundredUserNumCost;
 
+    @ApiModelProperty(value = "支付宝新用户累计充值金额")
+    private BigDecimal newUserTotalZfbAmount;
+
+    @ApiModelProperty(value = "微信新用户累计充值金额")
+    private BigDecimal newUserTotalWxAmount;
+
+    @ApiModelProperty(value = "米大师新用户累计充值金额")
+    private BigDecimal newUserTotalMdsAmount;
+
     /**
      * 买量新用户累计充值金额
      */

+ 13 - 3
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/vo/PitcherDataTotalVO.java

@@ -122,17 +122,17 @@ public class PitcherDataTotalVO {
     private Long newUserAmountCount;
 
     /**
-     * 支付宝金额
+     * 新用户充值金额(支付宝金额
      */
     @ApiModelProperty(value = "支付宝金额")
     private BigDecimal alipayAmount;
     /**
-     * 微信金额
+     * 新用户充值金额(微信金额
      */
     @ApiModelProperty(value = "微信金额")
     private BigDecimal wxAmount;
     /**
-     * 米大师金额
+     * 新用户充值金额(米大师金额
      */
     @ApiModelProperty(value = "米大师金额")
     private BigDecimal miMasterAmount;
@@ -233,6 +233,16 @@ public class PitcherDataTotalVO {
     @ApiModelProperty(value = "单日付费100+成本")
     private BigDecimal hundredUserNumCost;
 
+
+    @ApiModelProperty(value = "支付宝新用户累计充值金额")
+    private BigDecimal newUserTotalZfbAmount;
+
+    @ApiModelProperty(value = "微信新用户累计充值金额")
+    private BigDecimal newUserTotalWxAmount;
+
+    @ApiModelProperty(value = "米大师新用户累计充值金额")
+    private BigDecimal newUserTotalMdsAmount;
+
     /**
      * 买量新用户累计充值金额
      */

+ 2 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/IGameMonitorAlarmService.java

@@ -10,4 +10,6 @@ public interface IGameMonitorAlarmService {
 
     boolean sendMsgToUser();
 
+    boolean sendMsgToUserTest();
+
 }

+ 8 - 6
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/AdsOrderDetailServiceImpl.java

@@ -372,6 +372,8 @@ public class AdsOrderDetailServiceImpl implements IAdsOrderDetailService {
      *
      * @return String
      */
+   ////                	LEFT JOIN dm_game_order.t_game_user_role ab
+    ////                	on a.source_system = ab.source_system AND a.role_id = ab.role_id AND a.user_id = ab.user_id and a.game_id = ab.game_id
     private String getOrderDetailSql() {
         return """
                 SELECT
@@ -437,10 +439,9 @@ public class AdsOrderDetailServiceImpl implements IAdsOrderDetailService {
                  		l.id as back_id, -- 回传id
                  		l.back_table_name as back_table_name -- 回传表名
                 	FROM dm_game_order.t_game_order a
-                	LEFT JOIN dm_game_order.t_game_user_role ab
-                	on a.source_system = ab.source_system AND a.role_id = ab.role_id AND a.user_id = ab.user_id and a.game_id = ab.game_id
+
                 	LEFT JOIN dm_game_order.t_game_user_burst b
-                	on a.source_system = b.source_system AND a.user_id = b.id AND ab.create_time >= b.create_time AND ab.create_time <b.end_time
+                	on a.source_system = b.source_system AND a.user_id = b.id AND a.create_time >= b.create_time AND a.create_time <b.end_time
                 	LEFT JOIN dm_game_order.t_pitcher_agent c on a.source_system = c.source_system AND a.agent_id = c.id
                 	LEFT JOIN dm_game_order.t_pitcher_map d on c.source_system = d.source_system AND c.pitcher_id = d.zx_pitcher_id
                 	LEFT JOIN dm_game_order.t_cp e on a.source_system = e.source_system AND a.cp_id = e.id
@@ -544,6 +545,8 @@ public class AdsOrderDetailServiceImpl implements IAdsOrderDetailService {
      *
      * @return String
      */
+    //	LEFT JOIN dm_game_order.t_game_user_role ab
+    //                	on a.source_system = ab.source_system AND a.role_id = ab.role_id AND a.user_id = ab.user_id and a.game_id = ab.game_id
     private String getCountSql() {
         return """
                 SELECT
@@ -609,10 +612,9 @@ public class AdsOrderDetailServiceImpl implements IAdsOrderDetailService {
                  		l.id as back_id, -- 回传id
                  		l.back_table_name as back_table_name -- 回传表名
                 	FROM dm_game_order.t_game_order a
-                	LEFT JOIN dm_game_order.t_game_user_role ab
-                	on a.source_system = ab.source_system AND a.role_id = ab.role_id AND a.user_id = ab.user_id and a.game_id = ab.game_id
+                
                 	LEFT JOIN dm_game_order.t_game_user_burst b
-                	on a.source_system = b.source_system AND a.user_id = b.id AND ab.create_time >= b.create_time AND ab.create_time <b.end_time
+                	on a.source_system = b.source_system AND a.user_id = b.id AND a.create_time >= b.create_time AND a.create_time <b.end_time
                 	LEFT JOIN dm_game_order.t_pitcher_agent c on a.source_system = c.source_system AND a.agent_id = c.id
                 	LEFT JOIN dm_game_order.t_pitcher_map d on c.source_system = d.source_system AND c.pitcher_id = d.zx_pitcher_id
                 	LEFT JOIN dm_game_order.t_cp e on a.source_system = e.source_system AND a.cp_id = e.id

File diff suppressed because it is too large
+ 680 - 399
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/GameDataServiceImpl.java


+ 124 - 23
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/GameMonitorAlarmServiceImpl.java

@@ -8,6 +8,7 @@ import com.zanxiang.game.data.serve.service.IGameMonitorAlarmService;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.dubbo.config.annotation.DubboReference;
+import org.jetbrains.annotations.NotNull;
 import org.nutz.dao.Chain;
 import org.nutz.dao.Cnd;
 import org.nutz.dao.Dao;
@@ -18,7 +19,11 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * @author tianhua
@@ -46,37 +51,64 @@ public class GameMonitorAlarmServiceImpl implements IGameMonitorAlarmService {
         dao.execute(sql);
         //结果
         log.info("查询告警信息结束");
-        try{
+        try {
             List<GameMonitorAlarmVO> list1 = sql.getList(GameMonitorAlarmVO.class);
             log.info("告警信息:{}", list1);
-            if (CollectionUtils.isEmpty(list1)){
+            if (CollectionUtils.isEmpty(list1)) {
                 log.info("没有告警信息");
                 return true;
             }
+            //用type==4进行分组
+            Map<Boolean, List<GameMonitorAlarmVO>> partitionedMap = list1.stream()
+                    .collect(Collectors.partitioningBy(vo -> vo.getConfigType() == 4));
+            List<GameMonitorAlarmVO> listWithType4 = partitionedMap.get(true);
+
+            //如果有type==4的,则每个投手的消息整合为1条告警
+            if (CollectionUtils.isNotEmpty(listWithType4)) {
+                Map<String, List<GameMonitorAlarmVO>> map = new HashMap<>();
+                for (GameMonitorAlarmVO vo : listWithType4) {
+                    String[] pitcherIds = vo.getPitcherId().split("-");
+                    for (String pitcherId : pitcherIds) {
+                        if (map.get(pitcherId) != null) {
+                            map.get(pitcherId).add(vo);
+                        }else {
+                            ArrayList<GameMonitorAlarmVO> newList = new ArrayList<>();
+                            newList.add(vo);
+                            map.put(pitcherId,newList);
+                        }
+                    }
+                }
+                for (String pitcherId : map.keySet()) {
+                    List<GameMonitorAlarmVO> gameMonitorAlarmVOS = map.get(pitcherId);
+                    StringBuilder msgStr = new StringBuilder(0);
+                    //把消息拼成一条
+                    for (int i = 0; i < gameMonitorAlarmVOS.size(); i++) {
+                        String s = alarmStr(gameMonitorAlarmVOS.get(i),i);
+                        msgStr.append(s);
+                    }
+
+                    log.info("type类型为4的告警信息,投手id:{}",pitcherId);
+                    dingTalkMsgRpc.sendByUserId(Long.valueOf(pitcherId), new String(msgStr));
+                    log.info("type类型为4的告警信息发送成功,投手id:{}",pitcherId);
+                }
+                for (GameMonitorAlarmVO vo : listWithType4) {
+                    Criteria cri = getCriteria(vo);
+                    dao.update(AdsMonitorAlarm.class, Chain.make("warn_status", 1), cri);
+                }
+            }
+
+            //如果没有type==4的,则每个投手的消息单独发送
+            List<GameMonitorAlarmVO> listWithoutType4 = partitionedMap.get(false);
             log.info("准备发送告警信息");
-            for (GameMonitorAlarmVO vo : list1) {
+            for (GameMonitorAlarmVO vo : listWithoutType4) {
                 String[] pitcherIds = vo.getPitcherId().split("-");
                 for (String pitcherId : pitcherIds) {
                     //发送给多个投手
                     log.info("发送告警信息给投手:{}", pitcherId);
-                    dingTalkMsgRpc.sendByUserId(Long.valueOf(pitcherId), alarmStr(vo));
+                    dingTalkMsgRpc.sendByUserId(Long.valueOf(pitcherId), alarmStr(vo,null));
                     log.info("发送告警信息给投手:{}成功", pitcherId);
                 }
-                //更新的条件
-                Criteria cri = Cnd.cri();
-                if (vo.getId() != null) {
-                    cri.where().andEquals("id", vo.getId());
-                }
-                if (vo.getDt() != null) {
-                    cri.where().andEquals("dt", vo.getDt());
-                }
-                if (vo.getGameId() != null) {
-                    cri.where().andEquals("gameId", vo.getGameId());
-                }
-                if (vo.getUserId() != null) {
-                    cri.where().andEquals("userId", vo.getUserId());
-                }
-                log.info("更新告警信息状态");
+                Criteria cri = getCriteria(vo);
                 dao.update(AdsMonitorAlarm.class, Chain.make("warn_status", 1), cri);
             }
 
@@ -86,11 +118,76 @@ public class GameMonitorAlarmServiceImpl implements IGameMonitorAlarmService {
         return true;
     }
 
+    @Override
+    public boolean sendMsgToUserTest() {
+        Sql sql = Sqls.create(getMonitorAlarmInfoSql());
+        sql.setCallback(Sqls.callback.entities());
+        sql.setEntity(dao.getEntity(GameMonitorAlarmVO.class));
+        dao.execute(sql);
+        List<GameMonitorAlarmVO> list1 = sql.getList(GameMonitorAlarmVO.class);
+        //用type==4进行分组
+        Map<Boolean, List<GameMonitorAlarmVO>> partitionedMap = list1.stream()
+                .collect(Collectors.partitioningBy(vo -> vo.getConfigType() == 4));
+        List<GameMonitorAlarmVO> listWithType4 = partitionedMap.get(true);
+        //如果有type==4的,则每个投手的消息整合为1条告警
+        if (CollectionUtils.isNotEmpty(listWithType4)) {
+            Map<String, List<GameMonitorAlarmVO>> map = new HashMap<>();
+            for (GameMonitorAlarmVO vo : listWithType4) {
+                String[] pitcherIds = vo.getPitcherId().split("-");
+                for (String pitcherId : pitcherIds) {
+                    if (map.get(pitcherId) != null) {
+                        map.get(pitcherId).add(vo);
+                    }else {
+                        ArrayList<GameMonitorAlarmVO> newList = new ArrayList<>();
+                        newList.add(vo);
+                        map.put(pitcherId,newList);
+                    }
+                }
+            }
+            for (String pitcherId : map.keySet()) {
+                List<GameMonitorAlarmVO> gameMonitorAlarmVOS = map.get(pitcherId);
+                StringBuilder msgStr = new StringBuilder(0);
+                //把消息拼成一条
+                for (int i = 0; i < gameMonitorAlarmVOS.size(); i++) {
+                    String s = alarmStr(gameMonitorAlarmVOS.get(i),i);
+                    msgStr.append(s);
+                }
+
+                log.info("type类型为4的告警信息,投手id:{}",pitcherId);
+                log.info("type类型为4的告警信息:{}",msgStr);
+                log.info("type类型为4的告警信息发送成功,投手id:{}",pitcherId);
+            }
+        }
+        return true;
+    }
+
+    private  Criteria getCriteria(GameMonitorAlarmVO vo) {
+        //更新的条件
+        Criteria cri = Cnd.cri();
+        if (vo.getId() != null) {
+            cri.where().andEquals("id", vo.getId());
+        }
+        if (vo.getDt() != null) {
+            cri.where().andEquals("dt", vo.getDt());
+        }
+        if (vo.getGameId() != null) {
+            cri.where().andEquals("gameId", vo.getGameId());
+        }
+        if (vo.getUserId() != null) {
+            cri.where().andEquals("userId", vo.getUserId());
+        }
+        log.info("更新告警信息状态");
+        return cri;
+    }
+
     /**
      * 生成告警信息字符串
      */
-    private String alarmStr(GameMonitorAlarmVO vo) {
+    private String alarmStr(GameMonitorAlarmVO vo,Integer index) {
         StringBuilder msgStr = new StringBuilder(0);
+        if(index!=null){
+            msgStr.append("【"+(index+1)+"】 \n");
+        }
         msgStr.append("游戏策略响应时间:")
                 .append(vo.getDt())
                 .append(" ;")
@@ -112,13 +209,16 @@ public class GameMonitorAlarmServiceImpl implements IGameMonitorAlarmService {
                 .append(" ;")
                 .append("\n")
                 .append("该用户响应的策略属于:")
-                .append(vo.getConfigExplain());
+                .append(vo.getConfigExplain())
+                .append(";")
+                .append("\n");
 
         return msgStr.toString();
     }
 
     /**
      * 游戏监控告警sql
+     *
      * @return String
      */
     private String getMonitorAlarmInfoSql() {
@@ -139,6 +239,7 @@ public class GameMonitorAlarmServiceImpl implements IGameMonitorAlarmService {
                 	a.pitcher_id ,
                 	a.message ,
                 	a.config_explain ,
+                	a.config_type,
                 	a.warn_status
                 FROM game_ads.ads_monitor_alarm a
                 LEFT JOIN dm_game_order.t_game_user b on a.source_system = b.source_system AND a.user_id = b.id
@@ -155,6 +256,6 @@ public class GameMonitorAlarmServiceImpl implements IGameMonitorAlarmService {
                 WHERE a.warn_status = 0
                 """;
     }
-    
-    
+
+
 }

+ 9 - 9
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/OrderCostMonitorAlarmBySmsServiceImpl.java

@@ -46,18 +46,18 @@ public class OrderCostMonitorAlarmBySmsServiceImpl implements IOrderCostMonitorA
     private String phoneNumber;
 
     /**
-     * 10分钟扫一次,每次扫当前时间-半小时
+     * 30分钟扫一次,每次扫当前时间-1小时
      */
     @Override
     public void monitorDataStatus() {
         //获取当前时间前半小时的时间
-        LocalDateTime date = LocalDateTime.now().minusMinutes(30);
+        LocalDateTime date = LocalDateTime.now().minusMinutes(60);
         //查询订单表
         Sql orderSql = getSql(getOrderCountSql(date));
         int count = orderSql.getInt(0);
         //如果为0直接告警
         if (count == 0) {
-            String msg = "前小时订单表数据为空,请检查";
+            String msg = "前小时订单表数据为空,请检查";
             log.info(msg);
             if(!sendSms(msg)){
                 throw new RuntimeException("短信发送失败");
@@ -68,7 +68,7 @@ public class OrderCostMonitorAlarmBySmsServiceImpl implements IOrderCostMonitorA
     @Override
     public void monitorHeadCostStatus() {
         //获取当前时间前半小时的时间
-        LocalDateTime date = LocalDateTime.now().minusMinutes(30);
+        LocalDateTime date = LocalDateTime.now().minusMinutes(60);
         //查询头条广告表
         Sql headCostSql = getSql(getheadCostCountSql(date));
         int newHeadCostCount = headCostSql.getInt(0);
@@ -85,15 +85,15 @@ public class OrderCostMonitorAlarmBySmsServiceImpl implements IOrderCostMonitorA
                 }
             }
         }
-        //将新数据存入redis  30分钟
-        redisUtil.setCache(HEADLINE_COST_COUNT, Integer.toString(newHeadCostCount), 60 * 30);
+        //将新数据存入redis  60分钟
+        redisUtil.setCache(HEADLINE_COST_COUNT, Integer.toString(newHeadCostCount), 60 * 60);
 
     }
 
     @Override
     public void monitorTencentCostStatus() {
         //获取当前时间前半小时的时间
-        LocalDateTime date = LocalDateTime.now().minusMinutes(30);
+        LocalDateTime date = LocalDateTime.now().minusMinutes(60);
         //查询腾讯广告表
         Sql tencentCostSql = getSql(getTencentCostSqlSql(date));
         int newTencentCostCount = tencentCostSql.getInt(0);
@@ -108,8 +108,8 @@ public class OrderCostMonitorAlarmBySmsServiceImpl implements IOrderCostMonitorA
                 }
             }
         }
-        //将新数据存入redis  30分钟
-        redisUtil.setCache(TENCENT_COST_COUNT, Integer.toString(newTencentCostCount), 60 * 30);
+        //将新数据存入redis  60分钟
+        redisUtil.setCache(TENCENT_COST_COUNT, Integer.toString(newTencentCostCount), 60 * 60);
     }
 
 

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

@@ -509,6 +509,8 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
         } else {
             sql = Sqls.create(pitcherDataTotalSqlForParent(criA, criB, criAmount, criNewUser, criRoleNum) + orderByCri);
         }
+        // 打印SQL
+        System.out.println("Executing SQL: " + sql.getSourceSql());
         //设置自定义回显对象
         sql.setCallback(Sqls.callback.entities());
         sql.setEntity(dao.getEntity(PitcherDataTotalVO.class));
@@ -2385,7 +2387,8 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
                     first_role_rate,
                     new_user_total_role_rate,
                     role_num_rate,
-                    new_user_amount_ratio
+                    new_user_amount_ratio,
+                    total_five_hundred_user_count
                 FROM 
                 """ + tableName;
     }
@@ -2876,6 +2879,7 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
                     ROUND(IF(SUM(new_user_total_amount_num) > 0 , SUM(new_user_total_amount) / SUM(new_user_total_amount_num), 0), 2) as today_arpu,
                     ROUND(IF(SUM(amount_num) > 0 , SUM(amount) / SUM(amount_num), 0), 2) as paper_arpu,
                     SUM(hundred_user_num) as hundred_user_num,
+                    SUM(total_five_hundred_user_count) AS total_five_hundred_user_count,
                     ROUND(IF(SUM(hundred_user_num) > 0 , SUM(cost) / SUM(hundred_user_num), 0), 2) as hundred_user_num_cost,
                     ROUND(IF(SUM(cost) > 0 , SUM(da1) / SUM(cost), 0), 4) as roi1,
                     ROUND(IF(SUM(cost) > 0 , SUM(da2) / SUM(cost), 0), 4) as roi2,
@@ -3090,7 +3094,10 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
                 	ROUND(IF(new_user_total_amount_num > 0, IFNULL(new_user_order_again, 0) / new_user_total_amount_num, 0), 4) as new_user_again_rate,
                 	IFNULL(role_num, 0) as role_num,
                 	ROUND(IF(register_num > 0, IFNULL(role_num, 0) / register_num, 0), 4) as role_num_rate,
-                	ROUND(IF(role_num > 0, IFNULL(cost, 0) / role_num, 0), 2) as role_num_cost
+                	ROUND(IF(role_num > 0, IFNULL(cost, 0) / role_num, 0), 2) as role_num_cost,
+                	new_user_total_zfb_amount,
+                 	new_user_total_wx_amount,
+                 	new_user_total_mds_amount
                 FROM (
                 	SELECT
                 		pitcher_id,
@@ -3136,20 +3143,22 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
                 		ROUND(IF(SUM(new_user_total_amount_num) > 0 , SUM(new_user_total_amount) / SUM(new_user_total_amount_num), 0), 2) as today_arpu,
                 		SUM(hundred_user_num) as hundred_user_num,
                     	ROUND(IF(SUM(hundred_user_num) > 0 , SUM(cost) / SUM(hundred_user_num), 0), 2) as hundred_user_num_cost,
-                		""" + pitcherDataTotalRoiSql() +
-                """
-                            	ROUND(IF(SUM(IF(DATE_ADD(dt, INTERVAL 59 day) <= LocalDate.now(), cost, 0)) > 0 ,
-                                    SUM(da60) / SUM(IF(DATE_ADD(dt, INTERVAL 59 day) <= LocalDate.now(), cost, 0)), 0), 4) as roi60,
-                            	ROUND(IF(SUM(IF(DATE_ADD(dt, INTERVAL 89 day) <= LocalDate.now(), cost, 0)) > 0 ,
-                                    SUM(da90) / SUM(IF(DATE_ADD(dt, INTERVAL 89 day) <= LocalDate.now(), cost, 0)), 0), 4) as roi90,
-                                ROUND(IF(SUM(IF(DATE_ADD(dt, INTERVAL 179 day) <= LocalDate.now(), cost, 0)) > 0 ,
-                                    SUM(m6) / SUM(IF(DATE_ADD(dt, INTERVAL 179 day) <= LocalDate.now(), cost, 0)), 0), 4) as roi180,
-                                ROUND(IF(SUM(IF(DATE_ADD(dt, INTERVAL 1 year) <= LocalDate.now(), cost, 0)) > 0 ,
-                                    SUM(m12) / SUM(IF(DATE_ADD(dt, INTERVAL 1 year) <= LocalDate.now(), cost, 0)), 0), 4) as roi1yaer,
-                            	ROUND(IF(SUM(cost) > 0 , SUM(total) / SUM(cost), 0), 4) as roi_total
-                            FROM
-                            	game_ads.ads_pitcher_day
-                        """ + criA +
+                		""" + pitcherDataTotalRoiSql() + """
+                    	ROUND(IF(SUM(IF(DATE_ADD(dt, INTERVAL 59 day) <= LocalDate.now(), cost, 0)) > 0 ,
+                            SUM(da60) / SUM(IF(DATE_ADD(dt, INTERVAL 59 day) <= LocalDate.now(), cost, 0)), 0), 4) as roi60,
+                    	ROUND(IF(SUM(IF(DATE_ADD(dt, INTERVAL 89 day) <= LocalDate.now(), cost, 0)) > 0 ,
+                            SUM(da90) / SUM(IF(DATE_ADD(dt, INTERVAL 89 day) <= LocalDate.now(), cost, 0)), 0), 4) as roi90,
+                        ROUND(IF(SUM(IF(DATE_ADD(dt, INTERVAL 179 day) <= LocalDate.now(), cost, 0)) > 0 ,
+                            SUM(m6) / SUM(IF(DATE_ADD(dt, INTERVAL 179 day) <= LocalDate.now(), cost, 0)), 0), 4) as roi180,
+                        ROUND(IF(SUM(IF(DATE_ADD(dt, INTERVAL 1 year) <= LocalDate.now(), cost, 0)) > 0 ,
+                            SUM(m12) / SUM(IF(DATE_ADD(dt, INTERVAL 1 year) <= LocalDate.now(), cost, 0)), 0), 4) as roi1yaer,
+                    	ROUND(IF(SUM(cost) > 0 , SUM(total) / SUM(cost), 0), 4) as roi_total,
+                    	SUM(new_user_total_zfb_amount) AS new_user_total_zfb_amount,
+                         	SUM(new_user_total_wx_amount) AS new_user_total_wx_amount,
+                         	SUM(new_user_total_mds_amount) AS new_user_total_mds_amount
+                    FROM
+                    	game_ads.ads_pitcher_day
+                """ + criA +
                 """
                         ) a
                         LEFT JOIN (
@@ -3212,7 +3221,7 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
                                 user_zx_pitcher_id as f_pitcher_id,
                                 COUNT(DISTINCT role_user_id) as role_num
                             FROM
-                                dw_create_role_detail
+                                game_ads.dw_create_role_detail
                             """ + criRoleNum +
                 """
                                 AND NOT user_agent_id = 0
@@ -3782,6 +3791,9 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
                     ROUND(IF(SUM(new_user_total_amount_num) > 0 , SUM(new_user_total_amount) / SUM(new_user_total_amount_num), 0), 2) as today_arpu,
                     IFNULL(SUM(hundred_user_num), 0) as hundred_user_num,
                     ROUND(IF(SUM(hundred_user_num) > 0 , SUM(cost) / SUM(hundred_user_num), 0), 2) as hundred_user_num_cost,
+                    SUM(new_user_total_zfb_amount) AS new_user_total_zfb_amount,
+                    SUM(new_user_total_wx_amount) AS new_user_total_wx_amount,
+                    SUM(new_user_total_mds_amount) AS new_user_total_mds_amount,
                 """ + pitcherDataTotalRoiSql() +
                 """
                             ROUND(IF(SUM(IF(DATE_ADD(dt, INTERVAL 59 day) <= LocalDate.now(), cost, 0)) > 0 ,

+ 8 - 4
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/RoleManageServiceImpl.java

@@ -360,9 +360,9 @@ public class RoleManageServiceImpl implements IRoleManageService {
         if (dto.getGsId() != null) {
             //GS
             if (dto.getGsId() == 0L) {
-                criA.where().andIsNull("gs_id");
+                criA.where().andIsNull("gsId");
             } else {
-                criA.where().andEquals("gs_id", dto.getGsId());
+                criA.where().andEquals("gsId", dto.getGsId());
             }
         }
         if (dto.getPitcherId() != null) {
@@ -419,6 +419,10 @@ public class RoleManageServiceImpl implements IRoleManageService {
         if (dto.getLastActiveTimeMax() != null && dto.getLastActiveTimeMin() != null) {
             criA.where().andBetween("DATE(role_active_time)", dto.getLastActiveTimeMin(), dto.getLastActiveTimeMax());
         }
+        //角色最近充值时间
+        if(dto.getRoleLastPayTimeMin() != null && dto.getRoleLastPayTimeMax() != null){
+            criA.where().andBetween("DATE(role_last_pay_time)", dto.getRoleLastPayTimeMin(), dto.getRoleLastPayTimeMax());
+        }
         return criA;
     }
 
@@ -2366,7 +2370,7 @@ public class RoleManageServiceImpl implements IRoleManageService {
                         IF(TIMESTAMPDIFF(HOUR, f.pay_time, NOW()) < 72 , 0, 1) , 0) as is_remove_game_for_system, -- 是否退游 1-是;0-否(系统判定)
                         IFNULL(j.is_remove_game,2) as is_remove_game, -- 是否退游 1-是;0-否;2-代表未操作数据
                         IFNULL(j.is_wake_up,2) as is_wake_up, -- 是否唤醒 1-是;0-否 2-未操作
-                        j.gs_id as gs_id, -- GS_ID
+                        j.gs_id as gsId, -- GS_ID
                         j.customer_service_id as customer_service_id, -- 客服ID
                         j.oper_user_id as oper_user_id, -- 运营ID
                         j.is_delete as is_delete, -- 是否删除 1-删除;0-正常
@@ -4356,7 +4360,7 @@ public class RoleManageServiceImpl implements IRoleManageService {
                 			a.game_id ,
                 			b.parent_game_id,
                 			b.super_game_id ,
-                			ROW_NUMBER()over(partition by a.source_system , a.role_id, b.parent_game_id order by a.role_level desc,a.combat_num desc) as num
+                			ROW_NUMBER()over(partition by a.source_system , a.role_id, b.super_game_id order by a.role_level desc,a.combat_num desc) as num
                 		FROM dm_game_order.t_game_user_role a
                 		LEFT JOIN (
                 			SELECT

+ 2 - 2
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/task/OrderCostMonitorAlarmTask.java

@@ -69,9 +69,9 @@ public class OrderCostMonitorAlarmTask {
 
 
     /**
-     * 任务每10分钟运行一次
+     * 任务每30分钟运行一次
      */
-    @Scheduled(cron = "0 0/10 * * * ? ")
+    @Scheduled(cron = "0 0/30 * * * ? ")
     public void runTask(){
         log.info("订单与消耗监控告警定时任务开始.");
         ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

+ 15 - 1
game-gs-data/game-gs-data-serve/pom.xml

@@ -89,7 +89,21 @@
         <dependency>
             <groupId>com.mybatis-flex</groupId>
             <artifactId>mybatis-flex-spring-boot-starter</artifactId>
-            <version>1.7.5</version>
+            <version>1.9.2</version>
+        </dependency>
+        <dependency>
+            <groupId>com.mybatis-flex</groupId>
+            <artifactId>mybatis-flex-processor</artifactId>
+            <version>1.9.2</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.zaxxer</groupId>
+            <artifactId>HikariCP</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
         </dependency>
     </dependencies>
 

+ 23 - 0
game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/GameGsDataApplication.java

@@ -1,9 +1,32 @@
 package com.zanxiang.game.gs.data.serve;
 
+import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
 /**
  * @author : lingfeng
  * @time : 2024-06-03
  * @description : GS数据系统启动类
  */
+@EnableDiscoveryClient
+@SpringBootApplication
+@Configuration
+@EnableDubbo
+@EnableScheduling
 public class GameGsDataApplication {
+    public static void main(String[] args) {
+        SpringApplication.run(GameGsDataApplication.class, args);
+        System.out.println("游戏GS数据启动成功 \n" +
+                " ______  __     __     \n" +
+                "/_____/\\/__/\\ /__/\\    \n" +
+                "\\:::__\\/\\ \\::\\\\:.\\ \\   \n" +
+                "   /: /  \\_\\::_\\:_\\/   \n" +
+                "  /::/___  _\\/__\\_\\_/\\ \n" +
+                " /_:/____/\\\\ \\ \\ \\::\\ \\\n" +
+                " \\_______\\/ \\_\\/  \\__\\/\n");
+    }
 }

+ 11 - 0
game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/config/MybatisFlexConfig.java

@@ -0,0 +1,11 @@
+package com.zanxiang.game.gs.data.serve.config;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+@Configuration
+@EnableTransactionManagement
+@MapperScan(value = "com.zanxiang.game.gs.data.serve.dao.mapper**")
+public class MybatisFlexConfig {
+}

+ 2 - 2
game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/config/SwaggerConfig.java

@@ -29,7 +29,7 @@ public class SwaggerConfig {
                 .apiInfo(apiInfo())
                 .select()
                 .apis(RequestHandlerSelectors
-                        .basePackage("com.zanxiang.game.module.manage"))
+                        .basePackage("com.zanxiang.game.gs.data.serve"))
                 .paths(PathSelectors.any())
                 .build();
     }
@@ -41,7 +41,7 @@ public class SwaggerConfig {
      */
     private ApiInfo apiInfo() {
         return new ApiInfoBuilder()
-                .title("游戏管理后台服务")
+                .title("游戏GS数据")
                 .version("1.0")
                 .build();
     }

+ 33 - 0
game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/controller/GameParentController.java

@@ -0,0 +1,33 @@
+package com.zanxiang.game.gs.data.serve.controller;
+
+import com.mybatisflex.core.row.Row;
+import com.zanxiang.game.gs.data.serve.pojo.dto.BigRDTO;
+import com.zanxiang.game.gs.data.serve.pojo.vo.BigRVO;
+import com.zanxiang.game.gs.data.serve.pojo.vo.PageVO;
+import com.zanxiang.game.gs.data.serve.service.IAdsRoleAmountDataParentService;
+import com.zanxiang.module.util.pojo.ResultVO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+@Api(tags = {"GS充值付费比"})
+@RestController
+@RequestMapping("/game/parent")
+public class GameParentController {
+    @Resource
+    private IAdsRoleAmountDataParentService adsRoleAmountDataParentService;
+
+    @ApiOperation(value = "大R每日充值比")
+//    @PreAuthorize(permissionKey = "gameGs:bigR:list")
+    @PostMapping("/bigR/listOfPage")
+    public ResultVO<PageVO<BigRVO, Row>> bigRListOfPage(@Validated @RequestBody BigRDTO dto) {
+        return ResultVO.ok(adsRoleAmountDataParentService.bigRListOfPage(dto));
+    }
+
+}

+ 19 - 0
game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/dao/mapper/erp/SysUserMapper.java

@@ -0,0 +1,19 @@
+package com.zanxiang.game.gs.data.serve.dao.mapper.erp;
+
+import com.mybatisflex.annotation.UseDataSource;
+import com.zanxiang.game.gs.data.serve.pojo.entity.erp.SysUser;
+import com.mybatisflex.core.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 用户信息表 映射层。
+ *
+ * @author shaosong
+ * @since 1.0
+ */
+@Mapper
+@UseDataSource("dm_erp")
+public interface SysUserMapper extends BaseMapper<SysUser> {
+
+
+}

+ 19 - 0
game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/dao/mapper/game/order/GameAuthGroupMapper.java

@@ -0,0 +1,19 @@
+package com.zanxiang.game.gs.data.serve.dao.mapper.game.order;
+
+import com.mybatisflex.annotation.UseDataSource;
+import com.zanxiang.game.gs.data.serve.pojo.entity.game.order.GameAuthGroup;
+import com.mybatisflex.core.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 授权分组 映射层。
+ *
+ * @author shaosong
+ * @since 1.0
+ */
+@Mapper
+@UseDataSource("game_order")
+public interface GameAuthGroupMapper extends BaseMapper<GameAuthGroup> {
+
+
+}

+ 19 - 0
game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/dao/mapper/game/order/GameAuthRoleGroupMapper.java

@@ -0,0 +1,19 @@
+package com.zanxiang.game.gs.data.serve.dao.mapper.game.order;
+
+import com.mybatisflex.annotation.UseDataSource;
+import com.zanxiang.game.gs.data.serve.pojo.entity.game.order.GameAuthRoleGroup;
+import com.mybatisflex.core.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 游戏授权角色分组 映射层。
+ *
+ * @author shaosong
+ * @since 1.0
+ */
+@Mapper
+@UseDataSource("game_order")
+public interface GameAuthRoleGroupMapper extends BaseMapper<GameAuthRoleGroup> {
+
+
+}

+ 19 - 0
game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/dao/mapper/game/order/GameMapper.java

@@ -0,0 +1,19 @@
+package com.zanxiang.game.gs.data.serve.dao.mapper.game.order;
+
+import com.mybatisflex.annotation.UseDataSource;
+import com.zanxiang.game.gs.data.serve.pojo.entity.game.order.Game;
+import com.mybatisflex.core.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 游戏表 映射层。
+ *
+ * @author shaosong
+ * @since 1.0
+ */
+@Mapper
+@UseDataSource("game_order")
+public interface GameMapper extends BaseMapper<Game> {
+
+
+}

+ 19 - 0
game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/dao/mapper/game/order/GameServerMapper.java

@@ -0,0 +1,19 @@
+package com.zanxiang.game.gs.data.serve.dao.mapper.game.order;
+
+import com.mybatisflex.annotation.UseDataSource;
+import com.zanxiang.game.gs.data.serve.pojo.entity.game.order.GameServer;
+import com.mybatisflex.core.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 游戏区服表 映射层。
+ *
+ * @author shaosong
+ * @since 1.0
+ */
+@Mapper
+@UseDataSource("game_order")
+public interface GameServerMapper extends BaseMapper<GameServer> {
+
+
+}

+ 19 - 0
game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/dao/mapper/game/order/RoleOperateMapper.java

@@ -0,0 +1,19 @@
+package com.zanxiang.game.gs.data.serve.dao.mapper.game.order;
+
+import com.mybatisflex.annotation.UseDataSource;
+import com.zanxiang.game.gs.data.serve.pojo.entity.game.order.RoleOperate;
+import com.mybatisflex.core.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 角色操作表 映射层。
+ *
+ * @author shaosong
+ * @since 1.0
+ */
+@Mapper
+@UseDataSource("game_order")
+public interface RoleOperateMapper extends BaseMapper<RoleOperate> {
+
+
+}

+ 19 - 0
game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/dao/mapper/game/parent/AdsRoleAmountDataParentMapper.java

@@ -0,0 +1,19 @@
+package com.zanxiang.game.gs.data.serve.dao.mapper.game.parent;
+
+import com.mybatisflex.annotation.UseDataSource;
+import com.zanxiang.game.gs.data.serve.pojo.entity.game.parent.AdsRoleAmountDataParent;
+import com.mybatisflex.core.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 角色父游戏充值数据 映射层。
+ *
+ * @author shaosong
+ * @since 1.0
+ */
+@Mapper
+@UseDataSource("game_ads_parent")
+public interface AdsRoleAmountDataParentMapper extends BaseMapper<AdsRoleAmountDataParent> {
+
+
+}

+ 19 - 0
game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/dao/mapper/game/parent/AdsRoleAmountDataTodayParentMapper.java

@@ -0,0 +1,19 @@
+package com.zanxiang.game.gs.data.serve.dao.mapper.game.parent;
+
+import com.mybatisflex.annotation.UseDataSource;
+import com.zanxiang.game.gs.data.serve.pojo.entity.game.parent.AdsRoleAmountDataTodayParent;
+import com.mybatisflex.core.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 角色父游戏当天充值数据 映射层。
+ *
+ * @author shaosong
+ * @since 1.0
+ */
+@Mapper
+@UseDataSource("game_ads_parent")
+public interface AdsRoleAmountDataTodayParentMapper extends BaseMapper<AdsRoleAmountDataTodayParent> {
+
+
+}

+ 98 - 0
game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/handler/GlobalExceptionHandler.java

@@ -0,0 +1,98 @@
+package com.zanxiang.game.gs.data.serve.handler;
+
+import com.zanxiang.erp.security.exception.NoPermissionException;
+import com.zanxiang.module.util.DateUtil;
+import com.zanxiang.module.util.exception.BaseException;
+import com.zanxiang.module.util.pojo.ResultVO;
+import com.zanxiang.module.web.util.ServletUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.converter.HttpMessageNotReadableException;
+import org.springframework.validation.BindException;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
+
+import java.time.LocalDateTime;
+
+/**
+ * 全局异常代理
+ */
+@Slf4j
+@RestControllerAdvice
+public class GlobalExceptionHandler {
+
+    /**
+     * 业务异常
+     */
+    @ExceptionHandler(BaseException.class)
+    public ResultVO<?> baseException(BaseException e) {
+        return ResultVO.fail(e.getMessage());
+    }
+
+    /**
+     * http method错误
+     *
+     * @param e
+     * @return
+     */
+    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
+    public ResultVO<?> methodNotSupportedException(HttpRequestMethodNotSupportedException e) {
+        log.error("URL:{}, 请求 method:{}, 支持的 method:{}", ServletUtil.getRequest().getRequestURL(), ServletUtil.getRequest().getMethod(), e.getSupportedMethods());
+        return ResultVO.fail("http method错误!");
+    }
+
+    /**
+     * 自定义参数校验错误
+     */
+    @ExceptionHandler(BindException.class)
+    public ResultVO<?> validatedBindException(BindException e) {
+        String message = e.getAllErrors().get(0).getDefaultMessage();
+        return ResultVO.fail(message);
+    }
+
+    /**
+     * 自定义参数校验错误
+     */
+    @ExceptionHandler(MethodArgumentNotValidException.class)
+    public ResultVO<?> validExceptionHandler(MethodArgumentNotValidException e) {
+        String message = e.getBindingResult().getFieldError().getDefaultMessage();
+        return ResultVO.fail(message);
+    }
+
+    /**
+     * 自定义参数校验错误
+     */
+    @ExceptionHandler(HttpMessageNotReadableException.class)
+    public ResultVO<?> validExceptionHandler(HttpMessageNotReadableException e) {
+        log.error(e.getMessage(), e);
+        return ResultVO.fail("参数异常,请勿非法操作");
+    }
+
+    /**
+     * 参数类型不匹配导致转换异常
+     *
+     * @param e
+     * @return
+     */
+    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
+    public ResultVO<?> mismatchErrorHandler(MethodArgumentTypeMismatchException e) {
+        log.error("方法:{},字段:{},参数:{},错误信息:{}", e.getParameter().getMethod(), e.getName(), e.getValue(), e.getMessage());
+        return ResultVO.fail("请求参数异常,请勿非法操作");
+    }
+
+    /**
+     * 权限异常
+     */
+    @ExceptionHandler(NoPermissionException.class)
+    public ResultVO<?> preAuthorizeException(NoPermissionException e) {
+        return ResultVO.fail("没有权限,请联系管理员授权");
+    }
+
+    @ExceptionHandler(Exception.class)
+    public ResultVO<?> handleException(Exception e) {
+        log.error(e.getMessage(), e);
+        return ResultVO.fail(DateUtil.formatLocalDateTime(LocalDateTime.now()) + ": 服务异常,请联系管理员");
+    }
+}

+ 0 - 9
game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/pojo/BTable.java

@@ -1,9 +0,0 @@
-package com.zanxiang.game.gs.data.serve.pojo;
-
-/**
- * @author : lingfeng
- * @time : 2024-06-03
- * @description :
- */
-public class BTable {
-}

+ 22 - 0
game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/pojo/dto/BaseListDTO.java

@@ -0,0 +1,22 @@
+package com.zanxiang.game.gs.data.serve.pojo.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+
+@Data
+public class BaseListDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @NotNull(message = "分页对象不能为空")
+    @Min(value = 1L, message = "起始页最小为 1")
+    private Integer pageNum;
+
+    @NotNull(message = "分页对象不能为空")
+    @Min(value = 1L, message = "页面大小(2~999)之间")
+    @Max(value = 999L, message = "页面大小(2~999)之间")
+    private Integer pageSize;
+}

+ 28 - 0
game-gs-data/game-gs-data-serve/src/main/java/com/zanxiang/game/gs/data/serve/pojo/dto/BigRDTO.java

@@ -0,0 +1,28 @@
+package com.zanxiang.game.gs.data.serve.pojo.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import javax.validation.constraints.NotBlank;
+import java.time.LocalDate;
+import java.util.List;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class BigRDTO extends BaseListDTO {
+    @NotBlank
+    @ApiModelProperty(notes = "SDK来源")
+    private String sourceSystem;
+    @ApiModelProperty("排序字段")
+    private String sortFiled;
+    @ApiModelProperty("排序类型:升序 true;降序 false")
+    private Boolean sortAsc = true;
+
+    @ApiModelProperty("统计日期开始")
+    private LocalDate dtBegin;
+    @ApiModelProperty("统计日期结束")
+    private LocalDate dtEnd;
+    @ApiModelProperty("gs id列表")
+    private List<Long> gsIdList;
+}

Some files were not shown because too many files changed in this diff