package com.izouma.nineth.service; import com.izouma.nineth.config.GeneralProperties; import com.izouma.nineth.domain.Order; import com.izouma.nineth.domain.SysConfig; import com.izouma.nineth.enums.OrderStatus; import com.izouma.nineth.exception.BusinessException; import com.izouma.nineth.repo.*; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import java.time.LocalDateTime; import java.util.List; @Service @ConditionalOnProperty(value = "general.notify-server", havingValue = "true") @Slf4j @AllArgsConstructor public class OrderCancelService { private final GeneralProperties generalProperties; private final OrderRepo orderRepo; private final OrderService orderService; private final SysConfigRepo sysConfigRepo; private final MintOrderRepo mintOrderRepo; private final MintOrderService mintOrderService; private final GiftOrderRepo giftOrderRepo; private final GiftOrderService giftOrderService; private final OrderPayService orderPayService; private final RedisTemplate redisTemplate; private final AuctionOrderRepo auctionOrderRepo; private final AuctionOrderService auctionOrderService; private static int orderCancelInterval = 210; public static void setOrderCancelInterval(int orderCancelInterval) { log.info("设置订单取消时间间隔为 {}S", orderCancelInterval); OrderCancelService.orderCancelInterval = orderCancelInterval; } @PostConstruct public void init() { orderCancelInterval = sysConfigRepo.findByName("order_cancel_time") .map(SysConfig::getValue).map(Integer::parseInt).orElse(210); } @Scheduled(fixedRate = 30000, initialDelay = 10000) @RedisLock(value = "order_batch_cancel", expire = 3, unit = TimeUnit.MINUTES) public void batchCancel() { List orders = orderRepo.findByStatusAndCreatedAtBeforeAndDelFalse(OrderStatus.NOT_PAID, LocalDateTime.now().minusSeconds(orderCancelInterval)); orders.parallelStream().forEach(o -> { try { Order order = orderRepo.findById(o.getId()).orElseThrow(new BusinessException("订单不存在")); if (order.getStatus() == OrderStatus.NOT_PAID && canCancel(order.getId().toString())) { orderService.cancel(order); } } catch (Exception e) { log.error("取消订单错误 " + o.getId(), e); } }); } @Scheduled(fixedRate = 30000, initialDelay = 20000) @RedisLock(value = "mint_order_batch_cancel", expire = 3, unit = TimeUnit.MINUTES) public void batchCancelMintOrder() { List orders = mintOrderRepo.findByStatusAndCreatedAtBeforeAndDelFalse(MintOrderStatus.NOT_PAID, LocalDateTime.now().minusSeconds(orderCancelInterval)); orders.forEach(o -> { try { MintOrder order = mintOrderRepo.findById(o.getId()).orElseThrow(new BusinessException("订单不存在")); if (order.getStatus() == MintOrderStatus.NOT_PAID && canCancel(order.getId().toString())) { mintOrderService.cancel(order, false); } } catch (Exception ignored) { } }); } @Scheduled(fixedRate = 30000, initialDelay = 30000) @RedisLock(value = "gift_order_batch_cancel", expire = 3, unit = TimeUnit.MINUTES) public void batchCancelGiftOrder() { List orders = giftOrderRepo.findByStatusAndCreatedAtBeforeAndDelFalse(OrderStatus.NOT_PAID, LocalDateTime.now().minusSeconds(orderCancelInterval)); orders.forEach(o -> { try { GiftOrder order = giftOrderRepo.findById(o.getId()).orElseThrow(new BusinessException("订单不存在")); if (order.getStatus() == OrderStatus.NOT_PAID && canCancel(order.getId().toString())) { giftOrderService.cancel(order); } } catch (Exception ignored) { } }); } private boolean canCancel(String id) { String channel = null; Object payTmp = redisTemplate.opsForValue().get(RedisKeys.PAY_TMP + id); log.info("payTmp {}", payTmp); if (payTmp != null) { channel = (String) payTmp; } PayQuery query = new PayQuery(); try { query = orderPayService.query(id, channel); } catch (Exception e) { query.setExist(false); } if (query.isExist()) { if (query.getStatus() != null) { switch (query.getStatus()) { case SUCCESS: case PENDING: log.info("订单 {}, 状态 {}, 不能取消", id, query.getStatus().name()); return false; default: log.info("订单 {}, 状态 {}, 可以取消", id, query.getStatus().name()); return true; } } } return true; } @Scheduled(fixedRate = 30000) public void batchCancelledAuctionOrder() { List orders = auctionOrderRepo .findByStatusAndCreatedAtBeforeAndDelFalse(AuctionOrderStatus.NOT_PAID, LocalDateTime.now().minusSeconds(orderCancelInterval)); orders.parallelStream().forEach(o -> { try { AuctionOrder order = auctionOrderRepo.findById(o.getId()).orElseThrow(new BusinessException("订单不存在")); if (order.getStatus() == AuctionOrderStatus.NOT_PAID) { auctionOrderService.cancel(order); } } catch (Exception e) { log.error("取消拍卖订单错误 " + o.getId(), e); } }); } }