Преглед изворни кода

回传策略更新,支持拆单回传

wcc пре 1 година
родитељ
комит
b352ee6137
34 измењених фајлова са 1013 додато и 189 уклоњено
  1. 0 5
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/config/NacosDynamicParamConfig.java
  2. 34 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/controller/BackPolicyController.java
  3. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameOceanengineOrderSplitLogMapper.java
  4. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameTencentMiniGameOrderSplitLogMapper.java
  5. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/dao/mapper/GameTencentOrderSplitLogMapper.java
  6. 2 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/dto/GameBackPolicyDTO.java
  7. 5 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameBackPolicy.java
  8. 50 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameOceanengineOrderSplitLog.java
  9. 50 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentMiniGameOrderSplitLog.java
  10. 50 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentOrderSplitLog.java
  11. 4 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/enums/BackStatusEnum.java
  12. 28 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/vo/GameBackPolicyVO.java
  13. 1 1
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/rpc/impl/TencentMiniGameBackRpcImpl.java
  14. 1 1
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/rpc/impl/TencentUserActionBackRpcImpl.java
  15. 1 1
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/rpc/impl/TtMiniGameBackRpcImpl.java
  16. 5 1
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameOceanengineOrderLogService.java
  17. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameOceanengineOrderSplitLogService.java
  18. 3 2
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentMiniGameBackLogService.java
  19. 1 1
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentMiniGameOrderService.java
  20. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentMiniGameOrderSplitLogService.java
  21. 5 1
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentOrderService.java
  22. 7 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentOrderSplitLogService.java
  23. 6 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameBackPolicyServiceImpl.java
  24. 119 73
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameOceanengineOrderLogServiceImpl.java
  25. 14 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameOceanengineOrderSplitLogServiceImpl.java
  26. 16 14
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentMiniGameBackLogServiceImpl.java
  27. 88 43
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentMiniGameOrderServiceImpl.java
  28. 14 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentMiniGameOrderSplitLogServiceImpl.java
  29. 94 46
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentOrderServiceImpl.java
  30. 14 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentOrderSplitLogServiceImpl.java
  31. 112 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/task/OceanengineOrderSplitBackTask.java
  32. 115 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/task/TencentMiniOrderSplitBackTask.java
  33. 112 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/task/TencentOrderSplitBackTask.java
  34. 27 0
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/utils/BackPolicyUtil.java

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

@@ -9,9 +9,4 @@ import org.springframework.stereotype.Component;
 @Component
 @RefreshScope
 public class NacosDynamicParamConfig {
-    /**
-     * 按关键行为回传的广告账号列表
-     */
-    @Value("${nacos.dynamic.backOfKeyAccountIds:test}")
-    private String backOfKeyAccountIds;
 }

+ 34 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/controller/BackPolicyController.java

@@ -96,6 +96,7 @@ public class BackPolicyController {
         checkDownLevel(dto.getFirstDownLevel());
         checkDownLevel(dto.getRechargeDownLevel());
         checkDownLevel(dto.getMarkUpDownLevel());
+        checkSplitStrategy(dto.getSplitStrategy());
         if (dto.getFirstBackCountOfUser() != null && dto.getFirstBackCountOfUser() < 1) {
             throw new BaseException("单用户最大回传次数不能小于 1");
         }
@@ -136,4 +137,37 @@ public class BackPolicyController {
             }
         }
     }
+
+    private void checkSplitStrategy(List<GameBackPolicyVO.SplitStrategy> splitStrategyList) {
+        if (CollectionUtils.isEmpty(splitStrategyList)) {
+            return;
+        }
+        splitStrategyList.sort((val1, val2) -> val1.getPayMoney().compareTo(val2.getPayMoney()));
+        BigDecimal compareMoney = null;
+        for (GameBackPolicyVO.SplitStrategy splitStrategy : splitStrategyList) {
+            if (splitStrategy.getPayMoney() == null
+                    || CollectionUtils.isEmpty(splitStrategy.getSplitList())
+                    || splitStrategy.getBetweenMinuteMin() == null
+                    || splitStrategy.getBetweenMinuteMax() == null) {
+                throw new BaseException("拆单策略参数错误");
+            }
+            if (splitStrategy.getPayMoney().compareTo(BigDecimal.ZERO) <= 0) {
+                throw new BaseException("拆单策略支付金额错误![" + splitStrategy.getPayMoney() + "]");
+            }
+            splitStrategy.getSplitList().forEach(splitMoney -> {
+                if (splitMoney == null || splitMoney.compareTo(BigDecimal.ZERO) <= 0) {
+                    throw new BaseException("拆单策略拆分金额错误![" + splitMoney + "]");
+                }
+            });
+            if (splitStrategy.getBetweenMinuteMin() < 1 || splitStrategy.getBetweenMinuteMin() >= 60) {
+                throw new BaseException("拆单策略间隔时间错误![" + splitStrategy.getBetweenMinuteMin() + "]");
+            }
+            if (splitStrategy.getBetweenMinuteMax() < 1 || splitStrategy.getBetweenMinuteMax() >= 60) {
+                throw new BaseException("拆单策略间隔时间错误![" + splitStrategy.getBetweenMinuteMax() + "]");
+            }
+            if (splitStrategy.getBetweenMinuteMin().compareTo(splitStrategy.getBetweenMinuteMax()) >= 0) {
+                throw new BaseException("拆单策略间隔时间错误![" + splitStrategy.getBetweenMinuteMin() + ">=" + splitStrategy.getBetweenMinuteMax() + "]");
+            }
+        }
+    }
 }

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

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

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

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

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

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

+ 2 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/dto/GameBackPolicyDTO.java

@@ -256,5 +256,7 @@ public class GameBackPolicyDTO implements Serializable {
      */
     private BigDecimal supperSmallAmount;
 
+    private List<GameBackPolicyVO.SplitStrategy> splitStrategy;
+
 
 }

+ 5 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameBackPolicy.java

@@ -222,5 +222,10 @@ public class GameBackPolicy implements Serializable {
      */
     private Long supperSmallAmount;
 
+    /**
+     * 拆单策略
+     */
+    private String splitStrategy;
+
 
 }

+ 50 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameOceanengineOrderSplitLog.java

@@ -0,0 +1,50 @@
+package com.zanxiang.game.back.serve.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * 拆单回传
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@TableName("t_game_oceanengine_order_split_log")
+public class GameOceanengineOrderSplitLog implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    private LocalDate backDay;
+
+    private String orderNo;
+
+    private Integer backIndex;
+
+    private Integer backCount;
+
+    private Long splitMoney;
+
+    private LocalDateTime backTime;
+
+    private LocalDateTime executeTime;
+
+    private Integer backStatus;
+
+    private String backErrorMsg;
+
+    private LocalDateTime createTime;
+
+
+}

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

@@ -0,0 +1,50 @@
+package com.zanxiang.game.back.serve.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * 拆单回传
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@TableName("t_game_tencent_mini_game_order_split_log")
+public class GameTencentMiniGameOrderSplitLog implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    private LocalDate backDay;
+
+    private String orderNo;
+
+    private Integer backIndex;
+
+    private Integer backCount;
+
+    private Long splitMoney;
+
+    private LocalDateTime backTime;
+
+    private LocalDateTime executeTime;
+
+    private Integer backStatus;
+
+    private String backErrorMsg;
+
+    private LocalDateTime createTime;
+
+
+}

+ 50 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/entity/GameTencentOrderSplitLog.java

@@ -0,0 +1,50 @@
+package com.zanxiang.game.back.serve.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * 拆单回传
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@TableName("t_game_tencent_order_split_log")
+public class GameTencentOrderSplitLog implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    private LocalDate backDay;
+
+    private String orderNo;
+
+    private Integer backIndex;
+
+    private Integer backCount;
+
+    private Long splitMoney;
+
+    private LocalDateTime backTime;
+
+    private LocalDateTime executeTime;
+
+    private Integer backStatus;
+
+    private String backErrorMsg;
+
+    private LocalDateTime createTime;
+
+
+}

+ 4 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/enums/BackStatusEnum.java

@@ -14,6 +14,10 @@ public enum BackStatusEnum {
      * 回传成功
      */
     SUCCESS(1),
+    /**
+     * 部分成功
+     */
+    SUCCESS_PART(2),
     /**
      * 回传失败
      */

+ 28 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/pojo/vo/GameBackPolicyVO.java

@@ -242,6 +242,11 @@ public class GameBackPolicyVO implements Serializable {
      */
     private BigDecimal supperSmallAmount;
 
+    /**
+     * 拆单策略
+     */
+    private List<SplitStrategy> splitStrategy;
+
     @Data
     @NoArgsConstructor
     @AllArgsConstructor
@@ -255,5 +260,28 @@ public class GameBackPolicyVO implements Serializable {
         private BigDecimal backMoney;
     }
 
+    @Data
+    @NoArgsConstructor
+    @AllArgsConstructor
+    @Builder
+    public static class SplitStrategy {
+        /**
+         * 支付金额
+         */
+        private BigDecimal payMoney;
+        /**
+         * 拆分金额
+         */
+        private List<BigDecimal> splitList;
+        /**
+         * 回传间隔时间(/分钟)
+         */
+        private Integer betweenMinuteMin;
+        /**
+         * 回传间隔时间(/分钟)
+         */
+        private Integer betweenMinuteMax;
+    }
+
 
 }

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

@@ -85,7 +85,7 @@ public class TencentMiniGameBackRpcImpl implements ITencentMiniGameBackRpc {
             log.error("腾讯小游戏订单回传失败,找不到回传的用户 orderId: {}", orderLog.getOrderId());
             return ResultVO.fail("找不到回传用户");
         } else {
-            return ResultVO.ok(gameTencentMiniGameOrderService.orderBack(orderLog, false, null));
+            return ResultVO.ok(gameTencentMiniGameOrderService.orderBack(orderLog));
         }
     }
 

+ 1 - 1
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/rpc/impl/TencentUserActionBackRpcImpl.java

@@ -74,7 +74,7 @@ public class TencentUserActionBackRpcImpl implements ITencentUserActionBackRpc {
                 .isFirstOrder(isFirstOrder)
                 .build();
         gameTencentOrderService.save(gameTencentOrder);
-        return ResultVO.ok(gameTencentOrderService.orderBack(gameTencentOrder, false, null));
+        return ResultVO.ok(gameTencentOrderService.orderBack(gameTencentOrder));
     }
 
     @Override

+ 1 - 1
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/rpc/impl/TtMiniGameBackRpcImpl.java

@@ -96,7 +96,7 @@ public class TtMiniGameBackRpcImpl implements ITtMiniGameBackRpc {
         ) == null;
         orderLog.setIsFirstOrder(isFirstOrder);
         gameOceanengineOrderLogService.save(orderLog);
-        return ResultVO.ok(gameOceanengineOrderLogService.callback(orderLog, false, null));
+        return ResultVO.ok(gameOceanengineOrderLogService.callback(orderLog));
     }
 
     @Override

+ 5 - 1
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameOceanengineOrderLogService.java

@@ -2,17 +2,21 @@ package com.zanxiang.game.back.serve.service;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.github.sd4324530.jtuple.Tuple2;
 import com.zanxiang.game.back.serve.pojo.dto.GameOceanengineOrderLogDTO;
 import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineOrderLog;
+import com.zanxiang.game.back.serve.pojo.enums.BackStatusEnum;
 import com.zanxiang.game.back.serve.pojo.vo.GameOceanengineOrderLogVO;
 
 import java.util.List;
 
 public interface IGameOceanengineOrderLogService extends IService<GameOceanengineOrderLog> {
 
-    boolean callback(GameOceanengineOrderLog orderLog, boolean mustBack, Long backMoneyOfInput);
+    boolean callback(GameOceanengineOrderLog orderLog);
 
     IPage<GameOceanengineOrderLogVO> oceanengineOrderLogList(GameOceanengineOrderLogDTO dto);
 
     boolean oceanengineOrderReport(List<Long> ids, Long backMoney);
+
+    Tuple2<BackStatusEnum, String> doCallback(GameOceanengineOrderLog orderLog, Long backMoney);
 }

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

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

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

@@ -1,6 +1,7 @@
 package com.zanxiang.game.back.serve.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.github.sd4324530.jtuple.Tuple2;
 import com.zanxiang.game.back.serve.pojo.entity.GameTencentMiniGameBackLog;
 import com.zanxiang.game.back.serve.pojo.entity.GameTencentMiniGameOrder;
 import com.zanxiang.game.back.serve.pojo.entity.GameTencentMiniGameRoleRegister;
@@ -9,9 +10,9 @@ import com.zanxiang.game.back.serve.pojo.enums.BackStatusEnum;
 
 public interface IGameTencentMiniGameBackLogService extends IService<GameTencentMiniGameBackLog> {
 
-    BackStatusEnum userBack(GameTencentMiniGameUser userLog);
+    Tuple2<BackStatusEnum, String> userBack(GameTencentMiniGameUser userLog);
 
-    BackStatusEnum orderBack(GameTencentMiniGameOrder orderLog);
+    Tuple2<BackStatusEnum, String> orderBack(GameTencentMiniGameOrder orderLog, Long backMoney);
 
     BackStatusEnum roleRegisterBack(GameTencentMiniGameRoleRegister roleRegisterLog);
 }

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

@@ -10,7 +10,7 @@ import java.util.List;
 
 public interface IGameTencentMiniGameOrderService extends IService<GameTencentMiniGameOrder> {
 
-    boolean orderBack(GameTencentMiniGameOrder orderLog, boolean mustBack, Long backMoneyOfInput);
+    boolean orderBack(GameTencentMiniGameOrder orderLog);
 
     IPage<GameTencentMiniGameOrderVO> listOfPage(GameTencentMiniGameOrderDTO dto);
 

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

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

+ 5 - 1
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentOrderService.java

@@ -1,10 +1,12 @@
 package com.zanxiang.game.back.serve.service;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.github.sd4324530.jtuple.Tuple2;
 import com.zanxiang.game.back.serve.pojo.dto.GameBackPolicyListDTO;
 import com.zanxiang.game.back.serve.pojo.dto.GameTencentOrderDTO;
 import com.zanxiang.game.back.serve.pojo.entity.GameTencentOrder;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.zanxiang.game.back.serve.pojo.enums.BackStatusEnum;
 import com.zanxiang.game.back.serve.pojo.vo.GameTencentOrderVO;
 
 import java.util.List;
@@ -19,9 +21,11 @@ import java.util.List;
  */
 public interface IGameTencentOrderService extends IService<GameTencentOrder> {
 
-    boolean orderBack(GameTencentOrder tencentOrder, boolean mustBack, Long backMoneyOfInput);
+    boolean orderBack(GameTencentOrder tencentOrder);
 
     IPage<GameTencentOrderVO> tencentOrderLogList(GameTencentOrderDTO dto);
 
     boolean tencentOrderReport(List<Long> ids, Long backMoney);
+
+    Tuple2<BackStatusEnum, String> doCallback(GameTencentOrder orderLog, Long backMoney);
 }

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

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

+ 6 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameBackPolicyServiceImpl.java

@@ -17,6 +17,7 @@ import com.zanxiang.game.back.serve.service.IGameBackPolicyService;
 import com.zanxiang.game.back.serve.service.IGameTencentBackLogService;
 import com.zanxiang.game.back.serve.service.IGameTencentOrderService;
 import com.zanxiang.game.back.serve.service.IGameTencentUserService;
+import com.zanxiang.module.util.JsonUtil;
 import com.zanxiang.module.util.NumberUtil;
 import com.zanxiang.module.util.bean.BeanUtil;
 import com.zanxiang.module.util.exception.BaseException;
@@ -121,6 +122,7 @@ public class GameBackPolicyServiceImpl extends ServiceImpl<GameBackPolicyMapper,
                 .markUpBackCountOfUser(dto.getMarkUpBackCountOfUser())
                 .largeAmount(dto.getLargeAmount() == null ? null : NumberUtil.multiply100(dto.getLargeAmount()).longValue())
                 .supperSmallAmount(dto.getSupperSmallAmount() == null ? null : NumberUtil.multiply100(dto.getSupperSmallAmount()).longValue())
+                .splitStrategy(CollectionUtils.isEmpty(dto.getSplitStrategy()) ? null : JsonUtil.toString(dto.getSplitStrategy()))
                 .build();
         return gameBackPolicyService.save(backPolicy);
     }
@@ -173,6 +175,7 @@ public class GameBackPolicyServiceImpl extends ServiceImpl<GameBackPolicyMapper,
                 .markUpBackCountOfUser(dto.getMarkUpBackCountOfUser())
                 .largeAmount(dto.getLargeAmount() == null ? null : NumberUtil.multiply100(dto.getLargeAmount()).longValue())
                 .supperSmallAmount(dto.getSupperSmallAmount() == null ? null : NumberUtil.multiply100(dto.getSupperSmallAmount()).longValue())
+                .splitStrategy(CollectionUtils.isEmpty(dto.getSplitStrategy()) ? null : JsonUtil.toString(dto.getSplitStrategy()))
                 .build();
 
         return gameBackPolicyService.updateById(backPolicy);
@@ -226,6 +229,9 @@ public class GameBackPolicyServiceImpl extends ServiceImpl<GameBackPolicyMapper,
                     .collect(Collectors.toList())
             );
         }
+        if (StringUtils.isNotBlank(gameBackPolicy.getSplitStrategy())) {
+            vo.setSplitStrategy((List<GameBackPolicyVO.SplitStrategy>) JsonUtil.toList(gameBackPolicy.getSplitStrategy(), List.class, GameBackPolicyVO.SplitStrategy.class));
+        }
         return vo;
     }
 

+ 119 - 73
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameOceanengineOrderLogServiceImpl.java

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.github.sd4324530.jtuple.Tuple2;
 import com.github.sd4324530.jtuple.Tuple3;
 import com.github.sd4324530.jtuple.Tuples;
 import com.zanxiang.game.back.base.pojo.enums.OrderStatusEnum;
@@ -21,6 +22,7 @@ import com.zanxiang.game.back.serve.pojo.vo.GameOceanengineOrderLogVO;
 import com.zanxiang.game.back.serve.service.IGameBackPolicyService;
 import com.zanxiang.game.back.serve.service.IGameOceanengineBackLogService;
 import com.zanxiang.game.back.serve.service.IGameOceanengineOrderLogService;
+import com.zanxiang.game.back.serve.service.IGameOceanengineOrderSplitLogService;
 import com.zanxiang.game.back.serve.service.IGameOceanengineUserLogService;
 import com.zanxiang.game.back.serve.utils.BackPolicyUtil;
 import com.zanxiang.game.back.serve.utils.OrderUtil;
@@ -64,50 +66,83 @@ public class GameOceanengineOrderLogServiceImpl extends ServiceImpl<GameOceaneng
     private IAgentRpc agentRpc;
     @Autowired
     private NacosDynamicParamConfig dynamicParamConfig;
+    @Autowired
+    private IGameOceanengineOrderSplitLogService gameOceanengineOrderSplitLogService;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public boolean callback(GameOceanengineOrderLog orderLog, boolean mustBack, Long backMoneyOfInput) {
-        boolean doBack;
-        Long backMoney;
-        String backMsg;
-        if (mustBack) {
-            doBack = true;
-            backMoney = backMoneyOfInput;
-            backMsg = "手动触发的回传";
-        } else {
-            if (!Objects.equals(orderLog.getOrderStatus(), OrderStatusEnum.SUCCESS_PAY.getValue())) {
-                // 头条只要回传支付订单
-                return true;
-            }
-            // 用户回传失败
-            GameOceanengineUserLog userLog = userLog(orderLog);
-            if (userLog == null) {
-                doBack = false;
-                backMoney = orderLog.getAmount();
-                backMsg = "回传失败!找不到回传用户";
-            } else {
-                GameBackPolicy gameBackPolicy = gameBackPolicyService.getById(orderLog.getBackPolicyId());
-                Tuple3<Boolean, Long, String> backInfo = BackPolicyUtil.backOrder(orderLog.getOrderNo(), gameBackPolicy, orderLog.getAmount(),
-                        orderLog.getIsFirstOrder(),
-                        orderLog.getPayTime(),
-                        // 此处使用用户最近一次的重新染色时间
-                        userLog.getCreateTime(),
-                        orderLog.getOpenId(),
-                        new OceanengineOrderBackPolicyCheck(this, userLog, orderLog, gameBackPolicy)
+    public boolean callback(GameOceanengineOrderLog orderLog) {
+        if (!Objects.equals(orderLog.getOrderStatus(), OrderStatusEnum.SUCCESS_PAY.getValue())) {
+            // 头条只要回传支付订单
+            return true;
+        }
+        GameOceanengineUserLog userLog = userLog(orderLog);
+        if (userLog == null) {
+            // 找不到用户
+            return update(new LambdaUpdateWrapper<GameOceanengineOrderLog>()
+                    .set(GameOceanengineOrderLog::getBackStatus, BackStatusEnum.NO)
+                    .set(GameOceanengineOrderLog::getBackMoney, orderLog.getAmount())
+                    .set(GameOceanengineOrderLog::getBackMsg, "回传失败!找不到回传用户")
+                    .eq(GameOceanengineOrderLog::getId, orderLog.getId())
+            );
+        }
+
+        GameBackPolicy gameBackPolicy = gameBackPolicyService.getById(orderLog.getBackPolicyId());
+        Tuple3<Boolean, Long, String> backInfo = BackPolicyUtil.backOrder(orderLog.getOrderNo(), gameBackPolicy, orderLog.getAmount(),
+                orderLog.getIsFirstOrder(),
+                orderLog.getPayTime(),
+                // 此处使用用户最近一次的重新染色时间
+                userLog.getCreateTime(),
+                orderLog.getOpenId(),
+                new OceanengineOrderBackPolicyCheck(this, userLog, orderLog, gameBackPolicy)
+        );
+        boolean doBack = backInfo.first;
+        Long backMoney = backInfo.second;
+        String backMsg = backInfo.third;
+
+        if (!doBack) {
+            // 不回传
+            return update(new LambdaUpdateWrapper<GameOceanengineOrderLog>()
+                    .set(GameOceanengineOrderLog::getBackStatus, BackStatusEnum.NO.getBackStatus())
+                    .set(GameOceanengineOrderLog::getBackMoney, backMoney)
+                    .set(GameOceanengineOrderLog::getBackMsg, backMsg)
+                    .eq(GameOceanengineOrderLog::getId, orderLog.getId())
+            );
+        }
+        // 拆单
+        Tuple3<Boolean, Long, List<Tuple2<Long, LocalDateTime>>> splitResult = BackPolicyUtil.splitOrder(gameBackPolicy, backMoney);
+        if (splitResult.first) {
+            // 需要拆单
+            List<GameOceanengineOrderSplitLog> splitOrderLogList = new ArrayList<>(splitResult.third.size());
+            for (int i = 0; i < splitResult.third.size(); i++) {
+                Tuple2<Long, LocalDateTime> splitOrder = splitResult.third.get(i);
+                splitOrderLogList.add(GameOceanengineOrderSplitLog.builder()
+                        .backDay(splitOrder.second.toLocalDate())
+                        .orderNo(orderLog.getOrderNo())
+                        .backIndex(i + 1)
+                        .backCount(splitResult.third.size())
+                        .splitMoney(splitOrder.first)
+                        .backTime(splitOrder.second)
+                        .backStatus(BackStatusEnum.NO.getBackStatus())
+                        .createTime(LocalDateTime.now())
+                        .build()
                 );
-                doBack = backInfo.first;
-                backMoney = backInfo.second;
-                backMsg = backInfo.third;
             }
+            gameOceanengineOrderSplitLogService.saveBatch(splitOrderLogList);
+            return update(new LambdaUpdateWrapper<GameOceanengineOrderLog>()
+                    .set(GameOceanengineOrderLog::getBackStatus, BackStatusEnum.NO.getBackStatus())
+                    .set(GameOceanengineOrderLog::getBackMoney, splitResult.second)
+                    .set(GameOceanengineOrderLog::getBackMsg, backMsg)
+                    .eq(GameOceanengineOrderLog::getId, orderLog.getId())
+            );
         }
-        BackStatusEnum backStatus = BackStatusEnum.NO;
-        orderLog.setBackMoney(backMoney);
-        if (doBack) {
-            backStatus = doCallback(orderLog);
+
+        Tuple2<BackStatusEnum, String> backResult = doCallback(orderLog, backMoney);
+        if (StringUtils.isNotBlank(backResult.second)) {
+            backMsg = backMsg + ("回传失败:" + backResult.second);
         }
         return update(new LambdaUpdateWrapper<GameOceanengineOrderLog>()
-                .set(GameOceanengineOrderLog::getBackStatus, backStatus.getBackStatus())
+                .set(GameOceanengineOrderLog::getBackStatus, backResult.first.getBackStatus())
                 .set(GameOceanengineOrderLog::getBackMoney, backMoney)
                 .set(GameOceanengineOrderLog::getBackMsg, backMsg)
                 .eq(GameOceanengineOrderLog::getId, orderLog.getId())
@@ -141,47 +176,31 @@ public class GameOceanengineOrderLogServiceImpl extends ServiceImpl<GameOceaneng
         return result;
     }
 
-    private List<GameOceanengineOrderLogVO> toVOBatch(List<GameOceanengineOrderLog> logList) {
-        if (CollectionUtils.isEmpty(logList)) {
-            return Collections.emptyList();
-        }
-        Set<String> agentKeys = logList.stream().map(GameOceanengineOrderLog::getAgentKey).filter(StringUtils::isNotBlank).collect(Collectors.toSet());
-        Map<String, AgentRpcVO> agentMap = CollectionUtils.isEmpty(agentKeys) ? Collections.emptyMap() : agentRpc.getByAgentKeys(new ArrayList<>(agentKeys))
-                .getData().stream().collect(Collectors.toMap(AgentRpcVO::getAgentKey, Function.identity()));
-        return logList.stream().map(log -> {
-            GameOceanengineOrderLogVO vo = toVOSimple(log);
-            if (StringUtils.isNotBlank(log.getAgentKey())) {
-                AgentRpcVO agent = agentMap.get(log.getAgentKey());
-                if (agent != null) {
-                    vo.setAgentName(agent.getAgentName());
-                }
-            }
-            return vo;
-        }).collect(Collectors.toList());
-
-    }
-
-    private GameOceanengineOrderLogVO toVOSimple(GameOceanengineOrderLog log) {
-        if (log == null) {
-            return null;
-        }
-        GameOceanengineOrderLogVO vo = BeanUtil.copy(log, GameOceanengineOrderLogVO.class);
-        vo.setRegPayIntervalTime(OrderUtil.regPayIntervalTime(log.getPayTime(), log.getRegTime()));
-        return vo;
-    }
-
     @Override
     public boolean oceanengineOrderReport(List<Long> ids, Long backMoney) {
         listByIds(ids).stream()
                 .filter(order -> !Objects.equals(order.getBackStatus(), BackStatusEnum.SUCCESS.getBackStatus()))
                 .forEach(orderLog -> {
                     log.error("手动回传:{}-{}", orderLog.getId(), backMoney);
-                    callback(orderLog, true, backMoney);
+                    orderLog.setBackMoney(backMoney);
+                    Tuple2<BackStatusEnum, String> backResult = doCallback(orderLog, backMoney);
+                    String backMsg = "手动触发回传";
+                    if (StringUtils.isNotBlank(backResult.second)) {
+                        backMsg += ("回传失败:" + backResult.second);
+                    }
+                    update(new LambdaUpdateWrapper<GameOceanengineOrderLog>()
+                            .set(GameOceanengineOrderLog::getBackStatus, backResult.first.getBackStatus())
+                            .set(GameOceanengineOrderLog::getBackMoney, backMoney)
+                            .set(GameOceanengineOrderLog::getBackMsg, backMsg)
+                            .eq(GameOceanengineOrderLog::getId, orderLog.getId())
+                    );
                 });
         return true;
     }
 
-    private BackStatusEnum doCallback(GameOceanengineOrderLog orderLog) {
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Tuple2<BackStatusEnum, String> doCallback(GameOceanengineOrderLog orderLog, Long backMoney) {
         GameOceanengineUserLog userLog = userLog(orderLog);
         if (userLog == null) {
             gameOceanengineBackLogService.save(GameOceanengineBackLog.builder()
@@ -197,18 +216,16 @@ public class GameOceanengineOrderLogServiceImpl extends ServiceImpl<GameOceaneng
                     .backStatus(BackStatusEnum.FAILED.getBackStatus())
                     .errMsg("找不到用户注册信息")
                     .build());
-            return BackStatusEnum.FAILED;
+            return Tuple2.with(BackStatusEnum.FAILED, "找不到用户注册信息");
         }
-        Set<Long> keyAccountIds = StringUtils.isBlank(dynamicParamConfig.getBackOfKeyAccountIds()) ? Collections.emptySet() :
-                Arrays.stream(dynamicParamConfig.getBackOfKeyAccountIds().split(",")).map(Long::parseLong).collect(Collectors.toSet());
-        Integer eventType = keyAccountIds.contains(orderLog.getAccountId()) ? MiniGameCallback.EventType.GAME_ADDICTION.getEventType() : MiniGameCallback.EventType.ACTIVE_PAY.getEventType();
+        Integer eventType = MiniGameCallback.EventType.ACTIVE_PAY.getEventType();
         MiniGameCallback.MiniGameCallbackRequest request = MiniGameCallback.MiniGameCallbackRequest.builder()
                 .clue_token(userLog.getClueToken())
                 .open_id(orderLog.getOpenId())
                 .union_id(orderLog.getUnionId())
                 .event_type(String.valueOf(eventType))
                 .props(MiniGameCallback.MiniGameCallbackRequest.MiniGameCallbackRequestProps.builder()
-                        .pay_amount(orderLog.getBackMoney())
+                        .pay_amount(backMoney)
                         .build())
                 .build();
         BackStatusEnum backStatus = BackStatusEnum.SUCCESS;
@@ -237,7 +254,36 @@ public class GameOceanengineOrderLogServiceImpl extends ServiceImpl<GameOceaneng
                 .backStatus(backStatus.getBackStatus())
                 .errMsg(errMsg)
                 .build());
-        return backStatus;
+        return Tuple2.with(backStatus, errMsg);
+    }
+
+    private List<GameOceanengineOrderLogVO> toVOBatch(List<GameOceanengineOrderLog> logList) {
+        if (CollectionUtils.isEmpty(logList)) {
+            return Collections.emptyList();
+        }
+        Set<String> agentKeys = logList.stream().map(GameOceanengineOrderLog::getAgentKey).filter(StringUtils::isNotBlank).collect(Collectors.toSet());
+        Map<String, AgentRpcVO> agentMap = CollectionUtils.isEmpty(agentKeys) ? Collections.emptyMap() : agentRpc.getByAgentKeys(new ArrayList<>(agentKeys))
+                .getData().stream().collect(Collectors.toMap(AgentRpcVO::getAgentKey, Function.identity()));
+        return logList.stream().map(log -> {
+            GameOceanengineOrderLogVO vo = toVOSimple(log);
+            if (StringUtils.isNotBlank(log.getAgentKey())) {
+                AgentRpcVO agent = agentMap.get(log.getAgentKey());
+                if (agent != null) {
+                    vo.setAgentName(agent.getAgentName());
+                }
+            }
+            return vo;
+        }).collect(Collectors.toList());
+
+    }
+
+    private GameOceanengineOrderLogVO toVOSimple(GameOceanengineOrderLog log) {
+        if (log == null) {
+            return null;
+        }
+        GameOceanengineOrderLogVO vo = BeanUtil.copy(log, GameOceanengineOrderLogVO.class);
+        vo.setRegPayIntervalTime(OrderUtil.regPayIntervalTime(log.getPayTime(), log.getRegTime()));
+        return vo;
     }
 
     private GameOceanengineUserLog userLog(GameOceanengineOrderLog orderLog) {

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

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

+ 16 - 14
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentMiniGameBackLogServiceImpl.java

@@ -1,6 +1,7 @@
 package com.zanxiang.game.back.serve.service.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.github.sd4324530.jtuple.Tuple2;
 import com.zanxiang.advertising.tencent.base.pojo.dto.UserActionRpcDTO;
 import com.zanxiang.game.back.base.pojo.enums.OrderStatusEnum;
 import com.zanxiang.game.back.serve.dao.mapper.GameTencentMiniGameBackLogMapper;
@@ -40,7 +41,7 @@ public class GameTencentMiniGameBackLogServiceImpl extends ServiceImpl<GameTence
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public BackStatusEnum userBack(GameTencentMiniGameUser userLog) {
+    public Tuple2<BackStatusEnum, String> userBack(GameTencentMiniGameUser userLog) {
         GameTencentMiniGameBackLog backLog = GameTencentMiniGameBackLog.builder()
                 .gameId(userLog.getGameId())
                 .adAccountId(userLog.getAdAccountId())
@@ -51,14 +52,16 @@ public class GameTencentMiniGameBackLogServiceImpl extends ServiceImpl<GameTence
                 .actionType(ActionTypeEnum.REGISTER.getActionType())
                 .createTime(LocalDateTime.now())
                 .build();
-        callback(backLog);
+        Tuple2<BackStatusEnum, String> backResult = callback(backLog);
+        backLog.setBackStatus(backResult.first.getBackStatus());
+        backLog.setErrMsg(backResult.second);
         save(backLog);
-        return BackStatusEnum.getByValue(backLog.getBackStatus());
+        return backResult;
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public BackStatusEnum orderBack(GameTencentMiniGameOrder orderLog) {
+    public Tuple2<BackStatusEnum, String> orderBack(GameTencentMiniGameOrder orderLog, Long backMoney) {
         String actionType = orderLog.getOrderStatus().equals(OrderStatusEnum.SUCCESS_PAY.getValue()) ?
                 ActionTypeEnum.PURCHASE.getActionType() : ActionTypeEnum.COMPLETE_ORDER.getActionType();
         GameTencentMiniGameBackLog backLog = GameTencentMiniGameBackLog.builder()
@@ -69,13 +72,15 @@ public class GameTencentMiniGameBackLogServiceImpl extends ServiceImpl<GameTence
                 .wechatOpenid(orderLog.getWechatOpenid())
                 .wechatAppId(orderLog.getWechatAppId())
                 .actionType(actionType)
-                .amount(orderLog.getBackMoney())
+                .amount(backMoney)
                 .orderId(orderLog.getOrderId())
                 .createTime(LocalDateTime.now())
                 .build();
-        callback(backLog);
+        Tuple2<BackStatusEnum, String> backResult = callback(backLog);
+        backLog.setBackStatus(backResult.first.getBackStatus());
+        backLog.setErrMsg(backResult.second);
         save(backLog);
-        return BackStatusEnum.getByValue(backLog.getBackStatus());
+        return backResult;
     }
 
     @Override
@@ -96,7 +101,7 @@ public class GameTencentMiniGameBackLogServiceImpl extends ServiceImpl<GameTence
         return BackStatusEnum.getByValue(backLog.getBackStatus());
     }
 
-    private void callback(GameTencentMiniGameBackLog backLog) {
+    private Tuple2<BackStatusEnum, String> callback(GameTencentMiniGameBackLog backLog) {
         Map<String, Object> actionParam = null;
         if (backLog.getAmount() != null) {
             actionParam = new HashMap<>(2);
@@ -119,16 +124,13 @@ public class GameTencentMiniGameBackLogServiceImpl extends ServiceImpl<GameTence
             log.error("腾讯小游戏回传完成:{}", JsonUtil.toString(response.getBody()));
             if (response.getStatusCode().is2xxSuccessful()) {
                 if (Objects.equals(response.getBody().get("code").toString(), "0")) {
-                    backLog.setBackStatus(BackStatusEnum.SUCCESS.getBackStatus());
-                    return;
+                    return Tuple2.with(BackStatusEnum.SUCCESS, null);
                 }
             }
-            backLog.setBackStatus(BackStatusEnum.FAILED.getBackStatus());
-            backLog.setErrMsg(JsonUtil.toString(response.getBody()));
+            return Tuple2.with(BackStatusEnum.FAILED, JsonUtil.toString(response.getBody()));
         } catch (Exception e) {
             log.error(e.getMessage(), e);
-            backLog.setBackStatus(BackStatusEnum.FAILED.getBackStatus());
-            backLog.setErrMsg(e.getMessage());
+            return Tuple2.with(BackStatusEnum.FAILED, e.getMessage());
         }
     }
 

+ 88 - 43
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentMiniGameOrderServiceImpl.java

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.github.sd4324530.jtuple.Tuple2;
 import com.github.sd4324530.jtuple.Tuple3;
 import com.zanxiang.advertising.tencent.base.AdvertisingTencentServer;
 import com.zanxiang.advertising.tencent.base.rpc.IUserActionSetRpc;
@@ -16,13 +17,16 @@ 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.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.enums.BackStatusEnum;
 import com.zanxiang.game.back.serve.pojo.enums.BackUnitEnum;
 import com.zanxiang.game.back.serve.pojo.vo.GameTencentMiniGameOrderVO;
 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.utils.BackPolicyUtil;
 import com.zanxiang.game.back.serve.utils.OrderUtil;
@@ -66,60 +70,91 @@ public class GameTencentMiniGameOrderServiceImpl extends ServiceImpl<GameTencent
     private IGameBackPolicyService gameBackPolicyService;
     @DubboReference(providedBy = ServerInfo.SERVER_DUBBO_NAME)
     private IAgentRpc agentRpc;
+    @Autowired
+    private IGameTencentMiniGameOrderSplitLogService gameTencentMiniGameOrderSplitLogService;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public boolean orderBack(GameTencentMiniGameOrder orderLog, boolean mustBack, Long backMoneyOfInput) {
+    public boolean orderBack(GameTencentMiniGameOrder orderLog) {
         if (StringUtils.isBlank(orderLog.getClickId())) {
             // 没有点击 id(之后做监测链接,从监测链接里面找)
             return false;
         }
-        boolean doBack;
-        Long backMoney;
-        String backMsg;
-        if (mustBack) {
-            doBack = true;
-            backMoney = backMoneyOfInput;
-            backMsg = "手动触发的回传";
-        } else {
-            if (!Objects.equals(orderLog.getOrderStatus(), OrderStatusEnum.SUCCESS_PAY.getValue())) {
-                // 只要回传 支付行为
-                return true;
-            }
-            GameTencentMiniGameUser userLog = 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())
-                    .orderByDesc(GameTencentMiniGameUser::getCreateTime)
-                    .last("limit 1")
+        if (!Objects.equals(orderLog.getOrderStatus(), OrderStatusEnum.SUCCESS_PAY.getValue())) {
+            // 只要回传 支付行为
+            return true;
+        }
+        GameTencentMiniGameUser userLog = 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())
+                .orderByDesc(GameTencentMiniGameUser::getCreateTime)
+                .last("limit 1")
+        );
+        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())
             );
-            if (userLog == null) {
-                doBack = false;
-                backMoney = orderLog.getRechargeMoney();
-                backMsg = "回传失败!找不到回传用户";
-            } else {
-                GameBackPolicy gameBackPolicy = gameBackPolicyService.getById(orderLog.getBackPolicyId());
-                // 此处是否是首单用 limit 2。因为在执行判断之前订单已入库,所以库里只有一笔才是首单
-                Tuple3<Boolean, Long, String> backInfo = BackPolicyUtil.backOrder(orderLog.getOrderId(), gameBackPolicy, orderLog.getRechargeMoney(),
-                        orderLog.getIsFirstOrder(),
-                        orderLog.getPayTime(),
-                        // 此处使用用户最近一次的重新染色时间
-                        userLog.getCreateTime(),
-                        orderLog.getWechatOpenid(),
-                        new TencentMiniGameOrderBackPolicyCheck(this, gameBackPolicy, userLog, orderLog));
-                doBack = backInfo.first;
-                backMoney = backInfo.second;
-                backMsg = backInfo.third;
+        }
+
+        GameBackPolicy gameBackPolicy = gameBackPolicyService.getById(orderLog.getBackPolicyId());
+        // 此处是否是首单用 limit 2。因为在执行判断之前订单已入库,所以库里只有一笔才是首单
+        Tuple3<Boolean, Long, String> 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())
+            );
+        }
+        // 拆单
+        Tuple3<Boolean, Long, List<Tuple2<Long, LocalDateTime>>> splitResult = BackPolicyUtil.splitOrder(gameBackPolicy, backMoney);
+        if (splitResult.first) {
+            // 需要拆单
+            List<GameTencentMiniGameOrderSplitLog> splitOrderLogList = new ArrayList<>(splitResult.third.size());
+            for (int i = 0; i < splitResult.third.size(); i++) {
+                Tuple2<Long, LocalDateTime> splitOrder = splitResult.third.get(i);
+                splitOrderLogList.add(GameTencentMiniGameOrderSplitLog.builder()
+                        .backDay(splitOrder.second.toLocalDate())
+                        .orderNo(orderLog.getOrderId())
+                        .backIndex(i + 1)
+                        .backCount(splitResult.third.size())
+                        .splitMoney(splitOrder.first)
+                        .backTime(splitOrder.second)
+                        .backStatus(BackStatusEnum.NO.getBackStatus())
+                        .createTime(LocalDateTime.now())
+                        .build());
             }
+            gameTencentMiniGameOrderSplitLogService.saveBatch(splitOrderLogList);
+            return update(new LambdaUpdateWrapper<GameTencentMiniGameOrder>()
+                    .set(GameTencentMiniGameOrder::getBackStatus, BackStatusEnum.NO.getBackStatus())
+                    .set(GameTencentMiniGameOrder::getBackMoney, splitResult.second)
+                    .set(GameTencentMiniGameOrder::getBackMsg, backMsg)
+                    .eq(GameTencentMiniGameOrder::getId, orderLog.getId())
+            );
         }
-        BackStatusEnum backStatus = BackStatusEnum.NO;
-        orderLog.setBackMoney(backMoney);
-        if (doBack) {
-            backStatus = gameTencentMiniGameBackLogService.orderBack(orderLog);
+
+        Tuple2<BackStatusEnum, String> backResult = gameTencentMiniGameBackLogService.orderBack(orderLog, backMoney);
+        if (StringUtils.isNotBlank(backResult.second)) {
+            backMsg = backMsg + ("回传失败:" + backResult.second);
         }
         return update(new LambdaUpdateWrapper<GameTencentMiniGameOrder>()
-                .set(GameTencentMiniGameOrder::getBackStatus, backStatus.getBackStatus())
+                .set(GameTencentMiniGameOrder::getBackStatus, backResult.first.getBackStatus())
                 .set(GameTencentMiniGameOrder::getBackMoney, backMoney)
                 .set(GameTencentMiniGameOrder::getBackMsg, backMsg)
                 .eq(GameTencentMiniGameOrder::getId, orderLog.getId())
@@ -159,7 +194,17 @@ public class GameTencentMiniGameOrderServiceImpl extends ServiceImpl<GameTencent
                 .filter(order -> !Objects.equals(order.getBackStatus(), BackStatusEnum.SUCCESS.getBackStatus()))
                 .forEach(orderLog -> {
                     log.error("手动回传:{}-{}", orderLog.getId(), backMoney);
-                    orderBack(orderLog, true, backMoney);
+                    Tuple2<BackStatusEnum, String> backResult = gameTencentMiniGameBackLogService.orderBack(orderLog, backMoney);
+                    String backMsg = "手动触发回传!";
+                    if (StringUtils.isNotBlank(backResult.second)) {
+                        backMsg += ("回传失败:" + backResult.second);
+                    }
+                    update(new LambdaUpdateWrapper<GameTencentMiniGameOrder>()
+                            .set(GameTencentMiniGameOrder::getBackStatus, backResult.first.getBackStatus())
+                            .set(GameTencentMiniGameOrder::getBackMoney, backMoney)
+                            .set(GameTencentMiniGameOrder::getBackMsg, backMsg)
+                            .eq(GameTencentMiniGameOrder::getId, orderLog.getId())
+                    );
                 });
         return true;
     }

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

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

+ 94 - 46
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentOrderServiceImpl.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.github.sd4324530.jtuple.Tuple2;
 import com.github.sd4324530.jtuple.Tuple3;
 import com.zanxiang.advertising.tencent.base.AdvertisingTencentServer;
 import com.zanxiang.advertising.tencent.base.pojo.dto.DataReportOfAppIdRpcDTO;
@@ -19,6 +20,7 @@ import com.zanxiang.game.back.serve.pojo.entity.GameTencentBackLog;
 import com.zanxiang.game.back.serve.pojo.entity.GameTencentMiniGameOrder;
 import com.zanxiang.game.back.serve.pojo.entity.GameTencentOrder;
 import com.zanxiang.game.back.serve.dao.mapper.GameTencentOrderMapper;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentOrderSplitLog;
 import com.zanxiang.game.back.serve.pojo.entity.GameTencentUser;
 import com.zanxiang.game.back.serve.pojo.enums.ActionTypeEnum;
 import com.zanxiang.game.back.serve.pojo.enums.BackStatusEnum;
@@ -28,6 +30,7 @@ import com.zanxiang.game.back.serve.service.IGameBackPolicyService;
 import com.zanxiang.game.back.serve.service.IGameTencentBackLogService;
 import com.zanxiang.game.back.serve.service.IGameTencentOrderService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.game.back.serve.service.IGameTencentOrderSplitLogService;
 import com.zanxiang.game.back.serve.service.IGameTencentUserService;
 import com.zanxiang.game.back.serve.utils.BackPolicyUtil;
 import com.zanxiang.game.back.serve.utils.OrderUtil;
@@ -66,7 +69,8 @@ import java.util.stream.Collectors;
  */
 @Slf4j
 @Service
-public class GameTencentOrderServiceImpl extends ServiceImpl<GameTencentOrderMapper, GameTencentOrder> implements IGameTencentOrderService {
+public class GameTencentOrderServiceImpl extends ServiceImpl<GameTencentOrderMapper, GameTencentOrder>
+        implements IGameTencentOrderService {
     @DubboReference(providedBy = AdvertisingTencentServer.SERVER_DUBBO_NAME)
     private IUserActionSetRpc userActionSetRpc;
     @DubboReference(providedBy = ErpServer.SERVER_DUBBO_NAME)
@@ -79,54 +83,85 @@ public class GameTencentOrderServiceImpl extends ServiceImpl<GameTencentOrderMap
     private IAgentRpc agentRpc;
     @Autowired
     private IGameTencentUserService gameTencentUserService;
+    @Autowired
+    private IGameTencentOrderSplitLogService gameTencentOrderSplitLogService;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public boolean orderBack(GameTencentOrder orderLog, boolean mustBack, Long backMoneyOfInput) {
-        boolean doBack;
-        Long backMoney;
-        String backMsg;
-        if (mustBack) {
-            doBack = true;
-            backMoney = backMoneyOfInput;
-            backMsg = "手动触发的回传";
-        } else {
-            if (!Objects.equals(orderLog.getOrderStatus(), OrderStatusEnum.SUCCESS_PAY.getValue())) {
-                // 只要回传 支付行为
-                return false;
-            }
-            GameTencentUser userLog = gameTencentUserService.getOne(new LambdaQueryWrapper<GameTencentUser>()
-                    .eq(GameTencentUser::getGameId, orderLog.getGameId())
-                    .eq(GameTencentUser::getWechatAppId, orderLog.getWechatAppId())
-                    .eq(GameTencentUser::getWechatOpenid, orderLog.getWechatOpenid())
-                    .eq(GameTencentUser::getAdAccountId, orderLog.getAdAccountId())
-                    .orderByDesc(GameTencentUser::getCreateTime)
-                    .last("limit 1")
-            );if (userLog == null) {
-                doBack = false;
-                backMoney = orderLog.getRechargeMoney();
-                backMsg = "回传失败!找不到回传用户";
-            } else {
-                GameBackPolicy gameBackPolicy = gameBackPolicyService.getById(orderLog.getBackPolicyId());
-                Tuple3<Boolean, Long, String> backInfo = BackPolicyUtil.backOrder(orderLog.getOrderId(), gameBackPolicy, orderLog.getRechargeMoney(),
-                        orderLog.getIsFirstOrder(),
-                        orderLog.getPayTime(),
-                        // 此处使用用户最近一次的重新染色时间
-                        userLog.getCreateTime(),
-                        orderLog.getWechatOpenid(),
-                        new TencentOrderBackPolicyCheck(this, gameBackPolicy, userLog, orderLog));
-                doBack = backInfo.first;
-                backMoney = backInfo.second;
-                backMsg = backInfo.third;
+    public boolean orderBack(GameTencentOrder orderLog) {
+        if (!Objects.equals(orderLog.getOrderStatus(), OrderStatusEnum.SUCCESS_PAY.getValue())) {
+            // 只要回传 支付行为
+            return false;
+        }
+        GameTencentUser userLog = gameTencentUserService.getOne(new LambdaQueryWrapper<GameTencentUser>()
+                .eq(GameTencentUser::getGameId, orderLog.getGameId())
+                .eq(GameTencentUser::getWechatAppId, orderLog.getWechatAppId())
+                .eq(GameTencentUser::getWechatOpenid, orderLog.getWechatOpenid())
+                .eq(GameTencentUser::getAdAccountId, orderLog.getAdAccountId())
+                .orderByDesc(GameTencentUser::getCreateTime)
+                .last("limit 1")
+        );
+        if (userLog == null) {
+            return update(new LambdaUpdateWrapper<GameTencentOrder>()
+                    .set(GameTencentOrder::getIsBack, BackStatusEnum.FAILED.getBackStatus())
+                    .set(GameTencentOrder::getBackMoney, orderLog.getRechargeMoney())
+                    .set(GameTencentOrder::getBackMsg, "回传失败!找不到回传用户")
+                    .eq(GameTencentOrder::getId, orderLog.getId())
+            );
+        }
+
+        GameBackPolicy gameBackPolicy = gameBackPolicyService.getById(orderLog.getBackPolicyId());
+        Tuple3<Boolean, Long, String> backInfo = BackPolicyUtil.backOrder(orderLog.getOrderId(), gameBackPolicy, orderLog.getRechargeMoney(),
+                orderLog.getIsFirstOrder(),
+                orderLog.getPayTime(),
+                // 此处使用用户最近一次的重新染色时间
+                userLog.getCreateTime(),
+                orderLog.getWechatOpenid(),
+                new TencentOrderBackPolicyCheck(this, gameBackPolicy, userLog, orderLog));
+        boolean doBack = backInfo.first;
+        Long backMoney = backInfo.second;
+        String backMsg = backInfo.third;
+        if (!doBack) {
+            return update(new LambdaUpdateWrapper<GameTencentOrder>()
+                    .set(GameTencentOrder::getIsBack, BackStatusEnum.NO.getBackStatus())
+                    .set(GameTencentOrder::getBackMoney, backMoney)
+                    .set(GameTencentOrder::getBackMsg, backMsg)
+                    .eq(GameTencentOrder::getId, orderLog.getId())
+            );
+        }
+        // 拆单
+        Tuple3<Boolean, Long, List<Tuple2<Long, LocalDateTime>>> splitResult = BackPolicyUtil.splitOrder(gameBackPolicy, backMoney);
+        if (splitResult.first) {
+            // 需要拆单
+            List<GameTencentOrderSplitLog> splitOrderLogList = new ArrayList<>(splitResult.third.size());
+            for (int i = 0; i < splitResult.third.size(); i++) {
+                Tuple2<Long, LocalDateTime> splitOrder = splitResult.third.get(i);
+                splitOrderLogList.add(GameTencentOrderSplitLog.builder()
+                        .backDay(splitOrder.second.toLocalDate())
+                        .orderNo(orderLog.getOrderId())
+                        .backIndex(i + 1)
+                        .backCount(splitResult.third.size())
+                        .splitMoney(splitOrder.first)
+                        .backTime(splitOrder.second)
+                        .backStatus(BackStatusEnum.NO.getBackStatus())
+                        .createTime(LocalDateTime.now())
+                        .build());
             }
+            gameTencentOrderSplitLogService.saveBatch(splitOrderLogList);
+            return update(new LambdaUpdateWrapper<GameTencentOrder>()
+                    .set(GameTencentOrder::getIsBack, BackStatusEnum.NO.getBackStatus())
+                    .set(GameTencentOrder::getBackMoney, splitResult.second)
+                    .set(GameTencentOrder::getBackMsg, backMsg)
+                    .eq(GameTencentOrder::getId, orderLog.getId())
+            );
         }
-        BackStatusEnum backStatus = BackStatusEnum.NO;
-        orderLog.setBackMoney(backMoney);
-        if (doBack) {
-            backStatus = doCallback(orderLog);
+
+        Tuple2<BackStatusEnum, String> backResult = doCallback(orderLog, backMoney);
+        if (StringUtils.isNotBlank(backResult.second)) {
+            backMsg = backMsg + ("回传失败:" + backResult.second);
         }
         return update(new LambdaUpdateWrapper<GameTencentOrder>()
-                .set(GameTencentOrder::getIsBack, backStatus.getBackStatus())
+                .set(GameTencentOrder::getIsBack, backResult.first.getBackStatus())
                 .set(GameTencentOrder::getBackMoney, backMoney)
                 .set(GameTencentOrder::getBackMsg, backMsg)
                 .eq(GameTencentOrder::getId, orderLog.getId())
@@ -195,17 +230,30 @@ public class GameTencentOrderServiceImpl extends ServiceImpl<GameTencentOrderMap
                 .filter(order -> !Objects.equals(order.getIsBack(), BackStatusEnum.SUCCESS.getBackStatus()))
                 .forEach(orderLog -> {
                     log.error("手动回传:{}-{}", orderLog.getId(), backMoney);
-                    orderBack(orderLog, true, backMoney);
+
+                    Tuple2<BackStatusEnum, String> backResult = doCallback(orderLog, backMoney);
+                    String backMsg = "手动触发回传!";
+                    if (StringUtils.isNotBlank(backResult.second)) {
+                        backMsg += ("回传失败:" + backResult.second);
+                    }
+                    update(new LambdaUpdateWrapper<GameTencentOrder>()
+                            .set(GameTencentOrder::getIsBack, backResult.first.getBackStatus())
+                            .set(GameTencentOrder::getBackMoney, backMoney)
+                            .set(GameTencentOrder::getBackMsg, backMsg)
+                            .eq(GameTencentOrder::getId, orderLog.getId())
+                    );
                 });
         return true;
     }
 
-    private BackStatusEnum doCallback(GameTencentOrder orderLog) {
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Tuple2<BackStatusEnum, String> doCallback(GameTencentOrder orderLog, Long backMoney) {
         String actionType = orderLog.getOrderStatus().equals(OrderStatusEnum.SUCCESS_PAY.getValue()) ?
                 ActionTypeEnum.PURCHASE.getActionType() : ActionTypeEnum.COMPLETE_ORDER.getActionType();
         Map<String, Object> actionParam = new HashMap<>(2);
         actionParam.put("claim_type", 0);
-        actionParam.put("value", orderLog.getBackMoney());
+        actionParam.put("value", backMoney);
         DataReportOfAppIdRpcDTO dataReportOfAppIdRpcDTO = DataReportOfAppIdRpcDTO.builder()
                 .appId(orderLog.getWechatAppId())
                 .userActionSetId(orderLog.getUserActionSetId())
@@ -242,7 +290,7 @@ public class GameTencentOrderServiceImpl extends ServiceImpl<GameTencentOrderMap
             gameTencentBackLog.setBackLog(result.getMsg());
         }
         gameTencentBackLogService.save(gameTencentBackLog);
-        return backStatus;
+        return Tuple2.with(backStatus, gameTencentBackLog.getBackLog());
     }
 
     public static class TencentOrderBackPolicyCheck implements BackPolicyUtil.IBackPolicyCheck {

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

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

+ 112 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/task/OceanengineOrderSplitBackTask.java

@@ -0,0 +1,112 @@
+package com.zanxiang.game.back.serve.task;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.github.sd4324530.jtuple.Tuple2;
+import com.zanxiang.game.back.base.ServerInfo;
+import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineOrderLog;
+import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineOrderSplitLog;
+import com.zanxiang.game.back.serve.pojo.enums.BackStatusEnum;
+import com.zanxiang.game.back.serve.service.IGameOceanengineOrderLogService;
+import com.zanxiang.game.back.serve.service.IGameOceanengineOrderSplitLogService;
+import com.zanxiang.module.redis.service.IDistributedLockComponent;
+import com.zanxiang.module.util.DateUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 头条订单拆分回传任务
+ */
+@Slf4j
+@Component
+public class OceanengineOrderSplitBackTask {
+    public static final String KEY = ServerInfo.SERVER_NAME + ":oceanengineOrderSplitBack:";
+
+    @Autowired
+    private IGameOceanengineOrderLogService gameOceanengineOrderLogService;
+    @Autowired
+    private IGameOceanengineOrderSplitLogService gameOceanengineOrderSplitLogService;
+
+    @Autowired
+    private IDistributedLockComponent distributedLockComponent;
+
+    @Scheduled(cron = "0 * * * * ?")
+    public void execute() {
+        LocalDateTime now = LocalDateTime.now().withSecond(0).withNano(0);
+        if (!distributedLockComponent.doLock(KEY + DateUtil.formatLocalDateTime(now))) {
+            return;
+        }
+        List<GameOceanengineOrderSplitLog> orderSplitLogList = gameOceanengineOrderSplitLogService.list(new LambdaQueryWrapper<GameOceanengineOrderSplitLog>()
+                .in(GameOceanengineOrderSplitLog::getBackDay, Arrays.asList(LocalDate.now().minusDays(1), LocalDate.now()))
+                .lt(GameOceanengineOrderSplitLog::getBackTime, now.plusMinutes(1))
+                .eq(GameOceanengineOrderSplitLog::getBackStatus, BackStatusEnum.NO.getBackStatus())
+                .orderByAsc(GameOceanengineOrderSplitLog::getOrderNo)
+                .orderByAsc(GameOceanengineOrderSplitLog::getBackTime)
+        );
+        if (CollectionUtils.isEmpty(orderSplitLogList)) {
+            return;
+        }
+        log.error("准备回传分拆订单:{}", orderSplitLogList.size());
+        List<GameOceanengineOrderLog> orderList = gameOceanengineOrderLogService.list(new LambdaQueryWrapper<GameOceanengineOrderLog>()
+                .in(GameOceanengineOrderLog::getOrderNo, orderSplitLogList.stream().map(GameOceanengineOrderSplitLog::getOrderNo).collect(Collectors.toSet()))
+        );
+        Map<String, GameOceanengineOrderLog> orderMap = new HashMap<>(orderList.size());
+        orderList.forEach(order -> orderMap.put(order.getOrderNo(), order));
+
+        orderSplitLogList.forEach(orderSplitLog -> {
+            callback(orderMap.get(orderSplitLog.getOrderNo()), orderSplitLog);
+        });
+    }
+
+    private void callback(GameOceanengineOrderLog order, GameOceanengineOrderSplitLog orderSplitLog) {
+        log.error("开始回传拆分订单:{}-{}", orderSplitLog.getOrderNo(), orderSplitLog.getBackIndex());
+        try {
+            Tuple2<BackStatusEnum, String> backResult = gameOceanengineOrderLogService.doCallback(order, orderSplitLog.getSplitMoney());
+            gameOceanengineOrderSplitLogService.update(new LambdaUpdateWrapper<GameOceanengineOrderSplitLog>()
+                    .set(GameOceanengineOrderSplitLog::getExecuteTime, LocalDateTime.now())
+                    .set(GameOceanengineOrderSplitLog::getBackStatus, backResult.first.getBackStatus())
+                    .set(GameOceanengineOrderSplitLog::getBackErrorMsg, backResult.second)
+                    .eq(GameOceanengineOrderSplitLog::getId, orderSplitLog.getId())
+            );
+            if (backResult.first == BackStatusEnum.SUCCESS) {
+                gameOceanengineOrderLogService.update(new LambdaUpdateWrapper<GameOceanengineOrderLog>()
+                        .set(GameOceanengineOrderLog::getBackStatus, backResult.first.getBackStatus())
+                        .eq(GameOceanengineOrderLog::getId, order.getId())
+                );
+            } else {
+                gameOceanengineOrderLogService.update(new LambdaUpdateWrapper<GameOceanengineOrderLog>()
+                        .set(GameOceanengineOrderLog::getBackStatus, BackStatusEnum.SUCCESS_PART.getBackStatus())
+                        .eq(GameOceanengineOrderLog::getId, order.getId())
+                );
+            }
+            log.error("订单回传完成:{}-{}, {}-{}", orderSplitLog.getOrderNo(), orderSplitLog.getBackIndex(), backResult.first, backResult.second);
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            try {
+                gameOceanengineOrderSplitLogService.update(new LambdaUpdateWrapper<GameOceanengineOrderSplitLog>()
+                        .set(GameOceanengineOrderSplitLog::getExecuteTime, LocalDateTime.now())
+                        .set(GameOceanengineOrderSplitLog::getBackStatus, BackStatusEnum.FAILED.getBackStatus())
+                        .set(GameOceanengineOrderSplitLog::getBackErrorMsg, e.getMessage())
+                        .eq(GameOceanengineOrderSplitLog::getId, orderSplitLog.getId())
+                );
+                gameOceanengineOrderLogService.update(new LambdaUpdateWrapper<GameOceanengineOrderLog>()
+                        .set(GameOceanengineOrderLog::getBackStatus, BackStatusEnum.SUCCESS_PART.getBackStatus())
+                        .eq(GameOceanengineOrderLog::getId, order.getId())
+                );
+            } catch (Exception ex) {
+                log.error(ex.getMessage(), ex);
+            }
+        }
+    }
+}

+ 115 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/task/TencentMiniOrderSplitBackTask.java

@@ -0,0 +1,115 @@
+package com.zanxiang.game.back.serve.task;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.github.sd4324530.jtuple.Tuple2;
+import com.zanxiang.game.back.base.ServerInfo;
+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.enums.BackStatusEnum;
+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.module.redis.service.IDistributedLockComponent;
+import com.zanxiang.module.util.DateUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 头条订单拆分回传任务
+ */
+@Slf4j
+@Component
+public class TencentMiniOrderSplitBackTask {
+    public static final String KEY = ServerInfo.SERVER_NAME + ":tencentMiniOrderSplitBack:";
+
+    @Autowired
+    private IGameTencentMiniGameOrderService gameTencentMiniGameOrderService;
+    @Autowired
+    private IGameTencentMiniGameOrderSplitLogService gameTencentMiniGameOrderSplitLogService;
+
+    @Autowired
+    private IDistributedLockComponent distributedLockComponent;
+    @Autowired
+    private IGameTencentMiniGameBackLogService gameTencentMiniGameBackLogService;
+
+    @Scheduled(cron = "0 * * * * ?")
+    public void execute() {
+        LocalDateTime now = LocalDateTime.now().withSecond(0).withNano(0);
+        if (!distributedLockComponent.doLock(KEY + DateUtil.formatLocalDateTime(now))) {
+            return;
+        }
+        List<GameTencentMiniGameOrderSplitLog> orderSplitLogList = gameTencentMiniGameOrderSplitLogService.list(new LambdaQueryWrapper<GameTencentMiniGameOrderSplitLog>()
+                .in(GameTencentMiniGameOrderSplitLog::getBackDay, Arrays.asList(LocalDate.now().minusDays(1), LocalDate.now()))
+                .lt(GameTencentMiniGameOrderSplitLog::getBackTime, now.plusMinutes(1))
+                .eq(GameTencentMiniGameOrderSplitLog::getBackStatus, BackStatusEnum.NO.getBackStatus())
+                .orderByAsc(GameTencentMiniGameOrderSplitLog::getOrderNo)
+                .orderByAsc(GameTencentMiniGameOrderSplitLog::getBackTime)
+        );
+        if (CollectionUtils.isEmpty(orderSplitLogList)) {
+            return;
+        }
+        log.error("准备回传分拆订单:{}", orderSplitLogList.size());
+        List<GameTencentMiniGameOrder> orderList = gameTencentMiniGameOrderService.list(new LambdaQueryWrapper<GameTencentMiniGameOrder>()
+                .in(GameTencentMiniGameOrder::getOrderId, orderSplitLogList.stream().map(GameTencentMiniGameOrderSplitLog::getOrderNo).collect(Collectors.toSet()))
+        );
+        Map<String, GameTencentMiniGameOrder> orderMap = new HashMap<>(orderList.size());
+        orderList.forEach(order -> orderMap.put(order.getOrderId(), order));
+
+        orderSplitLogList.forEach(orderSplitLog -> {
+            callback(orderMap.get(orderSplitLog.getOrderNo()), orderSplitLog);
+        });
+    }
+
+    private void callback(GameTencentMiniGameOrder order, GameTencentMiniGameOrderSplitLog orderSplitLog) {
+        log.error("开始回传拆分订单:{}-{}", orderSplitLog.getOrderNo(), orderSplitLog.getBackIndex());
+        try {
+            Tuple2<BackStatusEnum, String> backResult = gameTencentMiniGameBackLogService.orderBack(order, orderSplitLog.getSplitMoney());
+            gameTencentMiniGameOrderSplitLogService.update(new LambdaUpdateWrapper<GameTencentMiniGameOrderSplitLog>()
+                    .set(GameTencentMiniGameOrderSplitLog::getExecuteTime, LocalDateTime.now())
+                    .set(GameTencentMiniGameOrderSplitLog::getBackStatus, backResult.first.getBackStatus())
+                    .set(GameTencentMiniGameOrderSplitLog::getBackErrorMsg, backResult.second)
+                    .eq(GameTencentMiniGameOrderSplitLog::getId, orderSplitLog.getId())
+            );
+            if (backResult.first == BackStatusEnum.SUCCESS) {
+                gameTencentMiniGameOrderService.update(new LambdaUpdateWrapper<GameTencentMiniGameOrder>()
+                        .set(GameTencentMiniGameOrder::getBackStatus, backResult.first.getBackStatus())
+                        .eq(GameTencentMiniGameOrder::getId, order.getId())
+                );
+            } else {
+                gameTencentMiniGameOrderService.update(new LambdaUpdateWrapper<GameTencentMiniGameOrder>()
+                        .set(GameTencentMiniGameOrder::getBackStatus, BackStatusEnum.SUCCESS_PART.getBackStatus())
+                        .eq(GameTencentMiniGameOrder::getId, order.getId())
+                );
+            }
+            log.error("订单回传完成:{}-{}, {}-{}", orderSplitLog.getOrderNo(), orderSplitLog.getBackIndex(), backResult.first, backResult.second);
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            try {
+                gameTencentMiniGameOrderSplitLogService.update(new LambdaUpdateWrapper<GameTencentMiniGameOrderSplitLog>()
+                        .set(GameTencentMiniGameOrderSplitLog::getExecuteTime, LocalDateTime.now())
+                        .set(GameTencentMiniGameOrderSplitLog::getBackStatus, BackStatusEnum.FAILED.getBackStatus())
+                        .set(GameTencentMiniGameOrderSplitLog::getBackErrorMsg, e.getMessage())
+                        .eq(GameTencentMiniGameOrderSplitLog::getId, orderSplitLog.getId())
+                );
+                gameTencentMiniGameOrderService.update(new LambdaUpdateWrapper<GameTencentMiniGameOrder>()
+                        .set(GameTencentMiniGameOrder::getBackStatus, BackStatusEnum.SUCCESS_PART.getBackStatus())
+                        .eq(GameTencentMiniGameOrder::getId, order.getId())
+                );
+            } catch (Exception ex) {
+                log.error(ex.getMessage(), ex);
+            }
+        }
+    }
+}

+ 112 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/task/TencentOrderSplitBackTask.java

@@ -0,0 +1,112 @@
+package com.zanxiang.game.back.serve.task;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.github.sd4324530.jtuple.Tuple2;
+import com.zanxiang.game.back.base.ServerInfo;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentOrder;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentOrderSplitLog;
+import com.zanxiang.game.back.serve.pojo.enums.BackStatusEnum;
+import com.zanxiang.game.back.serve.service.IGameTencentOrderService;
+import com.zanxiang.game.back.serve.service.IGameTencentOrderSplitLogService;
+import com.zanxiang.module.redis.service.IDistributedLockComponent;
+import com.zanxiang.module.util.DateUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 头条订单拆分回传任务
+ */
+@Slf4j
+@Component
+public class TencentOrderSplitBackTask {
+    public static final String KEY = ServerInfo.SERVER_NAME + ":tencentOrderSplitBack:";
+
+    @Autowired
+    private IGameTencentOrderService gameTencentOrderService;
+    @Autowired
+    private IGameTencentOrderSplitLogService gameTencentOrderSplitLogService;
+
+    @Autowired
+    private IDistributedLockComponent distributedLockComponent;
+
+    @Scheduled(cron = "0 * * * * ?")
+    public void execute() {
+        LocalDateTime now = LocalDateTime.now().withSecond(0).withNano(0);
+        if (!distributedLockComponent.doLock(KEY + DateUtil.formatLocalDateTime(now))) {
+            return;
+        }
+        List<GameTencentOrderSplitLog> orderSplitLogList = gameTencentOrderSplitLogService.list(new LambdaQueryWrapper<GameTencentOrderSplitLog>()
+                .in(GameTencentOrderSplitLog::getBackDay, Arrays.asList(LocalDate.now().minusDays(1), LocalDate.now()))
+                .lt(GameTencentOrderSplitLog::getBackTime, now.plusMinutes(1))
+                .eq(GameTencentOrderSplitLog::getBackStatus, BackStatusEnum.NO.getBackStatus())
+                .orderByAsc(GameTencentOrderSplitLog::getOrderNo)
+                .orderByAsc(GameTencentOrderSplitLog::getBackTime)
+        );
+        if (CollectionUtils.isEmpty(orderSplitLogList)) {
+            return;
+        }
+        log.error("准备回传分拆订单:{}", orderSplitLogList.size());
+        List<GameTencentOrder> orderList = gameTencentOrderService.list(new LambdaQueryWrapper<GameTencentOrder>()
+                .in(GameTencentOrder::getOrderId, orderSplitLogList.stream().map(GameTencentOrderSplitLog::getOrderNo).collect(Collectors.toSet()))
+        );
+        Map<String, GameTencentOrder> orderMap = new HashMap<>(orderList.size());
+        orderList.forEach(order -> orderMap.put(order.getOrderId(), order));
+
+        orderSplitLogList.forEach(orderSplitLog -> {
+            callback(orderMap.get(orderSplitLog.getOrderNo()), orderSplitLog);
+        });
+    }
+
+    private void callback(GameTencentOrder order, GameTencentOrderSplitLog orderSplitLog) {
+        log.error("开始回传拆分订单:{}-{}", orderSplitLog.getOrderNo(), orderSplitLog.getBackIndex());
+        try {
+            Tuple2<BackStatusEnum, String> backResult = gameTencentOrderService.doCallback(order, orderSplitLog.getSplitMoney());
+            gameTencentOrderSplitLogService.update(new LambdaUpdateWrapper<GameTencentOrderSplitLog>()
+                    .set(GameTencentOrderSplitLog::getExecuteTime, LocalDateTime.now())
+                    .set(GameTencentOrderSplitLog::getBackStatus, backResult.first.getBackStatus())
+                    .set(GameTencentOrderSplitLog::getBackErrorMsg, backResult.second)
+                    .eq(GameTencentOrderSplitLog::getId, orderSplitLog.getId())
+            );
+            if (backResult.first == BackStatusEnum.SUCCESS) {
+                gameTencentOrderService.update(new LambdaUpdateWrapper<GameTencentOrder>()
+                        .set(GameTencentOrder::getIsBack, backResult.first.getBackStatus())
+                        .eq(GameTencentOrder::getId, order.getId())
+                );
+            } else {
+                gameTencentOrderService.update(new LambdaUpdateWrapper<GameTencentOrder>()
+                        .set(GameTencentOrder::getIsBack, BackStatusEnum.SUCCESS_PART.getBackStatus())
+                        .eq(GameTencentOrder::getId, order.getId())
+                );
+            }
+            log.error("订单回传完成:{}-{}, {}-{}", orderSplitLog.getOrderNo(), orderSplitLog.getBackIndex(), backResult.first, backResult.second);
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            try {
+                gameTencentOrderSplitLogService.update(new LambdaUpdateWrapper<GameTencentOrderSplitLog>()
+                        .set(GameTencentOrderSplitLog::getExecuteTime, LocalDateTime.now())
+                        .set(GameTencentOrderSplitLog::getBackStatus, BackStatusEnum.FAILED.getBackStatus())
+                        .set(GameTencentOrderSplitLog::getBackErrorMsg, e.getMessage())
+                        .eq(GameTencentOrderSplitLog::getId, orderSplitLog.getId())
+                );
+                gameTencentOrderService.update(new LambdaUpdateWrapper<GameTencentOrder>()
+                        .set(GameTencentOrder::getIsBack, BackStatusEnum.SUCCESS_PART.getBackStatus())
+                        .eq(GameTencentOrder::getId, order.getId())
+                );
+            } catch (Exception ex) {
+                log.error(ex.getMessage(), ex);
+            }
+        }
+    }
+}

+ 27 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/utils/BackPolicyUtil.java

@@ -16,7 +16,10 @@ import org.apache.commons.lang3.StringUtils;
 
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 import java.util.function.Function;
@@ -216,6 +219,30 @@ public class BackPolicyUtil {
         return Tuples.tuple(userBackCount < maxBackCountOfUser, downLevel(rechargeMoney, downLevelString), backMsg);
     }
 
+    /**
+     * 拆单逻辑
+     */
+    public static Tuple3<Boolean, Long, List<Tuple2<Long, LocalDateTime>>> splitOrder(GameBackPolicy gameBackPolicy, Long backMoney) {
+        if (gameBackPolicy == null || StringUtils.isBlank(gameBackPolicy.getSplitStrategy())) {
+            return Tuple3.with(false, backMoney, null);
+        }
+        Collection<GameBackPolicyVO.SplitStrategy> splitStrategyList = JsonUtil.toList(gameBackPolicy.getSplitStrategy(), List.class, GameBackPolicyVO.SplitStrategy.class);
+        if (CollectionUtils.isEmpty(splitStrategyList)) {
+            return Tuple3.with(false, backMoney, null);
+        }
+        List<Tuple2<Long, LocalDateTime>> result = new ArrayList<>();
+        LocalDateTime beginTime = LocalDateTime.now();
+        Long sumMoney = 0L;
+        for (GameBackPolicyVO.SplitStrategy splitStrategy : splitStrategyList) {
+            long money = NumberUtil.multiply100(splitStrategy.getPayMoney()).longValue();
+            sumMoney += money;
+            result.add(Tuple2.with(money, beginTime));
+            int randomMinute = RandomUtils.nextInt(splitStrategy.getBetweenMinuteMin(), splitStrategy.getBetweenMinuteMax());
+            beginTime = beginTime.minusMinutes(randomMinute);
+        }
+        return Tuple3.with(true, sumMoney, result);
+    }
+
     private static Long downLevel(Long rechargeMoney, String downLevelStr) {
         if (StringUtils.isBlank(downLevelStr)) {
             return rechargeMoney;