diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderCancelTypeEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderCancelTypeEnum.java index 31d17fb..b614f78 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderCancelTypeEnum.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderCancelTypeEnum.java @@ -18,11 +18,7 @@ public enum TradeOrderCancelTypeEnum implements ArrayValuable { PAY_TIMEOUT(10, "超时未支付"), AFTER_SALE_CLOSE(20, "退款关闭"), MEMBER_CANCEL(30, "买家取消"), - COMBINATION_CLOSE(40, "拼团关闭"), - DEVICE_FAIL(50, "设备出货失败"); - /** - * 设备出货失败(例如:售货机接口返回缺货/无响应等) - */ + COMBINATION_CLOSE(40, "拼团关闭"); public static final Integer[] ARRAYS = Arrays.stream(values()).map(TradeOrderCancelTypeEnum::getType).toArray(Integer[]::new); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java index fa70edd..a3badfb 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java @@ -209,14 +209,6 @@ public interface TradeOrderUpdateService { */ void cancelPaidOrder(Long userId, Long orderId, Integer cancelType); - /** - * 设备出货失败:取消订单并发起原路退款 - * - * @param userId 用户编号 - * @param orderId 订单编号 - */ - void cancelPaidOrderByDeviceFail(Long userId, Long orderId); - /** * 更新下单赠送的优惠券编号到订单 * diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index 4022377..4c3a595 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -75,8 +75,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.transaction.support.TransactionSynchronization; -import org.springframework.transaction.support.TransactionSynchronizationManager; import javax.annotation.Resource; import javax.validation.constraints.NotNull; @@ -1017,52 +1015,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { .setReason(TradeOrderCancelTypeEnum.COMBINATION_CLOSE.getName()).setPrice(order.getPayPrice())); // 价格信息 } - @Override - @Transactional(rollbackFor = Exception.class) - public void cancelPaidOrderByDeviceFail(Long userId, Long orderId) { - // 1. 校验订单存在 - TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(orderId, userId); - if (order == null) { - throw exception(ORDER_NOT_FOUND); - } - - // 2. 校验订单是否支付 - if (!order.getPayStatus()) { - throw exception(ORDER_CANCEL_PAID_FAIL, "未支付"); - } - - // 3. 校验订单是否未退款(避免重复触发退款) - if (ObjUtil.notEqual(TradeOrderRefundStatusEnum.NONE.getStatus(), order.getRefundStatus())) { - return; - } - - // 4. 取消订单(会触发 TradeOrderHandler.afterCancelOrder,从而回补库存) - cancelOrder0(order, TradeOrderCancelTypeEnum.DEVICE_FAIL); - - // 5. 事务提交后发起退款,避免退款创建失败导致回滚库存 - TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { - @Override - public void afterCommit() { - // 0元订单通常没有实际支付资金,跳过退款创建避免无意义的退款单 - if (order.getPayPrice() == null || order.getPayPrice() <= 0) { - return; - } - try { - payRefundApi.createRefund(new PayRefundCreateReqDTO() - .setAppKey(tradeOrderProperties.getPayAppKey()) - .setUserIp(NetUtil.getLocalhostStr()) - .setMerchantOrderId(String.valueOf(order.getId())) - .setMerchantRefundId(String.valueOf(order.getId())) - .setReason(TradeOrderCancelTypeEnum.DEVICE_FAIL.getName()) - .setPrice(order.getPayPrice())); - } catch (Exception e) { - log.error("[cancelPaidOrderByDeviceFail][order({}) 发起退款失败]: {}", order.getId(), - e.getMessage(), e); - } - } - }); - } - @Override public void updateOrderGiveCouponIds(Long userId, Long orderId, List giveCouponIds) { // 1. 检验订单存在 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeDeviceOrderHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeDeviceOrderHandler.java index 79ee2e3..e26518b 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeDeviceOrderHandler.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeDeviceOrderHandler.java @@ -13,18 +13,17 @@ import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.trade.controller.admin.devicelog.vo.DeviceLogSaveReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; import cn.iocoder.yudao.module.trade.service.devicelog.DeviceLogService; import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; -import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService; import cn.iocoder.yudao.module.trade.service.order.bo.DispenseRequestBo; import cn.iocoder.yudao.module.trade.service.order.bo.DispenseResponseBo; import cn.iocoder.yudao.module.trade.service.order.bo.DispenseResultStatusEnum; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Lazy; import org.springframework.http.*; import org.springframework.stereotype.Component; import org.springframework.web.client.HttpClientErrorException; @@ -54,7 +53,7 @@ import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_RECEI * 3. 校验订单是否只涉及一种通道类型(同一个 cabinetType) * 4. 按设备协议格式组装出货指令 message,并调用 xr.cabinet.api_url 出货 * 5. 将出货结果写入“贩卖机出货日志” - * 6. 最后尝试将订单状态从当前状态更新为 COMPLETED(已完成) + * 6. 最后尝试将订单状态从当前状态更新为 COMPLETED(已完成);设备接口失败时仍会完成订单(支付不退),仅按 allocation 回补库存 * * @author 芋道源码 */ @@ -62,9 +61,6 @@ import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_RECEI @Slf4j public class TradeDeviceOrderHandler implements TradeOrderHandler { - @Resource - @Lazy // 延迟加载,避免循环依赖 - private TradeOrderUpdateService orderUpdateService; @Resource private TradeOrderQueryService orderQueryService; @@ -226,13 +222,17 @@ public class TradeDeviceOrderHandler implements TradeOrderHandler { order.getNo(), request.getDeviceId(), request.getMessage()); boolean dispenseSuccess = sendDispenseRequest(order, request, deviceLogSaveReqVO); - // 5.1 设备出货失败:取消订单并发起原路退款 + // 5.1 设备出货失败:按下单时扣减的货道回补库存(不取消订单、不退款) if (!dispenseSuccess) { - orderUpdateService.cancelPaidOrderByDeviceFail(order.getUserId(), order.getId()); - return; + try { + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems)); + log.warn("[售货机出货]订单:{} 设备出货失败,已回补库存(按 stockDeductionAllocation)", order.getNo()); + } catch (Exception e) { + log.error("[售货机出货]订单:{} 设备出货失败后回补库存异常: {}", order.getNo(), e.getMessage(), e); + } } - // 6. 出货成功:将订单状态更新为已完成 + // 6. 无论出货成功/失败,尝试将订单状态更新为已完成(保持原有语义) completeOrder(order); } @@ -560,8 +560,8 @@ public class TradeDeviceOrderHandler implements TradeOrderHandler { * 将订单状态更新为“已完成” * * 说明: - * - 出货成功后:将订单状态从当前状态更新为 COMPLETED - * - 如果状态不符合预期(例如已经被取消),则抛出业务异常 + * - 无论设备出货成功/失败,都会尝试将订单状态从当前状态更新为 COMPLETED + * - 如果状态不符合预期(例如已经不是“待发货/待收货”),则抛出业务异常 */ private void completeOrder(TradeOrderDO order) { TradeOrderDO tradeOrderDO = tradeOrderMapper.selectById(order.getId());