Преглед на файлове

feat : 订单过期自动取消策略

bilingfeng преди 2 години
родител
ревизия
1a12e7cad7

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

@@ -35,8 +35,8 @@ public class OrderPaySuccessListener {
     @Autowired
     private ICallBackService callBackService;
 
-    @EventListener
     @Async
+    @EventListener
     public void onApplicationEvent(OrderPaySuccessEvent event) {
         if (StringUtils.isEmpty(event.getOrderId())) {
             log.error("缺少订单ID");

+ 0 - 9
game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/IOrderService.java

@@ -2,7 +2,6 @@ package com.zanxiang.sdk.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.zanxiang.mybatis.entity.Order;
-import com.zanxiang.sdk.domain.bo.PlatformOrderBO;
 import com.zanxiang.sdk.domain.dto.PlatformOrderDTO;
 import com.zanxiang.sdk.domain.params.ProductPayParam;
 import com.zanxiang.sdk.domain.params.UserData;
@@ -25,14 +24,6 @@ public interface IOrderService extends IService<Order> {
      */
     Boolean createOrder(ProductPayParam payParam, UserData userData);
 
-    /**
-     * 订单支付
-     *
-     * @param platformOrderBO 平台订单薄
-     * @return {@link Boolean}
-     */
-    Boolean pay(PlatformOrderBO platformOrderBO);
-
     /**
      * 单一订单详情获取
      *

+ 16 - 34
game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/Impl/OrderServiceImpl.java

@@ -6,19 +6,19 @@ import com.zanxiang.common.enums.CallBackEnum;
 import com.zanxiang.common.enums.OrderStateEnum;
 import com.zanxiang.common.exception.BaseException;
 import com.zanxiang.common.utils.bean.BeanUtils;
+import com.zanxiang.module.util.DateUtil;
 import com.zanxiang.mybatis.entity.*;
 import com.zanxiang.mybatis.mapper.OrderMapper;
-import com.zanxiang.sdk.domain.bo.PlatformOrderBO;
+import com.zanxiang.sdk.constant.RedisKeyConstant;
 import com.zanxiang.sdk.domain.dto.GamePayWayDTO;
 import com.zanxiang.sdk.domain.dto.PlatformOrderDTO;
 import com.zanxiang.sdk.domain.params.ProductPayParam;
 import com.zanxiang.sdk.domain.params.UserData;
-import com.zanxiang.sdk.listener.OrderPaySuccessEvent;
 import com.zanxiang.sdk.service.*;
+import com.zanxiang.sdk.util.RedisUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ApplicationContext;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -33,7 +33,6 @@ import java.time.format.DateTimeFormatter;
  */
 @Slf4j
 @Service
-@Transactional(rollbackFor = {Exception.class, RuntimeException.class})
 public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {
 
     @Autowired
@@ -52,12 +51,13 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
     private IGameUserRoleService gameUserRoleService;
 
     @Autowired
-    private ApplicationContext applicationContext;
+    private IGamePayWayService gamePayWayService;
 
     @Autowired
-    private IGamePayWayService gamePayWayService;
+    private RedisUtil<String> redisUtil;
 
     @Override
+    @Transactional(rollbackFor = {Exception.class, RuntimeException.class})
     public Boolean createOrder(ProductPayParam payParam, UserData userData) {
         //用户id
         Long userId = userData.getUserId();
@@ -124,10 +124,20 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
                 .build());
         //设置订单号
         payParam.setOrderId(orderNum);
+        //设置订单过期
+        this.orderExpire(orderNum);
         //返回
         return Boolean.TRUE;
     }
 
+    private void orderExpire(String orderId) {
+        //过期时间
+        double expire = (double) DateUtil.localDateTimeToMilli(LocalDateTime.now().plusMinutes(5));
+        //设置缓存
+        redisUtil.addZSet(RedisKeyConstant.ORDER_EXPIRE, orderId, expire);
+        log.error("订单添加过期缓存, orderId : {}, expire : {}", orderId, expire);
+    }
+
     private String getOrderNum(Long userId) {
         //时间(精确到毫秒)
         DateTimeFormatter ofPattern = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
@@ -147,34 +157,6 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
         return localDate + str + randomNumeric;
     }
 
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public Boolean pay(PlatformOrderBO platformOrderBO) {
-        log.info("订单支付请求参数 platformOrderBO:{}", platformOrderBO);
-        try {
-            Order order = getOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderId, platformOrderBO.getOrderId()));
-            //已支付情况,直接返回成功
-            if (order.getStatus().equals(OrderStateEnum.SUCCESS_PAY.getCode())) {
-                return true;
-            }
-            if (!order.getStatus().equals(OrderStateEnum.WAIT_PAY.getCode())) {
-                throw new BaseException("订单状态非待支付");
-            }
-            platformOrderBO.setPayTime(LocalDateTime.now());
-            log.info("订单支付提交数据 data:{}", platformOrderBO);
-            boolean result = updateById(BeanUtils.copy(platformOrderBO, Order.class));
-            if (result) {
-                OrderPaySuccessEvent orderPaySuccessEvent = new OrderPaySuccessEvent(this, order.getOrderId());
-                applicationContext.publishEvent(orderPaySuccessEvent);
-                return true;
-            }
-            return false;
-        } catch (Exception e) {
-            log.error("订单支付失败 platformOrderBO:{}, error:{}", platformOrderBO, e);
-            return false;
-        }
-    }
-
     @Override
     public PlatformOrderDTO getByOrderId(String orderId) {
         Order order = getOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderId, orderId));

+ 0 - 2
game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/Impl/PayBoxServiceImpl.java

@@ -12,7 +12,6 @@ import com.zanxiang.sdk.service.IPayMerchantService;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.logging.log4j.util.Strings;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Service;
 
 import java.util.Arrays;
@@ -25,7 +24,6 @@ import java.util.stream.Collectors;
  * @author xufeng
  * @date 2022-06-22 15:26
  */
-@Component
 @Slf4j
 @Service
 public class PayBoxServiceImpl extends ServiceImpl<PayBoxMapper, PayBox> implements IPayBoxService {

+ 4 - 1
game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/Impl/PerformOrderServiceImpl.java

@@ -37,7 +37,6 @@ import java.util.Objects;
  */
 @Slf4j
 @Service
-@Transactional(rollbackFor = {RuntimeException.class, Exception.class})
 public class PerformOrderServiceImpl implements IPerformOrderService {
 
     @Autowired
@@ -65,6 +64,7 @@ public class PerformOrderServiceImpl implements IPerformOrderService {
     private IGameExtService gameExtService;
 
     @Override
+    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
     public Boolean pushCp(PlatformOrderDTO orderInfo) {
         log.info("充值回调CP, orderInfo : {} ----------start---------", JsonUtil.toString(orderInfo));
         if (Objects.equals(orderInfo.getCpStatus(), CpStatusEnum.SUCCESS.getStatus())) {
@@ -145,6 +145,7 @@ public class PerformOrderServiceImpl implements IPerformOrderService {
     }
 
     @Override
+    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
     public Boolean checkIsFirstRecharge(PlatformOrderDTO platformOrderDTO) {
         log.info("订单:{} 检查更新用户是否为首充 ----------start---------", platformOrderDTO.getOrderId());
         try {
@@ -166,6 +167,7 @@ public class PerformOrderServiceImpl implements IPerformOrderService {
     }
 
     @Override
+    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
     public Boolean userRechargeTotal(PlatformOrderDTO orderInfo) {
         log.info("订单:{} 更新用户充值统计 ----------start---------", orderInfo.getOrderId());
         try {
@@ -218,6 +220,7 @@ public class PerformOrderServiceImpl implements IPerformOrderService {
     }
 
     @Override
+    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
     public Boolean payMerchantTotal(PlatformOrderDTO platformOrderDTO) {
         log.info("订单:{} 更新商户号统计 ----------start---------", platformOrderDTO.getOrderId());
         try {

+ 7 - 10
game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/pay/AliPayService.java

@@ -123,8 +123,6 @@ public class AliPayService extends PayBaseService {
                 .set(Order::getMerchantName, payMerchant.getMerchantName())
                 .set(Order::getStatus, OrderStateEnum.WAIT_PAY.getCode())
                 .eq(Order::getOrderId, product.getOutTradeNo()));
-        //商户已下单, 设置订单过期缓存
-        this.orderExpire(product.getOutTradeNo());
         //返回结果
         return resultMap;
     }
@@ -146,8 +144,8 @@ public class AliPayService extends PayBaseService {
             configInit(gamePayWayService.getById(Long.valueOf(gamePayWayId)));
             Boolean flag = Factory.Payment.Common().verifyNotify(params);
             if (flag) {
-                if (paySuccess(orderNo, params.get("total_amount"), params.get("trade_no"), gamePayWayId)) {
-                    log.info("支付宝异步回调成功 request:{},orderNo:{},商户订单号为:{}", request, orderNo, params.get("trade_no"));
+                if (paySuccess(orderNo, params.get("total_amount"), params.get("trade_no"))) {
+                    log.info("支付宝异步回调成功, orderId : {}", orderNo);
                     return HttpStatusEnum.SUCCESS.getMsg();
                 }
             }
@@ -172,11 +170,11 @@ public class AliPayService extends PayBaseService {
                             : valueStr + values[i] + ",";
                 }
                 //乱码解决,这段代码在出现乱码时使用
-                valueStr = new String(valueStr.getBytes("ISO-8859-1"), StandardCharsets.UTF_8);
+                valueStr = new String(valueStr.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
                 params.put(name, valueStr);
             }
             //商户订单号
-            String orderNo = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), Constants.UTF8);
+            String orderNo = new String(request.getParameter("out_trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
             String gamePayWayId = params.get("gamePayWayId");
             //回调地址拼接参数不参加sign验证
             params.remove("gamePayWayId");
@@ -185,13 +183,12 @@ public class AliPayService extends PayBaseService {
             //验证签名
             Boolean flag = Factory.Payment.Common().verifyNotify(params);
             if (flag) {
-                log.info("订单号" + orderNo + "验证签名结果[成功].");
-                if (paySuccess(orderNo, params.get("total_amount"), params.get("trade_no"), gamePayWayId)) {
-                    log.info("支付宝同步回调成功 request:{},orderNo:{},商户订单号为:{}", request, orderNo, params.get("trade_no"));
+                if (paySuccess(orderNo, params.get("total_amount"), params.get("trade_no"))) {
+                    log.info("支付宝同步回调成功, orderId : {}", orderNo);
                     return ResultVO.ok();
                 }
             }
-            log.error("订单号" + orderNo + "验证签名结果[失败].");
+            log.error("支付宝同步回调验证签名结果失败, orderId : {}", orderNo);
             return ResultVO.fail(HttpStatusEnum.FAIL.getMsg());
         } catch (Exception e) {
             e.printStackTrace();

+ 9 - 8
game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/pay/MiPayService.java

@@ -89,9 +89,10 @@ public class MiPayService extends PayBaseService {
             String billNo = this.midasPay(openId, orderInfo);
             payParamMap.put("status", "0");
             payParamMap.put("billNo", billNo);
-        }
-        //余额不足, 返回订单id, 前端调充值接口, 充值完后再继续支付
-        if (balance < orderInfo.getAmount().longValue()) {
+            //支付成功
+            this.paySuccess(product.getOutTradeNo(), orderInfo.getAmount().toString(), config.getAppId());
+        } else {
+            //余额不足, 返回订单id, 前端调充值接口, 充值完后再继续支付
             payParamMap.put("currencyType", "CNY");
             payParamMap.put("mode", "game");
             payParamMap.put("zoneId", "1");
@@ -101,12 +102,12 @@ public class MiPayService extends PayBaseService {
             payParamMap.put("status", "1");
             payParamMap.put("balance", String.valueOf(balance));
             payParamMap.put("orderId", product.getOutTradeNo());
+            //更新订单商户信息
+            orderService.update(new LambdaUpdateWrapper<Order>()
+                    .set(Order::getMerchantNo, config.getAppId())
+                    .set(Order::getStatus, OrderStateEnum.WAIT_PAY.getCode())
+                    .eq(Order::getOrderId, product.getOutTradeNo()));
         }
-        //更新订单商户信息
-        orderService.update(new LambdaUpdateWrapper<Order>()
-                .set(Order::getMerchantNo, config.getAppId())
-                .set(Order::getStatus, OrderStateEnum.WAIT_PAY.getCode())
-                .eq(Order::getOrderId, product.getOutTradeNo()));
         return payParamMap;
     }
 

+ 24 - 31
game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/pay/PayBaseService.java

@@ -1,23 +1,22 @@
 package com.zanxiang.sdk.service.pay;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.zanxiang.common.enums.OrderStateEnum;
 import com.zanxiang.common.exception.BaseException;
-import com.zanxiang.module.util.DateUtil;
 import com.zanxiang.module.util.JsonUtil;
 import com.zanxiang.module.util.pojo.ResultVO;
 import com.zanxiang.mybatis.entity.Order;
-import com.zanxiang.sdk.constant.RedisKeyConstant;
-import com.zanxiang.sdk.domain.bo.PlatformOrderBO;
 import com.zanxiang.sdk.domain.bo.ProductPayAttachParamBO;
 import com.zanxiang.sdk.domain.bo.ProductPayParamBO;
 import com.zanxiang.sdk.domain.dto.GamePayWayDTO;
 import com.zanxiang.sdk.domain.dto.PlatformOrderDTO;
+import com.zanxiang.sdk.listener.OrderPaySuccessEvent;
 import com.zanxiang.sdk.service.IGamePayWayService;
 import com.zanxiang.sdk.service.IOrderService;
-import com.zanxiang.sdk.util.RedisUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.Lazy;
 
 import javax.servlet.http.HttpServletRequest;
@@ -45,7 +44,7 @@ public abstract class PayBaseService {
 
     @Lazy
     @Autowired
-    private RedisUtil<String> redisUtil;
+    private ApplicationContext applicationContext;
 
     /**
      * 自定义参数
@@ -91,24 +90,31 @@ public abstract class PayBaseService {
      *
      * @param orderNo         订单号
      * @param realAmount      真实金额
-     * @param merchantOrderNo 订单流水号
-     * @param gamePayWayId    具体游戏支付方式id
+     * @param merchantOrderNo 商户号
      * @return : 返回支付状态
      */
-    public Boolean paySuccess(String orderNo, String realAmount, String merchantOrderNo, String gamePayWayId) {
+    public Boolean paySuccess(String orderNo, String realAmount, String merchantOrderNo) {
         Order order = orderService.getOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderId, orderNo));
         if (order == null) {
-            throw new BaseException("支付成功回调, 订单信息不存在");
+            return Boolean.FALSE;
         }
-        PlatformOrderBO bo = new PlatformOrderBO();
-        bo.setId(order.getId());
-        bo.setOrderId(orderNo);
-        bo.setRealAmount(new BigDecimal(realAmount));
-        bo.setMerchantOrderNo(merchantOrderNo);
-        bo.setStatus(OrderStateEnum.SUCCESS_PAY.getCode());
-        bo.setGamePaywayId(gamePayWayId);
-        bo.setPayTime(LocalDateTime.now());
-        return orderService.pay(bo);
+        //已支付情况,直接返回成功
+        if (order.getStatus().equals(OrderStateEnum.SUCCESS_PAY.getCode())) {
+            return Boolean.TRUE;
+        }
+        //订单更新
+        boolean result = orderService.update(new LambdaUpdateWrapper<Order>()
+                .set(Order::getRealAmount, new BigDecimal(realAmount))
+                .set(Order::getStatus, OrderStateEnum.SUCCESS_PAY.getCode())
+                .set(Order::getPayTime, LocalDateTime.now())
+                .set(Order::getMerchantNo, merchantOrderNo)
+                .eq(Order::getOrderId, orderNo));
+        if (result) {
+            OrderPaySuccessEvent orderPaySuccessEvent = new OrderPaySuccessEvent(this, order.getOrderId());
+            applicationContext.publishEvent(orderPaySuccessEvent);
+            return Boolean.TRUE;
+        }
+        return Boolean.FALSE;
     }
 
     /**
@@ -125,19 +131,6 @@ public abstract class PayBaseService {
         return gamePayWayDTO;
     }
 
-    /**
-     * 订单设置过期时间缓存
-     *
-     * @param orderId : 订单id
-     */
-    public void orderExpire(String orderId) {
-        //过期时间
-        double expire = (double) DateUtil.localDateTimeToMilli(LocalDateTime.now().plusMinutes(5));
-        //设置缓存
-        redisUtil.addZSet(RedisKeyConstant.ORDER_EXPIRE, orderId, expire);
-        log.error("订单添加过期缓存, orderId : {}, expire : {}", orderId, expire);
-    }
-
     /**
      * 支付调起
      *

+ 3 - 5
game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/pay/WxPayService.java

@@ -133,8 +133,6 @@ public class WxPayService extends PayBaseService {
                 .set(Order::getMerchantName, config.getMachName())
                 .set(Order::getStatus, OrderStateEnum.WAIT_PAY.getCode())
                 .eq(Order::getOrderId, product.getOutTradeNo()));
-        //商户已下单, 设置订单过期缓存
-        this.orderExpire(product.getOutTradeNo());
         //返回支付参数
         return resultMap;
     }
@@ -167,9 +165,9 @@ public class WxPayService extends PayBaseService {
         Map<String, String> xmlMap = new HashMap<>();
         if (Constants.SUCCESS.equalsIgnoreCase(packageParams.get("result_code"))) {
             String orderNo = packageParams.get("out_trade_no");
-            log.info("微信订单号{}付款成功", orderNo);
-            if (paySuccess(attachBO.getOrderId(), String.valueOf(Float.parseFloat(packageParams.get("total_fee")) / 100),
-                    packageParams.get("transaction_id"), attachBO.getGamePayWayId().toString())) {
+            String totalFee = String.valueOf(Float.parseFloat(packageParams.get("total_fee")) / 100);
+            log.info("微信订单号回调成功, orderId : {}", orderNo);
+            if (paySuccess(attachBO.getOrderId(), totalFee, packageParams.get("transaction_id"))) {
                 // 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了
                 xmlMap.put("return_code", "SUCCESS");
                 xmlMap.put("return_msg", "OK");

+ 3 - 2
game-module/game-sdk/src/main/java/com/zanxiang/sdk/task/OrderExpireTask.java

@@ -83,8 +83,9 @@ public class OrderExpireTask {
         if (platformOrderDTO == null) {
             return;
         }
-        //订单不是待支付状态, 不处理
-        if (Objects.equals(OrderStateEnum.WAIT_PAY.getCode(), platformOrderDTO.getStatus())) {
+        //已支付订单或者已取消订单不处理
+        if (Objects.equals(OrderStateEnum.SUCCESS_PAY.getCode(), platformOrderDTO.getStatus())
+                || Objects.equals(OrderStateEnum.CANCEL_PAY.getCode(), platformOrderDTO.getStatus())) {
             return;
         }
         //关闭商户订单