需求:下单超时、支付超时、退款超时逻辑处理,业务中对应订单状态要根据redis-key失效之后做订单状态变更的处理。 实现思路:在下单业务中设置失效key,利用redis失效key的事件监听,conf中配置 notify-keyspace-events "Ex" /** * redis 失效key监听配置类 */ @Configuration public class RedisListenerConfig { @Bean RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(connectionFactory); return container; } }
/** * 监听redis-key过期 */ @Component @Log4j2 public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener { public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) { super(listenerContainer); } /** * 监听 redis key失效,触发订单状态流转 * @param message * @param pattern * @descripe redis.conf文件 需 追加参数【 notify-keyspace-events "Ex"】 */ @Override public void onMessage(Message message, byte[] pattern) { PaymentsService paymentsService = SpringContextHolder.getBean(PaymentsService.class); OrderService orderService = SpringContextHolder.getBean(OrderService.class); // 获取到失效的 key,进行取消订单业务处理 String expiredKey = message.toString(); String[] strKey = expiredKey.split("-"); Long orderId = Long.valueOf(strKey[2]); log.info("过期的订单主键 :{}", orderId); RedisLock redisLock = new RedisLock(SpringContextHolder.getBean(StringRedisTemplate.class), NrOrderConstant.ORDER_REDIS_LOCK + orderId); try { if (redisLock.lockBlock()) { NrOrder nrOrder = orderService.getById(orderId); NrPayment nrPayment = SpringContextHolder.getBean(PaymentsService.class) .getOne(Wrappers.<NrPayment>lambdaQuery() .eq(NrPayment::getOrderNo, nrOrder.getOrderNo())); switch (strKey[0]) { //待支付订单超时处理 case "order": //待支付超时 nrPayment.setStatus(PayOrderStateEnum.UNPAID_TIMEOUT.value()); //超时关闭 nrOrder.setStatus(OrderStateEnum.TIMEOUT.value()); paymentsService.updateById(nrPayment); orderService.updateById(nrOrder); //保存订单状态历史 OrderUtil.addHistory(nrOrder, OrderUserType.SYSTEM); break; case "pay": //支付中超时 nrPayment.setStatus(PayOrderStateEnum.PAYOFF_TIMEOUT.value()); //订单异常 nrOrder.setStatus(OrderStateEnum.PAID_FAILED.value()); paymentsService.updateById(nrPayment); orderService.updateById(nrOrder); //保存订单状态历史 OrderUtil.addHistory(nrOrder, OrderUserType.SYSTEM); break; //退款超时 case "refund": NrRefundItemService refundItemService = SpringContextHolder .getBean(NrRefundItemService.class); NrRefundService refundService = SpringContextHolder .getBean(NrRefundService.class); //获取退款单ids List<Long> refundIdList = refundItemService .list(Wrappers.<NrRefundItem>lambdaQuery() .eq(NrRefundItem::getOrderNo, nrOrder.getOrderNo())) .stream().map(NrRefundItem::getNrRefundId).collect( Collectors.toList()); List<NrRefund> nrRefundList = refundService.listByIds(refundIdList); //退款超时 nrRefundList.forEach(nrRefund -> { nrRefund.setStatus(RefundOrderStateEnum.REFUND_TIMEOUT.value()); nrRefund.setMessage("退款超时"); }); refundService.updateBatchById(nrRefundList); break; default: break; } } } finally { redisLock.unlock(); } } }