Commit ee1d362a7ccac4c917ac2ae8ccbda0663683ec77
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<TradeAfterSaleDO> { |
| 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 | } | ... | ... |