8.16 解决业务bug 营销订单可能未付款,这种情况下退单也调用了支付宝退单接口

This commit is contained in:
zhangsan 2025-08-16 12:25:40 +08:00
parent 7fc2af3327
commit e00c94f982
2 changed files with 58 additions and 66 deletions

View File

@ -147,79 +147,31 @@ public class OrderService extends AbstractOrderService{
} }
/** /**
* 预备退单 * 公共退款逻辑根据订单状态决定退单方式
*/ */
@Override private boolean doRefund(OrderEntity orderEntity) {
public boolean preRefundOrder(String userId, String orderId) { String userId = orderEntity.getUserId();
// 1. 查单 String orderId = orderEntity.getOrderId();
OrderEntity orderEntity = repository.queryOrderByUserIdAndOrderId(userId, orderId);
if (orderEntity == null) {
log.warn("退单失败,订单不存在或不属于该用户 userId:{} orderId:{}", userId, orderId);
return false;
}
String status = orderEntity.getOrderStatusVO().getCode(); String status = orderEntity.getOrderStatusVO().getCode();
// 已关闭直接拒绝
if (OrderStatusVO.CLOSE.getCode().equals(status)) {
log.warn("退单失败,订单已关闭 userId:{} orderId:{} status:{}", userId, orderId, status);
return false;
}
// 2. 营销锁单走营销通道 + 统一改库 // 1. 未付款仅改库
int marketType = orderEntity.getMarketType(); // 建议后续用枚举替代裸常量
if (marketType == 1) {
try {
port.refundMarketPayOrder(userId, orderId);
} catch (Exception e) {
// 这里按你的容忍度决定是否直接返回 false
log.error("营销退单通道异常 userId:{} orderId:{} err:{}", userId, orderId, e.getMessage(), e);
return false;
}
boolean result = repository.refundMarketOrder(userId, orderId);
if (result) {
log.info("营销退单成功(已改库) userId:{} orderId:{}", userId, orderId);
} else {
log.warn("营销退单失败(改库失败) userId:{} orderId:{}", userId, orderId);
}
return result;
}
// 3. 普通订单分未付款 / 已付款
if (OrderStatusVO.CREATE.getCode().equals(status) if (OrderStatusVO.CREATE.getCode().equals(status)
|| OrderStatusVO.PAY_WAIT.getCode().equals(status)) { || OrderStatusVO.PAY_WAIT.getCode().equals(status)) {
// 未付款仅改库
boolean result = repository.refundOrder(userId, orderId); boolean result = repository.refundOrder(userId, orderId);
if (result) { if (result) {
log.info("普通未付款退单成功(仅改库) userId:{} orderId:{}", userId, orderId); log.info("退款成功(未付款订单,仅改库) userId:{} orderId:{}", userId, orderId);
} else { } else {
log.warn("普通未付款退单失败(改库失败) userId:{} orderId:{}", userId, orderId); log.warn("退款失败(未付款订单改库失败) userId:{} orderId:{}", userId, orderId);
} }
return result; return result;
} else {
// 已付款三方退款 + 改库用你已有的方法
return refundPayOrder(userId, orderId);
}
} }
/** // 2. 已付款三方退款 + 改库
* 真正的退钱关闭订单逻辑 boolean dbOk = false;
*/
@Override
public boolean refundPayOrder(String userId, String orderId) /* throws AlipayApiException */ {
// 1. 查询订单信息验证订单是否存在且属于该用户
OrderEntity orderEntity = repository.queryOrderByUserIdAndOrderId(userId, orderId);
if (orderEntity == null) {
log.warn("退款失败,订单不存在或不属于该用户 userId:{} orderId:{}", userId, orderId);
return false;
}
boolean dbOk = false; // 以落库结果为最终返回
try { try {
// 2. 调用支付宝退款沙箱里允许失败
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest(); AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
AlipayTradeRefundModel refundModel = new AlipayTradeRefundModel(); AlipayTradeRefundModel refundModel = new AlipayTradeRefundModel();
refundModel.setOutTradeNo(orderEntity.getOrderId()); refundModel.setOutTradeNo(orderId);
refundModel.setRefundAmount(orderEntity.getPayAmount().toString()); refundModel.setRefundAmount(orderEntity.getPayAmount().toString());
refundModel.setRefundReason("交易退单"); refundModel.setRefundReason("交易退单");
request.setBizModel(refundModel); request.setBizModel(refundModel);
@ -228,16 +180,13 @@ public class OrderService extends AbstractOrderService{
if (resp.isSuccess()) { if (resp.isSuccess()) {
log.info("支付宝退款成功 userId:{} orderId:{}", userId, orderId); log.info("支付宝退款成功 userId:{} orderId:{}", userId, orderId);
} else { } else {
// 不影响后续改库
log.warn("支付宝退款失败(沙箱忽略) code={}, subCode={}, msg={}", log.warn("支付宝退款失败(沙箱忽略) code={}, subCode={}, msg={}",
resp.getCode(), resp.getSubCode(), resp.getSubMsg()); resp.getCode(), resp.getSubCode(), resp.getSubMsg());
} }
} catch (Exception e) { } catch (Exception e) {
// 捕获所有异常避免抛出导致 MQ 重试
log.error("调用支付宝退款异常(沙箱忽略) userId:{} orderId:{} err:{}", log.error("调用支付宝退款异常(沙箱忽略) userId:{} orderId:{} err:{}",
userId, orderId, e.getMessage(), e); userId, orderId, e.getMessage(), e);
} finally { } finally {
// 3. 必须执行状态变更你要求的必须执行
try { try {
dbOk = repository.refundOrder(userId, orderId); dbOk = repository.refundOrder(userId, orderId);
if (dbOk) { if (dbOk) {
@ -246,14 +195,57 @@ public class OrderService extends AbstractOrderService{
log.warn("订单状态更新失败 userId:{} orderId:{}", userId, orderId); log.warn("订单状态更新失败 userId:{} orderId:{}", userId, orderId);
} }
} catch (Exception de) { } catch (Exception de) {
// 落库异常要打日志并返回 false交由上层决定是否重试/告警
log.error("订单状态更新异常 userId:{} orderId:{} err:{}", log.error("订单状态更新异常 userId:{} orderId:{} err:{}",
userId, orderId, de.getMessage(), de); userId, orderId, de.getMessage(), de);
dbOk = false; dbOk = false;
} }
} }
// 返回以数据库落库为准支付宝失败在沙箱场景被忽略
return dbOk; return dbOk;
} }
/**
* 预备退单
*/
@Override
public boolean preRefundOrder(String userId, String orderId) {
OrderEntity orderEntity = repository.queryOrderByUserIdAndOrderId(userId, orderId);
if (orderEntity == null) {
log.warn("退单失败,订单不存在或不属于该用户 userId:{} orderId:{}", userId, orderId);
return false;
}
String status = orderEntity.getOrderStatusVO().getCode();
if (OrderStatusVO.CLOSE.getCode().equals(status)) {
log.warn("退单失败,订单已关闭 userId:{} orderId:{} status:{}", userId, orderId, status);
return false;
}
int marketType = orderEntity.getMarketType();
if (marketType == 1) {
try {
port.refundMarketPayOrder(userId, orderId);
} catch (Exception e) {
log.error("营销退单通道异常 userId:{} orderId:{} err:{}", userId, orderId, e.getMessage(), e);
return false;
}
return repository.refundMarketOrder(userId, orderId);
}
// 普通订单走统一逻辑
return doRefund(orderEntity);
}
/**
* 真正的退款逻辑 MQ 或别的地方直接调
*/
@Override
public boolean refundPayOrder(String userId, String orderId) {
OrderEntity orderEntity = repository.queryOrderByUserIdAndOrderId(userId, orderId);
if (orderEntity == null) {
log.warn("退款失败,订单不存在或不属于该用户 userId:{} orderId:{}", userId, orderId);
return false;
}
return doRefund(orderEntity);
}
} }

View File

@ -14,8 +14,8 @@ public class ProductRPC {
public ProductDTO queryProductByProductId(String productId){ public ProductDTO queryProductByProductId(String productId){
ProductDTO productVO = new ProductDTO(); ProductDTO productVO = new ProductDTO();
productVO.setProductId(productId); productVO.setProductId(productId);
productVO.setProductName("MyBatisBook"); productVO.setProductName("早晨从中午开始");
productVO.setProductDesc("MyBatisBook"); productVO.setProductDesc("早晨从中午开始");
productVO.setPrice(new BigDecimal("100.00")); productVO.setPrice(new BigDecimal("100.00"));
return productVO; return productVO;
} }