Эх сурвалжийг харах

fix(order): 优化海博订单状态同步及退款逻辑异常处理

- 在HBOrderService中增加甯傛皯璇烽泦璁㈠崟状态同步接口调用
- 取消订单和完成订单状态变更时添加异常捕获,避免推送失败导致影响业务流程
- OrderServiceImpl退款计算时使用Optional避免空指针,增强健壮性
- 添加日志警告用于订单项不存在情况的提醒
- XSBRefundOrderService新增甯傛皯璇烽泦售后申请接口,区分全额退款同步策略
- 完整退款时新增判断区分传统与甯傛皯璇烽泦流程状态同步行为
- 统一处理积分和退款金额计算中的空值,防止异常发生
Sheep 1 долоо хоног өмнө
parent
commit
b9f0a25a12

+ 27 - 2
yami-shop-service/src/main/java/com/yami/shop/service/hb/impl/HBOrderService.java

@@ -192,11 +192,18 @@ public class HBOrderService implements IHBOrderService {
             order.setHbOrderStatus(80);
         }
         orderMapper.updateById(order);
+        if (isSmqjhOrder) {
+            syncSmqjhOrderStatus(channelOrderId, order.getHbOrderStatus());
+        }
 
         //取消订单
         if (operatorType == 60) {
             log.info("取消订单{}", channelOrderId);
-            changeOrderStatus(channelOrderId, 60);
+            try {
+                changeOrderStatus(channelOrderId, 60);
+            } catch (Exception e) {
+                log.error("海博订单取消回调中推送HB状态失败,orderNumber: {}", channelOrderId, e);
+            }
             if (!isSmqjhOrder) {
                 //创建退款单
                 OrderRefundParam orderRefundParam = new OrderRefundParam();
@@ -351,7 +358,11 @@ public class HBOrderService implements IHBOrderService {
         }
         //成功直接通知海博
         if (order.getHbOrderStatus() == 80) {
-            changeOrderStatus(channelOrderId, OrderStatus.SUCCESS.value());
+            try {
+                changeOrderStatus(channelOrderId, OrderStatus.SUCCESS.value());
+            } catch (Exception e) {
+                log.error("海博订单完成回调中推送HB状态失败,orderNumber: {}", channelOrderId, e);
+            }
         }
 
         //TODO 市民请集合海博状态通知
@@ -370,6 +381,20 @@ public class HBOrderService implements IHBOrderService {
         }
     }
 
+    private void syncSmqjhOrderStatus(String orderNumber, Integer hbOrderStatus) {
+        try {
+            Map<Object, Object> map = new LinkedTreeMap<>();
+            map.put("orderNumber", orderNumber);
+            map.put("hbOrderStatus", hbOrderStatus);
+            String syncResult = HttpUtil.post(smqjhUtil.getOmsBaseUrl() + "/api/v1/xsb/order/updateHbOrderStatus", map);
+            log.info("甯傛皯璇烽泦鍚?鎺ㄩ€丱MS璁㈠崟鐘舵€佺粨鏋滐紝orderNumber: {}, operatorType: {}, result: {}",
+                    orderNumber, hbOrderStatus, syncResult);
+        } catch (Exception e) {
+            log.error("甯傛皯璇烽泦鍚?鎺ㄩ€丱MS璁㈠崟鐘舵€佸け璐ワ紝orderNumber: {}, operatorType: {}",
+                    orderNumber, hbOrderStatus, e);
+        }
+    }
+
     @Override
     public void updateLogisticStatus(JSONObject hBRequest) {
         log.info("海博订单更新通知请求参数{}", hBRequest);

+ 13 - 6
yami-shop-service/src/main/java/com/yami/shop/service/impl/OrderServiceImpl.java

@@ -1663,20 +1663,25 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
                         double totalRefundActual = 0.0;//需要退的总金额
                         int shoppingScore = 0;
                         for (OrderRefundSku refundSkus : orderRefundSkus) {
-                            Integer productCount = refundSkus.getProductCount();//退款的数量
+                            Integer productCount = Optional.ofNullable(refundSkus.getProductCount()).orElse(0);//退款的数量
                             OrderItem orderItem = orderItemMapper.selectById(refundSkus.getOrderItemId());
-                            Double actualTotal = orderItem.getActualTotal();//付的钱
-                            Integer useScore = orderItem.getUseScore();//使用的总积分
+                            if (orderItem == null) {
+                                log.warn("退款统计时订单项不存在,orderItemId={}", refundSkus.getOrderItemId());
+                                continue;
+                            }
+                            Double actualTotal = Optional.ofNullable(orderItem.getActualTotal()).orElse(0D);//付的钱
+                            Integer useScore = Optional.ofNullable(orderItem.getUseScore()).orElse(0);//使用的总积分
+                            Double itemPrice = Optional.ofNullable(orderItem.getPrice()).orElse(0D);
                             if (ObjectUtil.isNotEmpty(order.getOffsetPoints())) {
                                 shoppingScore = order.getOffsetPoints().intValue() + freightAmountScore;//退款商品的总积分
                             }
 
                             if (useScore > 0) {
                                 //退的积分不一定等于下单的数量
-                                totalRefundScore = (totalRefundScore + productCount * ((int) Arith.mul(orderItem.getPrice(), 100)));
+                                totalRefundScore = (totalRefundScore + productCount * ((int) Arith.mul(itemPrice, 100)));
                             }
                             if (actualTotal > 0) {
-                                totalRefundActual = Arith.add(totalRefundActual, productCount * orderItem.getPrice());
+                                totalRefundActual = Arith.add(totalRefundActual, productCount * itemPrice);
                             }
                         }
                         log.info("退款积分:refundOffsetPoints:" + refundOffsetPoints + ";shoppingScore:" + shoppingScore + ";totalRefundScore:" + totalRefundScore);
@@ -1685,7 +1690,9 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
                             refundScore = (long) totalRefundScore;
                             for (PointsRecord pointsRecord : pointsRecords) {
                                 //下单支付的金额
-                                int variablePoints = pointsRecord.getVariablePoints().intValue();//574
+                                int variablePoints = Optional.ofNullable(pointsRecord.getVariablePoints())
+                                        .map(BigDecimal::intValue)
+                                        .orElse(0);//574
                                 PointsRecord npr = new PointsRecord();
                                 BeanUtils.copyProperties(pointsRecord, npr);
                                 npr.setId(null);

+ 2 - 0
yami-shop-service/src/main/java/com/yami/shop/service/xsb/XSBRefundOrderService.java

@@ -13,6 +13,8 @@ public interface XSBRefundOrderService {
      */
     R<String> applyAfterSales(RefundOrderPushVo refundOrderPushVo,String logId);
 
+    R<String> applySmqjhAfterSales(RefundOrderPushVo refundOrderPushVo, String logId);
+
     /**
      * 同步物流修改信息
      * @param orderRefundExpressParam

+ 16 - 2
yami-shop-service/src/main/java/com/yami/shop/service/xsb/impl/XSBRefundOrderServiceImpl.java

@@ -83,6 +83,17 @@ public class XSBRefundOrderServiceImpl implements XSBRefundOrderService {
     @Transactional
     @Override
     public R<String> applyAfterSales(RefundOrderPushVo refundOrderPushVo,String logId) {
+        return applyAfterSalesInternal(refundOrderPushVo, logId, true);
+    }
+
+    @Transactional
+    @Override
+    public R<String> applySmqjhAfterSales(RefundOrderPushVo refundOrderPushVo, String logId) {
+        return applyAfterSalesInternal(refundOrderPushVo, logId, false);
+    }
+
+    private R<String> applyAfterSalesInternal(RefundOrderPushVo refundOrderPushVo, String logId,
+                                              boolean syncHbCloseOnEntireRefund) {
         R<String> stringR = checkParameter(refundOrderPushVo);
         if (!stringR.isSuccess()){
             return stringR;
@@ -251,14 +262,17 @@ public class XSBRefundOrderServiceImpl implements XSBRefundOrderService {
         log.info("【"+logId+"】"+"渠道推送申请退款:创建海博退款单,生成海博退款单信息{}", orderRefund);
         orderRefundService.createRefundOrder(orderRefund.getOrderNumber(), orderRefund.getRefundSn());
 
-        // Only entire-order refunds sync Haibo order status to CLOSE(60).
-        if (Objects.equals(refundOrderPushVo.getRefundType(), RefundType.ALL.value())) {
+        // The legacy XSB flow keeps the original behavior, while the SMQJH flow
+        // waits for merchant-side action before the Haibo order is closed.
+        if (syncHbCloseOnEntireRefund && Objects.equals(refundOrderPushVo.getRefundType(), RefundType.ALL.value())) {
             try {
                 hbOrderService.changeOrderStatus(order.getOrderNumber(), OrderStatus.CLOSE.value());
                 log.info("[{}] refund apply: entire-order refund, sync Haibo status to 60", logId);
             } catch (Exception e) {
                 log.error("[{}] refund apply: failed to sync Haibo status to 60", logId, e);
             }
+        } else if (Objects.equals(refundOrderPushVo.getRefundType(), RefundType.ALL.value())) {
+            log.info("[{}] refund apply: smqjh flow keeps Haibo order status unchanged until merchant-side action", logId);
         } else {
             log.info("[{}] refund apply: partial refund, keep Haibo order status unchanged", logId);
         }