Ver código fonte

新建一个接口,通过订单id进行退款

zhangchen 1 mês atrás
pai
commit
f51c561eb8

+ 24 - 0
alien-store/src/main/java/shop/alien/store/controller/StoreReservationController.java

@@ -272,4 +272,28 @@ public class StoreReservationController {
             return R.fail("退款失败:" + e.getMessage());
         }
     }
+
+    @ApiOperationSupport(order = 9)
+    @ApiOperation("通过订单ID退款(根据订单自动带出门店、商户订单号、金额、支付方式,成功时发送通知和短信)")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "orderId", value = "预订订单ID(user_reservation_order.id)", required = true, paramType = "query", dataType = "int"),
+            @ApiImplicitParam(name = "refundReason", value = "退款原因", required = false, paramType = "query", dataType = "String"),
+            @ApiImplicitParam(name = "refundType", value = "退款类型 0:用户取消 1:商家退款 2:部分退款等 3.扫码核销成功", required = false, paramType = "query", dataType = "int")
+    })
+    @PostMapping("/refundByOrderId")
+    public R<String> refundByOrderId(
+            @RequestParam Integer orderId,
+            @RequestParam(required = false) String refundReason,
+            @RequestParam(required = false) Integer refundType) {
+        log.info("StoreReservationController.refundByOrderId?orderId={}, refundReason={}, refundType={}", orderId, refundReason, refundType);
+        if (orderId == null) {
+            return R.fail("订单ID不能为空");
+        }
+        try {
+            return storeReservationService.refundByOrderId(orderId, refundReason, refundType);
+        } catch (Exception e) {
+            log.error("通过订单ID退款失败", e);
+            return R.fail("退款失败:" + e.getMessage());
+        }
+    }
 }

+ 8 - 0
alien-store/src/main/java/shop/alien/store/service/MerchantPaymentOrderService.java

@@ -29,6 +29,14 @@ public interface MerchantPaymentOrderService extends IService<MerchantPaymentOrd
     MerchantPaymentOrder getUnpaidByOrderId(Integer orderId);
 
     /**
+     * 根据业务订单ID查询已支付支付单(pay_status=1),用于按订单退款时获取 payType 等
+     *
+     * @param orderId user_reservation_order.id
+     * @return 已支付单,不存在返回 null
+     */
+    MerchantPaymentOrder getPaidByOrderId(Integer orderId);
+
+    /**
      * 查询近期创建的待支付单(用于无异步回调时的后端轮询同步)
      *
      * @param withinMinutes 在最近多少分钟内创建的

+ 11 - 1
alien-store/src/main/java/shop/alien/store/service/StoreReservationService.java

@@ -84,6 +84,16 @@ public interface StoreReservationService {
      * @param payType 支付类型 alipay/wechatPay
      * @return 退款结果
      */
-    shop.alien.entity.result.R<String> refundByOrder(Integer storeId, String outTradeNo, String refundAmount, 
+    shop.alien.entity.result.R<String> refundByOrder(Integer storeId, String outTradeNo, String refundAmount,
                                                        String refundReason, Integer refundType, String payType);
+
+    /**
+     * 通过预订订单ID退款(根据订单查出门店、商户订单号、金额、支付方式后调用支付退款,成功时发送通知和短信)
+     *
+     * @param orderId     预订订单ID(user_reservation_order.id)
+     * @param refundReason 退款原因,可选
+     * @param refundType   退款类型,可选,默认 1-商家退款
+     * @return 退款结果
+     */
+    shop.alien.entity.result.R<String> refundByOrderId(Integer orderId, String refundReason, Integer refundType);
 }

+ 13 - 0
alien-store/src/main/java/shop/alien/store/service/impl/MerchantPaymentOrderServiceImpl.java

@@ -70,6 +70,19 @@ public class MerchantPaymentOrderServiceImpl extends ServiceImpl<MerchantPayment
     }
 
     @Override
+    public MerchantPaymentOrder getPaidByOrderId(Integer orderId) {
+        if (orderId == null) {
+            return null;
+        }
+        LambdaQueryWrapper<MerchantPaymentOrder> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(MerchantPaymentOrder::getOrderId, orderId);
+        wrapper.eq(MerchantPaymentOrder::getPayStatus, 1);
+        wrapper.eq(MerchantPaymentOrder::getOrderType, "reservation_order");
+        wrapper.last("LIMIT 1");
+        return this.getOne(wrapper);
+    }
+
+    @Override
     public MerchantPaymentOrder getUnpaidByOrderId(Integer orderId) {
         if (orderId == null) {
             return null;

+ 41 - 0
alien-store/src/main/java/shop/alien/store/service/impl/StoreReservationServiceImpl.java

@@ -6,6 +6,7 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import shop.alien.entity.store.MerchantPaymentOrder;
 import shop.alien.entity.store.StoreBookingTable;
 import shop.alien.entity.store.StoreInfo;
 import shop.alien.entity.store.UserReservation;
@@ -23,6 +24,7 @@ import shop.alien.store.config.BaseRedisService;
 import shop.alien.store.listener.RedisKeyExpirationHandler;
 import shop.alien.store.service.StoreBookingTableService;
 import shop.alien.store.service.StoreInfoService;
+import shop.alien.store.service.MerchantPaymentOrderService;
 import shop.alien.store.service.StoreReservationService;
 import shop.alien.store.service.UserReservationOrderService;
 import shop.alien.store.service.StoreBookingBusinessHoursService;
@@ -75,6 +77,7 @@ public class StoreReservationServiceImpl extends ServiceImpl<StoreReservationMap
     private final StoreBookingBusinessHoursService storeBookingBusinessHoursService;
     private final StoreBookingSettingsService storeBookingSettingsService;
     private final EssentialHolidayComparisonMapper essentialHolidayComparisonMapper;
+    private final MerchantPaymentOrderService merchantPaymentOrderService;
 
     /** 预约状态:已取消 */
     private static final int STATUS_CANCELLED = 3;
@@ -1366,4 +1369,42 @@ public class StoreReservationServiceImpl extends ServiceImpl<StoreReservationMap
         }
         return null;
     }
+
+    @Override
+    public shop.alien.entity.result.R<String> refundByOrderId(Integer orderId, String refundReason, Integer refundType) {
+        log.info("StoreReservationServiceImpl.refundByOrderId?orderId={}, refundReason={}, refundType={}", orderId, refundReason, refundType);
+        if (orderId == null) {
+            return shop.alien.entity.result.R.fail("订单ID不能为空");
+        }
+        UserReservationOrder order = userReservationOrderService.getById(orderId);
+        if (order == null) {
+            return shop.alien.entity.result.R.fail("预订订单不存在");
+        }
+        if (order.getPaymentStatus() == null || order.getPaymentStatus() != 1) {
+            return shop.alien.entity.result.R.fail("订单未支付或已退款,无法退款");
+        }
+        if (order.getOrderCostType() == null || order.getOrderCostType() != 1) {
+            return shop.alien.entity.result.R.fail("免费订单无需退款");
+        }
+        if (order.getOutTradeNo() == null || order.getOutTradeNo().trim().isEmpty()) {
+            return shop.alien.entity.result.R.fail("订单无商户订单号,无法退款");
+        }
+        MerchantPaymentOrder paymentOrder = merchantPaymentOrderService.getPaidByOrderId(orderId);
+        if (paymentOrder == null || paymentOrder.getPayType() == null || paymentOrder.getPayType().trim().isEmpty()) {
+            return shop.alien.entity.result.R.fail("未找到已支付记录或支付方式,无法退款");
+        }
+        String amount = order.getDepositAmount() != null ? order.getDepositAmount().toString() : null;
+        if (amount == null || amount.trim().isEmpty()) {
+            return shop.alien.entity.result.R.fail("订单订金金额异常,无法退款");
+        }
+        String reason = refundReason != null && !refundReason.trim().isEmpty() ? refundReason.trim() : "按订单退款";
+        int type = refundType != null ? refundType : 1;
+        try {
+            MerchantPaymentStrategy strategy = merchantPaymentStrategyFactory.getStrategy(paymentOrder.getPayType());
+            return strategy.refund(order.getStoreId(), order.getOutTradeNo(), amount, reason, type);
+        } catch (Exception e) {
+            log.error("通过订单ID退款异常,orderId={}", orderId, e);
+            return shop.alien.entity.result.R.fail("退款失败:" + e.getMessage());
+        }
+    }
 }