Kaynağa Gözat

Merge remote-tracking branch 'origin/package' into package

zhangxianyu 9 ay önce
ebeveyn
işleme
beb288327a
67 değiştirilmiş dosya ile 4187 ekleme ve 1 silme
  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. 29 0
      game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/dto/TtAppOrderBackQueryRpcDTO.java
  5. 28 0
      game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/dto/TtAppRoleRegisterBackQueryRpcDTO.java
  6. 25 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. 21 0
      game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/rpc/ITencentAppBackRpc.java
  11. 43 0
      game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/rpc/ITtAppBackRpc.java
  12. 6 0
      game-back/game-back-serve/pom.xml
  13. 27 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/config/KafkaConfig.java
  14. 3 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/config/NacosDynamicParamConfig.java
  15. 33 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/controller/api/OceanengineCallbackApi.java
  16. 36 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/controller/api/TencentCallbackApi.java
  17. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameOceanengineAppBackLogMapper.java
  18. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameOceanengineAppCallbackMapper.java
  19. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameOceanengineAppOrderLogMapper.java
  20. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameOceanengineAppRoleRegisterLogMapper.java
  21. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameOceanengineAppUserLogMapper.java
  22. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameTencentAppBackLogMapper.java
  23. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameTencentAppCallbackMapper.java
  24. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameTencentAppOrderMapper.java
  25. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameTencentAppOrderSplitLogMapper.java
  26. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameTencentAppRoleRegisterMapper.java
  27. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameTencentAppUserMapper.java
  28. 218 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/dto/GameOceanengineAppCallbackDTO.java
  29. 185 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/dto/GameTencentAppCallbackDTO.java
  30. 90 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameOceanengineAppBackLog.java
  31. 239 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameOceanengineAppCallback.java
  32. 134 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameOceanengineAppOrderLog.java
  33. 100 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameOceanengineAppRoleRegisterLog.java
  34. 90 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameOceanengineAppUserLog.java
  35. 111 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentAppBackLog.java
  36. 204 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentAppCallback.java
  37. 161 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentAppOrder.java
  38. 84 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentAppOrderSplitLog.java
  39. 117 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentAppRoleRegister.java
  40. 117 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentAppUser.java
  41. 212 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/rpc/impl/TencentAppBackRpcImpl.java
  42. 250 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/rpc/impl/TtAppBackRpcImpl.java
  43. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameOceanengineAppBackLogService.java
  44. 10 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameOceanengineAppCallbackService.java
  45. 15 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameOceanengineAppOrderLogService.java
  46. 9 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameOceanengineAppRoleRegisterLogService.java
  47. 9 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameOceanengineAppUserLogService.java
  48. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentAppBackLogService.java
  49. 10 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentAppCallbackService.java
  50. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentAppOrderService.java
  51. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentAppOrderSplitLogService.java
  52. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentAppRoleRegisterService.java
  53. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentAppUserService.java
  54. 14 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameOceanengineAppBackLogServiceImpl.java
  55. 44 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameOceanengineAppCallbackServiceImpl.java
  56. 336 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameOceanengineAppOrderLogServiceImpl.java
  57. 100 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameOceanengineAppRoleRegisterLogServiceImpl.java
  58. 73 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameOceanengineAppUserLogServiceImpl.java
  59. 14 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentAppBackLogServiceImpl.java
  60. 65 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentAppCallbackServiceImpl.java
  61. 14 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentAppOrderServiceImpl.java
  62. 14 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentAppOrderSplitLogServiceImpl.java
  63. 14 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentAppRoleRegisterServiceImpl.java
  64. 178 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentAppUserServiceImpl.java
  65. 53 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/task/CallbackClearTask.java
  66. 6 1
      game-module/game-module-base/src/main/java/com/zanxiang/game/module/base/pojo/enums/AccountTypeEnum.java
  67. 6 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/controller/AgentController.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;
+}

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

@@ -0,0 +1,29 @@
+package com.zanxiang.game.back.base.pojo.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 创角是否回传
+ */
+@Data
+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;
+}

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

@@ -0,0 +1,28 @@
+package com.zanxiang.game.back.base.pojo.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 创角是否回传
+ */
+@Data
+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;
+}

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

@@ -0,0 +1,25 @@
+package com.zanxiang.game.back.base.pojo.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 创角是否回传
+ */
+@Data
+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;
+}

+ 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);
+}

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

@@ -0,0 +1,43 @@
+package com.zanxiang.game.back.base.rpc;
+
+import com.zanxiang.game.back.base.pojo.dto.*;
+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<Boolean> 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));
+    }
+}

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

@@ -0,0 +1,250 @@
+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.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<Boolean> 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(Boolean.FALSE);
+        }
+        return ResultVO.ok(BackStatusEnum.getByValue(orderLog.getBackStatus()) ==  BackStatusEnum.SUCCESS);
+    }
+
+    @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);
+        }
+    }
+}

+ 6 - 1
game-module/game-module-base/src/main/java/com/zanxiang/game/module/base/pojo/enums/AccountTypeEnum.java

@@ -11,7 +11,12 @@ public enum AccountTypeEnum {
     // 头条小游戏
     BYTE(2),
     // 腾讯小游戏
-    TENCENT_MINI_GAME(3);
+    TENCENT_MINI_GAME(3),
+    // 腾讯APP
+    TENCENT_APP(4),
+    // 头条APP
+    BYTE_APP(5)
+    ;
 
     private final Integer value;
 

+ 6 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/controller/AgentController.java

@@ -57,6 +57,12 @@ public class AgentController {
             }
             dto.setReportToken(dto.getReportToken().trim());
             dto.setReportUrl(dto.getReportUrl().trim());
+        } else if (accountType == AccountTypeEnum.TENCENT_APP) {
+            if (dto.getUserActionSetId() == null) {
+                throw new BaseException("腾讯广告账号必须选回传的数据源");
+            }
+        } else if (accountType == AccountTypeEnum.BYTE_APP) {
+            //
         }
         if (dto.getPutStatus() == null) {
             dto.setPutStatus(Agent.PUT_STATUS_ING);