订单未支付30分钟自动取消是如何实现的?
很多时候都能看到,当下了订单后10分钟或30分钟未支付,订单会自动取消,具体是如何实现的呢?
本文使用最常用的几种方式,只说明关键的部分,已30分钟为例。
1.借助redis的过期特性
逻辑:
下单时,订单状态是待支付。将订单编号作为key,下单的时间戳作为value,设置过期时间是30分钟。服务器监听redis的key过期事件,如果是订单过期(还会有其他key过期),则修改订单的状态为已取消。当30分钟后未支付则触发redis过期事件,只需修改订单状态即可。若30分钟内支付成功,则需要删除此订单在redis的值。当然,在支付时,需要检查订单是否已超时或已支付。
关键点:
很明确,只需要在应用中添加监听器监听redis过期即可。
首先是配置redis监听器
package com.zxh.example.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.listener.RedisMessageListenerContainer; @Configuration public class RedisListenerConfig { @Bean RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(connectionFactory); return container; } }
继承redis键过期监听器,进行业务处理
package com.zxh.example.config; import com.zxh.example.service.OrderService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.connection.Message; import org.springframework.data.redis.listener.KeyExpirationEventMessageListener; import org.springframework.data.redis.listener.RedisMessageListenerContainer; import org.springframework.stereotype.Component; @Component @Slf4j public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener { @Autowired private OrderService orderService; public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) { super(listenerContainer); } @Override public void onMessage(Message message, byte[] pattern) { // message.toString()可获取失效的key String expiredKey = message.toString(); log.info("------------------redis key 失效; key = {}", expiredKey); if (expiredKey.startsWith("order")) { // 获取订单orderNo String orderNo = expiredKey.substring(expiredKey.lastIndexOf(":") + 1); // 将待支付的订单改为已取消(超时未支付) orderService.orderPaidTimeout(orderNo); } } }
注意:由于存在多个键的过期,故必须对键进行判断,是否是订单超时造成的过期。
2.使用RabbitMQ的过期队列
利用RabbitMQ的过期队列与死信队列,设置消息的存活时间,消息在设置的时间内未被消费,将其投递到死信队列,然后监听死信队列。具体请参考RabbitMQ基本入门 这篇文章
就是这么简单,你学废了吗?感觉有用的话,给笔者点个赞吧 !

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号