ソースを参照

fix: 用户端退款申请不立即执行,改为创建PENDING记录等待管理员审核

- refund(Map) 默认仅创建退款申请记录,不执行第三方退款
- 新增 immediate 参数,管理员直接退款时传入 immediate=true 即时执行
- 管理后台 OrderController 传入 immediate=true
- 小程序 PaymentController 提示语改为"退款申请已提交,请等待审核"

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
skyline 2 週間 前
コミット
75e7b6967c

+ 1 - 0
haha-admin/src/main/java/com/haha/admin/controller/OrderController.java

@@ -115,6 +115,7 @@ public class OrderController {
         Map<String, Object> params = new HashMap<>();
         params.put("orderId", id);
         params.put("reason", dto.getReason() != null ? dto.getReason() : "管理员退款");
+        params.put("immediate", true); // 管理员直接退款,立即执行
 
         // 如果有商品明细,传入商品列表
         if (dto.getProducts() != null && !dto.getProducts().isEmpty()) {

+ 16 - 5
haha-miniapp/src/main/java/com/haha/miniapp/controller/PaymentController.java

@@ -155,16 +155,27 @@ public class PaymentController {
      * @param params 退款参数
      * @return 退款结果
      */
+    /**
+     * 退款申请
+     * POST /api/payment/refund
+     *
+     * 用户提交退款申请,创建退款记录(PENDING),由管理员审核后执行。
+     * 请求参数:
+     * - orderId: 订单ID(必填)
+     * - reason: 退款原因(可选)
+     * - products: 退款商品列表(可选)
+     * - refundAmount: 自定义退款金额(可选)
+     */
     @PostMapping("/refund")
     public Result<RefundResult> refund(@RequestBody Map<String, Object> params) {
         try {
             RefundResult result = paymentService.refund(params);
 
             if (result.isSuccess()) {
-                log.info("退款成功 - 订单ID: {}, 退款单号: {}", params.get("orderId"), result.getRefundId());
-                return Result.success("退款成功", result);
+                log.info("退款申请已提交 - 订单ID: {}, 退款单号: {}", params.get("orderId"), result.getRefundId());
+                return Result.success("退款申请已提交,请等待审核", result);
             } else {
-                log.warn("退款失败 - 订单ID: {}, 错误: {}", params.get("orderId"), result.getErrorMsg());
+                log.warn("退款申请失败 - 订单ID: {}, 错误: {}", params.get("orderId"), result.getErrorMsg());
                 return ResponseEnum.OPERATION_FAILED.toResult(result.getErrorMsg());
             }
 
@@ -172,8 +183,8 @@ public class PaymentController {
             log.error("参数格式错误", e);
             return ResponseEnum.PARAM_FORMAT_ERROR.toResult("参数格式错误:orderId 必须为数字");
         } catch (Exception e) {
-            log.error("退款失败", e);
-            return ResponseEnum.OPERATION_FAILED.toResult("退款失败:" + e.getMessage());
+            log.error("退款申请失败", e);
+            return ResponseEnum.OPERATION_FAILED.toResult("退款申请失败:" + e.getMessage());
         }
     }
 

+ 26 - 23
haha-service/src/main/java/com/haha/service/payment/impl/PaymentServiceImpl.java

@@ -541,43 +541,46 @@ public class PaymentServiceImpl implements PaymentService {
             customRefundAmount = new BigDecimal(params.get("refundAmount").toString());
         }
 
-        // 如果指定了商品或自定义金额,走部分退款流程
-        boolean hasProducts = products != null && !products.isEmpty();
-        boolean hasCustomAmount = customRefundAmount != null;
-        if (hasProducts || hasCustomAmount) {
-            try {
-                // 创建退款记录(PENDING),内部完成金额计算和校验
-                com.haha.entity.Refund refundRecord = refundService.createRefundRecord(orderId, reason, products, customRefundAmount);
-                BigDecimal refundAmount = refundRecord.getRefundAmount();
-
-                // 执行第三方退款
-                RefundResult result = refund(orderId, reason, refundAmount);
+        // 是否立即执行退款(管理员直接退款 vs 用户提交申请)
+        boolean immediate = params.containsKey("immediate") && Boolean.TRUE.equals(params.get("immediate"));
+
+        try {
+            // 创建退款记录(PENDING)
+            com.haha.entity.Refund refundRecord = refundService.createRefundRecord(orderId, reason, products, customRefundAmount);
+            BigDecimal refundAmount = refundRecord.getRefundAmount();
 
+            if (immediate) {
+                // 管理员直接退款:立即执行第三方退款
+                RefundResult result = refund(orderId, reason, refundAmount);
                 if (result.isSuccess()) {
                     refundService.markRefunded(refundRecord.getId(), result.getRefundId());
-                    // 更新订单关联的退款记录ID
                     Order order = orderService.getById(orderId);
                     if (order != null) {
                         order.setCurrentRefundId(refundRecord.getId());
                         orderService.updateById(order);
                     }
-                    log.info("退款成功(含商品明细) - orderId: {}, refundId: {}, amount: {}, items: {}",
-                            orderId, refundRecord.getId(), refundAmount, products != null ? products.size() : 0);
+                    log.info("管理员直接退款成功 - orderId: {}, refundId: {}, amount: {}",
+                            orderId, refundRecord.getId(), refundAmount);
                 }
                 return result;
-            } catch (Exception e) {
-                log.error("退款失败 - orderId: {}, error: {}", orderId, e.getMessage());
+            } else {
+                // 用户端提交:仅创建申请,等待管理员审核
+                log.info("退款申请已创建,等待审核 - orderId: {}, refundId: {}, amount: {}, items: {}",
+                        orderId, refundRecord.getId(), refundRecord.getRefundAmount(),
+                        products != null ? products.size() : 0);
                 return RefundResult.builder()
-                        .success(false)
-                        .errorCode("REFUND_ERROR")
-                        .errorMsg(e.getMessage())
+                        .success(true)
+                        .refundId(String.valueOf(refundRecord.getId()))
                         .build();
             }
+        } catch (Exception e) {
+            log.error("退款申请失败 - orderId: {}, error: {}", orderId, e.getMessage());
+            return RefundResult.builder()
+                    .success(false)
+                    .errorCode("REFUND_ERROR")
+                    .errorMsg(e.getMessage())
+                    .build();
         }
-
-        // 无商品选择、无自定义金额 → 全额退款(兼容旧行为)
-        log.info("退款请求(全额) - 订单ID: {}, 原因: {}", orderId, reason);
-        return refund(orderId, reason);
     }
 
     @Override