支付过程中,用户长时间没有完成支付,比如限时三十分钟,如何实现订单自动关闭_

这个需求是线上项目必有的,考验大家是否真的做过线上项目,大家只需要心里有一个流程就行,细节不太需要关注。

1. 定义支付超时规则

首先,需要在订单表中设置一个 payment_timeout 字段,记录订单创建的时间,以及设定一个支付超时时间(比如 30 分钟)。

2. 记录支付开始时间

当用户创建支付订单时,需要记录订单的开始时间,例如:

@Entity
public class PaymentOrder {
    @Id
    private Long id;
    private String status;
    private LocalDateTime paymentStartTime;
    private LocalDateTime paymentTimeout;

}
Java

当用户开始支付时,记录 paymentStartTimepaymentTimeout(支付开始时间 + 30 分钟):

LocalDateTime paymentStartTime = LocalDateTime.now();
LocalDateTime paymentTimeout = paymentStartTime.plusMinutes(30);

PaymentOrder order = new PaymentOrder();
order.setPaymentStartTime(paymentStartTime);
order.setPaymentTimeout(paymentTimeout);
order.setStatus("PAYING");
paymentOrderRepository.save(order);
Java

3. 定时任务自动关闭超时订单

系统可以通过定时任务定期扫描支付订单,检查哪些订单已经超过了支付超时时间(如 30 分钟)。如果超时,则自动更新订单状态为“已关闭”或“超时”。

我们可以使用框架提供的定时任务功能(如 Spring Scheduler)定期执行超时订单检测。另外还有其他方法,如MQ的延迟队列,Redis的过期key,Redis的延迟队列,详情可以参考这个文章https://blog.csdn.net/zhangshengqiang168/article/details/104718979。在这我介绍Spring自带的定时注解,例如,在 Spring 中,你可以使用 @Scheduled 注解来创建一个定时任务,每隔一段时间检查是否有订单超时:

@Scheduled(fixedRate = 60000)  // 每 1 分钟检查一次
public void checkPaymentTimeout() {
    LocalDateTime now = LocalDateTime.now();
    //从数据库查找支付状态为支付中的订单,再将该订单的过期时间和现在的时间作比较,小于现在的时间则过期
    List<PaymentOrder> overdueOrders = paymentOrderRepository.findByStatusAndPaymentTimeoutBefore("PAYING", now);
    for (PaymentOrder order : overdueOrders) {
        order.setStatus("TIMEOUT");
        paymentOrderRepository.save(order);
        // 这里可以加入解冻库存、解锁资金等操作
        releaseStock(order.getProductId(), order.getQuantity());
    }
}
Java

4. 支付超时后的操作

当检测到订单超时,除了更新订单状态为 TIMEOUTCANCELLED,还需要进行一些资源释放操作,比如:

  • 解冻库存:如果支付超时,订单相关的商品库存需要被释放。
  • 解冻资金:如果支付过程中已冻结了用户的资金,需要解除资金冻结。
public void releaseStock(Long productId, int quantity) {
    // 解冻库存
    productService.releaseStock(productId, quantity);
}

public void releaseFunds(Long userId, BigDecimal amount) {
    // 解冻用户资金
    userService.releaseFunds(userId, amount);
}
Java

5. 用户通知

如果订单超时,可以通过通知用户(如短信、邮件、App 推送等)来告知他们支付失败或超时。这样可以减少用户不满并提供更好的用户体验。

public void sendTimeoutNotification(PaymentOrder order) {
// 发送超时通知
notificationService.sendMessage(order.getUserId(), "您的订单已超时,支付未完成。");
}
Java

6. 订单关闭后状态管理

在支付超时后,订单将被标记为 TIMEOUTCANCELLED,此时需要做以下几件事:

  • 防止重复处理:一旦订单状态变更为 TIMEOUTCANCELLED,系统应防止进一步的支付操作。比如,用户再次尝试支付时,需要先检查订单状态是否已经超时或关闭。
  • 后续操作:订单关闭后,需要根据实际情况(如是否涉及退款、库存恢复等)执行相应的操作。对于已经冻结的库存、优惠券或资金,需要通过相关接口进行解冻。

总结:订单超时自动关闭的步骤为先在订单创建时记录支付开始时间和超时时间, 定时任务监控订单 ,然后 处理超时后的资源释放 ,最后提升用户体验通知用户支付未完成。

发表评论

后才能评论