Browse Source

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

zhangxianyu 6 months ago
parent
commit
54f51f3977
43 changed files with 1642 additions and 302 deletions
  1. 42 0
      game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/dto/TencentMiniGameOrderBackQueryRpcDTO.java
  2. 5 0
      game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/vo/GameBackPolicyRpcVO.java
  3. 24 1
      game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/rpc/ITencentMiniGameBackRpc.java
  4. 1 1
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/GameBackApplication.java
  5. 11 8
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/controller/TencentMiniGameLogController.java
  6. 6 1
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentMiniGameBackLog.java
  7. 27 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentMiniGameOrder.java
  8. 1 1
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentMiniGameOrderSplitLog.java
  9. 9 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentMiniGameRoleRegister.java
  10. 7 4
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentMiniGameUser.java
  11. 29 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/enums/BackTypeEnum.java
  12. 206 10
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/rpc/impl/TencentMiniGameBackRpcImpl.java
  13. 0 2
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentMiniGameBackLogService.java
  14. 2 2
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentMiniGameOrderService.java
  15. 2 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentMiniGameRoleRegisterService.java
  16. 2 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentMiniGameUserService.java
  17. 5 20
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentMiniGameBackLogServiceImpl.java
  18. 146 21
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentMiniGameOrderServiceImpl.java
  19. 90 23
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentMiniGameRoleRegisterServiceImpl.java
  20. 41 13
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentMiniGameUserServiceImpl.java
  21. 5 0
      game-module/game-module-base/src/main/java/com/zanxiang/game/module/base/pojo/enums/HttpStatusEnum.java
  22. 6 5
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/RoleAssignRecordServiceImpl.java
  23. 5 0
      game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/entity/Game.java
  24. 81 0
      game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/entity/GameBackLogMediaSdk.java
  25. 16 0
      game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/mapper/GameBackLogMediaSdkMapper.java
  26. 1 1
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/SDKApplication.java
  27. 4 3
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/adapter/ArgumentAdapter.java
  28. 23 7
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/controller/CallBackController.java
  29. 59 8
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/enums/CallBackTypeEnum.java
  30. 15 0
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/exception/TokenExpireException.java
  31. 9 0
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/handler/GlobalExceptionHandler.java
  32. 38 0
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/pojo/param/BackLogMediaSdkParam.java
  33. 5 0
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/pojo/param/CallBackControlParam.java
  34. 6 0
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/pojo/vo/UserLoginVO.java
  35. 8 0
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/IAgentService.java
  36. 0 11
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/ICallBackService.java
  37. 35 0
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/IGameBackLogMediaSdkService.java
  38. 2 1
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/AgentServiceImpl.java
  39. 67 153
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/CallBackServiceImpl.java
  40. 543 0
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/GameBackLogMediaSdkServiceImpl.java
  41. 51 6
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/GameServiceImpl.java
  42. 3 0
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/LoginServiceImpl.java
  43. 4 0
      game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/UserCardServiceImpl.java

+ 42 - 0
game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/dto/TencentMiniGameOrderBackQueryRpcDTO.java

@@ -0,0 +1,42 @@
+package com.zanxiang.game.back.base.pojo.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @author : lingfeng
+ * @time : 2024-11-22
+ * @description :
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class TencentMiniGameOrderBackQueryRpcDTO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 游戏 id
+     */
+    private Long gameId;
+
+    /**
+     * sdk 里面的用户 openId(要求唯一)
+     */
+    private String wechatOpenid;
+
+    /**
+     * 订单编号
+     */
+    private String orderId;
+
+    /**
+     * 渠道标识
+     */
+    private String agentKey;
+}

+ 5 - 0
game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/pojo/vo/GameBackPolicyRpcVO.java

@@ -105,4 +105,9 @@ public class GameBackPolicyRpcVO implements Serializable {
     private LocalDateTime createTime;
 
     private Long createBy;
+
+    /**
+     * 完成新手引导条件
+     */
+    private String tutorialFinishJson;
 }

+ 24 - 1
game-back/game-back-base/src/main/java/com/zanxiang/game/back/base/rpc/ITencentMiniGameBackRpc.java

@@ -1,8 +1,10 @@
 package com.zanxiang.game.back.base.rpc;
 
+import com.zanxiang.game.back.base.pojo.dto.TencentMiniGameOrderBackQueryRpcDTO;
 import com.zanxiang.game.back.base.pojo.dto.TencentOrderDTO;
 import com.zanxiang.game.back.base.pojo.dto.TencentRoleRegisterRpcDTO;
 import com.zanxiang.game.back.base.pojo.dto.TencentUserDTO;
+import com.zanxiang.game.back.base.pojo.vo.OrderBackQueryRpcVO;
 import com.zanxiang.module.util.pojo.ResultVO;
 
 /**
@@ -10,18 +12,39 @@ import com.zanxiang.module.util.pojo.ResultVO;
  * 文档地址:https://docs.qq.com/doc/DRkpGUU5jSFVxQVFN
  */
 public interface ITencentMiniGameBackRpc {
+
+    /**
+     * 订单回传查询-媒体SDK回传
+     */
+    ResultVO<OrderBackQueryRpcVO> orderBackQuery(TencentMiniGameOrderBackQueryRpcDTO dto);
+
     /**
      * 订单回传
      */
     ResultVO<Boolean> backOrder(TencentOrderDTO dto);
 
+    /**
+     * 订单回传-媒体SDK回传
+     */
+    ResultVO<Boolean> callBackOrder(TencentOrderDTO dto);
+
     /**
      * 用户回传
      */
     ResultVO<Boolean> backUser(TencentUserDTO dto);
 
     /**
-     * 用户回传
+     * 用户回传-媒体SDK回传
+     */
+    ResultVO<Boolean> callBackUser(TencentUserDTO dto);
+
+    /**
+     * 角色回传
      */
     ResultVO<Boolean> backRoleRegister(TencentRoleRegisterRpcDTO dto);
+
+    /**
+     * 角色回传-媒体SDK
+     */
+    ResultVO<Boolean> callBackRole(TencentRoleRegisterRpcDTO dto);
 }

+ 1 - 1
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/GameBackApplication.java

@@ -18,7 +18,7 @@ public class GameBackApplication {
 
     public static void main(String[] args) {
         SpringApplication.run(GameBackApplication.class, args);
-        System.out.println("角色新手引导回传bug, 判定条件修改 ( ´・・)ノ(._.`)  \n" +
+        System.out.println("腾讯小游戏上报新增类型 (腾讯小游戏回传新增回传类型´・・)ノ(._.`)  \n" +
                 " ______  __     __     \n" +
                 "/_____/\\/__/\\ /__/\\    \n" +
                 "\\:::__\\/\\ \\::\\\\:.\\ \\   \n" +

+ 11 - 8
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/controller/TencentMiniGameLogController.java

@@ -5,14 +5,13 @@ import com.zanxiang.erp.security.annotation.PreAuthorize;
 import com.zanxiang.game.back.serve.pojo.dto.GameTencentMiniGameOrderDTO;
 import com.zanxiang.game.back.serve.pojo.dto.GameTencentMiniGameUserDTO;
 import com.zanxiang.game.back.serve.pojo.dto.OrderReportDTO;
-import com.zanxiang.game.back.serve.pojo.vo.GameOceanengineOrderSplitLogVO;
 import com.zanxiang.game.back.serve.pojo.vo.GameTencentMiniGameOrderVO;
 import com.zanxiang.game.back.serve.pojo.vo.GameTencentMiniGameUserVO;
 import com.zanxiang.game.back.serve.pojo.vo.GameTencentMiniOrderSplitLogVO;
 import com.zanxiang.game.back.serve.service.IGameTencentMiniGameOrderService;
 import com.zanxiang.game.back.serve.service.IGameTencentMiniGameOrderSplitLogService;
+import com.zanxiang.game.back.serve.service.IGameTencentMiniGameRoleRegisterService;
 import com.zanxiang.game.back.serve.service.IGameTencentMiniGameUserService;
-import com.zanxiang.module.util.NumberUtil;
 import com.zanxiang.module.util.exception.BaseException;
 import com.zanxiang.module.util.pojo.ResultVO;
 import io.swagger.annotations.Api;
@@ -20,12 +19,7 @@ import io.swagger.annotations.ApiOperation;
 import org.apache.commons.collections4.CollectionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import java.math.BigDecimal;
 import java.util.Collections;
@@ -41,6 +35,8 @@ public class TencentMiniGameLogController {
     private IGameTencentMiniGameOrderService gameTencentMiniGameOrderService;
     @Autowired
     private IGameTencentMiniGameOrderSplitLogService gameTencentMiniGameOrderSplitLogService;
+    @Autowired
+    private IGameTencentMiniGameRoleRegisterService gameTencentMiniGameRoleRegisterService;
 
     @PreAuthorize(permissionKey = "gameBack:tencentMiniGame:orderLogs")
     @PostMapping("/orderLogs")
@@ -108,4 +104,11 @@ public class TencentMiniGameLogController {
     public ResultVO<Boolean> tencentUserReport(@PathVariable("ids") List<Long> ids) {
         return ResultVO.ok(gameTencentMiniGameUserService.doReport(ids));
     }
+
+    @PreAuthorize(permissionKey = "gameBack:tencentMiniGame:roleReport")
+    @PostMapping("/roleReport/{ids}")
+    @ApiOperation(value = "腾讯创角手动上报")
+    public ResultVO<Boolean> tencentRoleReport(@PathVariable("ids") List<Long> ids) {
+        return ResultVO.ok(gameTencentMiniGameRoleRegisterService.doReport(ids));
+    }
 }

+ 6 - 1
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentMiniGameBackLog.java

@@ -79,14 +79,19 @@ public class GameTencentMiniGameBackLog implements Serializable {
      * 回传时间
      */
     private LocalDateTime createTime;
+
     /**
      * 回传状态
      */
     private Integer backStatus;
+
     /**
      * 回传失败的错误日志
      */
     private String errMsg;
 
-
+    /**
+     * 回传方式
+     */
+    private String backType;
 }

+ 27 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentMiniGameOrder.java

@@ -27,8 +27,12 @@ import java.time.LocalDateTime;
 public class GameTencentMiniGameOrder implements Serializable {
     private static final long serialVersionUID = 1L;
 
+    /**
+     * 主键id
+     */
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
+
     /**
      * 渠道号
      */
@@ -99,15 +103,38 @@ public class GameTencentMiniGameOrder implements Serializable {
      */
     private Integer backStatus;
 
+    /**
+     * 创建时间
+     */
     private LocalDateTime createTime;
 
+    /**
+     * 角色id
+     */
     private String roleId;
 
+    /**
+     * 角色名称
+     */
     private String roleName;
 
+    /**
+     * 是否首单
+     */
     private Boolean isFirstOrder;
 
+    /**
+     * 回传金额
+     */
     private Long backMoney;
 
+    /**
+     * 回传信息
+     */
     private String backMsg;
+
+    /**
+     * 回传方式
+     */
+    private String backType;
 }

+ 1 - 1
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentMiniGameOrderSplitLog.java

@@ -46,5 +46,5 @@ public class GameTencentMiniGameOrderSplitLog implements Serializable {
 
     private LocalDateTime createTime;
 
-
+    private String backType;
 }

+ 9 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentMiniGameRoleRegister.java

@@ -28,6 +28,9 @@ public class GameTencentMiniGameRoleRegister implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
+    /**
+     * 主键id
+     */
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
@@ -35,6 +38,7 @@ public class GameTencentMiniGameRoleRegister implements Serializable {
      * 回传策略id
      */
     private Long backPolicyId;
+
     /**
      * 渠道号
      */
@@ -104,4 +108,9 @@ public class GameTencentMiniGameRoleRegister implements Serializable {
      * 回传信息
      */
     private String backMsg;
+
+    /**
+     * 回传方式
+     */
+    private String backType;
 }

+ 7 - 4
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentMiniGameUser.java

@@ -28,6 +28,9 @@ public class GameTencentMiniGameUser implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
+    /**
+     * 主键id
+     */
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
@@ -77,12 +80,12 @@ public class GameTencentMiniGameUser implements Serializable {
     private Integer backStatus;
 
     /**
-     * 回传状态-沉默唤起
+     * 创建时间
      */
-    private Integer reActiveBackStatus;
+    private LocalDateTime createTime;
 
     /**
-     * 创建时间
+     * 回传方式
      */
-    private LocalDateTime createTime;
+    private String backType;
 }

+ 29 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/enums/BackTypeEnum.java

@@ -0,0 +1,29 @@
+package com.zanxiang.game.back.serve.pojo.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author : lingfeng
+ * @time : 2024-12-03
+ * @description :
+ */
+@Getter
+@AllArgsConstructor
+public enum BackTypeEnum {
+
+    /**
+     * API回传
+     */
+    BACK_API("BACK_API"),
+
+    /**
+     * 媒体SDK回传
+     */
+    BACK_MEDIA_SDK("BACK_MEDIA_SDK");
+
+    /**
+     * 回传类型
+     */
+    private final String backType;
+}

+ 206 - 10
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/rpc/impl/TencentMiniGameBackRpcImpl.java

@@ -2,33 +2,40 @@ package com.zanxiang.game.back.serve.rpc.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.zanxiang.game.back.base.ServerInfo;
+import com.zanxiang.game.back.base.pojo.dto.TencentMiniGameOrderBackQueryRpcDTO;
 import com.zanxiang.game.back.base.pojo.dto.TencentOrderDTO;
 import com.zanxiang.game.back.base.pojo.dto.TencentRoleRegisterRpcDTO;
 import com.zanxiang.game.back.base.pojo.dto.TencentUserDTO;
 import com.zanxiang.game.back.base.pojo.enums.OrderStatusEnum;
+import com.zanxiang.game.back.base.pojo.vo.OrderBackQueryRpcVO;
 import com.zanxiang.game.back.base.rpc.ITencentMiniGameBackRpc;
-import com.zanxiang.game.back.serve.pojo.entity.GameBackPolicy;
-import com.zanxiang.game.back.serve.pojo.entity.GameTencentMiniGameOrder;
-import com.zanxiang.game.back.serve.pojo.entity.GameTencentMiniGameRoleRegister;
-import com.zanxiang.game.back.serve.pojo.entity.GameTencentMiniGameUser;
+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.IGameTencentMiniGameOrderService;
-import com.zanxiang.game.back.serve.service.IGameTencentMiniGameRoleRegisterService;
-import com.zanxiang.game.back.serve.service.IGameTencentMiniGameUserService;
+import com.zanxiang.game.back.serve.pojo.enums.BackTypeEnum;
+import com.zanxiang.game.back.serve.service.*;
 import com.zanxiang.module.util.JsonUtil;
 import com.zanxiang.module.util.pojo.ResultVO;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.dubbo.config.annotation.DubboService;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
 
 import java.time.LocalDateTime;
+import java.util.Collections;
+import java.util.List;
 import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 @Slf4j
 @DubboService
 public class TencentMiniGameBackRpcImpl implements ITencentMiniGameBackRpc {
 
+    @Autowired
+    private RedisTemplate<String, Object> redisTemplate;
+
     @Autowired
     private IGameBackPolicyService gameBackPolicyService;
 
@@ -41,6 +48,64 @@ public class TencentMiniGameBackRpcImpl implements ITencentMiniGameBackRpc {
     @Autowired
     private IGameTencentMiniGameRoleRegisterService gameTencentMiniGameRoleRegisterService;
 
+    @Autowired
+    private IGameTencentMiniGameOrderSplitLogService gameTencentMiniGameOrderSplitLogService;
+
+    @Override
+    public ResultVO<OrderBackQueryRpcVO> orderBackQuery(TencentMiniGameOrderBackQueryRpcDTO dto) {
+        log.error("微信小游戏订单媒体SDK回传结果查询:{}", JsonUtil.toString(dto));
+        GameTencentMiniGameOrder orderLog = this.queryOrder(dto);
+        if (orderLog == null) {
+            try {
+                Thread.sleep(15 * 1000L);
+            } catch (Exception e) {
+                log.error(e.getMessage(), e);
+            }
+            orderLog = this.queryOrder(dto);
+        }
+        if (orderLog == null) {
+            return ResultVO.ok(OrderBackQueryRpcVO.builder()
+                    .doBack(Boolean.FALSE)
+                    .backMsg("回传异常,找不到订单:" + dto.getOrderId())
+                    .build());
+        }
+        List<Long> splitMoney = gameTencentMiniGameOrderSplitLogService.list(new LambdaQueryWrapper<GameTencentMiniGameOrderSplitLog>()
+                .eq(GameTencentMiniGameOrderSplitLog::getOrderNo, orderLog.getOrderId())
+                .eq(GameTencentMiniGameOrderSplitLog::getBackType, BackTypeEnum.BACK_MEDIA_SDK.getBackType())
+                .orderByAsc(GameTencentMiniGameOrderSplitLog::getBackIndex)
+        ).stream().map(GameTencentMiniGameOrderSplitLog::getSplitMoney).collect(Collectors.toList());
+        return ResultVO.ok(OrderBackQueryRpcVO.builder()
+                .doBack(BackStatusEnum.getByValue(orderLog.getBackStatus()) == BackStatusEnum.SUCCESS)
+                .backMoney(CollectionUtils.isEmpty(splitMoney) ? Collections.singletonList(orderLog.getBackMoney()) : splitMoney)
+                .backMsg(orderLog.getBackMsg())
+                .build());
+    }
+
+    private GameTencentMiniGameOrder queryOrder(TencentMiniGameOrderBackQueryRpcDTO dto) {
+        String lockKey = ServerInfo.SERVER_NAME + ":TencentMiniGameBack:" + dto.getGameId() + ":" + dto.getOrderId();
+        int maxCount = 0;
+        while (true) {
+            if (redisTemplate.opsForValue().get(lockKey) == null) {
+                break;
+            }
+            if (maxCount++ >= 120 / 10) {
+                break;
+            }
+            try {
+                Thread.sleep(10 * 1000L);
+            } catch (Exception e) {
+                log.error(e.getMessage(), e);
+            }
+        }
+        return gameTencentMiniGameOrderService.getOne(new LambdaQueryWrapper<GameTencentMiniGameOrder>()
+                .eq(GameTencentMiniGameOrder::getOrderId, dto.getOrderId())
+                .eq(GameTencentMiniGameOrder::getGameId, dto.getGameId())
+                .eq(GameTencentMiniGameOrder::getAgentKey, dto.getAgentKey())
+                .eq(GameTencentMiniGameOrder::getWechatOpenid, dto.getWechatOpenid())
+                .eq(GameTencentMiniGameOrder::getBackType, BackTypeEnum.BACK_MEDIA_SDK.getBackType())
+        );
+    }
+
     @Override
     public ResultVO<Boolean> backOrder(TencentOrderDTO dto) {
         if (Objects.equals(OrderStatusEnum.SUCCESS_PAY.getValue(), dto.getOrderStatus())) {
@@ -56,8 +121,8 @@ public class TencentMiniGameBackRpcImpl implements ITencentMiniGameBackRpc {
                 .eq(GameTencentMiniGameOrder::getAdAccountId, dto.getAdAccountId())
                 .eq(GameTencentMiniGameOrder::getOrderStatus, OrderStatusEnum.SUCCESS_PAY.getValue())
                 .eq(GameTencentMiniGameOrder::getWechatOpenid, dto.getWechatOpenid())
-                .last("limit 1")
-        ) == null;
+                .eq(GameTencentMiniGameOrder::getBackType, BackTypeEnum.BACK_API.getBackType())
+                .last("limit 1")) == null;
         GameTencentMiniGameUser userLog = gameTencentMiniGameUserService.getOne(new LambdaQueryWrapper<GameTencentMiniGameUser>()
                 .select(GameTencentMiniGameUser::getBackStatus, GameTencentMiniGameUser::getClickId)
                 .eq(GameTencentMiniGameUser::getGameId, dto.getGameId())
@@ -65,6 +130,7 @@ public class TencentMiniGameBackRpcImpl implements ITencentMiniGameBackRpc {
                 .eq(GameTencentMiniGameUser::getWechatOpenid, dto.getWechatOpenid())
                 .eq(GameTencentMiniGameUser::getAdAccountId, dto.getAdAccountId())
                 .orderByDesc(GameTencentMiniGameUser::getCreateTime)
+                .eq(GameTencentMiniGameUser::getBackType, BackTypeEnum.BACK_API.getBackType())
                 .last("limit 1")
         );
         GameTencentMiniGameOrder orderLog = GameTencentMiniGameOrder.builder()
@@ -87,6 +153,7 @@ public class TencentMiniGameBackRpcImpl implements ITencentMiniGameBackRpc {
                 .roleId(dto.getRoleId())
                 .roleName(dto.getRoleName())
                 .isFirstOrder(isFirstOrder)
+                .backType(BackTypeEnum.BACK_API.getBackType())
                 .build();
         gameTencentMiniGameOrderService.save(orderLog);
         if (userLog == null) {
@@ -97,6 +164,55 @@ public class TencentMiniGameBackRpcImpl implements ITencentMiniGameBackRpc {
         }
     }
 
+    @Override
+    public ResultVO<Boolean> callBackOrder(TencentOrderDTO dto) {
+        if (Objects.equals(OrderStatusEnum.SUCCESS_PAY.getValue(), dto.getOrderStatus())) {
+            log.error("腾讯小游戏订单媒体SDK回传收到:{}。", JsonUtil.toString(dto));
+        } else {
+            log.error("腾讯小游戏订单媒体SDK回传收到:{}。订单未支付,直接过滤", JsonUtil.toString(dto));
+            return ResultVO.ok(true);
+        }
+        // 此处加锁防止 cp 方调用过快,导致查询回传结果时判断逻辑没走完
+        String lockKey = ServerInfo.SERVER_NAME + ":TencentMiniGameOrderBack:" + dto.getGameId() + ":" + dto.getOrderId();
+        redisTemplate.opsForValue().set(lockKey, dto.getOrderId(), 2L, TimeUnit.MINUTES);
+        try {
+            boolean isFirstOrder = gameTencentMiniGameOrderService.getOne(new LambdaQueryWrapper<GameTencentMiniGameOrder>()
+                    .select(GameTencentMiniGameOrder::getOrderId)
+                    .eq(GameTencentMiniGameOrder::getGameId, dto.getGameId())
+                    .eq(GameTencentMiniGameOrder::getWechatAppId, dto.getWechatAppId())
+                    .eq(GameTencentMiniGameOrder::getAdAccountId, dto.getAdAccountId())
+                    .eq(GameTencentMiniGameOrder::getOrderStatus, OrderStatusEnum.SUCCESS_PAY.getValue())
+                    .eq(GameTencentMiniGameOrder::getWechatOpenid, dto.getWechatOpenid())
+                    .eq(GameTencentMiniGameOrder::getBackType, BackTypeEnum.BACK_MEDIA_SDK.getBackType())
+                    .last("limit 1")) == null;
+            GameTencentMiniGameOrder orderLog = GameTencentMiniGameOrder.builder()
+                    .adAccountId(dto.getAdAccountId())
+                    .gameId(dto.getGameId())
+                    .orderId(dto.getOrderId())
+                    .agentKey(dto.getChannel())
+                    .rechargeMoney(dto.getRechargeMoney())
+                    .rechargeTime(dto.getRechargeTime())
+                    .subscribeTime(dto.getSubscribeTime())
+                    .registerTime(dto.getRegisterTime())
+                    .wechatAppId(dto.getWechatAppId())
+                    .wechatOpenid(dto.getWechatOpenid())
+                    .orderStatus(dto.getOrderStatus())
+                    .payTime(dto.getPayTime())
+                    .createTime(LocalDateTime.now())
+                    .backStatus(BackStatusEnum.NO.getBackStatus())
+                    .backPolicyId(dto.getBackPolicyId())
+                    .roleId(dto.getRoleId())
+                    .roleName(dto.getRoleName())
+                    .isFirstOrder(isFirstOrder)
+                    .backType(BackTypeEnum.BACK_MEDIA_SDK.getBackType())
+                    .build();
+            gameTencentMiniGameOrderService.save(orderLog);
+            return ResultVO.ok(gameTencentMiniGameOrderService.callback(orderLog));
+        } finally {
+            redisTemplate.delete(lockKey);
+        }
+    }
+
     @Override
     public ResultVO<Boolean> backUser(TencentUserDTO dto) {
         log.error("腾讯小游戏用户回传收到:{}", JsonUtil.toString(dto));
@@ -111,6 +227,7 @@ public class TencentMiniGameBackRpcImpl implements ITencentMiniGameBackRpc {
                 .backStatus(BackStatusEnum.NO.getBackStatus())
                 .clickId(dto.getClickId())
                 .createTime(LocalDateTime.now())
+                .backType(BackTypeEnum.BACK_API.getBackType())
                 .build();
         gameTencentMiniGameUserService.save(userLog);
         //查询回传策略
@@ -123,6 +240,25 @@ public class TencentMiniGameBackRpcImpl implements ITencentMiniGameBackRpc {
         return ResultVO.ok(Boolean.TRUE);
     }
 
+    public ResultVO<Boolean> callBackUser(TencentUserDTO dto) {
+        log.error("腾讯小游戏用户媒体SDK回传收到:{}", JsonUtil.toString(dto));
+        GameTencentMiniGameUser userLog = GameTencentMiniGameUser.builder()
+                .adAccountId(dto.getAdAccountId())
+                .gameId(dto.getGameId())
+                .agentKey(dto.getChannel())
+                .subscribeTime(dto.getSubscribeTime())
+                .registerTime(dto.getRegisterTime())
+                .wechatAppId(dto.getWechatAppId())
+                .wechatOpenid(dto.getWechatOpenid())
+                .backStatus(BackStatusEnum.NO.getBackStatus())
+                .clickId(dto.getClickId())
+                .createTime(LocalDateTime.now())
+                .backType(BackTypeEnum.BACK_MEDIA_SDK.getBackType())
+                .build();
+        gameTencentMiniGameUserService.save(userLog);
+        return ResultVO.ok(gameTencentMiniGameUserService.callback(userLog));
+    }
+
     @Override
     public ResultVO<Boolean> backRoleRegister(TencentRoleRegisterRpcDTO dto) {
         log.error("腾讯小游戏创角回传收到:{}", JsonUtil.toString(dto));
@@ -132,6 +268,7 @@ public class TencentMiniGameBackRpcImpl implements ITencentMiniGameBackRpc {
                 .eq(GameTencentMiniGameRoleRegister::getWechatAppId, dto.getWechatAppId())
                 .eq(GameTencentMiniGameRoleRegister::getWechatOpenid, dto.getWechatOpenid())
                 .eq(GameTencentMiniGameRoleRegister::getRoleId, dto.getRoleId())
+                .eq(GameTencentMiniGameRoleRegister::getBackType, BackTypeEnum.BACK_API.getBackType())
                 .last("limit 1")
         );
         if (oldRole != null) {
@@ -163,6 +300,7 @@ public class TencentMiniGameBackRpcImpl implements ITencentMiniGameBackRpc {
                     .eq(GameTencentMiniGameUser::getWechatAppId, dto.getWechatAppId())
                     .eq(GameTencentMiniGameUser::getWechatOpenid, dto.getWechatOpenid())
                     .eq(GameTencentMiniGameUser::getAdAccountId, dto.getAdAccountId())
+                    .eq(GameTencentMiniGameUser::getBackType, BackTypeEnum.BACK_API.getBackType())
                     .orderByDesc(GameTencentMiniGameUser::getCreateTime)
                     .last("limit 1")
             );
@@ -180,9 +318,67 @@ public class TencentMiniGameBackRpcImpl implements ITencentMiniGameBackRpc {
                     .roleId(dto.getRoleId())
                     .roleName(dto.getRoleName())
                     .roleLevel(dto.getRoleLevel())
+                    .backType(BackTypeEnum.BACK_API.getBackType())
                     .build();
             gameTencentMiniGameRoleRegisterService.save(roleRegisterLog);
         }
         return ResultVO.ok(gameTencentMiniGameRoleRegisterService.roleRegisterBack(roleRegisterLog));
     }
+
+    @Override
+    public ResultVO<Boolean> callBackRole(TencentRoleRegisterRpcDTO dto) {
+        log.error("腾讯小游戏创角媒体SDK回传收到:{}", JsonUtil.toString(dto));
+        GameTencentMiniGameRoleRegister roleRegisterLog;
+        GameTencentMiniGameRoleRegister oldRole = gameTencentMiniGameRoleRegisterService.getOne(new LambdaQueryWrapper<GameTencentMiniGameRoleRegister>()
+                .eq(GameTencentMiniGameRoleRegister::getGameId, dto.getGameId())
+                .eq(GameTencentMiniGameRoleRegister::getWechatAppId, dto.getWechatAppId())
+                .eq(GameTencentMiniGameRoleRegister::getWechatOpenid, dto.getWechatOpenid())
+                .eq(GameTencentMiniGameRoleRegister::getRoleId, dto.getRoleId())
+                .eq(GameTencentMiniGameRoleRegister::getBackType, BackTypeEnum.BACK_MEDIA_SDK.getBackType())
+                .last("limit 1")
+        );
+        if (oldRole != null) {
+            roleRegisterLog = oldRole;
+            if (dto.getRoleLevel() != null && (oldRole.getRoleLevel() == null || oldRole.getRoleLevel() < dto.getRoleLevel())) {
+                gameTencentMiniGameRoleRegisterService.update(new LambdaUpdateWrapper<GameTencentMiniGameRoleRegister>()
+                        .set(GameTencentMiniGameRoleRegister::getRoleLevel, dto.getRoleLevel())
+                        .set(GameTencentMiniGameRoleRegister::getRoleName, dto.getRoleName())
+                        .eq(GameTencentMiniGameRoleRegister::getId, oldRole.getId())
+                );
+            }
+            // 创角已回传, 不重复执行回传
+            if (Objects.equals(oldRole.getBackStatus(), BackStatusEnum.SUCCESS.getBackStatus())) {
+                return ResultVO.ok(Boolean.TRUE);
+            }
+        } else {
+            GameTencentMiniGameUser userLog = gameTencentMiniGameUserService.getOne(new LambdaQueryWrapper<GameTencentMiniGameUser>()
+                    .select(GameTencentMiniGameUser::getBackStatus, GameTencentMiniGameUser::getClickId)
+                    .eq(GameTencentMiniGameUser::getGameId, dto.getGameId())
+                    .eq(GameTencentMiniGameUser::getWechatAppId, dto.getWechatAppId())
+                    .eq(GameTencentMiniGameUser::getWechatOpenid, dto.getWechatOpenid())
+                    .eq(GameTencentMiniGameUser::getAdAccountId, dto.getAdAccountId())
+                    .eq(GameTencentMiniGameUser::getBackType, BackTypeEnum.BACK_MEDIA_SDK.getBackType())
+                    .orderByDesc(GameTencentMiniGameUser::getCreateTime)
+                    .last("limit 1")
+            );
+            roleRegisterLog = GameTencentMiniGameRoleRegister.builder()
+                    .backPolicyId(dto.getBackPolicyId())
+                    .agentKey(dto.getChannel())
+                    .gameId(dto.getGameId())
+                    .adAccountId(dto.getAdAccountId())
+                    .wechatAppId(dto.getWechatAppId())
+                    .wechatOpenid(dto.getWechatOpenid())
+                    .clickId(userLog == null ? null : userLog.getClickId())
+                    .registerTime(dto.getRegisterTime())
+                    .backStatus(BackStatusEnum.NO.getBackStatus())
+                    .createTime(LocalDateTime.now())
+                    .roleId(dto.getRoleId())
+                    .roleName(dto.getRoleName())
+                    .roleLevel(dto.getRoleLevel())
+                    .backType(BackTypeEnum.BACK_MEDIA_SDK.getBackType())
+                    .build();
+            gameTencentMiniGameRoleRegisterService.save(roleRegisterLog);
+        }
+        return ResultVO.ok(gameTencentMiniGameRoleRegisterService.callback(roleRegisterLog));
+    }
 }

+ 0 - 2
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentMiniGameBackLogService.java

@@ -14,8 +14,6 @@ public interface IGameTencentMiniGameBackLogService extends IService<GameTencent
 
     Tuple2<BackStatusEnum, String> userBack(GameTencentMiniGameUser userLog);
 
-    Tuple2<BackStatusEnum, String> reActiveBack(GameTencentMiniGameUser userLog);
-
     Tuple2<BackStatusEnum, String> orderBack(GameTencentMiniGameOrder orderLog, LocalDateTime backTime, Long backMoney);
 
     Tuple2<BackStatusEnum, String> roleRegisterBack(GameTencentMiniGameRoleRegister roleRegisterLog);

+ 2 - 2
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentMiniGameOrderService.java

@@ -7,12 +7,12 @@ import com.zanxiang.game.back.serve.pojo.dto.OrderReportDTO;
 import com.zanxiang.game.back.serve.pojo.entity.GameTencentMiniGameOrder;
 import com.zanxiang.game.back.serve.pojo.vo.GameTencentMiniGameOrderVO;
 
-import java.util.List;
-
 public interface IGameTencentMiniGameOrderService extends IService<GameTencentMiniGameOrder> {
 
     boolean orderBack(GameTencentMiniGameOrder orderLog);
 
+    boolean callback(GameTencentMiniGameOrder orderLog);
+
     IPage<GameTencentMiniGameOrderVO> listOfPage(GameTencentMiniGameOrderDTO dto);
 
     boolean doReport(OrderReportDTO dto);

+ 2 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentMiniGameRoleRegisterService.java

@@ -13,6 +13,8 @@ public interface IGameTencentMiniGameRoleRegisterService extends IService<GameTe
 
     boolean roleRegisterBack(GameTencentMiniGameRoleRegister roleRegisterLog);
 
+    boolean callback(GameTencentMiniGameRoleRegister roleRegisterLog);
+
     void tutorialFinishBack(GameTencentMiniGameRoleRegister roleRegisterLog, GameBackPolicy gameBackPolicy);
 
     IPage<GameTencentMiniGameRoleRegisterVO> listOfPage(GameTencentMiniGameRoleRegisterDTO dto);

+ 2 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentMiniGameUserService.java

@@ -12,6 +12,8 @@ public interface IGameTencentMiniGameUserService extends IService<GameTencentMin
 
     boolean userBack(GameTencentMiniGameUser userLog);
 
+    boolean callback(GameTencentMiniGameUser userLog);
+
     IPage<GameTencentMiniGameUserVO> listOfPage(GameTencentMiniGameUserDTO dto);
 
     boolean doReport(List<Long> userLogIds);

+ 5 - 20
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentMiniGameBackLogServiceImpl.java

@@ -10,6 +10,7 @@ import com.zanxiang.game.back.serve.pojo.entity.GameTencentMiniGameRoleRegister;
 import com.zanxiang.game.back.serve.pojo.entity.GameTencentMiniGameUser;
 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.enums.BackTypeEnum;
 import com.zanxiang.game.back.serve.service.IGameTencentMiniGameBackLogService;
 import com.zanxiang.module.util.DateUtil;
 import com.zanxiang.module.util.JsonUtil;
@@ -46,26 +47,7 @@ public class GameTencentMiniGameBackLogServiceImpl extends ServiceImpl<GameTence
                 .wechatAppId(userLog.getWechatAppId())
                 .actionType(ActionTypeEnum.REGISTER.getActionType())
                 .createTime(LocalDateTime.now())
-                .build();
-        Tuple2<BackStatusEnum, String> backResult = callback(backLog);
-        backLog.setBackStatus(backResult.first.getBackStatus());
-        backLog.setErrMsg(backResult.second);
-        save(backLog);
-        return backResult;
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public Tuple2<BackStatusEnum, String> reActiveBack(GameTencentMiniGameUser userLog) {
-        GameTencentMiniGameBackLog backLog = GameTencentMiniGameBackLog.builder()
-                .gameId(userLog.getGameId())
-                .adAccountId(userLog.getAdAccountId())
-                .clickId(userLog.getClickId())
-                .actionTime(LocalDateTime.now())
-                .wechatOpenid(userLog.getWechatOpenid())
-                .wechatAppId(userLog.getWechatAppId())
-                .actionType(ActionTypeEnum.RE_ACTIVE.getActionType())
-                .createTime(LocalDateTime.now())
+                .backType(BackTypeEnum.BACK_API.getBackType())
                 .build();
         Tuple2<BackStatusEnum, String> backResult = callback(backLog);
         backLog.setBackStatus(backResult.first.getBackStatus());
@@ -90,6 +72,7 @@ public class GameTencentMiniGameBackLogServiceImpl extends ServiceImpl<GameTence
                 .amount(backMoney)
                 .orderId(orderLog.getOrderId())
                 .createTime(LocalDateTime.now())
+                .backType(BackTypeEnum.BACK_API.getBackType())
                 .build();
         Tuple2<BackStatusEnum, String> backResult = callback(backLog);
         backLog.setBackStatus(backResult.first.getBackStatus());
@@ -110,6 +93,7 @@ public class GameTencentMiniGameBackLogServiceImpl extends ServiceImpl<GameTence
                 .wechatAppId(roleRegisterLog.getWechatAppId())
                 .actionType(ActionTypeEnum.CREATE_ROLE.getActionType())
                 .createTime(LocalDateTime.now())
+                .backType(BackTypeEnum.BACK_API.getBackType())
                 .build();
         Tuple2<BackStatusEnum, String> backResult = callback(backLog);
         backLog.setBackStatus(backResult.first.getBackStatus());
@@ -130,6 +114,7 @@ public class GameTencentMiniGameBackLogServiceImpl extends ServiceImpl<GameTence
                 .wechatAppId(roleRegisterLog.getWechatAppId())
                 .actionType(ActionTypeEnum.TUTORIAL_FINISH.getActionType())
                 .createTime(LocalDateTime.now())
+                .backType(BackTypeEnum.BACK_API.getBackType())
                 .build();
         Tuple2<BackStatusEnum, String> backResult = callback(backLog);
         backLog.setBackStatus(backResult.first.getBackStatus());

+ 146 - 21
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentMiniGameOrderServiceImpl.java

@@ -7,7 +7,6 @@ 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.github.sd4324530.jtuple.Tuple2;
-import com.github.sd4324530.jtuple.Tuple3;
 import com.github.sd4324530.jtuple.Tuple4;
 import com.zanxiang.advertising.tencent.base.AdvertisingTencentServer;
 import com.zanxiang.advertising.tencent.base.rpc.IUserActionSetRpc;
@@ -17,20 +16,14 @@ import com.zanxiang.game.back.base.pojo.enums.OrderStatusEnum;
 import com.zanxiang.game.back.serve.dao.mapper.GameTencentMiniGameOrderMapper;
 import com.zanxiang.game.back.serve.pojo.dto.GameTencentMiniGameOrderDTO;
 import com.zanxiang.game.back.serve.pojo.dto.OrderReportDTO;
-import com.zanxiang.game.back.serve.pojo.entity.GameBackPolicy;
-import com.zanxiang.game.back.serve.pojo.entity.GameTencentMiniGameOrder;
-import com.zanxiang.game.back.serve.pojo.entity.GameTencentMiniGameOrderSplitLog;
-import com.zanxiang.game.back.serve.pojo.entity.GameTencentMiniGameUser;
-import com.zanxiang.game.back.serve.pojo.entity.GameTencentOrderSplitLog;
+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.enums.BackTypeEnum;
 import com.zanxiang.game.back.serve.pojo.enums.BackUnitEnum;
 import com.zanxiang.game.back.serve.pojo.vo.GameTencentMiniGameOrderVO;
 import com.zanxiang.game.back.serve.pojo.vo.GameTencentMiniOrderSplitLogVO;
-import com.zanxiang.game.back.serve.service.IGameBackPolicyService;
-import com.zanxiang.game.back.serve.service.IGameTencentMiniGameBackLogService;
-import com.zanxiang.game.back.serve.service.IGameTencentMiniGameOrderService;
-import com.zanxiang.game.back.serve.service.IGameTencentMiniGameOrderSplitLogService;
-import com.zanxiang.game.back.serve.service.IGameTencentMiniGameUserService;
+import com.zanxiang.game.back.serve.service.*;
 import com.zanxiang.game.back.serve.utils.BackPolicyUtil;
 import com.zanxiang.game.back.serve.utils.OrderUtil;
 import com.zanxiang.game.module.base.ServerInfo;
@@ -51,12 +44,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 import java.time.LocalDateTime;
 import java.time.LocalTime;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
+import java.util.*;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.Function;
 import java.util.stream.Collectors;
@@ -66,18 +54,24 @@ import java.util.stream.Collectors;
 public class GameTencentMiniGameOrderServiceImpl extends ServiceImpl<GameTencentMiniGameOrderMapper, GameTencentMiniGameOrder>
         implements IGameTencentMiniGameOrderService {
 
-    @DubboReference(providedBy = AdvertisingTencentServer.SERVER_DUBBO_NAME)
-    private IUserActionSetRpc userActionSetRpc;
+    @DubboReference(providedBy = ServerInfo.SERVER_DUBBO_NAME)
+    private IAgentRpc agentRpc;
+
     @DubboReference(providedBy = ErpServer.SERVER_DUBBO_NAME)
     private ISysUserRpc sysUserRpc;
+
+    @DubboReference(providedBy = AdvertisingTencentServer.SERVER_DUBBO_NAME)
+    private IUserActionSetRpc userActionSetRpc;
+
     @Autowired
     private IGameTencentMiniGameBackLogService gameTencentMiniGameBackLogService;
+
     @Autowired
     private IGameTencentMiniGameUserService gameTencentMiniGameUserService;
+
     @Autowired
     private IGameBackPolicyService gameBackPolicyService;
-    @DubboReference(providedBy = ServerInfo.SERVER_DUBBO_NAME)
-    private IAgentRpc agentRpc;
+
     @Autowired
     private IGameTencentMiniGameOrderSplitLogService gameTencentMiniGameOrderSplitLogService;
 
@@ -97,6 +91,7 @@ public class GameTencentMiniGameOrderServiceImpl extends ServiceImpl<GameTencent
                 .eq(GameTencentMiniGameUser::getWechatAppId, orderLog.getWechatAppId())
                 .eq(GameTencentMiniGameUser::getWechatOpenid, orderLog.getWechatOpenid())
                 .eq(GameTencentMiniGameUser::getAdAccountId, orderLog.getAdAccountId())
+                .eq(GameTencentMiniGameUser::getBackType, BackTypeEnum.BACK_API.getBackType())
                 .orderByDesc(GameTencentMiniGameUser::getCreateTime)
                 .last("limit 1")
         );
@@ -145,6 +140,7 @@ public class GameTencentMiniGameOrderServiceImpl extends ServiceImpl<GameTencent
                         .backTime(splitOrder.second)
                         .backStatus(BackStatusEnum.NO.getBackStatus())
                         .createTime(LocalDateTime.now())
+                        .backType(BackTypeEnum.BACK_API.getBackType())
                         .build());
             }
             gameTencentMiniGameOrderSplitLogService.saveBatch(splitOrderLogList);
@@ -168,6 +164,135 @@ public class GameTencentMiniGameOrderServiceImpl extends ServiceImpl<GameTencent
         );
     }
 
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean callback(GameTencentMiniGameOrder orderLog) {
+        if (!Objects.equals(orderLog.getOrderStatus(), OrderStatusEnum.SUCCESS_PAY.getValue())) {
+            // 只要回传 支付行为
+            return true;
+        }
+        GameTencentMiniGameUser userLog = this.userLog(orderLog);
+        if (userLog == null) {
+            return update(new LambdaUpdateWrapper<GameTencentMiniGameOrder>()
+                    .set(GameTencentMiniGameOrder::getBackStatus, BackStatusEnum.FAILED.getBackStatus())
+                    .set(GameTencentMiniGameOrder::getBackMoney, orderLog.getRechargeMoney())
+                    .set(GameTencentMiniGameOrder::getBackMsg, "回传失败!找不到回传用户")
+                    .eq(GameTencentMiniGameOrder::getId, orderLog.getId())
+            );
+        }
+
+        GameBackPolicy gameBackPolicy = gameBackPolicyService.getById(orderLog.getBackPolicyId());
+        // 此处是否是首单用 limit 2。因为在执行判断之前订单已入库,所以库里只有一笔才是首单
+        Tuple4<Boolean, Long, String, List<Tuple2<Long, LocalDateTime>>> backInfo = BackPolicyUtil.backOrder(orderLog.getOrderId(), gameBackPolicy, orderLog.getRechargeMoney(),
+                orderLog.getIsFirstOrder(),
+                orderLog.getPayTime(),
+                // 此处使用用户最近一次的重新染色时间
+                userLog.getCreateTime(),
+                orderLog.getWechatOpenid(),
+                new TencentMiniGameOrderBackPolicyCheck(this, gameBackPolicy, userLog, orderLog));
+        boolean doBack = backInfo.first;
+        Long backMoney = backInfo.second;
+        String backMsg = backInfo.third;
+
+        if (!doBack) {
+            return update(new LambdaUpdateWrapper<GameTencentMiniGameOrder>()
+                    .set(GameTencentMiniGameOrder::getBackStatus, BackStatusEnum.NO.getBackStatus())
+                    .set(GameTencentMiniGameOrder::getBackMoney, backMoney)
+                    .set(GameTencentMiniGameOrder::getBackMsg, backMsg)
+                    .eq(GameTencentMiniGameOrder::getId, orderLog.getId())
+            );
+        }
+        // 拆单
+        if (CollectionUtils.isNotEmpty(backInfo.fourth)) {
+            // 需要拆单
+            List<GameTencentMiniGameOrderSplitLog> splitOrderLogList = new ArrayList<>(backInfo.fourth.size());
+            for (int i = 0; i < backInfo.fourth.size(); i++) {
+                Tuple2<Long, LocalDateTime> splitOrder = backInfo.fourth.get(i);
+                splitOrderLogList.add(GameTencentMiniGameOrderSplitLog.builder()
+                        .backDay(splitOrder.second.toLocalDate())
+                        .orderNo(orderLog.getOrderId())
+                        .backIndex(i + 1)
+                        .backCount(backInfo.fourth.size())
+                        .splitMoney(splitOrder.first)
+                        .backTime(splitOrder.second)
+                        .backStatus(BackStatusEnum.SUCCESS.getBackStatus())
+                        .createTime(LocalDateTime.now())
+                        .backType(BackTypeEnum.BACK_MEDIA_SDK.getBackType())
+                        .build());
+            }
+            gameTencentMiniGameOrderSplitLogService.saveBatch(splitOrderLogList);
+            return update(new LambdaUpdateWrapper<GameTencentMiniGameOrder>()
+                    .set(GameTencentMiniGameOrder::getBackStatus, BackStatusEnum.SUCCESS.getBackStatus())
+                    .set(GameTencentMiniGameOrder::getBackMoney, backInfo.second)
+                    .set(GameTencentMiniGameOrder::getBackMsg, backMsg)
+                    .eq(GameTencentMiniGameOrder::getId, orderLog.getId())
+            );
+        }
+
+        Tuple2<BackStatusEnum, String> backResult = this.doCallbackMediaSdk(orderLog, orderLog.getPayTime(), backMoney);
+        if (StringUtils.isNotBlank(backResult.second)) {
+            backMsg = backMsg + ("回传失败:" + backResult.second);
+        }
+        return update(new LambdaUpdateWrapper<GameTencentMiniGameOrder>()
+                .set(GameTencentMiniGameOrder::getBackStatus, backResult.first.getBackStatus())
+                .set(GameTencentMiniGameOrder::getBackMoney, backMoney)
+                .set(GameTencentMiniGameOrder::getBackMsg, backMsg)
+                .eq(GameTencentMiniGameOrder::getId, orderLog.getId())
+        );
+    }
+
+    private Tuple2<BackStatusEnum, String> doCallbackMediaSdk(GameTencentMiniGameOrder orderLog, LocalDateTime backTime, Long backMoney) {
+        GameTencentMiniGameUser userLog = this.userLog(orderLog);
+        String actionType = orderLog.getOrderStatus().equals(OrderStatusEnum.SUCCESS_PAY.getValue()) ?
+                ActionTypeEnum.PURCHASE.getActionType() : ActionTypeEnum.COMPLETE_ORDER.getActionType();
+        if (userLog == null) {
+            gameTencentMiniGameBackLogService.save(GameTencentMiniGameBackLog.builder()
+                    .gameId(orderLog.getGameId())
+                    .adAccountId(orderLog.getAdAccountId())
+                    .clickId(orderLog.getClickId())
+                    .actionTime(backTime)
+                    .wechatOpenid(orderLog.getWechatOpenid())
+                    .wechatAppId(orderLog.getWechatAppId())
+                    .actionType(actionType)
+                    .amount(backMoney)
+                    .orderId(orderLog.getOrderId())
+                    .createTime(LocalDateTime.now())
+                    .backStatus(BackStatusEnum.FAILED.getBackStatus())
+                    .errMsg("找不到用户注册信息")
+                    .backType(BackTypeEnum.BACK_MEDIA_SDK.getBackType())
+                    .build());
+            return Tuple2.with(BackStatusEnum.FAILED, "找不到用户注册信息");
+        }
+        BackStatusEnum backStatus = BackStatusEnum.SUCCESS;
+        gameTencentMiniGameBackLogService.save(GameTencentMiniGameBackLog.builder()
+                .gameId(orderLog.getGameId())
+                .adAccountId(orderLog.getAdAccountId())
+                .clickId(orderLog.getClickId())
+                .actionTime(backTime)
+                .wechatOpenid(orderLog.getWechatOpenid())
+                .wechatAppId(orderLog.getWechatAppId())
+                .actionType(actionType)
+                .amount(backMoney)
+                .orderId(orderLog.getOrderId())
+                .createTime(LocalDateTime.now())
+                .backStatus(backStatus.getBackStatus())
+                .errMsg(null)
+                .backType(BackTypeEnum.BACK_MEDIA_SDK.getBackType())
+                .build());
+        return Tuple2.with(backStatus, null);
+    }
+
+    private GameTencentMiniGameUser userLog(GameTencentMiniGameOrder orderLog) {
+        return gameTencentMiniGameUserService.getOne(new LambdaQueryWrapper<GameTencentMiniGameUser>()
+                .eq(GameTencentMiniGameUser::getGameId, orderLog.getGameId())
+                .eq(GameTencentMiniGameUser::getWechatAppId, orderLog.getWechatAppId())
+                .eq(GameTencentMiniGameUser::getWechatOpenid, orderLog.getWechatOpenid())
+                .eq(GameTencentMiniGameUser::getAdAccountId, orderLog.getAdAccountId())
+                .eq(GameTencentMiniGameUser::getBackType, BackTypeEnum.BACK_MEDIA_SDK.getBackType())
+                .orderByDesc(GameTencentMiniGameUser::getCreateTime)
+                .last("limit 1"));
+    }
+
     @Override
     public IPage<GameTencentMiniGameOrderVO> listOfPage(GameTencentMiniGameOrderDTO dto) {
         IPage<GameTencentMiniGameOrder> page = page(dto.toPage(), new LambdaQueryWrapper<GameTencentMiniGameOrder>()

+ 90 - 23
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentMiniGameRoleRegisterServiceImpl.java

@@ -17,6 +17,7 @@ import com.zanxiang.game.back.serve.pojo.entity.GameTencentMiniGameRoleRegister;
 import com.zanxiang.game.back.serve.pojo.entity.GameTencentMiniGameUser;
 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.enums.BackTypeEnum;
 import com.zanxiang.game.back.serve.pojo.vo.GameTencentMiniGameRoleRegisterVO;
 import com.zanxiang.game.back.serve.service.IGameBackPolicyService;
 import com.zanxiang.game.back.serve.service.IGameTencentMiniGameBackLogService;
@@ -47,14 +48,18 @@ import java.util.stream.Collectors;
 public class GameTencentMiniGameRoleRegisterServiceImpl extends ServiceImpl<GameTencentMiniGameRoleRegisterMapper, GameTencentMiniGameRoleRegister>
         implements IGameTencentMiniGameRoleRegisterService {
 
+    @DubboReference(providedBy = ServerInfo.SERVER_DUBBO_NAME)
+    private IAgentRpc agentRpc;
+
     @DubboReference(providedBy = AdvertisingTencentServer.SERVER_DUBBO_NAME)
     private IUserActionSetRpc userActionSetRpc;
+
     @Autowired
     private IGameTencentMiniGameBackLogService gameTencentMiniGameBackLogService;
-    @DubboReference(providedBy = ServerInfo.SERVER_DUBBO_NAME)
-    private IAgentRpc agentRpc;
+
     @Autowired
     private IGameTencentMiniGameUserService gameTencentMiniGameUserService;
+
     @Autowired
     private IGameBackPolicyService gameBackPolicyService;
 
@@ -71,6 +76,15 @@ public class GameTencentMiniGameRoleRegisterServiceImpl extends ServiceImpl<Game
         );
     }
 
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean callback(GameTencentMiniGameRoleRegister roleRegisterLog) {
+        BackStatusEnum backStatusEnum = this.doCallbackMediaSdk(roleRegisterLog);
+        return update(new LambdaUpdateWrapper<GameTencentMiniGameRoleRegister>()
+                .set(GameTencentMiniGameRoleRegister::getBackStatus, backStatusEnum.getBackStatus())
+                .eq(GameTencentMiniGameRoleRegister::getId, roleRegisterLog.getId())
+        );
+    }
 
     @Override
     public IPage<GameTencentMiniGameRoleRegisterVO> listOfPage(GameTencentMiniGameRoleRegisterDTO dto) {
@@ -122,7 +136,13 @@ public class GameTencentMiniGameRoleRegisterServiceImpl extends ServiceImpl<Game
             }
             return vo;
         }).collect(Collectors.toList());
+    }
 
+    private GameTencentMiniGameRoleRegisterVO toVOSimple(GameTencentMiniGameRoleRegister roleRegisterLog) {
+        if (roleRegisterLog == null) {
+            return null;
+        }
+        return BeanUtil.copy(roleRegisterLog, GameTencentMiniGameRoleRegisterVO.class);
     }
 
     private Tuple2<BackStatusEnum, String> doCallback(GameTencentMiniGameRoleRegister roleRegisterLog) {
@@ -132,6 +152,7 @@ public class GameTencentMiniGameRoleRegisterServiceImpl extends ServiceImpl<Game
                 .eq(GameTencentMiniGameUser::getWechatAppId, roleRegisterLog.getWechatAppId())
                 .eq(GameTencentMiniGameUser::getWechatOpenid, roleRegisterLog.getWechatOpenid())
                 .eq(GameTencentMiniGameUser::getAdAccountId, roleRegisterLog.getAdAccountId())
+                .eq(GameTencentMiniGameUser::getBackType, BackTypeEnum.BACK_API.getBackType())
                 .orderByDesc(GameTencentMiniGameUser::getCreateTime)
                 .last("limit 1"));
         //回传策略
@@ -146,6 +167,7 @@ public class GameTencentMiniGameRoleRegisterServiceImpl extends ServiceImpl<Game
                 .eq(GameTencentMiniGameBackLog::getAdAccountId, roleRegisterLog.getAdAccountId())
                 .eq(GameTencentMiniGameBackLog::getActionType, ActionTypeEnum.CREATE_ROLE.getActionType())
                 .eq(GameTencentMiniGameBackLog::getBackStatus, BackStatusEnum.SUCCESS.getBackStatus())
+                .eq(GameTencentMiniGameBackLog::getBackType, BackTypeEnum.BACK_API.getBackType())
         ) > 0) {
             //新手引导回传
             this.tutorialFinishBack(roleRegisterLog, gameBackPolicy);
@@ -159,13 +181,10 @@ public class GameTencentMiniGameRoleRegisterServiceImpl extends ServiceImpl<Game
             return Tuple2.with(BackStatusEnum.NO, "等级小于回传策略等级 " + gameBackPolicy.getRoleLevelMin() + "。不回传");
         }
 
-        //判断注册或者沉默唤起是否回传
-        if (user != null) {
-            if (Objects.equals(BackStatusEnum.NO.getBackStatus(), user.getBackStatus())
-                    || Objects.equals(BackStatusEnum.NO.getBackStatus(), user.getReActiveBackStatus())) {
-                //注册或者沉默唤起回传
-                gameTencentMiniGameUserService.userBack(user);
-            }
+        //判断注册是否回传
+        if (user != null && Objects.equals(BackStatusEnum.NO.getBackStatus(), user.getBackStatus())) {
+            //执行注册回传
+            gameTencentMiniGameUserService.userBack(user);
         }
 
         //创角回传
@@ -175,10 +194,12 @@ public class GameTencentMiniGameRoleRegisterServiceImpl extends ServiceImpl<Game
     @Override
     public void tutorialFinishBack(GameTencentMiniGameRoleRegister roleRegisterLog, GameBackPolicy gameBackPolicy) {
         //角色判断完成新手引导回传
-        if (super.count(new LambdaQueryWrapper<GameTencentMiniGameRoleRegister>()
-                .eq(GameTencentMiniGameRoleRegister::getGameId, roleRegisterLog.getGameId())
-                .eq(GameTencentMiniGameRoleRegister::getRoleId, roleRegisterLog.getRoleId())
-                .eq(GameTencentMiniGameRoleRegister::getTutorialFinishBackStatus, BackStatusEnum.SUCCESS.getBackStatus())
+        if (gameTencentMiniGameBackLogService.count(new LambdaQueryWrapper<GameTencentMiniGameBackLog>()
+                .eq(GameTencentMiniGameBackLog::getGameId, roleRegisterLog.getGameId())
+                .eq(GameTencentMiniGameBackLog::getWechatAppId, roleRegisterLog.getWechatAppId())
+                .eq(GameTencentMiniGameBackLog::getWechatOpenid, roleRegisterLog.getWechatOpenid())
+                .eq(GameTencentMiniGameBackLog::getActionType, ActionTypeEnum.TUTORIAL_FINISH.getActionType())
+                .eq(GameTencentMiniGameBackLog::getBackStatus, BackStatusEnum.SUCCESS.getBackStatus())
         ) > 0) {
             return;
         }
@@ -186,13 +207,11 @@ public class GameTencentMiniGameRoleRegisterServiceImpl extends ServiceImpl<Game
         if (gameBackPolicy == null || Strings.isBlank(gameBackPolicy.getTutorialFinishJson())) {
             return;
         }
-        TutorialFinish tutorialFinish = JsonUtil.toObj(gameBackPolicy.getTutorialFinishJson(), TutorialFinish.class);
-        //条件设置为空, 不回传
-        if (tutorialFinish == null || tutorialFinish.getRoleLevel() == null) {
-            return;
-        }
+        //获取新手回传等级限制
+        Long roleLevel = Optional.ofNullable(JsonUtil.toObj(gameBackPolicy.getTutorialFinishJson(), TutorialFinish.class))
+                .map(TutorialFinish::getRoleLevel).orElse(null);
         //不满足等级条件判断, 不回传
-        if (roleRegisterLog.getRoleLevel() < tutorialFinish.getRoleLevel()) {
+        if (roleLevel != null && roleRegisterLog.getRoleLevel() < roleLevel) {
             return;
         }
         //执行完成新手引导回传
@@ -203,10 +222,58 @@ public class GameTencentMiniGameRoleRegisterServiceImpl extends ServiceImpl<Game
                 .eq(GameTencentMiniGameRoleRegister::getId, roleRegisterLog.getId()));
     }
 
-    private GameTencentMiniGameRoleRegisterVO toVOSimple(GameTencentMiniGameRoleRegister roleRegisterLog) {
-        if (roleRegisterLog == null) {
-            return null;
+    private BackStatusEnum doCallbackMediaSdk(GameTencentMiniGameRoleRegister roleRegisterLog) {
+        GameTencentMiniGameUser user = gameTencentMiniGameUserService.getOne(new LambdaQueryWrapper<GameTencentMiniGameUser>()
+                .eq(GameTencentMiniGameUser::getGameId, roleRegisterLog.getGameId())
+                .eq(GameTencentMiniGameUser::getWechatAppId, roleRegisterLog.getWechatAppId())
+                .eq(GameTencentMiniGameUser::getWechatOpenid, roleRegisterLog.getWechatOpenid())
+                .eq(GameTencentMiniGameUser::getAdAccountId, roleRegisterLog.getAdAccountId())
+                .eq(GameTencentMiniGameUser::getBackType, BackTypeEnum.BACK_MEDIA_SDK.getBackType())
+                .orderByDesc(GameTencentMiniGameUser::getCreateTime)
+                .last("limit 1"));
+        if (user == null) {
+            gameTencentMiniGameBackLogService.save(GameTencentMiniGameBackLog.builder()
+                    .gameId(roleRegisterLog.getGameId())
+                    .adAccountId(roleRegisterLog.getAdAccountId())
+                    .clickId(roleRegisterLog.getClickId())
+                    .actionTime(roleRegisterLog.getRegisterTime())
+                    .wechatOpenid(roleRegisterLog.getWechatOpenid())
+                    .wechatAppId(roleRegisterLog.getWechatAppId())
+                    .actionType(ActionTypeEnum.CREATE_ROLE.getActionType())
+                    .createTime(LocalDateTime.now())
+                    .backStatus(BackStatusEnum.FAILED.getBackStatus())
+                    .errMsg("找不到用户注册信息")
+                    .backType(BackTypeEnum.BACK_MEDIA_SDK.getBackType())
+                    .build());
+            return BackStatusEnum.FAILED;
         }
-        return BeanUtil.copy(roleRegisterLog, GameTencentMiniGameRoleRegisterVO.class);
+        //判断创角是否回传
+        if (gameTencentMiniGameBackLogService.count(new LambdaQueryWrapper<GameTencentMiniGameBackLog>()
+                .eq(GameTencentMiniGameBackLog::getGameId, roleRegisterLog.getGameId())
+                .eq(GameTencentMiniGameBackLog::getWechatAppId, roleRegisterLog.getWechatAppId())
+                .eq(GameTencentMiniGameBackLog::getWechatOpenid, roleRegisterLog.getWechatOpenid())
+                .eq(GameTencentMiniGameBackLog::getAdAccountId, roleRegisterLog.getAdAccountId())
+                .eq(GameTencentMiniGameBackLog::getActionType, ActionTypeEnum.CREATE_ROLE.getActionType())
+                .eq(GameTencentMiniGameBackLog::getBackStatus, BackStatusEnum.SUCCESS.getBackStatus())
+                .eq(GameTencentMiniGameBackLog::getBackType, BackTypeEnum.BACK_MEDIA_SDK.getBackType())
+        ) > 0) {
+            //创角已回传
+            return BackStatusEnum.NO;
+        }
+        BackStatusEnum backStatus = BackStatusEnum.SUCCESS;
+        gameTencentMiniGameBackLogService.save(GameTencentMiniGameBackLog.builder()
+                .gameId(roleRegisterLog.getGameId())
+                .adAccountId(roleRegisterLog.getAdAccountId())
+                .clickId(roleRegisterLog.getClickId())
+                .actionTime(roleRegisterLog.getRegisterTime())
+                .wechatOpenid(roleRegisterLog.getWechatOpenid())
+                .wechatAppId(roleRegisterLog.getWechatAppId())
+                .actionType(ActionTypeEnum.CREATE_ROLE.getActionType())
+                .createTime(LocalDateTime.now())
+                .backStatus(backStatus.getBackStatus())
+                .errMsg(null)
+                .backType(BackTypeEnum.BACK_MEDIA_SDK.getBackType())
+                .build());
+        return backStatus;
     }
 }

+ 41 - 13
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentMiniGameUserServiceImpl.java

@@ -14,6 +14,7 @@ import com.zanxiang.game.back.serve.pojo.entity.GameTencentMiniGameBackLog;
 import com.zanxiang.game.back.serve.pojo.entity.GameTencentMiniGameUser;
 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.enums.BackTypeEnum;
 import com.zanxiang.game.back.serve.pojo.vo.GameTencentMiniGameUserVO;
 import com.zanxiang.game.back.serve.service.IGameTencentMiniGameBackLogService;
 import com.zanxiang.game.back.serve.service.IGameTencentMiniGameUserService;
@@ -61,6 +62,16 @@ public class GameTencentMiniGameUserServiceImpl extends ServiceImpl<GameTencentM
         );
     }
 
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean callback(GameTencentMiniGameUser userLog) {
+        BackStatusEnum backStatus = this.doCallbackMediaSdk(userLog);
+        return update(new LambdaUpdateWrapper<GameTencentMiniGameUser>()
+                .set(GameTencentMiniGameUser::getBackStatus, backStatus.getBackStatus())
+                .eq(GameTencentMiniGameUser::getId, userLog.getId())
+        );
+    }
+
     @Override
     public IPage<GameTencentMiniGameUserVO> listOfPage(GameTencentMiniGameUserDTO dto) {
         IPage<GameTencentMiniGameUser> page = page(dto.toPage(), new LambdaQueryWrapper<GameTencentMiniGameUser>()
@@ -123,20 +134,8 @@ public class GameTencentMiniGameUserServiceImpl extends ServiceImpl<GameTencentM
                 .eq(GameTencentMiniGameBackLog::getAdAccountId, userLog.getAdAccountId())
                 .eq(GameTencentMiniGameBackLog::getActionType, ActionTypeEnum.REGISTER.getActionType())
                 .eq(GameTencentMiniGameBackLog::getBackStatus, BackStatusEnum.SUCCESS.getBackStatus())
+                .eq(GameTencentMiniGameBackLog::getBackType, BackTypeEnum.BACK_API.getBackType())
         ) > 0) {
-            //该广告账号渠道未回传, 执行沉默唤起回传
-            if (super.count(new LambdaQueryWrapper<GameTencentMiniGameUser>()
-                    .eq(GameTencentMiniGameUser::getGameId, userLog.getGameId())
-                    .eq(GameTencentMiniGameUser::getWechatAppId, userLog.getWechatAppId())
-                    .eq(GameTencentMiniGameUser::getWechatOpenid, userLog.getWechatOpenid())
-                    .eq(GameTencentMiniGameUser::getAdAccountId, userLog.getAdAccountId())
-                    .eq(GameTencentMiniGameUser::getAgentKey, userLog.getAgentKey())
-            ) <= 0) {
-                BackStatusEnum backStatus = gameTencentMiniGameBackLogService.reActiveBack(userLog).first;
-                super.update(new LambdaUpdateWrapper<GameTencentMiniGameUser>()
-                        .set(GameTencentMiniGameUser::getReActiveBackStatus, backStatus.getBackStatus())
-                        .eq(GameTencentMiniGameUser::getId, userLog.getId()));
-            }
             //返回注册已回传
             return Tuple2.with(BackStatusEnum.NO, null);
         }
@@ -149,4 +148,33 @@ public class GameTencentMiniGameUserServiceImpl extends ServiceImpl<GameTencentM
         }
         return BeanUtil.copy(userLog, GameTencentMiniGameUserVO.class);
     }
+
+    private BackStatusEnum doCallbackMediaSdk(GameTencentMiniGameUser userLog) {
+        if (gameTencentMiniGameBackLogService.count(new LambdaQueryWrapper<GameTencentMiniGameBackLog>()
+                .eq(GameTencentMiniGameBackLog::getGameId, userLog.getGameId())
+                .eq(GameTencentMiniGameBackLog::getWechatAppId, userLog.getWechatAppId())
+                .eq(GameTencentMiniGameBackLog::getWechatOpenid, userLog.getWechatOpenid())
+                .eq(GameTencentMiniGameBackLog::getAdAccountId, userLog.getAdAccountId())
+                .eq(GameTencentMiniGameBackLog::getActionType, ActionTypeEnum.REGISTER.getActionType())
+                .eq(GameTencentMiniGameBackLog::getBackStatus, BackStatusEnum.SUCCESS.getBackStatus())
+                .eq(GameTencentMiniGameBackLog::getBackType, BackTypeEnum.BACK_MEDIA_SDK.getBackType())
+        ) > 0) {
+            return BackStatusEnum.NO;
+        }
+        BackStatusEnum backStatus = BackStatusEnum.SUCCESS;
+        gameTencentMiniGameBackLogService.save(GameTencentMiniGameBackLog.builder()
+                .gameId(userLog.getGameId())
+                .adAccountId(userLog.getAdAccountId())
+                .clickId(userLog.getClickId())
+                .actionTime(LocalDateTime.now())
+                .wechatOpenid(userLog.getWechatOpenid())
+                .wechatAppId(userLog.getWechatAppId())
+                .actionType(ActionTypeEnum.REGISTER.getActionType())
+                .createTime(LocalDateTime.now())
+                .backStatus(backStatus.getBackStatus())
+                .errMsg(null)
+                .backType(BackTypeEnum.BACK_MEDIA_SDK.getBackType())
+                .build());
+        return backStatus;
+    }
 }

+ 5 - 0
game-module/game-module-base/src/main/java/com/zanxiang/game/module/base/pojo/enums/HttpStatusEnum.java

@@ -277,6 +277,11 @@ public enum HttpStatusEnum {
      */
     AUTHENTICATION_FAIL(41515, "实名认证失败"),
 
+    /**
+     * 实名认证失败, 未成年禁止认证
+     */
+    AUTHENTICATION_FAIL_UNDERAGE(41516, "实名认证失败, 未成年禁止认证"),
+
     /**
      * 参数为空
      */

+ 6 - 5
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/RoleAssignRecordServiceImpl.java

@@ -98,6 +98,7 @@ public class RoleAssignRecordServiceImpl extends ServiceImpl<RoleAssignRecordMap
     public boolean configSysUser(RoleSysUserAssignParam param) {
         Long sysUserId = SecurityUtil.getUserId();
         LocalDateTime now = LocalDateTime.now();
+        boolean singleConfig = param.getRoleInfoAndAgentParamList().size() == 1;
         List<RoleAssignRecord> lastAssignRecordList = new ArrayList<>();
         List<RoleAssignRecord> insertAssignRecordList = new ArrayList<>();
         param.getRoleInfoAndAgentParamList().forEach(item -> {
@@ -127,7 +128,7 @@ public class RoleAssignRecordServiceImpl extends ServiceImpl<RoleAssignRecordMap
                 //存在记录,更新最后一条记录
                 int compare = param.getStartTime().compareTo(lastAssignRecord.getStartTime());
                 if (compare < 0) {
-                    throw new BaseException("角色" + item.getRoleId() + "开始时间不能早于上条指派记录的开始时间!!!");
+                    throw new BaseException("角色id:" + item.getRoleId() + ",开始时间不能早于上条指派记录的开始时间!!!");
                 }
                 lastAssignRecord.setUpdateBy(sysUserId);
                 lastAssignRecord.setUpdateTime(now);
@@ -139,10 +140,10 @@ public class RoleAssignRecordServiceImpl extends ServiceImpl<RoleAssignRecordMap
                     lastAssignRecord.setIsOperUpdate(previousAssignRecord == null ? Boolean.TRUE : param.getOperUserId() != null && !Objects.equals(param.getOperUserId(), previousAssignRecord.getOperUserId()));
                     lastAssignRecord.setIsCustomerUpdate(previousAssignRecord == null ? Boolean.TRUE : param.getCustomerServiceId() != null && !Objects.equals(param.getCustomerServiceId(), previousAssignRecord.getCustomerServiceId()));
                     //参数变更
-                    lastAssignRecord.setGsId(param.getGsId());
-                    lastAssignRecord.setOperUserId(param.getOperUserId());
-                    lastAssignRecord.setCustomerServiceId(param.getCustomerServiceId());
-                    lastAssignRecord.setRemark(param.getRemark());
+                    lastAssignRecord.setGsId(singleConfig ? param.getGsId() : null != param.getGsId() ? param.getGsId() : lastAssignRecord.getGsId());
+                    lastAssignRecord.setOperUserId(singleConfig ? param.getOperUserId() : null != param.getOperUserId() ? param.getOperUserId() : lastAssignRecord.getOperUserId());
+                    lastAssignRecord.setCustomerServiceId(singleConfig ? param.getCustomerServiceId() : null != param.getCustomerServiceId() ? param.getCustomerServiceId() : lastAssignRecord.getCustomerServiceId());
+                    lastAssignRecord.setRemark(singleConfig ? param.getRemark() : null != param.getRemark() ? param.getRemark() : lastAssignRecord.getRemark());
                 } else {
                     lastAssignRecord.setEndTime(param.getStartTime());
                     insertAssignRecordList.add(insertRoleAssignRecord);

+ 5 - 0
game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/entity/Game.java

@@ -163,4 +163,9 @@ public class Game implements Serializable {
      */
     private Boolean isMonitorLink;
 
+    /**
+     * API回传开关
+     */
+    private Boolean apiBackSwitch;
+
 }

+ 81 - 0
game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/entity/GameBackLogMediaSdk.java

@@ -0,0 +1,81 @@
+package com.zanxiang.game.module.mybatis.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * @author : lingfeng
+ * @time : 2022-06-06
+ * @description : 媒体sdk回传日志
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@ToString
+@Builder
+@TableName("t_game_back_log_media_sdk")
+public class GameBackLogMediaSdk implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 游戏id
+     */
+    private Long gameId;
+
+    /**
+     * 用户id
+     */
+    private Long userId;
+
+    /**
+     * 回传类型
+     */
+    private String callBackTypeEnum;
+
+    /**
+     * 服务端回传判断
+     */
+    private String callBackJudgeResult;
+
+    /**
+     * 角色id
+     */
+    private String roleId;
+
+    /**
+     * 角色等级
+     */
+    private Long level;
+
+    /**
+     * 订单id
+     */
+    private String orderId;
+
+    /**
+     * 媒体sdk回传参数
+     */
+    private String callBackParam;
+
+    /**
+     * 媒体sdk错误消息
+     */
+    private String errorMsg;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+}

+ 16 - 0
game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/mapper/GameBackLogMediaSdkMapper.java

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

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

@@ -23,7 +23,7 @@ public class SDKApplication {
 
     public static void main(String[] args) {
         SpringApplication.run(SDKApplication.class, args);
-        System.out.println("赞象SDK服务启动成功 <数据库慢sql优化, 代码修改> ( ´・・)ノ(._.`) \n" +
+        System.out.println("赞象SDK服务启动成功 <腾讯媒体sdk回传兼容API同步回传> ( ´・・)ノ(._.`) \n" +
                 " ___________ _   __\n" +
                 "/  ___|  _  \\ | / /\n" +
                 "\\ `--.| | | | |/ / \n" +

+ 4 - 3
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/adapter/ArgumentAdapter.java

@@ -3,6 +3,7 @@ package com.zanxiang.game.module.sdk.adapter;
 import com.zanxiang.game.module.base.pojo.enums.HttpStatusEnum;
 import com.zanxiang.game.module.mybatis.entity.GameExt;
 import com.zanxiang.game.module.sdk.annotation.ValidLogin;
+import com.zanxiang.game.module.sdk.exception.TokenExpireException;
 import com.zanxiang.game.module.sdk.pojo.dto.UserTokenDTO;
 import com.zanxiang.game.module.sdk.pojo.param.UserData;
 import com.zanxiang.game.module.sdk.service.IGameExtService;
@@ -54,7 +55,7 @@ public class ArgumentAdapter implements HandlerMethodArgumentResolver {
         String token = request.getHeader("token");
         //需要登录, token不存在
         if (b && Strings.isBlank(token)) {
-            throw new BaseException(HttpStatusEnum.USER_NO_LOGIN.getMsg());
+            throw new TokenExpireException(HttpStatusEnum.USER_NO_LOGIN.getMsg());
         }
         //设备类型
         Integer deviceType = Integer.valueOf(request.getHeader("deviceType"));
@@ -85,12 +86,12 @@ public class ArgumentAdapter implements HandlerMethodArgumentResolver {
         UserTokenDTO userTokenDTO = userTokenService.getTokenInfoByTokenDevice(token, deviceType);
         if (userTokenDTO == null) {
             if (b) {
-                throw new BaseException(HttpStatusEnum.USER_NO_LOGIN.getMsg());
+                throw new TokenExpireException(HttpStatusEnum.USER_NO_LOGIN.getMsg());
             }
             return data;
         }
         if (b && userTokenDTO.getUserId() == null) {
-            throw new BaseException(HttpStatusEnum.USER_NO_LOGIN.getMsg());
+            throw new TokenExpireException(HttpStatusEnum.USER_NO_LOGIN.getMsg());
         }
         data.setUserId(userTokenDTO.getUserId());
         data.setToken(userTokenDTO.getToken());

+ 23 - 7
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/controller/CallBackController.java

@@ -1,9 +1,10 @@
 package com.zanxiang.game.module.sdk.controller;
 
 import com.zanxiang.game.module.sdk.annotation.ValidLogin;
+import com.zanxiang.game.module.sdk.pojo.param.BackLogMediaSdkParam;
 import com.zanxiang.game.module.sdk.pojo.param.CallBackControlParam;
 import com.zanxiang.game.module.sdk.pojo.param.UserData;
-import com.zanxiang.game.module.sdk.service.ICallBackService;
+import com.zanxiang.game.module.sdk.service.IGameBackLogMediaSdkService;
 import com.zanxiang.game.module.sdk.service.IGameService;
 import com.zanxiang.module.util.JsonUtil;
 import com.zanxiang.module.util.pojo.ResultVO;
@@ -33,21 +34,36 @@ public class CallBackController {
     private IGameService gameService;
 
     @Autowired
-    private ICallBackService callBackService;
+    private IGameBackLogMediaSdkService backLogMediaSdkService;
 
     @ApiOperation(value = "获取游戏广告媒体回传sdk配置")
     @GetMapping("/ad/sdk/config")
     @ApiResponses(value = {@ApiResponse(code = 200, message = "成功", response = Map.class)})
     public ResultVO<Map<String, Object>> getAdSdkConfig(UserData userData) {
-        return ResultVO.ok(gameService.getAdSdkConfig(userData));
+        log.error("媒体初始化配置请求 userData : {}", JsonUtil.toString(userData));
+        Map<String, Object> adSdkConfigMap = gameService.getAdSdkConfig(userData);
+        log.error("媒体初始化配置返回, map : {}", JsonUtil.toString(adSdkConfigMap));
+        return ResultVO.ok(adSdkConfigMap);
     }
 
     @ApiOperation(value = "判断事件是否回传")
     @PostMapping("/call/judge")
+    @ApiResponses(value = {@ApiResponse(code = 200, message = "成功", response = Map.class)})
+    public ResultVO<Map<String, Object>> callBackJudge(@Validated @RequestBody CallBackControlParam param,
+                                                       @ValidLogin UserData userData) {
+        log.error("事件回传判断请求, param : {},  userData : {}", JsonUtil.toString(param), JsonUtil.toString(userData));
+        Map<String, Object> resultMap = backLogMediaSdkService.callBackJudge(param, userData);
+        log.error("事件回传判断结果, param : {},  userData : {}, resultMap : {}", JsonUtil.toString(param),
+                JsonUtil.toString(userData), JsonUtil.toString(resultMap));
+        return ResultVO.ok(resultMap);
+    }
+
+    @ApiOperation(value = "提交媒体sdk执行回传日志")
+    @PostMapping("/add/log")
     @ApiResponses(value = {@ApiResponse(code = 200, message = "成功", response = Boolean.class)})
-    public ResultVO<Map<String, Object>> callBackJudge(@Validated @RequestBody CallBackControlParam param, @ValidLogin UserData userData) {
-        ResultVO<Map<String, Object>> ok = ResultVO.ok(callBackService.callBackJudge(param, userData));
-        log.error("事件回传判断结果, param : {}, 返回结果 ok : {}", JsonUtil.toString(param), JsonUtil.toString(ok));
-        return ok;
+    public ResultVO<Boolean> addMediaSdkBackLog(@Validated @RequestBody BackLogMediaSdkParam param,
+                                                @ValidLogin UserData userData) {
+        log.error("媒体sdk执行回传日志提交, param : {},  userData : {}", JsonUtil.toString(param), JsonUtil.toString(userData));
+        return ResultVO.ok(backLogMediaSdkService.addMediaSdkBackLog(param, userData));
     }
 }

+ 59 - 8
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/enums/CallBackTypeEnum.java

@@ -12,28 +12,79 @@ import lombok.Getter;
 @AllArgsConstructor
 public enum CallBackTypeEnum {
 
+    //--------------- 公共回传事件 ---------------
+
     /**
-     * 注册(新创建账号)
+     * 注册
      */
     CALL_BACK_REGISTER("CALL_BACK_REGISTER"),
 
     /**
-     * 激活(创建角色)
+     * 付费
      */
-    CALL_BACK_ACTIVATE("CALL_BACK_ACTIVATE"),
+    CALL_BACK_PAY_ORDER("CALL_BACK_PAY_ORDER"),
+
+    //--------------- 腾讯小游戏回传事件 ---------------
+
+    /**
+     * 沉默唤起
+     */
+    CALL_BACK_RE_ACTIVE("CALL_BACK_RE_ACTIVE"),
+
+    /**
+     * 创角
+     */
+    CALL_BACK_CREATE_ROLE("CALL_BACK_CREATE_ROLE"),
+
+    /**
+     * 完成新手引导
+     */
+    CALL_BACK_TUTORIAL_FINISH("CALL_BACK_TUTORIAL_FINISH"),
+
+    /**
+     * 游戏等级提升
+     */
+    CALL_BACK_UPDATE_LEVEL("CALL_BACK_UPDATE_LEVEL"),
+
+    /**
+     * 收藏小游戏
+     */
+    CALL_BACK_ADD_TO_WISHLIST("CALL_BACK_ADD_TO_WISHLIST"),
+
+    /**
+     * 分享-转发给朋友
+     */
+    CALL_BACK_ON_SHARE_APP_MESSAGE("CALL_BACK_ON_SHARE_APP_MESSAGE"),
+
+    /**
+     * 分享-朋友圈
+     */
+    CALL_BACK_ON_SHARE_TIME_LINE("CALL_BACK_ON_SHARE_TIME_LINE"),
 
     /**
-     * 登录(老账号登录)
+     * 浏览商城页面
      */
-    CALL_BACK_LOGIN_IN("CALL_BACK_LOGIN_IN"),
+    CALL_BACK_VIEW_CONTENT_MALL("CALL_BACK_VIEW_CONTENT_MALL"),
+
+    /**
+     * 浏览游戏活动
+     */
+    CALL_BACK_VIEW_CONTENT_ACTIVITY("CALL_BACK_VIEW_CONTENT_ACTIVITY"),
+
+    //--------------- 头条APP回传事件 ---------------
+
+    /**
+     * 激活(巨量平台代表创角)
+     */
+    CALL_BACK_ACTIVATE("CALL_BACK_ACTIVATE"),
 
     /**
-     * 支付
+     * 登录
      */
-    CALL_BACK_PAY_ORDER("CALL_BACK_PAY_ORDER");
+    CALL_BACK_LOGIN_IN("CALL_BACK_LOGIN_IN");
 
     /**
      * 枚举值
      */
-    private String value;
+    private final String value;
 }

+ 15 - 0
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/exception/TokenExpireException.java

@@ -0,0 +1,15 @@
+package com.zanxiang.game.module.sdk.exception;
+
+/**
+ * @author : lingfeng
+ * @time : 2024-08-16
+ * @description : token失效异常
+ */
+public class TokenExpireException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    public TokenExpireException(String message) {
+        super(message);
+    }
+}

+ 9 - 0
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/handler/GlobalExceptionHandler.java

@@ -1,5 +1,6 @@
 package com.zanxiang.game.module.sdk.handler;
 
+import com.zanxiang.game.module.sdk.exception.TokenExpireException;
 import com.zanxiang.module.util.exception.BaseException;
 import com.zanxiang.module.util.pojo.ResultVO;
 import com.zanxiang.module.web.util.ServletUtil;
@@ -21,6 +22,14 @@ import org.springframework.web.method.annotation.MethodArgumentTypeMismatchExcep
 @RestControllerAdvice
 public class GlobalExceptionHandler {
 
+    /**
+     * token失效异常
+     */
+    @ExceptionHandler(TokenExpireException.class)
+    public ResultVO<?> tokenExpireException(TokenExpireException e) {
+        return ResultVO.reLogin();
+    }
+
     /**
      * 业务异常
      */

+ 38 - 0
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/pojo/param/BackLogMediaSdkParam.java

@@ -0,0 +1,38 @@
+package com.zanxiang.game.module.sdk.pojo.param;
+
+import com.zanxiang.game.module.sdk.enums.CallBackTypeEnum;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+import java.util.Map;
+
+/**
+ * @author : lingfeng
+ * @time : 2024-11-21
+ * @description : 媒体sdk回传日志参数
+ */
+@Data
+public class BackLogMediaSdkParam {
+
+    /**
+     * 用户行为回传类型, 必传
+     */
+    @NotNull(message = "用户行为回传类型不可为空")
+    private CallBackTypeEnum callBackTypeEnum;
+
+    /**
+     * 服务端回传判断结果, 必传
+     */
+    private Map<String, Object> callBackJudgeResult;
+
+    /**
+     * 调用媒体sdk回传时给的参数
+     */
+    private Map<String, Object> callBackParam;
+
+    /**
+     * 媒体sdk调用出现异常的错误消息
+     */
+    private String errorMsg;
+
+}

+ 5 - 0
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/pojo/param/CallBackControlParam.java

@@ -28,4 +28,9 @@ public class CallBackControlParam {
      * 角色id, 当行为类型为激活(创建角色)时, 需要传
      */
     private String roleId;
+
+    /**
+     * 角色等级
+     */
+    private Long level;
 }

+ 6 - 0
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/pojo/vo/UserLoginVO.java

@@ -23,6 +23,12 @@ public class UserLoginVO {
     @ApiModelProperty(notes = "用户id, 唯一标识")
     private Long userId;
 
+    /**
+     * 小程序用户唯一标识
+     */
+    @ApiModelProperty(notes = "小程序用户唯一标识")
+    private String openId;
+
     /**
      * 用户名
      */

+ 8 - 0
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/IAgentService.java

@@ -31,6 +31,14 @@ public interface IAgentService extends IService<Agent> {
      */
     Tuple3<Long, Map<String, String>, String> getUserAgentId(Game game, UserData userData);
 
+    /**
+     * 根据channel解析获取渠道信息
+     *
+     * @param urlParamMap : 渠道解析信息
+     * @return : 返回渠道对象
+     */
+    Agent getAgentByKey(Map<String, String> urlParamMap);
+
     /**
      * channel解析
      *

+ 0 - 11
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/ICallBackService.java

@@ -3,8 +3,6 @@ package com.zanxiang.game.module.sdk.service;
 import com.zanxiang.game.module.mybatis.entity.GameUserRole;
 import com.zanxiang.game.module.mybatis.entity.User;
 import com.zanxiang.game.module.sdk.pojo.dto.PlatformOrderDTO;
-import com.zanxiang.game.module.sdk.pojo.param.CallBackControlParam;
-import com.zanxiang.game.module.sdk.pojo.param.UserData;
 
 import java.util.Map;
 
@@ -15,15 +13,6 @@ import java.util.Map;
  */
 public interface ICallBackService {
 
-    /**
-     * 回传判断
-     *
-     * @param param    : 参数
-     * @param userData : 玩家信息
-     * @return : 返回是否回传
-     */
-    Map<String, Object> callBackJudge(CallBackControlParam param, UserData userData);
-
     /**
      * 用户回传
      *

+ 35 - 0
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/IGameBackLogMediaSdkService.java

@@ -0,0 +1,35 @@
+package com.zanxiang.game.module.sdk.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zanxiang.game.module.mybatis.entity.GameBackLogMediaSdk;
+import com.zanxiang.game.module.sdk.pojo.param.BackLogMediaSdkParam;
+import com.zanxiang.game.module.sdk.pojo.param.CallBackControlParam;
+import com.zanxiang.game.module.sdk.pojo.param.UserData;
+
+import java.util.Map;
+
+/**
+ * @author : lingfeng
+ * @time : 2022-11-10
+ * @description : 媒体sdk回传日志
+ */
+public interface IGameBackLogMediaSdkService extends IService<GameBackLogMediaSdk> {
+
+    /**
+     * 媒体sdk事件回传判断
+     *
+     * @param param    : 参数
+     * @param userData : 用户信息
+     * @return : 返回结果
+     */
+    Map<String, Object> callBackJudge(CallBackControlParam param, UserData userData);
+
+    /**
+     * 添加媒体sdk回传日志
+     *
+     * @param param    : 参数
+     * @param userData : 用户信息
+     * @return : 返回添加结果
+     */
+    boolean addMediaSdkBackLog(BackLogMediaSdkParam param, UserData userData);
+}

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

@@ -316,7 +316,8 @@ public class AgentServiceImpl extends ServiceImpl<AgentMapper, Agent> implements
         return userVisitLogList.stream().filter(user -> Objects.equals(user.getId(), minId)).findFirst().orElse(null);
     }
 
-    private Agent getAgentByKey(Map<String, String> urlParamMap) {
+    @Override
+    public Agent getAgentByKey(Map<String, String> urlParamMap) {
         //参数不存在
         if (CollectionUtils.isEmpty(urlParamMap)) {
             return null;

+ 67 - 153
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/CallBackServiceImpl.java

@@ -4,18 +4,12 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.zanxiang.game.back.base.ServerInfo;
 import com.zanxiang.game.back.base.pojo.dto.*;
-import com.zanxiang.game.back.base.pojo.vo.OrderBackQueryRpcVO;
 import com.zanxiang.game.back.base.rpc.*;
 import com.zanxiang.game.module.base.pojo.enums.AccountTypeEnum;
 import com.zanxiang.game.module.base.pojo.enums.GameCategoryEnum;
 import com.zanxiang.game.module.mybatis.entity.*;
-import com.zanxiang.game.module.sdk.constant.RedisKeyConstant;
-import com.zanxiang.game.module.sdk.enums.CallBackTypeEnum;
 import com.zanxiang.game.module.sdk.pojo.dto.PlatformOrderDTO;
-import com.zanxiang.game.module.sdk.pojo.param.CallBackControlParam;
-import com.zanxiang.game.module.sdk.pojo.param.UserData;
 import com.zanxiang.game.module.sdk.service.*;
-import com.zanxiang.module.redis.service.IDistributedLockComponent;
 import com.zanxiang.module.util.JsonUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.dubbo.config.annotation.DubboReference;
@@ -25,14 +19,13 @@ import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
-import java.util.*;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
+import java.util.Map;
+import java.util.Objects;
 
 /**
  * @author : lingfeng
  * @time : 2022-11-10
- * @description : 回传
+ * @description : IAP游戏SDK回传方法
  */
 @Slf4j
 @Service
@@ -68,137 +61,9 @@ public class CallBackServiceImpl implements ICallBackService {
     @Autowired
     private IGameExtService gameExtService;
 
-    @Autowired
-    private IOrderService orderService;
-
     @Autowired
     private IGameBackLogService gameBackLogService;
 
-    @Autowired
-    private IDistributedLockComponent distributedLockComponent;
-
-    @Autowired
-    private IUserEventService userEventService;
-
-    @Override
-    public Map<String, Object> callBackJudge(CallBackControlParam param, UserData userData) {
-        log.error("事件回传判断请求, param : {},  userData : {}", JsonUtil.toString(param), JsonUtil.toString(userData));
-        Map<String, Object> resultMap = new HashMap<>(7);
-        resultMap.put("callBackTypeEnum", param.getCallBackTypeEnum().getValue());
-        resultMap.put("userId", userData.getUserId());
-        resultMap.put("gameId", userData.getGameId());
-        //事件类型枚举
-        CallBackTypeEnum callBackTypeEnum = param.getCallBackTypeEnum();
-        Game game = gameService.getById(userData.getGameId());
-        //判断游戏状态, 对接上包过程中, 全量回传
-        if (this.isUserEvent(game, userData.getUserId())) {
-            resultMap.put("callBack", Boolean.TRUE);
-            if (Objects.equals(callBackTypeEnum, CallBackTypeEnum.CALL_BACK_PAY_ORDER)) {
-                PlatformOrderDTO platformOrderDTO = orderService.getByOrderId(param.getOrderId());
-                if (platformOrderDTO != null) {
-                    resultMap.put("amount", Collections.singletonList(platformOrderDTO.getAmount().intValue()));
-                }
-            }
-            return resultMap;
-        }
-        //线程锁
-        String lockKey = RedisKeyConstant.CALL_BACK_JUDGE_LOCK + callBackTypeEnum.getValue() + "_" + userData.getUserId();
-        if (Objects.equals(callBackTypeEnum, CallBackTypeEnum.CALL_BACK_ACTIVATE)) {
-            lockKey = lockKey + "_" + param.getRoleId();
-        }
-        if (Objects.equals(callBackTypeEnum, CallBackTypeEnum.CALL_BACK_PAY_ORDER)) {
-            lockKey = lockKey + "_" + param.getOrderId();
-        }
-        //上锁
-        if (!distributedLockComponent.doLock(lockKey, 0L, 1L, TimeUnit.MINUTES)) {
-            log.error("重复请求触发线程锁, 直接返回false, lockKey : {}", lockKey);
-            resultMap.put("callBack", Boolean.FALSE);
-            return resultMap;
-        }
-        //查询玩家
-        User user = userService.getById(userData.getUserId());
-        //不存在渠道
-        Agent agent = agentService.getById(user.getAgentId());
-        if (agent == null) {
-            resultMap.put("callBack", Boolean.FALSE);
-            return resultMap;
-        }
-        //判断回传
-        try {
-            this.checkCallBack(user.getId(), agent, callBackTypeEnum, resultMap, param);
-        } catch (Exception e) {
-            log.error("事件回传判断, 出现异常, param : {},  userData : {}, e : {}", JsonUtil.toString(param),
-                    JsonUtil.toString(userData), e.getMessage(), e);
-            resultMap.put("callBack", Boolean.FALSE);
-        }
-        //返回结果
-        return resultMap;
-    }
-
-    private boolean isUserEvent(Game game, Long userId) {
-        if (Objects.equals(game.getStatus(), 2)) {
-            return true;
-        }
-        //查询玩家
-        User user = userService.getById(userId);
-        //判断是否测试过事件用户
-        return userEventService.count(new LambdaQueryWrapper<UserEvent>()
-                .eq(UserEvent::getGameId, game.getId())
-                .and(qw -> qw.eq(UserEvent::getUsername, user.getUsername())
-                        .or().eq(UserEvent::getMobile, user.getMobile())
-                )
-        ) > 0;
-    }
-
-    private void checkCallBack(Long userId, Agent agent, CallBackTypeEnum callBackTypeEnum, Map<String, Object> resultMap,
-                               CallBackControlParam param) {
-        switch (callBackTypeEnum) {
-            case CALL_BACK_REGISTER:
-                // 注册
-                TtAppUserBackQueryRpcDTO userTransform = this.transform(userId, agent);
-                resultMap.put("callBack", ttAppBackRpc.userBackQuery(userTransform).getData());
-                break;
-            case CALL_BACK_LOGIN_IN:
-                // 登录
-                resultMap.put("callBack", Boolean.FALSE);
-                break;
-            case CALL_BACK_ACTIVATE:
-                // 激活(创角)
-                if (Strings.isBlank(param.getRoleId())) {
-                    resultMap.put("callBack", Boolean.FALSE);
-                    resultMap.put("roleId", "unknown");
-                    break;
-                }
-                TtAppRoleRegisterBackQueryRpcDTO roleTransform = this.transform(userId, agent, param.getRoleId());
-                resultMap.put("roleId", param.getRoleId());
-                resultMap.put("callBack", ttAppBackRpc.roleRegisterBackQuery(roleTransform).getData());
-                break;
-            case CALL_BACK_PAY_ORDER:
-                // 支付
-                if (Strings.isBlank(param.getOrderId())) {
-                    resultMap.put("callBack", Boolean.FALSE);
-                    resultMap.put("orderId", "unknown");
-                    break;
-                }
-                TtAppOrderBackQueryRpcDTO orderTransform = this.transform(userId, param.getOrderId(), agent);
-                OrderBackQueryRpcVO orderBackQueryRpcVO = ttAppBackRpc.orderBackQuery(orderTransform).getData();
-                resultMap.put("orderId", param.getOrderId());
-                resultMap.put("callBack", orderBackQueryRpcVO.getDoBack());
-                resultMap.put("backMsg", orderBackQueryRpcVO.getBackMsg());
-                if (Objects.equals(orderBackQueryRpcVO.getDoBack(), Boolean.TRUE)) {
-                    //传过来的金额是分, 换算成元, 存在小数直接舍弃
-                    List<Long> backMoney = orderBackQueryRpcVO.getBackMoney()
-                            .stream().map(money -> money / 100)
-                            .collect(Collectors.toList());
-                    resultMap.put("amount", backMoney);
-                }
-                break;
-            default:
-                // 处理未知类型
-                resultMap.put("callBack", Boolean.FALSE);
-        }
-    }
-
     @Override
     public void userCallBack(User user, Map<String, String> urlParamMap) {
         //判断游戏是否开启广告回传, 未开启, 不回传
@@ -229,12 +94,7 @@ public class CallBackServiceImpl implements ICallBackService {
             }
             //腾讯小游戏回传
             if (Objects.equals(agent.getAccountType(), AccountTypeEnum.TENCENT_MINI_GAME.getValue())) {
-                TencentUserDTO tencentUserDTO = this.transform(user, agent, gameApplet);
-                //解析设置clickId
-                Map<String, String> channelMap = agentService.channelTransform(user.getChannel());
-                tencentUserDTO.setClickId(channelMap.get("gdt_vid"));
-                tencentMiniGameBackRpc.backUser(tencentUserDTO);
-                gameBackLogService.addLog(user.getId(), null, "腾讯小游戏用户回传提交", JsonUtil.toString(tencentUserDTO));
+                this.userCallBackTencentMiniGame(user, agent, gameApplet);
             }
             //腾讯APP私域
             if (Objects.equals(agent.getAccountType(), AccountTypeEnum.TENCENT_APP_API.getValue())) {
@@ -263,6 +123,28 @@ public class CallBackServiceImpl implements ICallBackService {
         }
     }
 
+    private void userCallBackTencentMiniGame(User user, Agent agent, GameApplet gameApplet) {
+        //查询游戏信息
+        Game game = gameService.getById(agent.getGameId());
+        //构造回传参数
+        TencentUserDTO tencentUserDTO = this.transform(user, agent, gameApplet);
+        //解析设置clickId
+        Map<String, String> channelMap = agentService.channelTransform(user.getChannel());
+        tencentUserDTO.setClickId(channelMap.get("gdt_vid"));
+        //判断API回传开关是否关掉, 未设置关掉, 则执行API回传
+        if (game.getApiBackSwitch() == null || game.getApiBackSwitch()) {
+            tencentMiniGameBackRpc.backUser(tencentUserDTO);
+            gameBackLogService.addLog(user.getId(), null, "腾讯小游戏用户回传提交",
+                    JsonUtil.toString(tencentUserDTO));
+        }
+        //判断是否配置了媒体SDK, 配置了则执行媒体SDK回传
+        if (Strings.isNotBlank(game.getAdSdkConfig())) {
+            tencentMiniGameBackRpc.callBackUser(tencentUserDTO);
+            gameBackLogService.addLog(user.getId(), null, "腾讯小游戏用户媒体SDK回传提交",
+                    JsonUtil.toString(tencentUserDTO));
+        }
+    }
+
     @Override
     public void roleCallBack(GameUserRole gameUserRole) {
         //判断游戏是否开启广告回传, 未开启, 不回传
@@ -290,9 +172,7 @@ public class CallBackServiceImpl implements ICallBackService {
             }
             //腾讯小游戏回传
             if (Objects.equals(agent.getAccountType(), AccountTypeEnum.TENCENT_MINI_GAME.getValue())) {
-                TencentRoleRegisterRpcDTO tencentRoleRegisterRpcDTO = this.transform(user, agent, gameApplet, gameUserRole);
-                tencentMiniGameBackRpc.backRoleRegister(tencentRoleRegisterRpcDTO);
-                gameBackLogService.addLog(user.getId(), gameUserRole.getRoleId(), "腾讯小游戏创角回传提交", JsonUtil.toString(tencentRoleRegisterRpcDTO));
+                this.roleCallBackTencentMiniGame(user, agent, gameApplet, gameUserRole);
             }
             //腾讯APP私域
             if (Objects.equals(agent.getAccountType(), AccountTypeEnum.TENCENT_APP_API.getValue())) {
@@ -321,6 +201,24 @@ public class CallBackServiceImpl implements ICallBackService {
         }
     }
 
+    private void roleCallBackTencentMiniGame(User user, Agent agent, GameApplet gameApplet, GameUserRole gameUserRole) {
+        //查询游戏信息
+        Game game = gameService.getById(agent.getGameId());
+        TencentRoleRegisterRpcDTO tencentRoleRegisterRpcDTO = this.transform(user, agent, gameApplet, gameUserRole);
+        //判断API回传开关是否关掉, 未设置关掉, 则执行API回传
+        if (game.getApiBackSwitch() == null || game.getApiBackSwitch()) {
+            tencentMiniGameBackRpc.backRoleRegister(tencentRoleRegisterRpcDTO);
+            gameBackLogService.addLog(user.getId(), gameUserRole.getRoleId(), "腾讯小游戏创角回传提交",
+                    JsonUtil.toString(tencentRoleRegisterRpcDTO));
+        }
+        //判断是否配置了媒体SDK, 配置了则执行媒体SDK回传
+        if (Strings.isNotBlank(game.getAdSdkConfig())) {
+            tencentMiniGameBackRpc.callBackRole(tencentRoleRegisterRpcDTO);
+            gameBackLogService.addLog(user.getId(), gameUserRole.getRoleId(), "腾讯小游戏创角媒体SDK回传提交",
+                    JsonUtil.toString(tencentRoleRegisterRpcDTO));
+        }
+    }
+
     @Override
     public void orderCallBack(PlatformOrderDTO platformOrderDTO) {
         //判断游戏是否开启广告回传, 未开启, 不回传
@@ -349,12 +247,7 @@ public class CallBackServiceImpl implements ICallBackService {
             }
             //腾讯小游戏回传
             if (Objects.equals(agent.getAccountType(), AccountTypeEnum.TENCENT_MINI_GAME.getValue())) {
-                TencentOrderDTO tencentOrderDTO = this.transform(platformOrderDTO, user, agent, gameApplet);
-                //解析设置clickId
-                Map<String, String> channelMap = agentService.channelTransform(user.getChannel());
-                tencentOrderDTO.setClickId(channelMap.get("gdt_vid"));
-                tencentMiniGameBackRpc.backOrder(tencentOrderDTO);
-                gameBackLogService.addLog(user.getId(), platformOrderDTO.getOrderId(), "腾讯小游戏订单回传提交", JsonUtil.toString(tencentOrderDTO));
+                this.orderCallBackTencentMiniGame(user, agent, gameApplet, platformOrderDTO);
             }
             //腾讯APP私域
             if (Objects.equals(agent.getAccountType(), AccountTypeEnum.TENCENT_APP_API.getValue())) {
@@ -383,6 +276,27 @@ public class CallBackServiceImpl implements ICallBackService {
         }
     }
 
+    private void orderCallBackTencentMiniGame(User user, Agent agent, GameApplet gameApplet, PlatformOrderDTO platformOrderDTO) {
+        //查询游戏信息
+        Game game = gameService.getById(agent.getGameId());
+        TencentOrderDTO tencentOrderDTO = this.transform(platformOrderDTO, user, agent, gameApplet);
+        //解析设置clickId
+        Map<String, String> channelMap = agentService.channelTransform(user.getChannel());
+        tencentOrderDTO.setClickId(channelMap.get("gdt_vid"));
+        //判断API回传开关是否关掉, 未设置关掉, 则执行API回传
+        if (game.getApiBackSwitch() == null || game.getApiBackSwitch()) {
+            tencentMiniGameBackRpc.backOrder(tencentOrderDTO);
+            gameBackLogService.addLog(user.getId(), platformOrderDTO.getOrderId(), "腾讯小游戏订单回传提交",
+                    JsonUtil.toString(tencentOrderDTO));
+        }
+        //判断是否配置了媒体SDK, 配置了则执行媒体SDK回传
+        if (Strings.isNotBlank(game.getAdSdkConfig())) {
+            tencentMiniGameBackRpc.callBackOrder(tencentOrderDTO);
+            gameBackLogService.addLog(user.getId(), platformOrderDTO.getOrderId(), "腾讯小游戏订单媒体SDK回传提交",
+                    JsonUtil.toString(tencentOrderDTO));
+        }
+    }
+
     private TencentRoleRegisterRpcDTO transform(User user, Agent agent, GameApplet gameApplet, GameUserRole gameUserRole) {
         return TencentRoleRegisterRpcDTO.builder()
                 .backPolicyId(agent.getBackPolicyId())

+ 543 - 0
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/GameBackLogMediaSdkServiceImpl.java

@@ -0,0 +1,543 @@
+package com.zanxiang.game.module.sdk.service.impl;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+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.ServerInfo;
+import com.zanxiang.game.back.base.pojo.dto.TencentMiniGameOrderBackQueryRpcDTO;
+import com.zanxiang.game.back.base.pojo.dto.TtAppOrderBackQueryRpcDTO;
+import com.zanxiang.game.back.base.pojo.vo.GameBackPolicyRpcVO;
+import com.zanxiang.game.back.base.pojo.vo.OrderBackQueryRpcVO;
+import com.zanxiang.game.back.base.rpc.IGameBackPolicyRpc;
+import com.zanxiang.game.back.base.rpc.ITencentMiniGameBackRpc;
+import com.zanxiang.game.back.base.rpc.ITtAppBackRpc;
+import com.zanxiang.game.module.base.pojo.enums.AccountTypeEnum;
+import com.zanxiang.game.module.base.pojo.enums.GameCategoryEnum;
+import com.zanxiang.game.module.mybatis.entity.*;
+import com.zanxiang.game.module.mybatis.mapper.GameBackLogMediaSdkMapper;
+import com.zanxiang.game.module.sdk.constant.RedisKeyConstant;
+import com.zanxiang.game.module.sdk.enums.CallBackTypeEnum;
+import com.zanxiang.game.module.sdk.pojo.dto.PlatformOrderDTO;
+import com.zanxiang.game.module.sdk.pojo.param.BackLogMediaSdkParam;
+import com.zanxiang.game.module.sdk.pojo.param.CallBackControlParam;
+import com.zanxiang.game.module.sdk.pojo.param.UserData;
+import com.zanxiang.game.module.sdk.service.*;
+import com.zanxiang.module.redis.service.IDistributedLockComponent;
+import com.zanxiang.module.util.JsonUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.apache.logging.log4j.util.Strings;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.temporal.ChronoUnit;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+/**
+ * @author : lingfeng
+ * @time : 2022-11-10
+ * @description : 媒体sdk回传日志
+ */
+@Slf4j
+@Service
+public class GameBackLogMediaSdkServiceImpl extends ServiceImpl<GameBackLogMediaSdkMapper, GameBackLogMediaSdk> implements IGameBackLogMediaSdkService {
+
+    @DubboReference(providedBy = ServerInfo.SERVER_DUBBO_NAME)
+    private ITtAppBackRpc ttAppBackRpc;
+
+    @DubboReference(providedBy = ServerInfo.SERVER_DUBBO_NAME)
+    private IGameBackPolicyRpc gameBackPolicyRpc;
+
+    @DubboReference(providedBy = ServerInfo.SERVER_DUBBO_NAME)
+    private ITencentMiniGameBackRpc tencentMiniGameBackRpc;
+
+    @Autowired
+    private IUserService userService;
+
+    @Autowired
+    private IOrderService orderService;
+
+    @Autowired
+    private IAgentService agentService;
+
+    @Autowired
+    private IGameService gameService;
+
+    @Autowired
+    private IUserEventService userEventService;
+
+    @Autowired
+    private IGameUserRoleService gameUserRoleService;
+
+    @Autowired
+    private IUserLoginLogService userLoginLogService;
+
+    @Autowired
+    private IDistributedLockComponent distributedLockComponent;
+
+    @Override
+    public Map<String, Object> callBackJudge(CallBackControlParam param, UserData userData) {
+        //线程锁, 避免重复请求
+        String lockKey = this.getLockKey(param, userData.getUserId());
+        if (!distributedLockComponent.doLock(lockKey, 0L, 20L, TimeUnit.SECONDS)) {
+            log.error("重复请求触发线程锁, 直接返回false, lockKey : {}", lockKey);
+            Map<String, Object> resultMap = this.getResultMap(param, userData);
+            resultMap.put("backMsg", "重复请求触发线程锁, 直接返回false, lockKey : " + lockKey);
+            return resultMap;
+        }
+        //判断结果返回对象
+        Map<String, Object> resultMap = this.getResultMap(param, userData);
+        try {
+            //参数判断, 检测不通过
+            if (!this.callBackParamCheck(param, resultMap)) {
+                return resultMap;
+            }
+            //查询玩家信息
+            User user = userService.getById(userData.getUserId());
+            //测试账号判断
+            if (this.userEventTest(param, user, resultMap)) {
+                return resultMap;
+            }
+            //玩家渠道信息回传检测
+            Tuple2<Boolean, Agent> userAgentCheckTuple2 = this.userAgentCheck(user, resultMap);
+            if (!userAgentCheckTuple2.first) {
+                return resultMap;
+            }
+            //执行回传条件判断
+            this.checkCallBack(user, userAgentCheckTuple2.second, resultMap, param);
+        } catch (Exception e) {
+            log.error("事件回传判断, 出现异常, param : {},  userData : {}, e : {}", JsonUtil.toString(param),
+                    JsonUtil.toString(userData), e.getMessage(), e);
+            resultMap.put("backMsg", "事件回传判断, 出现异常");
+        } finally {
+            //等级提升和订单付费, 不释放锁, 其他事件锁释放
+            if (!Objects.equals(param.getCallBackTypeEnum(), CallBackTypeEnum.CALL_BACK_UPDATE_LEVEL)
+                    && !Objects.equals(param.getCallBackTypeEnum(), CallBackTypeEnum.CALL_BACK_PAY_ORDER)) {
+                distributedLockComponent.unlock(lockKey);
+            }
+        }
+        //返回结果
+        return resultMap;
+    }
+
+    private Map<String, Object> getResultMap(CallBackControlParam param, UserData userData) {
+        Map<String, Object> resultMap = new HashMap<>(10);
+        resultMap.put("callBackTypeEnum", param.getCallBackTypeEnum().getValue());
+        resultMap.put("userId", userData.getUserId());
+        resultMap.put("gameId", userData.getGameId());
+        resultMap.put("callBack", Boolean.FALSE);
+        return resultMap;
+    }
+
+    private String getLockKey(CallBackControlParam param, Long userId) {
+        //回传枚举
+        CallBackTypeEnum callBackTypeEnum = param.getCallBackTypeEnum();
+        //线程锁
+        String lockKey = RedisKeyConstant.CALL_BACK_JUDGE_LOCK + callBackTypeEnum.getValue() + "_" + userId;
+        //创角, 新手引导回传锁
+        if (Objects.equals(callBackTypeEnum, CallBackTypeEnum.CALL_BACK_ACTIVATE)
+                || Objects.equals(callBackTypeEnum, CallBackTypeEnum.CALL_BACK_CREATE_ROLE)
+                || Objects.equals(callBackTypeEnum, CallBackTypeEnum.CALL_BACK_TUTORIAL_FINISH)) {
+            if (Strings.isNotBlank(param.getRoleId())) {
+                lockKey = lockKey + "_" + param.getRoleId();
+            }
+        }
+        //等级提升回传锁
+        if (Objects.equals(callBackTypeEnum, CallBackTypeEnum.CALL_BACK_UPDATE_LEVEL) && param.getLevel() != null) {
+            lockKey = lockKey + "_" + param.getRoleId() + "_" + param.getLevel();
+        }
+        //付费回传锁
+        if (Objects.equals(callBackTypeEnum, CallBackTypeEnum.CALL_BACK_PAY_ORDER) && Strings.isNotBlank(param.getOrderId())) {
+            lockKey = lockKey + "_" + param.getOrderId();
+        }
+        return lockKey;
+    }
+
+    private boolean callBackParamCheck(CallBackControlParam param, Map<String, Object> resultMap) {
+        CallBackTypeEnum callBackTypeEnum = param.getCallBackTypeEnum();
+        //创角, 新手引导, 必须传角色id
+        if (Objects.equals(callBackTypeEnum, CallBackTypeEnum.CALL_BACK_ACTIVATE)
+                || Objects.equals(callBackTypeEnum, CallBackTypeEnum.CALL_BACK_CREATE_ROLE)
+                || Objects.equals(callBackTypeEnum, CallBackTypeEnum.CALL_BACK_TUTORIAL_FINISH)) {
+            if (Strings.isBlank(param.getRoleId())) {
+                resultMap.put("backMsg", "参数错误, 创角, 新手引导或者等级提升回传, 必须传角色id");
+                return false;
+            }
+            resultMap.put("roleId", param.getRoleId());
+        }
+        //等级提升回传, 必须传角色id, 角色当前等级
+        if (Objects.equals(callBackTypeEnum, CallBackTypeEnum.CALL_BACK_UPDATE_LEVEL)) {
+            if (Strings.isBlank(param.getRoleId()) || param.getLevel() == null) {
+                resultMap.put("backMsg", "参数错误,等级提升回传, 必须传角色id和角色当前等级");
+                return false;
+            }
+            resultMap.put("roleId", param.getRoleId());
+            resultMap.put("level", param.getLevel());
+        }
+        //付费回传, 必须传订单id
+        if (Objects.equals(callBackTypeEnum, CallBackTypeEnum.CALL_BACK_PAY_ORDER)) {
+            if (Strings.isBlank(param.getOrderId())) {
+                resultMap.put("backMsg", "参数错误, 付费回传, 必须传订单id");
+                return false;
+            }
+            resultMap.put("orderId", param.getOrderId());
+        }
+        return true;
+    }
+
+    private boolean userEventTest(CallBackControlParam param, User user, Map<String, Object> resultMap) {
+        //查询游戏信息
+        Game game = gameService.getById(user.getGameId());
+        //判断是否测试过事件用户
+        if (!Objects.equals(game.getStatus(), 2) && userEventService.count(new LambdaQueryWrapper<UserEvent>()
+                .eq(UserEvent::getGameId, user.getGameId())
+                .and(qw -> qw.eq(UserEvent::getUsername, user.getUsername())
+                        .or().eq(UserEvent::getUsername, user.getOpenId())
+                        .or().eq(UserEvent::getMobile, user.getMobile()))
+        ) <= 0) {
+            return false;
+        }
+        //判断沉默唤起回传, 新手引导回传, 是否已经执行, 不重复执行
+        if (Objects.equals(param.getCallBackTypeEnum(), CallBackTypeEnum.CALL_BACK_RE_ACTIVE)
+                || Objects.equals(param.getCallBackTypeEnum(), CallBackTypeEnum.CALL_BACK_TUTORIAL_FINISH)) {
+            if (super.count(new LambdaQueryWrapper<GameBackLogMediaSdk>()
+                    .eq(GameBackLogMediaSdk::getGameId, user.getGameId())
+                    .eq(GameBackLogMediaSdk::getUserId, user.getId())
+                    .eq(GameBackLogMediaSdk::getCallBackTypeEnum, param.getCallBackTypeEnum().getValue())
+            ) > 0) {
+                return false;
+            }
+        }
+        //等级提升回传, 判断当前等级是否已执行回传
+        if (Objects.equals(param.getCallBackTypeEnum(), CallBackTypeEnum.CALL_BACK_UPDATE_LEVEL)) {
+            if (super.count(new LambdaQueryWrapper<GameBackLogMediaSdk>()
+                    .eq(GameBackLogMediaSdk::getGameId, user.getGameId())
+                    .eq(GameBackLogMediaSdk::getUserId, user.getId())
+                    .eq(GameBackLogMediaSdk::getRoleId, param.getRoleId())
+                    .eq(GameBackLogMediaSdk::getLevel, param.getLevel())
+                    .eq(GameBackLogMediaSdk::getCallBackTypeEnum, CallBackTypeEnum.CALL_BACK_UPDATE_LEVEL.getValue())
+            ) > 0) {
+                return false;
+            }
+        }
+        //测试账号, 回传默认全量回传, 不做判断
+        resultMap.put("callBack", Boolean.TRUE);
+        resultMap.put("backMsg", "测试账号, 回传默认全量回传, 不做判断");
+        //回传类型
+        CallBackTypeEnum callBackTypeEnum = param.getCallBackTypeEnum();
+        //判断是否沉默唤起回传, 添加沉默唤起判断天数
+        if (Objects.equals(callBackTypeEnum, CallBackTypeEnum.CALL_BACK_RE_ACTIVE)) {
+            resultMap.put("backFlowDay", 30);
+        }
+        //判断是否订单付费回传, 添加回传金额
+        if (Objects.equals(callBackTypeEnum, CallBackTypeEnum.CALL_BACK_PAY_ORDER) && Strings.isNotBlank(param.getOrderId())) {
+            PlatformOrderDTO platformOrderDTO = orderService.getByOrderId(param.getOrderId());
+            if (platformOrderDTO == null || platformOrderDTO.getAmount() == null) {
+                return false;
+            }
+            //头条APP媒体回传, 返回的单位是元
+            if (Objects.equals(game.getCategory(), GameCategoryEnum.CATEGORY_APP.getId())) {
+                resultMap.put("amount", Collections.singletonList(platformOrderDTO.getAmount().intValue()));
+            }
+            //腾讯小游戏媒体SDK回传, 返回的单位是分, 乘以100
+            if (Objects.equals(game.getCategory(), GameCategoryEnum.CATEGORY_WX_APPLET.getId())) {
+                int amount = platformOrderDTO.getAmount().multiply(new BigDecimal(100)).intValue();
+                resultMap.put("amount", Collections.singletonList(amount));
+            }
+        }
+        //返回结果
+        return true;
+    }
+
+    private Tuple2<Boolean, Agent> userAgentCheck(User user, Map<String, Object> resultMap) {
+        //判断玩家是否为自然量或者被分享用户, 是则不执行回传
+        if (Objects.equals(user.getAgentId(), Agent.DEFAULT_AGENT) || user.getShareUserId() != null) {
+            resultMap.put("backMsg", "玩家属于自然量或者被分享用户, 不回传");
+            return Tuple2.with(Boolean.FALSE, null);
+        }
+        //判断玩家是否存在渠道, 不存在渠道则不回传
+        Agent agent = agentService.getById(user.getAgentId());
+        if (agent == null) {
+            resultMap.put("backMsg", "根据玩家渠道id查询渠道信息为空, 无法执行回传");
+            return Tuple2.with(Boolean.FALSE, null);
+        }
+        //返回执行回传, 且返回渠道信息
+        return Tuple2.with(Boolean.TRUE, agent);
+    }
+
+    private void checkCallBack(User user, Agent agent, Map<String, Object> resultMap, CallBackControlParam param) {
+        //玩家id
+        Long userId = user.getId();
+        //游戏id
+        Long gameId = agent.getGameId();
+        //角色id
+        String roleId = param.getRoleId();
+        //角色等级
+        Long level = param.getLevel();
+        //回传类型
+        CallBackTypeEnum callBackTypeEnum = param.getCallBackTypeEnum();
+        //按不同类型判断
+        switch (callBackTypeEnum) {
+            case CALL_BACK_LOGIN_IN:
+                break;
+            case CALL_BACK_REGISTER:
+            case CALL_BACK_ACTIVATE:
+            case CALL_BACK_CREATE_ROLE:
+            case CALL_BACK_UPDATE_LEVEL:
+                Tuple2<Boolean, String> distinctCheck = this.callBackDistinctCheck(callBackTypeEnum, gameId, userId, roleId, level);
+                resultMap.put("callBack", distinctCheck.first);
+                resultMap.put("backMsg", distinctCheck.second);
+                break;
+            case CALL_BACK_ADD_TO_WISHLIST:
+            case CALL_BACK_ON_SHARE_TIME_LINE:
+            case CALL_BACK_ON_SHARE_APP_MESSAGE:
+            case CALL_BACK_VIEW_CONTENT_MALL:
+            case CALL_BACK_VIEW_CONTENT_ACTIVITY:
+                resultMap.put("callBack", Boolean.TRUE);
+                break;
+            case CALL_BACK_RE_ACTIVE:
+                Tuple3<Boolean, Long, String> tuple = this.callBackReActiveCheck(roleId, userId, gameId);
+                resultMap.put("callBack", tuple.first);
+                resultMap.put("backFlowDay", tuple.second);
+                resultMap.put("backMsg", tuple.third);
+                break;
+            case CALL_BACK_TUTORIAL_FINISH:
+                Tuple2<Boolean, String> tuple2 = this.callBackTutorialFinishCheck(roleId, userId, gameId, agent);
+                resultMap.put("callBack", tuple2.first);
+                resultMap.put("backMsg", tuple2.second);
+                break;
+            case CALL_BACK_PAY_ORDER:
+                Tuple3<Boolean, List<Long>, String> tuple3 = this.callBackOrderCheck(param.getOrderId(), user, agent);
+                resultMap.put("callBack", tuple3.first);
+                resultMap.put("amount", tuple3.second);
+                resultMap.put("backMsg", tuple3.third);
+                break;
+            default:
+                resultMap.put("backMsg", "未知的回传类型");
+        }
+    }
+
+    private Tuple2<Boolean, String> callBackDistinctCheck(CallBackTypeEnum callBackTypeEnum, Long gameId, Long userId,
+                                                          String roleId, Long level) {
+        //注册回传去重判断
+        if (Objects.equals(callBackTypeEnum, CallBackTypeEnum.CALL_BACK_REGISTER)
+                && super.count(new LambdaQueryWrapper<GameBackLogMediaSdk>()
+                .eq(GameBackLogMediaSdk::getGameId, gameId)
+                .eq(GameBackLogMediaSdk::getUserId, userId)
+                .eq(GameBackLogMediaSdk::getCallBackTypeEnum, callBackTypeEnum.getValue())
+        ) > 0) {
+            return Tuple2.with(Boolean.FALSE, "当前用户注册已回传, 不重复执行");
+        }
+        //创角回传去重和前置判断
+        if (Objects.equals(callBackTypeEnum, CallBackTypeEnum.CALL_BACK_ACTIVATE)
+                || Objects.equals(callBackTypeEnum, CallBackTypeEnum.CALL_BACK_CREATE_ROLE)) {
+            //创角是否已回传, 已回传则不重复执行
+            if (super.count(new LambdaQueryWrapper<GameBackLogMediaSdk>()
+                    .eq(GameBackLogMediaSdk::getGameId, gameId)
+                    .eq(GameBackLogMediaSdk::getUserId, userId)
+                    .eq(GameBackLogMediaSdk::getRoleId, roleId)
+                    .eq(GameBackLogMediaSdk::getCallBackTypeEnum, callBackTypeEnum.getValue())
+            ) > 0) {
+                return Tuple2.with(Boolean.FALSE, "当前角色创角已回传, 不重复执行");
+            }
+            //腾讯小游戏的创角回传, 可以判断前置注册回传是否已执行, 未执行无法回传
+            if (Objects.equals(callBackTypeEnum, CallBackTypeEnum.CALL_BACK_CREATE_ROLE)
+                    && super.count(new LambdaQueryWrapper<GameBackLogMediaSdk>()
+                    .eq(GameBackLogMediaSdk::getGameId, gameId)
+                    .eq(GameBackLogMediaSdk::getUserId, userId)
+                    .eq(GameBackLogMediaSdk::getCallBackTypeEnum, CallBackTypeEnum.CALL_BACK_REGISTER.getValue())
+            ) <= 0) {
+                return Tuple2.with(Boolean.FALSE, "当前用户注册未回传, 无法执行创角回传");
+            }
+        }
+        //等级提升回传去重和前置条件判断
+        if (Objects.equals(callBackTypeEnum, CallBackTypeEnum.CALL_BACK_UPDATE_LEVEL)) {
+            //当前等级是否已回传, 已回传则不重复执行
+            if (super.count(new LambdaQueryWrapper<GameBackLogMediaSdk>()
+                    .eq(GameBackLogMediaSdk::getGameId, gameId)
+                    .eq(GameBackLogMediaSdk::getUserId, userId)
+                    .eq(GameBackLogMediaSdk::getRoleId, roleId)
+                    .eq(GameBackLogMediaSdk::getLevel, level)
+                    .eq(GameBackLogMediaSdk::getCallBackTypeEnum, CallBackTypeEnum.CALL_BACK_UPDATE_LEVEL.getValue())
+            ) > 0) {
+                return Tuple2.with(Boolean.FALSE, "角色当前等级已回传, 不重复执行");
+            }
+            //腾讯小游戏的等级提升回传, 可以判断前置创角回传是否已执行, 未执行无法回传
+            if (super.count(new LambdaQueryWrapper<GameBackLogMediaSdk>()
+                    .eq(GameBackLogMediaSdk::getGameId, gameId)
+                    .eq(GameBackLogMediaSdk::getUserId, userId)
+                    .eq(GameBackLogMediaSdk::getRoleId, roleId)
+                    .eq(GameBackLogMediaSdk::getCallBackTypeEnum, CallBackTypeEnum.CALL_BACK_CREATE_ROLE.getValue())
+            ) <= 0) {
+                return Tuple2.with(Boolean.FALSE, "角色创角未回传, 无法执行等级提升回传");
+            }
+        }
+        return Tuple2.with(Boolean.TRUE, "执行回传");
+    }
+
+    private Tuple3<Boolean, Long, String> callBackReActiveCheck(String roleId, Long userId, Long gameId) {
+        //判断玩家今日是否已经沉默唤起回传
+        if (super.count(new LambdaQueryWrapper<GameBackLogMediaSdk>()
+                .eq(GameBackLogMediaSdk::getGameId, gameId)
+                .eq(GameBackLogMediaSdk::getUserId, userId)
+                .eq(GameBackLogMediaSdk::getRoleId, roleId)
+                .eq(GameBackLogMediaSdk::getCallBackTypeEnum, CallBackTypeEnum.CALL_BACK_RE_ACTIVE.getValue())
+                .ge(GameBackLogMediaSdk::getCreateTime, LocalDateTime.of(LocalDate.now(), LocalTime.MIN))
+        ) > 0) {
+            return Tuple3.with(Boolean.FALSE, null, "今日已执行沉默唤起回传, 不重复执行");
+        }
+        //获取玩家今天之前最后一次登录日志
+        UserLoginLog userLoginLog = userLoginLogService.getOne(new LambdaQueryWrapper<UserLoginLog>()
+                .eq(UserLoginLog::getUserId, userId)
+                .lt(UserLoginLog::getCreateTime, LocalDateTime.of(LocalDate.now(), LocalTime.MIN))
+                .orderByDesc(UserLoginLog::getCreateTime)
+                .last("limit 1"));
+        if (userLoginLog == null) {
+            return Tuple3.with(Boolean.FALSE, null, "不存在今日之前的登录日志, 不执行沉默唤起回传");
+        }
+        //最长未登录天数, 判断标准暂定 30 天
+        long backFlowDay = 30;
+        long betweenDay = ChronoUnit.DAYS.between(userLoginLog.getCreateTime().toLocalDate(), LocalDate.now());
+        //返回判断结果
+        return Tuple3.with(betweenDay >= backFlowDay, backFlowDay, "沉默唤起判断依据登录日志id: " + userLoginLog.getId());
+    }
+
+    private Tuple2<Boolean, String> callBackTutorialFinishCheck(String roleId, Long userId, Long gameId, Agent agent) {
+        //判断创角是否回传, 新手引导回传必须在创角回传之后执行
+        if (super.count(new LambdaQueryWrapper<GameBackLogMediaSdk>()
+                .eq(GameBackLogMediaSdk::getGameId, gameId)
+                .eq(GameBackLogMediaSdk::getUserId, userId)
+                .eq(GameBackLogMediaSdk::getRoleId, roleId)
+                .and(qw -> qw.eq(GameBackLogMediaSdk::getCallBackTypeEnum, CallBackTypeEnum.CALL_BACK_CREATE_ROLE.getValue())
+                        .or().eq(GameBackLogMediaSdk::getCallBackTypeEnum, CallBackTypeEnum.CALL_BACK_ACTIVATE.getValue()))
+        ) <= 0) {
+            return Tuple2.with(Boolean.FALSE, "创角回传未执行, 无法执行新手引导回传");
+        }
+        //判断用户是否已经执行过新手引导回传, 新手引导回传以用户为回传单位, 不以角色为回传单位
+        if (super.count(new LambdaQueryWrapper<GameBackLogMediaSdk>()
+                .eq(GameBackLogMediaSdk::getGameId, gameId)
+                .eq(GameBackLogMediaSdk::getUserId, userId)
+                .eq(GameBackLogMediaSdk::getCallBackTypeEnum, CallBackTypeEnum.CALL_BACK_TUTORIAL_FINISH.getValue())
+        ) > 0) {
+            return Tuple2.with(Boolean.FALSE, "角色已执行新手引导回传, 不重复执行");
+        }
+        //渠道关联的策略
+        Long backPolicyId = agent.getBackPolicyId();
+        //判断角色当前等级是否满足策略限制等级
+        if (backPolicyId == null) {
+            return Tuple2.with(Boolean.FALSE, "渠道未绑定策略, 无法执行新手引导回传, agentId : " + agent.getId());
+        }
+        //查询策略信息
+        Map<Long, GameBackPolicyRpcVO> policyRpcVOMap = gameBackPolicyRpc.listByIds(
+                Collections.singletonList(backPolicyId)).getData();
+        GameBackPolicyRpcVO gameBackPolicyRpcVO = policyRpcVOMap.get(backPolicyId);
+        if (gameBackPolicyRpcVO == null || Strings.isBlank(gameBackPolicyRpcVO.getTutorialFinishJson())) {
+            return Tuple2.with(Boolean.FALSE, "渠道绑定的策略信息不存在, 或者未设置新手引导回传等级, 无法执行新手引导回传, agentId : " + agent.getId());
+        }
+        JSONObject tutorialFinish = JSONObject.parse(gameBackPolicyRpcVO.getTutorialFinishJson());
+        Long roleLevel = tutorialFinish.getLong("roleLevel");
+        if (roleLevel == null) {
+            return Tuple2.with(Boolean.FALSE, "新手引导回传等级roleLevel设置为空, 无法执行新手引导回传, agentId : " + agent.getId());
+        }
+        //查询角色当前等级
+        GameUserRole gameUserRole = gameUserRoleService.getOne(new LambdaQueryWrapper<GameUserRole>()
+                .eq(GameUserRole::getUserId, userId)
+                .eq(GameUserRole::getGameId, gameId)
+                .eq(GameUserRole::getRoleId, roleId)
+                .orderByDesc(GameUserRole::getCreateTime).last("limit 1"));
+        if (gameUserRole == null || gameUserRole.getRoleLevel() == null) {
+            return Tuple2.with(Boolean.FALSE, "角色信息或者角色等级信息不存在, 无法执行新手引导回传, roleId : " + roleId);
+        }
+        //等级判断
+        if (gameUserRole.getRoleLevel() < roleLevel) {
+            return Tuple2.with(Boolean.FALSE, "角色等级未达到策略等级限制要求, 不执行新手引导回传, agentId : " + agent.getId());
+        }
+        //返回执行新手引导回传
+        return Tuple2.with(Boolean.TRUE, "执行新手引导回传");
+    }
+
+    private Tuple3<Boolean, List<Long>, String> callBackOrderCheck(String orderId, User user, Agent agent) {
+        Boolean doBack = Boolean.FALSE;
+        List<Long> amount = null;
+        String backMsg = null;
+        //头条APP直投回传
+        if (Objects.equals(agent.getAccountType(), AccountTypeEnum.BYTE_APP.getValue())) {
+            TtAppOrderBackQueryRpcDTO orderQuery = this.transform(user.getId(), orderId, agent);
+            OrderBackQueryRpcVO orderBackQueryRpcVO = ttAppBackRpc.orderBackQuery(orderQuery).getData();
+            //传过来的金额是分, 头条媒体SDK需要换算成元, 存在小数直接舍弃
+            if (Objects.equals(orderBackQueryRpcVO.getDoBack(), Boolean.TRUE)) {
+                amount = orderBackQueryRpcVO.getBackMoney().stream().map(money -> money / 100).collect(Collectors.toList());
+            }
+            doBack = orderBackQueryRpcVO.getDoBack();
+            backMsg = orderBackQueryRpcVO.getBackMsg();
+        }
+        //腾讯小游戏媒体SDK回传
+        if (Objects.equals(agent.getAccountType(), AccountTypeEnum.TENCENT_MINI_GAME.getValue())) {
+            TencentMiniGameOrderBackQueryRpcDTO orderQuery = this.transform(user.getOpenId(), orderId, agent);
+            OrderBackQueryRpcVO orderBackQueryRpcVO = tencentMiniGameBackRpc.orderBackQuery(orderQuery).getData();
+            if (Objects.equals(orderBackQueryRpcVO.getDoBack(), Boolean.TRUE)) {
+                amount = orderBackQueryRpcVO.getBackMoney();
+            }
+            doBack = orderBackQueryRpcVO.getDoBack();
+            backMsg = orderBackQueryRpcVO.getBackMsg();
+        }
+        return Tuple3.with(doBack, amount, Strings.isBlank(backMsg) ? "未知的渠道投放类型" : backMsg);
+    }
+
+    @Override
+    public boolean addMediaSdkBackLog(BackLogMediaSdkParam param, UserData userData) {
+        GameBackLogMediaSdk gameBackLogMediaSdk = this.transform(param, userData);
+        Map<String, Object> callBackJudgeResult = param.getCallBackJudgeResult();
+        //回传判断结果参数不为空
+        if (!callBackJudgeResult.isEmpty()) {
+            if (callBackJudgeResult.containsKey("roleId")) {
+                gameBackLogMediaSdk.setRoleId(String.valueOf(callBackJudgeResult.get("roleId")));
+            }
+            if (callBackJudgeResult.containsKey("orderId")) {
+                gameBackLogMediaSdk.setOrderId(String.valueOf(callBackJudgeResult.get("orderId")));
+            }
+            if (callBackJudgeResult.containsKey("level")) {
+                gameBackLogMediaSdk.setLevel(Long.parseLong(String.valueOf(callBackJudgeResult.get("level"))));
+            }
+        }
+        return super.save(gameBackLogMediaSdk);
+    }
+
+    private GameBackLogMediaSdk transform(BackLogMediaSdkParam param, UserData userData) {
+        return GameBackLogMediaSdk.builder()
+                .gameId(userData.getGameId())
+                .userId(userData.getUserId())
+                .callBackTypeEnum(param.getCallBackTypeEnum().getValue())
+                .callBackJudgeResult(JsonUtil.toString(param.getCallBackJudgeResult()))
+                .callBackParam(JsonUtil.toString(param.getCallBackParam()))
+                .errorMsg(param.getErrorMsg())
+                .createTime(LocalDateTime.now())
+                .build();
+    }
+
+    private TtAppOrderBackQueryRpcDTO transform(Long userId, String orderId, Agent agent) {
+        return TtAppOrderBackQueryRpcDTO.builder()
+                .gameId(agent.getGameId())
+                .userId(userId.toString())
+                .orderId(orderId)
+                .agentKey(agent.getAgentKey())
+                .build();
+    }
+
+    private TencentMiniGameOrderBackQueryRpcDTO transform(String wechatOpenid, String orderId, Agent agent) {
+        return TencentMiniGameOrderBackQueryRpcDTO.builder()
+                .gameId(agent.getGameId())
+                .wechatOpenid(wechatOpenid)
+                .orderId(orderId)
+                .agentKey(agent.getAgentKey())
+                .build();
+    }
+}

+ 51 - 6
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/GameServiceImpl.java

@@ -1,17 +1,25 @@
 package com.zanxiang.game.module.sdk.service.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.game.module.base.pojo.enums.AccountTypeEnum;
+import com.zanxiang.game.module.base.pojo.enums.GameCategoryEnum;
+import com.zanxiang.game.module.mybatis.entity.Agent;
 import com.zanxiang.game.module.mybatis.entity.Game;
+import com.zanxiang.game.module.mybatis.entity.User;
 import com.zanxiang.game.module.mybatis.mapper.GameMapper;
 import com.zanxiang.game.module.sdk.pojo.param.UserData;
+import com.zanxiang.game.module.sdk.service.IAgentService;
 import com.zanxiang.game.module.sdk.service.IGameService;
+import com.zanxiang.game.module.sdk.service.IUserService;
 import com.zanxiang.module.util.JsonUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.logging.log4j.util.Strings;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.Collections;
 import java.util.Map;
+import java.util.Objects;
 
 /**
  * @author : lingfeng
@@ -22,18 +30,55 @@ import java.util.Map;
 @Service
 public class GameServiceImpl extends ServiceImpl<GameMapper, Game> implements IGameService {
 
-    @Override
-    public Map<String, Object> getAdSdkConfig(UserData userData) {
+    @Autowired
+    private IAgentService agentService;
 
-        log.error("媒体初始化配置请求 userData : {}", JsonUtil.toString(userData));
+    @Autowired
+    private IUserService userService;
 
+    @Override
+    public Map<String, Object> getAdSdkConfig(UserData userData) {
         Game game = super.getById(userData.getGameId());
         if (Strings.isBlank(game.getAdSdkConfig())) {
             return Collections.singletonMap("adSdk", 0);
         }
-        Map<String, Object> map = JsonUtil.toMap(game.getAdSdkConfig(), Map.class, Object.class);
+        //判断是否为APP, APP直接返回配置
+        if (Objects.equals(game.getCategory(), GameCategoryEnum.CATEGORY_APP.getId())) {
+            return JsonUtil.toMap(game.getAdSdkConfig(), Map.class, Object.class);
+        }
+        //不是微信小程序, 不返回配置
+        if (!Objects.equals(game.getCategory(), GameCategoryEnum.CATEGORY_WX_APPLET.getId())) {
+            //默认返回不初始化
+            return Collections.singletonMap("adSdk", 0);
+        }
+        //目前只有投腾讯才返回
+        Agent agent = this.getUserAgent(userData.getUserId());
+        if (agent != null) {
+            //腾讯广告
+            if (Objects.equals(agent.getAccountType(), AccountTypeEnum.TENCENT_MINI_GAME.getValue())) {
+                return JsonUtil.toMap(game.getAdSdkConfig(), Map.class, Object.class);
+            }
+            //头条广告
+            if (Objects.equals(agent.getAccountType(), AccountTypeEnum.BYTE.getValue())) {
+                return Collections.singletonMap("adSdk", 0);
+            }
+        }
+        //当前调试阶段
+        if (userData.getUserId() != null && Objects.equals(game.getStatus(), 2)) {
+            return JsonUtil.toMap(game.getAdSdkConfig(), Map.class, Object.class);
+        }
+        //默认返回不初始化
+        return Collections.singletonMap("adSdk", 0);
+    }
 
-        log.error("媒体初始化配置返回, map : {}", JsonUtil.toString(map));
-        return map;
+    private Agent getUserAgent(Long userId) {
+        if (userId == null) {
+            return null;
+        }
+        User user = userService.getById(userId);
+        if (user == null) {
+            return null;
+        }
+        return agentService.getById(user.getAgentId());
     }
 }

+ 3 - 0
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/LoginServiceImpl.java

@@ -144,6 +144,7 @@ public class LoginServiceImpl implements IRegisterLoginService {
             agentService.userAgentUpdate(user, userData);
             //返回登录信息
             UserLoginVO userLoginVO = this.createUserLoginVO(user, userData);
+            userLoginVO.setRegUser(Boolean.FALSE);
             userLoginVO.setAppletShellSwitch(gameAppletShellService.getUserShellSwitch(user, Boolean.FALSE, request));
             userLoginVO.setAccessToken(wxApiService.getAccessToken(gameAppletDTO.getAppId(), gameAppletDTO.getAppSecret()));
             log.error("返回用户登录信息, userLoginVO : {}", JsonUtil.toString(userLoginVO));
@@ -153,6 +154,7 @@ public class LoginServiceImpl implements IRegisterLoginService {
         user = userCreateSave(userData, openId, null, null, openId, sessionKey);
         //返回登录信息
         UserLoginVO userLoginVO = this.createUserLoginVO(user, userData);
+        userLoginVO.setRegUser(Boolean.TRUE);
         userLoginVO.setAppletShellSwitch(gameAppletShellService.getUserShellSwitch(user, Boolean.TRUE, request));
         userLoginVO.setAccessToken(wxApiService.getAccessToken(gameAppletDTO.getAppId(), gameAppletDTO.getAppSecret()));
         log.error("返回用户登录信息, userLoginVO : {}", JsonUtil.toString(userLoginVO));
@@ -374,6 +376,7 @@ public class LoginServiceImpl implements IRegisterLoginService {
         //构造用户登录信息
         UserLoginVO userLoginVO = UserLoginVO.builder()
                 .userId(user.getId())
+                .openId(user.getOpenId())
                 .userName(user.getUsername())
                 .token(userToken)
                 .authentication(user.getAuthentication())

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

@@ -69,6 +69,10 @@ public class UserCardServiceImpl extends ServiceImpl<UserCardMapper, UserCard> i
         if (!idCheck) {
             return ResultVO.fail(HttpStatusEnum.CARD_ID_ERROR.getMsg());
         }
+        //未成年禁止认证
+        if (this.getAge(cardId) < 18){
+            return ResultVO.fail(HttpStatusEnum.AUTHENTICATION_FAIL_UNDERAGE.getMsg());
+        }
         //阿里实名认证
         Tuple2<Boolean, String> tuple2 = aliApiService.userCardCheck(cardName, cardId);
         //实名认证失败