取消售货机接口返回失败原路退款功能,售货机存在接口返回失败扔出货的情况
This commit is contained in:
1 parent
cc4ec95819
commit
fbc2cf433a
4 files changed
+13
-73
No files matched your search
+1
-5
@@ -18,11 +18,7 @@ public enum TradeOrderCancelTypeEnum implements ArrayValuable<Integer> {
|
||||
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);
|
||||
|
||||
|
||||
-8
@@ -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);
|
||||
|
||||
/**
|
||||
* 更新下单赠送的优惠券编号到订单
|
||||
*
|
||||
|
||||
-48
@@ -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<Long> giveCouponIds) {
|
||||
// 1. 检验订单存在
|
||||
|
||||
+12
-12
@@ -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());
|
||||
|
||||
Reference in new issue
Block a user