feat(order): 实现订单未支付自动取消功能

- 新增延迟队列处理订单未支付自动取消逻辑
- 在订单创建时将订单ID加入延迟队列
- 配置订单未支付超时时间为15分钟(900秒)
- 使用Redis实现订单取消的延时队列监听与处理
- 更新缓存名称常量以支持订单延时取消队列标识
This commit is contained in:
huk 2025-09-28 18:06:42 +08:00
parent 8634a3e357
commit 5b7c78e024
5 changed files with 50 additions and 5 deletions

View File

@ -100,7 +100,7 @@
<id>local</id>
<properties>
<profiles.active>local</profiles.active>
<logging.level>warn</logging.level>
<logging.level>debug</logging.level>
<monitor.username>ruoyi</monitor.username>
<monitor.password>123456</monitor.password>
</properties>

View File

@ -81,8 +81,8 @@ public interface CacheNames {
String SYS_OSS_CONFIG = GlobalConstants.GLOBAL_REDIS_KEY + "sys_oss_config";
/**
* 在线用户
* 延时队列订单未支付取消
*/
String ONLINE_TOKEN = "online_tokens";
String DELAY_ORDER_UNPAY = GlobalConstants.GLOBAL_REDIS_KEY + "order_unpay";
}

View File

@ -72,5 +72,10 @@ public interface Constants {
*/
Long TOP_PARENT_ID = 0L;
/**
* 订单未支付自动取消时间
*/
Long ORDER_CANCEL_TIME = 900L;
}

View File

@ -44,6 +44,7 @@ import org.dromara.common.mq.domain.MQMessage;
import org.dromara.common.mq.enums.MQMessageType;
import org.dromara.common.mq.enums.MessageActionEnum;
import org.dromara.common.mq.utils.MqUtil;
import org.dromara.common.redis.utils.QueueUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.system.domain.SysTenant;
@ -60,8 +61,12 @@ import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import static org.dromara.common.core.constant.CacheNames.DELAY_ORDER_UNPAY;
import static org.dromara.common.core.constant.Constants.ORDER_CANCEL_TIME;
/**
* 订单表Service业务层处理
@ -275,6 +280,8 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
return orderItem;
}).toList();
orderItemMapper.insert(orderItemList);
// 添加订单到延迟队列
QueueUtils.addDelayedQueueObject(DELAY_ORDER_UNPAY, order.getId(), ORDER_CANCEL_TIME, TimeUnit.SECONDS);
return BeanUtil.copyProperties(order, OrderVO.class);
}

View File

@ -1,20 +1,33 @@
package com.wzj.soopin.order.task;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.wzj.soopin.order.domain.entity.Order;
import com.wzj.soopin.order.emum.OrderStatusEnum;
import com.wzj.soopin.order.service.OrderItemService;
import com.wzj.soopin.order.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.redis.utils.QueueUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.concurrent.CompletableFuture;
import static org.dromara.common.core.constant.CacheNames.DELAY_ORDER_UNPAY;
/**
* 订单相关定时任务
*
*
* @author wzj
*/
@Slf4j
@Component
public class OrderScheduledTask {
@Autowired
private OrderService orderService;
@Autowired
private OrderItemService orderItemService;
@ -32,4 +45,24 @@ public class OrderScheduledTask {
log.error("定时任务执行失败缓存交易量最多商品到Redis时发生异常", e);
}
}
}
/**
* 订阅redis延迟队列取消未支付的订单
*/
@PostConstruct
public void orderCancelByDelayedQueue() {
log.info("订单未支付延时队列: {} 监听中......",DELAY_ORDER_UNPAY);
// 项目初始化设置一次即可
QueueUtils.subscribeBlockingQueue(DELAY_ORDER_UNPAY, (Long orderId) -> {
// 观察接收时间
log.info("订单未支付延时队列: {}, 收到订单id: {}", DELAY_ORDER_UNPAY, orderId);
return CompletableFuture.runAsync(() -> {
// 异步处理数据逻辑 不要在上方处理业务逻辑
orderService.update(Wrappers.lambdaUpdate(Order.class)
.eq(Order::getId, orderId)
.eq(Order::getStatus, OrderStatusEnum.UNPAID.getValue())
.set(Order::getStatus, OrderStatusEnum.CLOSED.getValue()));
});
}, true);
}
}