diff --git a/ebike-payment/src/main/java/com/cdzy/payment/config/WxPayConfig.java b/ebike-payment/src/main/java/com/cdzy/payment/config/WxPayConfig.java index 4345e6d..9a6e791 100644 --- a/ebike-payment/src/main/java/com/cdzy/payment/config/WxPayConfig.java +++ b/ebike-payment/src/main/java/com/cdzy/payment/config/WxPayConfig.java @@ -59,14 +59,20 @@ public class WxPayConfig { private String refundNotifyUrl; /** * 支付、退款过期时间(分钟) - * 默认24小时,超过24小时订单会自动关闭 + * 默认2小时,超过2小时订单会自动关闭 */ - private Integer expireMinute = 1440; + private Integer expireMinute = 120; + + /** + * 定时任务单次查寻最大条数 + */ + private Integer queryLimit = 100; + /** * 支付状态检查定时任务执行表达式 - * 默认每12小时执行1次 + * 默认每2小时执行1次 */ - private String paySchedule = "0 0 0/12 * * ?"; + private String paySchedule = "0 0 0/2 * * ?"; /** * 退款状态检查定时任务执行表达式 * 默认每30分钟执行1次 diff --git a/ebike-payment/src/main/java/com/cdzy/payment/service/EbikeOrderService.java b/ebike-payment/src/main/java/com/cdzy/payment/service/EbikeOrderService.java index 9c3764b..a75d823 100644 --- a/ebike-payment/src/main/java/com/cdzy/payment/service/EbikeOrderService.java +++ b/ebike-payment/src/main/java/com/cdzy/payment/service/EbikeOrderService.java @@ -47,4 +47,11 @@ public interface EbikeOrderService extends IService { * @param orderId 订单ID */ void rejectRefund(Long orderId); + + /** + * 取消订单 + * + * @param orderId 订单id + */ + void cancelOrder(Long orderId); } diff --git a/ebike-payment/src/main/java/com/cdzy/payment/service/EbikePaymentService.java b/ebike-payment/src/main/java/com/cdzy/payment/service/EbikePaymentService.java index 00fc0a8..b774bd5 100644 --- a/ebike-payment/src/main/java/com/cdzy/payment/service/EbikePaymentService.java +++ b/ebike-payment/src/main/java/com/cdzy/payment/service/EbikePaymentService.java @@ -23,7 +23,7 @@ public interface EbikePaymentService extends IService { * @param duration 订单创建时间超过duration分钟,单位分钟 * @return 未支付订单列表 */ - List getNoPayNotTimeOutOrder(int duration); + List getNoPayNotTimeOutOrder(int duration, int queryLimit); /** * 查询未支付订单, 超时的 @@ -31,7 +31,7 @@ public interface EbikePaymentService extends IService { * @param duration 订单创建时间超过duration分钟,单位分钟 * @return 未支付订单列表 */ - List getNoPayOvertimeOrder(int duration); + List getNoPayOvertimeOrder(int duration, int queryLimit); /** * 更新支付状态 @@ -64,4 +64,11 @@ public interface EbikePaymentService extends IService { * @return 支付记录详情 */ EbikePayment getByOrderId(Long orderId); + + /** + * 取消支付订单 + * + * @param paymentId 支付id + */ + void cancelPayment(Long paymentId); } diff --git a/ebike-payment/src/main/java/com/cdzy/payment/service/EbikeRefundService.java b/ebike-payment/src/main/java/com/cdzy/payment/service/EbikeRefundService.java index b4cc1f6..98781ea 100644 --- a/ebike-payment/src/main/java/com/cdzy/payment/service/EbikeRefundService.java +++ b/ebike-payment/src/main/java/com/cdzy/payment/service/EbikeRefundService.java @@ -23,7 +23,7 @@ public interface EbikeRefundService extends IService { * @param duration 订单创建时间超过duration分钟,单位分钟 * @return 未成功退款订单列表 */ - List getNoSuccessRefundOrderByDuration(int duration); + List getNoSuccessRefundOrderByDuration(int duration, int queryLimit); /** * 更新退款状态 diff --git a/ebike-payment/src/main/java/com/cdzy/payment/service/impl/EbikeOrderServiceImpl.java b/ebike-payment/src/main/java/com/cdzy/payment/service/impl/EbikeOrderServiceImpl.java index d5b48c6..2fe7632 100644 --- a/ebike-payment/src/main/java/com/cdzy/payment/service/impl/EbikeOrderServiceImpl.java +++ b/ebike-payment/src/main/java/com/cdzy/payment/service/impl/EbikeOrderServiceImpl.java @@ -74,4 +74,14 @@ public class EbikeOrderServiceImpl extends ServiceImpl getNoPayNotTimeOutOrder(int duration) { + public List getNoPayNotTimeOutOrder(int duration, int queryLimit) { // 未支付状态(已超时),创建时间 >= 当前时间 - duration 分钟 + LocalDateTime cutoffTime = LocalDateTime.now().minusMinutes(duration); QueryWrapper query = QueryWrapper.create() - .where(EBIKE_PAYMENT.TRADE_STATUS.eq(Transaction.TradeStateEnum.NOTPAY.ordinal())) - .and(createTimeFilter(duration, ">=")); + .where(EBIKE_PAYMENT.TRADE_STATUS.eq(EbikeOrderStatus.PENDING_PAYMENT)) + .ge(EbikePayment::getCreateTime, cutoffTime) + .limit(queryLimit); return list(query); } @Override - public List getNoPayOvertimeOrder(int duration) { + public List getNoPayOvertimeOrder(int duration, int queryLimit) { // 未支付状态(未超时),创建时间 < 当前时间 - duration 分钟 + LocalDateTime cutoffTime = LocalDateTime.now().minusMinutes(duration); QueryWrapper query = QueryWrapper.create() - .where(EBIKE_PAYMENT.TRADE_STATUS.eq(Transaction.TradeStateEnum.NOTPAY.ordinal())) - .and(createTimeFilter(duration, "<")); + .where(EBIKE_PAYMENT.TRADE_STATUS.eq(EbikeOrderStatus.PENDING_PAYMENT)) + .lt(EbikePayment::getCreateTime, cutoffTime) + .limit(queryLimit); return list(query); } @Override public Boolean updatePaymentStatus(Transaction transaction) { EbikePayment ebikePayment = getByPaymentId(transaction.getOutTradeNo()); + if (Objects.isNull(ebikePayment)) { + log.warn("未找到本地订单,outTradeNo: {}", transaction.getOutTradeNo()); + return false; + } ebikePayment.setTradeStatus(transaction.getTradeState().ordinal()); if (Transaction.TradeStateEnum.SUCCESS.equals(transaction.getTradeState())) { - // 支付成功, 更新订单状态 + // 支付成功, 更新支付状态 BigDecimal totalAmount = calculateTotalAmount(transaction); ebikePayment.setTotal(totalAmount); String paymentTime = transaction.getSuccessTime(); ebikePayment.setPaymentTime(StringUtils.toLocalDatetime(paymentTime)); ebikePayment.setTransactionId(transaction.getTransactionId()); - // 同步支付状态 + // 同步订单状态 EbikeOrderPaymentDto paymentParam = new EbikeOrderPaymentDto(); paymentParam.setOrderId(ebikePayment.getOrderId()); paymentParam.setPaymentTime(ebikePayment.getPaymentTime()); paymentParam.setPaymentMethod(PaymentMethod.WECHAT); ebikeOrderService.payment(paymentParam); + } else if (Transaction.TradeStateEnum.CLOSED.equals(transaction.getTradeState())) { + // 微信订单已取消,同步更新订单为取消 + ebikeOrderService.cancelOrder(ebikePayment.getOrderId()); } return updateById(ebikePayment); } @@ -143,6 +157,18 @@ public class EbikePaymentServiceImpl extends ServiceImpl getNoSuccessRefundOrderByDuration(int duration) { - // trade_state 等于2(退款状态中), 并且创建时间超过duration分钟的订单 - int totalSeconds = duration * 60; - - String timeFilter = String.format( - "%s + INTERVAL '%d seconds' <= NOW()", - EBIKE_REFUND.CREATE_TIME.getName(), - totalSeconds - ); + public List getNoSuccessRefundOrderByDuration(int duration, int queryLimit) { + // 查询创建时间已超过指定分钟数、且退款状态仍为“处理中”的退款单。 + LocalDateTime cutoffTime = LocalDateTime.now().minusMinutes(duration); QueryWrapper query = QueryWrapper.create() .where(EBIKE_REFUND.REFUND_STATUS.eq(RefundStatus.PROCESSING)) - .and(timeFilter); + .lt(EbikeRefund::getCreateTime, cutoffTime) + .limit(queryLimit); return list(query); } @@ -69,7 +67,11 @@ public class EbikeRefundServiceImpl extends ServiceImpl ebikeOrderService.refund(orderId); + // 退款中 + case PROCESSING -> ebikeOrderService.refund(orderId); + // 退款成功 case SUCCESS -> ebikeOrderService.doneRefund(orderId); - case ABNORMAL -> ebikeOrderService.failRefund(orderId); + // 退款失败/关闭 → 订单“退款失败” + case ABNORMAL, CLOSED -> ebikeOrderService.failRefund(orderId); } return updateById(ebikeRefund); } diff --git a/ebike-payment/src/main/java/com/cdzy/payment/task/WxPayTask.java b/ebike-payment/src/main/java/com/cdzy/payment/task/WxPayTask.java index 8a88237..424e8e7 100644 --- a/ebike-payment/src/main/java/com/cdzy/payment/task/WxPayTask.java +++ b/ebike-payment/src/main/java/com/cdzy/payment/task/WxPayTask.java @@ -13,6 +13,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.List; +import java.util.Objects; /** * 用户订单支付任务。检测支付状态,更新订单状态。 @@ -38,54 +39,64 @@ public class WxPayTask { /** - * 查询创建未超过24小时,并且未支付的订单 + * 查询创建未超过2小时,并且未支付的订单 */ public void checkOrderStatus() { log.info("checkOrderStatus 执行......"); // 1. 查询未支付的未超时的订单 - List ebikePaymentList = ebikePaymentService.getNoPayNotTimeOutOrder(wxPayConfig.getExpireMinute()); + List ebikePaymentList = ebikePaymentService.getNoPayNotTimeOutOrder(wxPayConfig.getExpireMinute(), wxPayConfig.getQueryLimit()); + if (ebikePaymentList.isEmpty()) { + log.debug("当前无未支付订单"); + return; + } + log.info("共发现 {} 笔待检查订单", ebikePaymentList.size()); // 2. 遍历订单,查询支付状态 for (EbikePayment ebikePayment : ebikePaymentList) { - log.warn("未支付的订单号 ===> {}", ebikePayment.getOrderId()); + log.info("未支付的订单号 ===> {}", ebikePayment.getOrderId()); // 调用微信支付查询接口,查询支付状态 Transaction transaction = wxPayService.queryOrderByOutTradeNo(String.valueOf(ebikePayment.getTradeId())); - // 3. 更新订单状态 - if (transaction != null) { + if (Objects.nonNull(transaction)) { + // 更新订单状态 ebikePaymentService.updatePaymentStatus(transaction); } } } /** - * 查询创建超过24小时,并且未支付的订单 + * 查询创建超过2小时,并且未支付的订单 直接关闭订单 【未使用】 */ public void closeOrder() { log.info("closeOrder 执行......"); // 1. 查询未支付的超时订单 - List ebikePaymentList = ebikePaymentService.getNoPayOvertimeOrder(wxPayConfig.getExpireMinute()); + List ebikePaymentList = ebikePaymentService.getNoPayOvertimeOrder(wxPayConfig.getExpireMinute(), wxPayConfig.getQueryLimit()); + if (ebikePaymentList.isEmpty()) { + log.debug("当前无超时未支付订单"); + return; + } + log.info("共发现 {} 笔超时订单,准备处理...", ebikePaymentList.size()); // 2. 遍历订单,关闭订单 for (EbikePayment ebikePayment : ebikePaymentList) { log.warn("超时未支付的订单号 ===> {}", ebikePayment.getOrderId()); - // 调用微信支付关闭接口,关闭订单 - boolean close = wxPayService.closeOrder(String.valueOf(ebikePayment.getTradeId())); - if (close) { - // 3. 更新订单状态 - Transaction transaction = new Transaction(); - transaction.setTradeState(Transaction.TradeStateEnum.CLOSED); - transaction.setTradeStateDesc("订单关闭"); - ebikePaymentService.updatePaymentStatus(transaction); - } + // 调用微信支付关闭接口,关闭订单(*超时微信会自动关闭) + //boolean close = wxPayService.closeOrder(String.valueOf(ebikePayment.getTradeId())); + // 更新订单状态 订单状态变为取消、支付订单状态变为取消 + ebikePaymentService.cancelPayment(ebikePayment.getPaymentId()); } } /** - * 查询创建未超过24小时,并且未成功的退款单 + * 查询创建未超过2小时,并且未成功的退款单 */ public void checkRefundStatus() { log.info("checkRefundStatus 执行......"); // 1. 查询未成功的退款单 - List ebikeRefundList = ebikeRefundService.getNoSuccessRefundOrderByDuration(wxPayConfig.getExpireMinute()); + List ebikeRefundList = ebikeRefundService.getNoSuccessRefundOrderByDuration(wxPayConfig.getExpireMinute(), wxPayConfig.getQueryLimit()); + if (ebikeRefundList.isEmpty()) { + log.debug("当前无退款中的退款单"); + return; + } + log.info("共发现 {} 笔待处理的退款单", ebikeRefundList.size()); // 2. 遍历退款单,查询退款状态 for (EbikeRefund ebikeRefund : ebikeRefundList) { log.warn("超时未退款的退款单号 ===> {}", ebikeRefund.getRefundId()); diff --git a/ebike-payment/src/main/resources/application-dev.yml b/ebike-payment/src/main/resources/application-dev.yml index fcbf394..f6740d9 100644 --- a/ebike-payment/src/main/resources/application-dev.yml +++ b/ebike-payment/src/main/resources/application-dev.yml @@ -56,8 +56,9 @@ payment: public-key-id: PUB_KEY_ID_0117151470052025042500331704000601 pay-notify_url: https://www.cdzhuojing.cn/ebike/payment/wxPayment/notify/pay refund-notify_url: https://www.cdzhuojing.cn/ebike/payment/wxPayment/notify/refund - expire-minutes: 1440 - pay-schedule: 0 0 0/12 * * ? + expire-minute: 120 + query-limit: 100 + pay-schedule: 0 0 0/2 * * ? refund-schedule: 0 0/30 * * * ? task-scheduler-pool: poolSize: 100