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,6 +34,9 @@ public interface ErrorCodeConstants {
34 ErrorCode AFTER_SALE_UPDATE_STATUS_FAIL = new ErrorCode(1011000107, "操作售后单失败,请刷新后重试"); 34 ErrorCode AFTER_SALE_UPDATE_STATUS_FAIL = new ErrorCode(1011000107, "操作售后单失败,请刷新后重试");
35 ErrorCode AFTER_SALE_DELIVERY_FAIL_STATUS_NOT_SELLER_PASS = new ErrorCode(1011000108, "退货失败,售后单状态不处于【待买家退货】"); 35 ErrorCode AFTER_SALE_DELIVERY_FAIL_STATUS_NOT_SELLER_PASS = new ErrorCode(1011000108, "退货失败,售后单状态不处于【待买家退货】");
36 ErrorCode AFTER_SALE_CONFIRM_FAIL_STATUS_NOT_BUYER_RETURN = new ErrorCode(1011000109, "确认收货失败,售后单状态不处于【待确认收货】"); 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 // ========== Cart 模块 1-011-001-000 ========== 41 // ========== Cart 模块 1-011-001-000 ==========
39 ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1011002000, "购物车项不存在"); 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,16 +5,15 @@ import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSal
5 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleConfirmReqVO; 5 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleConfirmReqVO;
6 import cn.iocoder.yudao.module.trade.service.aftersale.TradeAfterSaleService; 6 import cn.iocoder.yudao.module.trade.service.aftersale.TradeAfterSaleService;
7 import io.swagger.annotations.Api; 7 import io.swagger.annotations.Api;
  8 +import io.swagger.annotations.ApiImplicitParam;
8 import io.swagger.annotations.ApiOperation; 9 import io.swagger.annotations.ApiOperation;
9 import lombok.extern.slf4j.Slf4j; 10 import lombok.extern.slf4j.Slf4j;
10 import org.springframework.security.access.prepost.PreAuthorize; 11 import org.springframework.security.access.prepost.PreAuthorize;
11 import org.springframework.validation.annotation.Validated; 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 import javax.annotation.Resource; 15 import javax.annotation.Resource;
  16 +import javax.annotation.security.PermitAll;
18 17
19 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 18 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
20 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; 19 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
@@ -46,4 +45,13 @@ public class TradeAfterSaleController { @@ -46,4 +45,13 @@ public class TradeAfterSaleController {
46 return success(true); 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,12 +125,17 @@ public class TradeAfterSaleDO extends BaseDO {
125 */ 125 */
126 private Integer refundPrice; 126 private Integer refundPrice;
127 /** 127 /**
128 - * 支付退款编号 TODO 128 + * 支付退款编号
129 * 129 *
130 * 对接 pay-module-biz 支付服务的退款订单编号,即 PayRefundDO 的 id 编号 130 * 对接 pay-module-biz 支付服务的退款订单编号,即 PayRefundDO 的 id 编号
131 */ 131 */
132 private Long payRefundId; 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,4 +13,8 @@ public interface TradeAfterSaleMapper extends BaseMapperX&lt;TradeAfterSaleDO&gt; {
13 .eq(TradeAfterSaleDO::getId, id).eq(TradeAfterSaleDO::getStatus, status)); 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,4 +49,11 @@ public interface TradeAfterSaleService {
49 */ 49 */
50 void confirmAfterSale(Long userId, String userIp, TradeAfterSaleConfirmReqVO confirmReqVO); 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,6 +4,8 @@ import cn.hutool.core.util.ObjectUtil;
4 import cn.hutool.core.util.RandomUtil; 4 import cn.hutool.core.util.RandomUtil;
5 import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi; 5 import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi;
6 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; 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 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleAuditReqVO; 9 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleAuditReqVO;
8 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleConfirmReqVO; 10 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleConfirmReqVO;
9 import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO; 11 import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO;
@@ -276,4 +278,42 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService { @@ -276,4 +278,42 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService {
276 // TODO 发送售后消息 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 package cn.iocoder.yudao.module.pay.api.refund; 1 package cn.iocoder.yudao.module.pay.api.refund;
2 2
3 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; 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 import javax.validation.Valid; 6 import javax.validation.Valid;
6 7
@@ -19,4 +20,12 @@ public interface PayRefundApi { @@ -19,4 +20,12 @@ public interface PayRefundApi {
19 */ 20 */
20 Long createPayRefund(@Valid PayRefundCreateReqDTO reqDTO); 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,6 +3,8 @@ package cn.iocoder.yudao.module.pay.enums.refund;
3 import lombok.AllArgsConstructor; 3 import lombok.AllArgsConstructor;
4 import lombok.Getter; 4 import lombok.Getter;
5 5
  6 +import java.util.Objects;
  7 +
6 @Getter 8 @Getter
7 @AllArgsConstructor 9 @AllArgsConstructor
8 public enum PayRefundStatusEnum { 10 public enum PayRefundStatusEnum {
@@ -14,4 +16,9 @@ public enum PayRefundStatusEnum { @@ -14,4 +16,9 @@ public enum PayRefundStatusEnum {
14 16
15 private final Integer status; 17 private final Integer status;
16 private final String name; 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 package cn.iocoder.yudao.module.pay.api.refund; 1 package cn.iocoder.yudao.module.pay.api.refund;
2 2
3 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; 3 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
  4 +import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO;
4 import org.springframework.stereotype.Service; 5 import org.springframework.stereotype.Service;
5 import org.springframework.validation.annotation.Validated; 6 import org.springframework.validation.annotation.Validated;
6 7
@@ -18,4 +19,11 @@ public class PayRefundApiImpl implements PayRefundApi { @@ -18,4 +19,11 @@ public class PayRefundApiImpl implements PayRefundApi {
18 // TODO 芋艿:暂未实现 19 // TODO 芋艿:暂未实现
19 return null; 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,6 +194,4 @@ public class PayRefundDO extends BaseDO {
194 private LocalDateTime notifyTime; 194 private LocalDateTime notifyTime;
195 195
196 196
197 -  
198 -  
199 } 197 }