Commit ee1d362a7ccac4c917ac2ae8ccbda0663683ec77

Authored by YunaiV
1 parent 67050eea

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

Showing 12 changed files with 134 additions and 8 deletions
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 {
34 34 ErrorCode AFTER_SALE_UPDATE_STATUS_FAIL = new ErrorCode(1011000107, "操作售后单失败,请刷新后重试");
35 35 ErrorCode AFTER_SALE_DELIVERY_FAIL_STATUS_NOT_SELLER_PASS = new ErrorCode(1011000108, "退货失败,售后单状态不处于【待买家退货】");
36 36 ErrorCode AFTER_SALE_CONFIRM_FAIL_STATUS_NOT_BUYER_RETURN = new ErrorCode(1011000109, "确认收货失败,售后单状态不处于【待确认收货】");
  37 + ErrorCode AFTER_SALE_REFUND_FAIL_PAY_REFUND_NOT_FOUND = new ErrorCode(1011000110, "退款失败,支付退款单不存在");
  38 + ErrorCode AFTER_SALE_REFUND_FAIL_PAY_REFUND_STATUS_NOT_SUCCESS = new ErrorCode(1011000111, "退款失败,支付退款单状态不是【成功】");
  39 + ErrorCode AFTER_SALE_REFUND_FAIL_STATUS_NOT_WAIT_REFUND = new ErrorCode(1011000112, "退款失败,售后单状态不是【待退款】");
37 40  
38 41 // ========== Cart 模块 1-011-001-000 ==========
39 42 ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1011002000, "购物车项不存在");
... ...
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
5 5 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleConfirmReqVO;
6 6 import cn.iocoder.yudao.module.trade.service.aftersale.TradeAfterSaleService;
7 7 import io.swagger.annotations.Api;
  8 +import io.swagger.annotations.ApiImplicitParam;
8 9 import io.swagger.annotations.ApiOperation;
9 10 import lombok.extern.slf4j.Slf4j;
10 11 import org.springframework.security.access.prepost.PreAuthorize;
11 12 import org.springframework.validation.annotation.Validated;
12   -import org.springframework.web.bind.annotation.PutMapping;
13   -import org.springframework.web.bind.annotation.RequestBody;
14   -import org.springframework.web.bind.annotation.RequestMapping;
15   -import org.springframework.web.bind.annotation.RestController;
  13 +import org.springframework.web.bind.annotation.*;
16 14  
17 15 import javax.annotation.Resource;
  16 +import javax.annotation.security.PermitAll;
18 17  
19 18 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
20 19 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
... ... @@ -46,4 +45,13 @@ public class TradeAfterSaleController {
46 45 return success(true);
47 46 }
48 47  
  48 + @PostMapping("/refund")
  49 + @ApiOperation(value = "确认退款", notes = "提供给【pay】支付服务,退款成功后进行回调")
  50 + @ApiImplicitParam(name = "payRefundId", value = "支付退款编号", required = true, example = "18888")
  51 + @PermitAll
  52 + public CommonResult<Boolean> refundAfterSale(@RequestParam("payRefundId") Long payRefundId) {
  53 + afterSaleService.refundAfterSale(payRefundId);
  54 + return success(true);
  55 + }
  56 +
49 57 }
... ...
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 {
125 125 */
126 126 private Integer refundPrice;
127 127 /**
128   - * 支付退款编号 TODO
  128 + * 支付退款编号
129 129 *
130 130 * 对接 pay-module-biz 支付服务的退款订单编号,即 PayRefundDO 的 id 编号
131 131 */
132 132 private Long payRefundId;
133   - // TODO 芋艿:看看是否有必要冗余,order_number、order_amount、flow_trade_no、out_refund_no、pay_type、return_money_sts、refund_time
  133 + /**
  134 + * 退款时间
  135 + *
  136 + * 退款成功后,才记录该时间
  137 + */
  138 + private LocalDateTime refundTime;
134 139  
135 140 // ========== 退货相关 ==========
136 141 /**
... ...
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&lt;TradeAfterSaleDO&gt; {
13 13 .eq(TradeAfterSaleDO::getId, id).eq(TradeAfterSaleDO::getStatus, status));
14 14 }
15 15  
  16 + default TradeAfterSaleDO selectByPayRefundId(Long payRefundId) {
  17 + return selectOne(TradeAfterSaleDO::getPayRefundId, payRefundId);
  18 + }
  19 +
16 20 }
... ...
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 {
49 49 */
50 50 void confirmAfterSale(Long userId, String userIp, TradeAfterSaleConfirmReqVO confirmReqVO);
51 51  
  52 + /**
  53 + * 确认退款,由【pay】支付服务回调
  54 + *
  55 + * @param payRefundId 支付退款编号
  56 + */
  57 + void refundAfterSale(Long payRefundId);
  58 +
52 59 }
... ...
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;
4 4 import cn.hutool.core.util.RandomUtil;
5 5 import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi;
6 6 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
  7 +import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO;
  8 +import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
7 9 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleAuditReqVO;
8 10 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleConfirmReqVO;
9 11 import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO;
... ... @@ -276,4 +278,42 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService {
276 278 // TODO 发送售后消息
277 279 }
278 280  
  281 + @Override
  282 + public void refundAfterSale(Long payRefundId) {
  283 + // 校验退款单
  284 + PayRefundRespDTO payRefund = validatePayRefundSuccess(payRefundId);
  285 +
  286 + // 校验售后单的状态,并状态待退款
  287 + TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectByPayRefundId(payRefundId);
  288 + if (afterSale == null) {
  289 + throw exception(AFTER_SALE_NOT_FOUND);
  290 + }
  291 + if (ObjectUtil.notEqual(afterSale.getStatus(), TradeAfterSaleStatusEnum.WAIT_REFUND.getStatus())) {
  292 + throw exception(AFTER_SALE_REFUND_FAIL_STATUS_NOT_WAIT_REFUND);
  293 + }
  294 +
  295 + // 更新售后单的状态为【已完成】
  296 + updateAfterSaleStatus(afterSale.getId(), TradeAfterSaleStatusEnum.WAIT_REFUND.getStatus(), new TradeAfterSaleDO()
  297 + .setStatus(TradeAfterSaleStatusEnum.COMPLETE.getStatus()).setRefundTime(payRefund.getSuccessTime()));
  298 +
  299 + // 更新交易订单项的售后状态为【已完成】
  300 + tradeOrderService.updateOrderItemAfterSaleStatus(afterSale.getOrderItemId(),
  301 + TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus());
  302 +
  303 + // TODO 记录售后日志
  304 +
  305 + // TODO 发送售后消息
  306 + }
  307 +
  308 + private PayRefundRespDTO validatePayRefundSuccess(Long payRefundId) {
  309 + PayRefundRespDTO payRefund = payRefundApi.getPayRefund(payRefundId);
  310 + if (payRefund == null) {
  311 + throw exception(AFTER_SALE_REFUND_FAIL_PAY_REFUND_NOT_FOUND);
  312 + }
  313 + if (PayRefundStatusEnum.isSuccess(payRefund.getStatus())) {
  314 + throw exception(AFTER_SALE_REFUND_FAIL_PAY_REFUND_STATUS_NOT_SUCCESS);
  315 + }
  316 + return payRefund;
  317 + }
  318 +
279 319 }
... ...
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/refund/PayRefundApi.java
1 1 package cn.iocoder.yudao.module.pay.api.refund;
2 2  
3 3 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
  4 +import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO;
4 5  
5 6 import javax.validation.Valid;
6 7  
... ... @@ -19,4 +20,12 @@ public interface PayRefundApi {
19 20 */
20 21 Long createPayRefund(@Valid PayRefundCreateReqDTO reqDTO);
21 22  
  23 + /**
  24 + * 获得退款单
  25 + *
  26 + * @param id 退款单编号
  27 + * @return 退款单
  28 + */
  29 + PayRefundRespDTO getPayRefund(Long id);
  30 +
22 31 }
... ...
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/refund/dto/PayRefundRespDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.pay.api.refund.dto;
  2 +
  3 +import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
  4 +import lombok.Data;
  5 +
  6 +import java.time.LocalDateTime;
  7 +
  8 +/**
  9 + * 退款单信息 Response DTO
  10 + *
  11 + * TODO 芋艿:还没定好字段
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@Data
  16 +public class PayRefundRespDTO {
  17 +
  18 + /**
  19 + * 退款单编号
  20 + */
  21 + private Long id;
  22 +
  23 + // ========== 退款相关字段 ==========
  24 + /**
  25 + * 退款状态
  26 + *
  27 + * 枚举 {@link PayRefundStatusEnum}
  28 + */
  29 + private Integer status;
  30 +
  31 + // ========== 渠道相关字段 ==========
  32 + /**
  33 + * 退款成功时间
  34 + */
  35 + private LocalDateTime successTime;
  36 +
  37 +}
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderStatusEnum.java renamed to yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderStatusEnum.java
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/enums/refund/PayRefundStatusEnum.java renamed to 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;
3 3 import lombok.AllArgsConstructor;
4 4 import lombok.Getter;
5 5  
  6 +import java.util.Objects;
  7 +
6 8 @Getter
7 9 @AllArgsConstructor
8 10 public enum PayRefundStatusEnum {
... ... @@ -14,4 +16,9 @@ public enum PayRefundStatusEnum {
14 16  
15 17 private final Integer status;
16 18 private final String name;
  19 +
  20 + public static boolean isSuccess(Integer status) {
  21 + return Objects.equals(status, SUCCESS.getStatus());
  22 + }
  23 +
17 24 }
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/refund/PayRefundApiImpl.java
1 1 package cn.iocoder.yudao.module.pay.api.refund;
2 2  
3 3 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
  4 +import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO;
4 5 import org.springframework.stereotype.Service;
5 6 import org.springframework.validation.annotation.Validated;
6 7  
... ... @@ -18,4 +19,11 @@ public class PayRefundApiImpl implements PayRefundApi {
18 19 // TODO 芋艿:暂未实现
19 20 return null;
20 21 }
  22 +
  23 + @Override
  24 + public PayRefundRespDTO getPayRefund(Long id) {
  25 + // TODO 芋艿:暂未实现
  26 + return null;
  27 + }
  28 +
21 29 }
... ...
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 {
194 194 private LocalDateTime notifyTime;
195 195  
196 196  
197   -
198   -
199 197 }
... ...