|  | @@ -28,6 +28,7 @@ import org.redisson.api.RedissonClient;
 | 
	
		
			
				|  |  |  import org.slf4j.Logger;
 | 
	
		
			
				|  |  |  import org.slf4j.LoggerFactory;
 | 
	
		
			
				|  |  |  import org.springframework.beans.factory.annotation.Autowired;
 | 
	
		
			
				|  |  | +import org.springframework.core.annotation.Order;
 | 
	
		
			
				|  |  |  import org.springframework.stereotype.Service;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.biz.dal.dto.search.OrderSearch;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.biz.dal.dao.UserOrderDao;
 | 
	
	
		
			
				|  | @@ -36,6 +37,7 @@ import org.springframework.transaction.annotation.Transactional;
 | 
	
		
			
				|  |  |  import javax.annotation.PostConstruct;
 | 
	
		
			
				|  |  |  import java.math.BigDecimal;
 | 
	
		
			
				|  |  |  import java.math.RoundingMode;
 | 
	
		
			
				|  |  | +import java.time.LocalDateTime;
 | 
	
		
			
				|  |  |  import java.util.*;
 | 
	
		
			
				|  |  |  import java.util.concurrent.Future;
 | 
	
		
			
				|  |  |  import java.util.concurrent.TimeUnit;
 | 
	
	
		
			
				|  | @@ -67,9 +69,6 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
 | 
	
		
			
				|  |  |      @Autowired
 | 
	
		
			
				|  |  |      private MusicSheetService musicSheetService;
 | 
	
		
			
				|  |  |      @Autowired
 | 
	
		
			
				|  |  | -    private StudentTimeService studentTimeService;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    @Autowired
 | 
	
		
			
				|  |  |      private RedissonClient redissonClient;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      //验证订单是否可以下单
 | 
	
	
		
			
				|  | @@ -166,6 +165,7 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Override
 | 
	
		
			
				|  |  | +    @Transactional(rollbackFor = Exception.class)
 | 
	
		
			
				|  |  |      public HttpResponseResult<Boolean> orderCancel(OrderPayReq payReq) {
 | 
	
		
			
				|  |  |          UserOrderVo detail = detail(payReq.getOrderNo());
 | 
	
		
			
				|  |  |          if (null == detail) {
 | 
	
	
		
			
				|  | @@ -207,6 +207,24 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Override
 | 
	
		
			
				|  |  | +    public void setOrderStatus(String orderNo, OrderStatusEnum orderStatus) {
 | 
	
		
			
				|  |  | +        UserOrderVo detail = detail(orderNo);
 | 
	
		
			
				|  |  | +        if(OrderStatusEnum.WAIT_PAY.equals(detail.getStatus())
 | 
	
		
			
				|  |  | +            || OrderStatusEnum.PAYING.equals(detail.getStatus())){
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if(OrderStatusEnum.CLOSE.equals(orderStatus)){
 | 
	
		
			
				|  |  | +                doOrderCancel(detail,orderStatus,"测试接口-订单关闭");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            if(OrderStatusEnum.FAIL.equals(orderStatus)){
 | 
	
		
			
				|  |  | +                doOrderCancel(detail,orderStatus,"测试接口-订单交易失败");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            if(OrderStatusEnum.PAID.equals(orderStatus)){
 | 
	
		
			
				|  |  | +                orderSuccess(detail);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  |      public IPage<UserOrderVo> selectPage(IPage<UserOrderVo> page, OrderSearch query) {
 | 
	
		
			
				|  |  |          return page.setRecords(baseMapper.selectPage(page, query));
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -300,6 +318,7 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Override
 | 
	
		
			
				|  |  | +    @Transactional(rollbackFor = Exception.class)
 | 
	
		
			
				|  |  |      public void orderCallback(String data, String type) {
 | 
	
		
			
				|  |  |          JSONObject hfRes = JSONObject.parseObject(data);
 | 
	
		
			
				|  |  |          if (type.equals("payment.succeeded")) {//支付成功
 | 
	
	
		
			
				|  | @@ -407,66 +426,30 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
 | 
	
		
			
				|  |  |          //查询半小时前创建的并且还未完成的订单 WAIT_PAY 待支付订单 PAYING 支付中订单
 | 
	
		
			
				|  |  |          OrderSearch search = new OrderSearch();
 | 
	
		
			
				|  |  |          search.setStatus(OrderStatusEnum.WAIT_PAY.getCode());
 | 
	
		
			
				|  |  | +        search.setEndTime(LocalDateTime.now().minusMinutes(30));
 | 
	
		
			
				|  |  |          //查询待支付订单
 | 
	
		
			
				|  |  |          List<UserOrderVo> waitPayOrderList = baseMapper.selectList(search);
 | 
	
		
			
				|  |  | -        ((Runnable) () -> {
 | 
	
		
			
				|  |  | -            List<UserOrderVo> dataList = waitPayOrderList;
 | 
	
		
			
				|  |  | -            for (UserOrderVo orderVo : dataList) {
 | 
	
		
			
				|  |  | -                long now = System.currentTimeMillis();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                Date createTime = orderVo.getCreateTime();
 | 
	
		
			
				|  |  | -                long interval = 0L;
 | 
	
		
			
				|  |  | -                //订单到期时间为创建时间往后30分钟
 | 
	
		
			
				|  |  | -                if(null != createTime){
 | 
	
		
			
				|  |  | -                    interval = createTime.getTime() + 1000 * 60 * 30l - now;
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                //等待时间后取消订单
 | 
	
		
			
				|  |  | -                try {
 | 
	
		
			
				|  |  | -                    Thread.sleep(interval);
 | 
	
		
			
				|  |  | -                } catch (InterruptedException e) {
 | 
	
		
			
				|  |  | -                    e.printStackTrace();
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                //取消订单要获取锁,防止在轮询取消时,用户修改订单状态
 | 
	
		
			
				|  |  | -                boolean b = DistributedLock.of(redissonClient)
 | 
	
		
			
				|  |  | -                        .runIfLockCanGet(CacheNameEnum.LOCK_EXECUTE_ORDER.getRedisKey(orderVo.getUserId())
 | 
	
		
			
				|  |  | -                                , () -> pollingCancelOrder(orderVo.getOrderNo()), 60L, TimeUnit.SECONDS);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }).run();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +        for (UserOrderVo orderVo : waitPayOrderList) {
 | 
	
		
			
				|  |  | +            //取消订单要获取锁,防止在轮询取消时,用户修改订单状态
 | 
	
		
			
				|  |  | +            boolean b = DistributedLock.of(redissonClient)
 | 
	
		
			
				|  |  | +                    .runIfLockCanGet(CacheNameEnum.LOCK_EXECUTE_ORDER.getRedisKey(orderVo.getUserId())
 | 
	
		
			
				|  |  | +                            , () -> pollingCancelOrder(orderVo.getOrderNo()), 60L, TimeUnit.SECONDS);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          search.setStatus(OrderStatusEnum.PAYING.getCode());
 | 
	
		
			
				|  |  | +        search.setEndTime(LocalDateTime.now().minusMinutes(120));
 | 
	
		
			
				|  |  |          //查询待支付中订单
 | 
	
		
			
				|  |  |          List<UserOrderVo> payingOrderList = baseMapper.selectList(search);
 | 
	
		
			
				|  |  | -        ((Runnable) () -> {
 | 
	
		
			
				|  |  | -            List<UserOrderVo> dataList = payingOrderList;
 | 
	
		
			
				|  |  | -            for (UserOrderVo orderVo : dataList) {
 | 
	
		
			
				|  |  | -                long now = System.currentTimeMillis();
 | 
	
		
			
				|  |  | -                Date createTime = orderVo.getCreateTime();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                long interval = 0L;
 | 
	
		
			
				|  |  | -                //订单到期时间为创建时间往后30分钟
 | 
	
		
			
				|  |  | -                if(null != createTime){
 | 
	
		
			
				|  |  | -                    interval = createTime.getTime() + 1000 * 60 * 120l - now;
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                //间隔时间超过30分钟的,留给下次轮询处理
 | 
	
		
			
				|  |  | -                if(interval >= 1000 * 60 * 30){
 | 
	
		
			
				|  |  | -                    continue;
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                //等待时间后取消订单
 | 
	
		
			
				|  |  | -                try {
 | 
	
		
			
				|  |  | -                    Thread.sleep(interval);
 | 
	
		
			
				|  |  | -                } catch (InterruptedException e) {
 | 
	
		
			
				|  |  | -                    e.printStackTrace();
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                //取消订单要获取锁,防止在轮询取消时,用户修改订单状态
 | 
	
		
			
				|  |  | -                boolean b = DistributedLock.of(redissonClient)
 | 
	
		
			
				|  |  | -                        .runIfLockCanGet(CacheNameEnum.LOCK_EXECUTE_ORDER.getRedisKey(orderVo.getUserId())
 | 
	
		
			
				|  |  | -                                , () -> pollingCancelOrder(orderVo.getOrderNo()), 60L, TimeUnit.SECONDS);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }).run();
 | 
	
		
			
				|  |  | +        for (UserOrderVo orderVo : payingOrderList) {
 | 
	
		
			
				|  |  | +            //取消订单要获取锁,防止在轮询取消时,用户修改订单状态
 | 
	
		
			
				|  |  | +            boolean b = DistributedLock.of(redissonClient)
 | 
	
		
			
				|  |  | +                    .runIfLockCanGet(CacheNameEnum.LOCK_EXECUTE_ORDER.getRedisKey(orderVo.getUserId())
 | 
	
		
			
				|  |  | +                            , () -> pollingCancelOrder(orderVo.getOrderNo()), 60L, TimeUnit.SECONDS);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    private void pollingCancelOrder(String orderNo){
 | 
	
		
			
				|  |  | +    @Transactional(rollbackFor = Exception.class)
 | 
	
		
			
				|  |  | +    void pollingCancelOrder(String orderNo) {
 | 
	
		
			
				|  |  |          UserOrderVo detail = detail(orderNo);
 | 
	
		
			
				|  |  |          if (null == detail) {
 | 
	
		
			
				|  |  |              return;
 | 
	
	
		
			
				|  | @@ -475,7 +458,9 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
 | 
	
		
			
				|  |  |              try {
 | 
	
		
			
				|  |  |                  Map<String, Object> resMap = paymentSdk.queryPayment(detail.getTransNo());
 | 
	
		
			
				|  |  |                  //支付成功
 | 
	
		
			
				|  |  | -                if (TradeStatusEnum.succeeded.getCode().equals(resMap.get("status").toString())) {
 | 
	
		
			
				|  |  | +                if (TradeStatusEnum.succeeded.getCode().equals(resMap.get("status").toString())
 | 
	
		
			
				|  |  | +                        && (OrderStatusEnum.WAIT_PAY.equals(detail.getStatus())
 | 
	
		
			
				|  |  | +                        || OrderStatusEnum.PAYING.equals(detail.getStatus()))) {
 | 
	
		
			
				|  |  |                      orderSuccess(detail);
 | 
	
		
			
				|  |  |                      return;
 | 
	
		
			
				|  |  |                  }
 | 
	
	
		
			
				|  | @@ -780,24 +765,6 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
 | 
	
		
			
				|  |  |              return;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        UserOrderPayment orderPayment = orderPaymentService.detailByOrderNo(userOrder.getOrderNo());
 | 
	
		
			
				|  |  | -        if (null != orderPayment) {
 | 
	
		
			
				|  |  | -            //更新付款单
 | 
	
		
			
				|  |  | -            orderPayment.setStatus(TradeStatusEnum.failed);
 | 
	
		
			
				|  |  | -            orderPayment.setPayFailMsg(StringUtil.isEmpty(reason) ? "交易取消" : reason);
 | 
	
		
			
				|  |  | -            orderPayment.setUpdateTime(new Date());
 | 
	
		
			
				|  |  | -            //发送支付关单请求
 | 
	
		
			
				|  |  | -            HttpResponseResult<Map<String, Object>> responseResult = paymentSdk.closePayment(userOrder.getTransNo(), reason, "");
 | 
	
		
			
				|  |  | -            if (!responseResult.getStatus()) {
 | 
	
		
			
				|  |  | -                orderPayment.setCloseStatus(TradeStatusEnum.failed);
 | 
	
		
			
				|  |  | -                orderPayment.setCloseFailMsg(responseResult.getMsg());
 | 
	
		
			
				|  |  | -                orderPaymentService.updateById(orderPayment);
 | 
	
		
			
				|  |  | -                return;
 | 
	
		
			
				|  |  | -            } else {
 | 
	
		
			
				|  |  | -                orderPayment.setCloseStatus(TradeStatusEnum.pending);
 | 
	
		
			
				|  |  | -                orderPaymentService.updateById(orderPayment);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  |          List<UserOrderDetailVo> orderDetailList = orderDetailService.getOrderDetilListByOrderNo(userOrder.getOrderNo());
 | 
	
		
			
				|  |  |          for (UserOrderDetailVo orderDetailVo : orderDetailList) {
 | 
	
		
			
				|  |  |              orderDetailVo.setUserId(userOrder.getUserId());
 | 
	
	
		
			
				|  | @@ -808,10 +775,30 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
 | 
	
		
			
				|  |  |                  userOrderVoConsumer.accept(orderDetailVo);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +        userOrder.setReason(reason);
 | 
	
		
			
				|  |  |          userOrder.setStatus(orderStatus);
 | 
	
		
			
				|  |  |          userOrder.setUpdateTime(new Date());
 | 
	
		
			
				|  |  |          baseMapper.updateById(userOrder);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        UserOrderPayment orderPayment = orderPaymentService.detailByOrderNo(userOrder.getOrderNo());
 | 
	
		
			
				|  |  | +        if (null != orderPayment) {
 | 
	
		
			
				|  |  | +            //更新付款单
 | 
	
		
			
				|  |  | +            orderPayment.setStatus(TradeStatusEnum.failed);
 | 
	
		
			
				|  |  | +            orderPayment.setPayFailMsg(StringUtil.isEmpty(reason) ? "交易取消" : reason);
 | 
	
		
			
				|  |  | +            orderPayment.setUpdateTime(new Date());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        //发送支付关单请求
 | 
	
		
			
				|  |  | +        HttpResponseResult<Map<String, Object>> responseResult = paymentSdk.closePayment(userOrder.getTransNo(), reason, "");
 | 
	
		
			
				|  |  | +        if (!responseResult.getStatus()) {
 | 
	
		
			
				|  |  | +            orderPayment.setCloseStatus(TradeStatusEnum.failed);
 | 
	
		
			
				|  |  | +            orderPayment.setCloseFailMsg(responseResult.getMsg());
 | 
	
		
			
				|  |  | +            orderPaymentService.updateById(orderPayment);
 | 
	
		
			
				|  |  | +            return;
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +            orderPayment.setCloseStatus(TradeStatusEnum.pending);
 | 
	
		
			
				|  |  | +            orderPaymentService.updateById(orderPayment);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      void orderSuccess(UserOrderVo detail) {
 |