Browse Source

trade:【交易售后】回调退款

YunaiV 2 years ago
parent
commit
ee1d362a7c
12 changed files with 134 additions and 8 deletions
  1. 3 0
      yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
  2. 12 4
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java
  3. 7 2
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleDO.java
  4. 4 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/TradeAfterSaleMapper.java
  5. 7 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleService.java
  6. 40 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java
  7. 9 0
      yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/refund/PayRefundApi.java
  8. 37 0
      yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/refund/dto/PayRefundRespDTO.java
  9. 0 0
      yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderStatusEnum.java
  10. 7 0
      yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/refund/PayRefundStatusEnum.java
  11. 8 0
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/refund/PayRefundApiImpl.java
  12. 0 2
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/refund/PayRefundDO.java

+ 3 - 0
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java

@@ -34,6 +34,9 @@ public interface ErrorCodeConstants {
     ErrorCode AFTER_SALE_UPDATE_STATUS_FAIL = new ErrorCode(1011000107, "操作售后单失败,请刷新后重试");
     ErrorCode AFTER_SALE_DELIVERY_FAIL_STATUS_NOT_SELLER_PASS = new ErrorCode(1011000108, "退货失败,售后单状态不处于【待买家退货】");
     ErrorCode AFTER_SALE_CONFIRM_FAIL_STATUS_NOT_BUYER_RETURN = new ErrorCode(1011000109, "确认收货失败,售后单状态不处于【待确认收货】");
+    ErrorCode AFTER_SALE_REFUND_FAIL_PAY_REFUND_NOT_FOUND = new ErrorCode(1011000110, "退款失败,支付退款单不存在");
+    ErrorCode AFTER_SALE_REFUND_FAIL_PAY_REFUND_STATUS_NOT_SUCCESS = new ErrorCode(1011000111, "退款失败,支付退款单状态不是【成功】");
+    ErrorCode AFTER_SALE_REFUND_FAIL_STATUS_NOT_WAIT_REFUND = new ErrorCode(1011000112, "退款失败,售后单状态不是【待退款】");
 
     // ==========  Cart 模块 1-011-001-000 ==========
     ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1011002000, "购物车项不存在");

+ 12 - 4
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java

@@ -5,16 +5,15 @@ import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSal
 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleConfirmReqVO;
 import cn.iocoder.yudao.module.trade.service.aftersale.TradeAfterSaleService;
 import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
+import javax.annotation.security.PermitAll;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
@@ -46,4 +45,13 @@ public class TradeAfterSaleController {
         return success(true);
     }
 
+    @PostMapping("/refund")
+    @ApiOperation(value = "确认退款", notes = "提供给【pay】支付服务,退款成功后进行回调")
+    @ApiImplicitParam(name = "payRefundId", value = "支付退款编号", required = true, example = "18888")
+    @PermitAll
+    public CommonResult<Boolean> refundAfterSale(@RequestParam("payRefundId") Long payRefundId) {
+        afterSaleService.refundAfterSale(payRefundId);
+        return success(true);
+    }
+
 }

+ 7 - 2
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleDO.java

@@ -125,12 +125,17 @@ public class TradeAfterSaleDO extends BaseDO {
      */
     private Integer refundPrice;
     /**
-     * 支付退款编号 TODO
+     * 支付退款编号
      *
      * 对接 pay-module-biz 支付服务的退款订单编号,即 PayRefundDO 的 id 编号
      */
     private Long payRefundId;
-    // TODO 芋艿:看看是否有必要冗余,order_number、order_amount、flow_trade_no、out_refund_no、pay_type、return_money_sts、refund_time
+    /**
+     * 退款时间
+     *
+     * 退款成功后,才记录该时间
+     */
+    private LocalDateTime refundTime;
 
     // ========== 退货相关 ==========
     /**

+ 4 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/TradeAfterSaleMapper.java

@@ -13,4 +13,8 @@ public interface TradeAfterSaleMapper extends BaseMapperX<TradeAfterSaleDO> {
                 .eq(TradeAfterSaleDO::getId, id).eq(TradeAfterSaleDO::getStatus, status));
     }
 
+    default TradeAfterSaleDO selectByPayRefundId(Long payRefundId) {
+        return selectOne(TradeAfterSaleDO::getPayRefundId, payRefundId);
+    }
+
 }

+ 7 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleService.java

@@ -49,4 +49,11 @@ public interface TradeAfterSaleService {
      */
     void confirmAfterSale(Long userId, String userIp, TradeAfterSaleConfirmReqVO confirmReqVO);
 
+    /**
+     * 确认退款,由【pay】支付服务回调
+     *
+     * @param payRefundId 支付退款编号
+     */
+    void refundAfterSale(Long payRefundId);
+
 }

+ 40 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java

@@ -4,6 +4,8 @@ import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.RandomUtil;
 import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi;
 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
+import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO;
+import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleAuditReqVO;
 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleConfirmReqVO;
 import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO;
@@ -276,4 +278,42 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService {
         // TODO 发送售后消息
     }
 
+    @Override
+    public void refundAfterSale(Long payRefundId) {
+        // 校验退款单
+        PayRefundRespDTO payRefund = validatePayRefundSuccess(payRefundId);
+
+        // 校验售后单的状态,并状态待退款
+        TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectByPayRefundId(payRefundId);
+        if (afterSale == null) {
+            throw exception(AFTER_SALE_NOT_FOUND);
+        }
+        if (ObjectUtil.notEqual(afterSale.getStatus(), TradeAfterSaleStatusEnum.WAIT_REFUND.getStatus())) {
+            throw exception(AFTER_SALE_REFUND_FAIL_STATUS_NOT_WAIT_REFUND);
+        }
+
+        // 更新售后单的状态为【已完成】
+        updateAfterSaleStatus(afterSale.getId(), TradeAfterSaleStatusEnum.WAIT_REFUND.getStatus(), new TradeAfterSaleDO()
+                .setStatus(TradeAfterSaleStatusEnum.COMPLETE.getStatus()).setRefundTime(payRefund.getSuccessTime()));
+
+        // 更新交易订单项的售后状态为【已完成】
+        tradeOrderService.updateOrderItemAfterSaleStatus(afterSale.getOrderItemId(),
+                TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus());
+
+        // TODO 记录售后日志
+
+        // TODO 发送售后消息
+    }
+
+    private PayRefundRespDTO validatePayRefundSuccess(Long payRefundId) {
+        PayRefundRespDTO payRefund = payRefundApi.getPayRefund(payRefundId);
+        if (payRefund == null) {
+            throw exception(AFTER_SALE_REFUND_FAIL_PAY_REFUND_NOT_FOUND);
+        }
+        if (PayRefundStatusEnum.isSuccess(payRefund.getStatus())) {
+            throw exception(AFTER_SALE_REFUND_FAIL_PAY_REFUND_STATUS_NOT_SUCCESS);
+        }
+        return payRefund;
+    }
+
 }

+ 9 - 0
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/refund/PayRefundApi.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.pay.api.refund;
 
 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
+import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO;
 
 import javax.validation.Valid;
 
@@ -19,4 +20,12 @@ public interface PayRefundApi {
      */
     Long createPayRefund(@Valid PayRefundCreateReqDTO reqDTO);
 
+    /**
+     * 获得退款单
+     *
+     * @param id 退款单编号
+     * @return 退款单
+     */
+    PayRefundRespDTO getPayRefund(Long id);
+
 }

+ 37 - 0
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/refund/dto/PayRefundRespDTO.java

@@ -0,0 +1,37 @@
+package cn.iocoder.yudao.module.pay.api.refund.dto;
+
+import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * 退款单信息 Response DTO
+ *
+ * TODO 芋艿:还没定好字段
+ *
+ * @author 芋道源码
+ */
+@Data
+public class PayRefundRespDTO {
+
+    /**
+     * 退款单编号
+     */
+    private Long id;
+
+    // ========== 退款相关字段 ==========
+    /**
+     * 退款状态
+     *
+     * 枚举 {@link PayRefundStatusEnum}
+     */
+    private Integer status;
+
+    // ========== 渠道相关字段 ==========
+    /**
+     * 退款成功时间
+     */
+    private LocalDateTime successTime;
+
+}

+ 0 - 0
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderStatusEnum.java → yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderStatusEnum.java


+ 7 - 0
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/enums/refund/PayRefundStatusEnum.java → yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/refund/PayRefundStatusEnum.java

@@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.pay.enums.refund;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 
+import java.util.Objects;
+
 @Getter
 @AllArgsConstructor
 public enum PayRefundStatusEnum {
@@ -14,4 +16,9 @@ public enum PayRefundStatusEnum {
 
     private final Integer status;
     private final String name;
+
+    public static boolean isSuccess(Integer status) {
+        return Objects.equals(status, SUCCESS.getStatus());
+    }
+
 }

+ 8 - 0
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/refund/PayRefundApiImpl.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.pay.api.refund;
 
 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
+import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
@@ -18,4 +19,11 @@ public class PayRefundApiImpl implements PayRefundApi {
         // TODO 芋艿:暂未实现
         return null;
     }
+
+    @Override
+    public PayRefundRespDTO getPayRefund(Long id) {
+        // TODO 芋艿:暂未实现
+        return null;
+    }
+
 }

+ 0 - 2
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/refund/PayRefundDO.java

@@ -194,6 +194,4 @@ public class PayRefundDO extends BaseDO {
     private LocalDateTime notifyTime;
 
 
-
-
 }