mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-04 12:18:42 +08:00 
			
		
		
		
	重构退款逻辑,去掉退款后处理
This commit is contained in:
		@@ -2,19 +2,17 @@ package cn.iocoder.yudao.coreservice.modules.pay.convert.order;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundPostReqDTO;
 | 
			
		||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedRespDTO;
 | 
			
		||||
import org.mapstruct.Mapper;
 | 
			
		||||
import org.mapstruct.factory.Mappers;
 | 
			
		||||
import org.mapstruct.Mapping;
 | 
			
		||||
import org.mapstruct.Mappings;
 | 
			
		||||
import org.mapstruct.factory.Mappers;
 | 
			
		||||
 | 
			
		||||
@Mapper
 | 
			
		||||
public interface PayRefundCoreConvert {
 | 
			
		||||
 | 
			
		||||
    PayRefundCoreConvert INSTANCE = Mappers.getMapper(PayRefundCoreConvert.class);
 | 
			
		||||
 | 
			
		||||
    PayRefundPostReqDTO convert(PayRefundUnifiedRespDTO respDTO);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //TODO 太多需要处理了, 暂时不用
 | 
			
		||||
    @Mappings(value = {
 | 
			
		||||
 
 | 
			
		||||
@@ -42,9 +42,10 @@ public class PayRefundDO extends BaseDO {
 | 
			
		||||
     * 注:针对同一次退款请求,如果调用接口失败或异常了,重试时需要保证退款请求号不能变更,
 | 
			
		||||
     * 防止该笔交易重复退款。支付宝会保证同样的退款请求号多次请求只会退一次。
 | 
			
		||||
     * 退款单请求号,根据规则生成
 | 
			
		||||
      *
 | 
			
		||||
     * 例如说,R202109181134287570000
 | 
			
		||||
      * 废弃,使用 merchantRefundNo 做退款请求号
 | 
			
		||||
     */
 | 
			
		||||
    @Deprecated
 | 
			
		||||
    private String reqNo;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -82,7 +83,7 @@ public class PayRefundDO extends BaseDO {
 | 
			
		||||
    /**
 | 
			
		||||
     * 交易订单号,根据规则生成
 | 
			
		||||
     * 调用支付渠道时,使用该字段作为对接的订单号。
 | 
			
		||||
     * 1. 调用微信支付 https://api.mch.weixin.qq.com/pay/unifiedorder 时,使用该字段作为 out_trade_no
 | 
			
		||||
     * 1. 调用微信支付 https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 时,使用该字段作为 out_trade_no
 | 
			
		||||
     * 2. 调用支付宝 https://opendocs.alipay.com/apis 时,使用该字段作为 out_trade_no
 | 
			
		||||
     *  这里对应 pay_extension 里面的 no
 | 
			
		||||
     * 例如说,P202110132239124200055
 | 
			
		||||
@@ -95,10 +96,20 @@ public class PayRefundDO extends BaseDO {
 | 
			
		||||
     * 商户订单编号
 | 
			
		||||
     */
 | 
			
		||||
    private String merchantOrderId;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 商户退款订单号, 由商户系统产生, 由他们保证唯一,不能为空,通知商户时会传该字段。发送channel 使用 reqNo
 | 
			
		||||
     * 商户退款订单号, 由商户系统产生, 由他们保证唯一,不能为空,通知商户时会传该字段。
 | 
			
		||||
     * 例如说,内部系统 A 的退款订单号。需要保证每个 PayMerchantDO 唯一
 | 
			
		||||
     * TODO 芋艿:我理解 一个商户退款订单,可以对应多条退款记录, 因为有可能失败。但是 退款请求号 reqNo 必须唯一
 | 
			
		||||
     * 个商户退款订单,对应一条退款请求记录。可多次提交。 渠道保持幂等
 | 
			
		||||
     * 使用商户退款单,作为退款请求号
 | 
			
		||||
     * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_9.shtml 中的 out_refund_no
 | 
			
		||||
     * https://opendocs.alipay.com/apis alipay.trade.refund 中的 out_request_no
 | 
			
		||||
     * 退款请求号。
 | 
			
		||||
     * 标识一次退款请求,需要保证在交易号下唯一,如需部分退款,则此参数必传。
 | 
			
		||||
     * 注:针对同一次退款请求,如果调用接口失败或异常了,重试时需要保证退款请求号不能变更,
 | 
			
		||||
     * 防止该笔交易重复退款。支付宝会保证同样的退款请求号多次请求只会退一次。
 | 
			
		||||
     * 退款单请求号,根据规则生成
 | 
			
		||||
     * 例如说,R202109181134287570000
 | 
			
		||||
     *
 | 
			
		||||
     */
 | 
			
		||||
    private String merchantRefundNo;
 | 
			
		||||
@@ -151,6 +162,9 @@ public class PayRefundDO extends BaseDO {
 | 
			
		||||
     */
 | 
			
		||||
    private String channelOrderNo;
 | 
			
		||||
    /**
 | 
			
		||||
     * 微信中的 refund_id
 | 
			
		||||
     * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_9.shtml
 | 
			
		||||
     * 支付宝没有
 | 
			
		||||
     * 渠道退款单号,渠道返回
 | 
			
		||||
     */
 | 
			
		||||
    private String channelRefundNo;
 | 
			
		||||
 
 | 
			
		||||
@@ -15,4 +15,8 @@ public interface PayRefundCoreMapper extends BaseMapperX<PayRefundDO> {
 | 
			
		||||
    default PayRefundDO selectByReqNo(String reqNo) {
 | 
			
		||||
        return selectOne("req_no", reqNo);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    default  PayRefundDO selectByTradeNoAndMerchantRefundNo(String tradeNo, String merchantRefundNo){
 | 
			
		||||
        return  selectOne("trade_no", tradeNo, "merchant_refund_no", merchantRefundNo);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -46,9 +46,10 @@ public interface PayErrorCodeCoreConstants {
 | 
			
		||||
    ErrorCode PAY_REFUND_AMOUNT_EXCEED = new ErrorCode(1007006000, "退款金额超过订单可退款金额");
 | 
			
		||||
    ErrorCode PAY_REFUND_ALL_REFUNDED = new ErrorCode(1007006001, "订单已经全额退款");
 | 
			
		||||
    ErrorCode PAY_REFUND_CHN_ORDER_NO_IS_NULL = new ErrorCode(1007006002, "该订单的渠道订单为空");
 | 
			
		||||
    ErrorCode PAY_REFUND_POST_HANDLER_NOT_FOUND = new ErrorCode(1007006003, "未找到对应的退款后置处理类");
 | 
			
		||||
    ErrorCode PAY_REFUND_SUCCEED = new ErrorCode(1007006003, "已经退款成功");
 | 
			
		||||
    ErrorCode PAY_REFUND_NOT_FOUND = new ErrorCode(1007006004, "支付退款单不存在");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * ========== 支付商户信息 1-007-004-000 ==========
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -9,10 +9,6 @@ public enum PayRefundStatusEnum {
 | 
			
		||||
    CREATE(0, "退款订单生成"),
 | 
			
		||||
    SUCCESS(1, "退款成功"),
 | 
			
		||||
    FAILURE(2, "退款失败"),
 | 
			
		||||
    PROCESSING_NOTIFY(3,"退款中, 渠道通知结果"),
 | 
			
		||||
    PROCESSING_QUERY(4,"退款中, 系统查询结果"),
 | 
			
		||||
    UNKNOWN_RETRY(5,"状态未知,需要重试"),
 | 
			
		||||
    UNKNOWN_QUERY(6,"状态未知,系统查询结果"),
 | 
			
		||||
    CLOSE(99, "退款关闭");
 | 
			
		||||
 | 
			
		||||
    private final Integer status;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,40 +0,0 @@
 | 
			
		||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayOrderCoreMapper;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayRefundCoreMapper;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 支付退款订单渠道返回后 , 后置处理抽象类, 处理公用的逻辑
 | 
			
		||||
 * @author  jason
 | 
			
		||||
 */
 | 
			
		||||
public abstract  class PayRefundAbstractChannelPostHandler implements PayRefundChannelPostHandler {
 | 
			
		||||
 | 
			
		||||
    private final PayOrderCoreMapper payOrderCoreMapper;
 | 
			
		||||
    private final PayRefundCoreMapper payRefundMapper;
 | 
			
		||||
 | 
			
		||||
    public PayRefundAbstractChannelPostHandler(PayOrderCoreMapper payOrderCoreMapper,
 | 
			
		||||
                                               PayRefundCoreMapper payRefundMapper){
 | 
			
		||||
        this.payOrderCoreMapper = payOrderCoreMapper;
 | 
			
		||||
        this.payRefundMapper = payRefundMapper;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 更新退款单
 | 
			
		||||
     * @param refundDO  需要更新的退款单信息
 | 
			
		||||
     */
 | 
			
		||||
    protected void updatePayRefund(PayRefundDO refundDO){
 | 
			
		||||
        payRefundMapper.updateById(refundDO);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 更新原始支付订单
 | 
			
		||||
     * @param payOrderDO 支付订单信息
 | 
			
		||||
     */
 | 
			
		||||
    protected void updatePayOrder(PayOrderDO payOrderDO){
 | 
			
		||||
        payOrderCoreMapper.updateById(payOrderDO);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,26 +0,0 @@
 | 
			
		||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundPostReqDTO;
 | 
			
		||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelRespEnum;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 支付退款订单 ,渠道返回后 后置处理
 | 
			
		||||
 *
 | 
			
		||||
 * @author jason
 | 
			
		||||
 */
 | 
			
		||||
public interface PayRefundChannelPostHandler {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 支持的渠道返回值
 | 
			
		||||
     *
 | 
			
		||||
     * @return 支持的渠道返回值数组
 | 
			
		||||
     */
 | 
			
		||||
    PayChannelRespEnum[] supportHandleResp();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据渠道返回,处理支付退款单
 | 
			
		||||
     *
 | 
			
		||||
     * @param req 退款后置处理请求
 | 
			
		||||
     */
 | 
			
		||||
    void handleRefundChannelResp(PayRefundPostReqDTO req);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,99 +0,0 @@
 | 
			
		||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order.dto;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundTypeEnum;
 | 
			
		||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelRespEnum;
 | 
			
		||||
import lombok.AllArgsConstructor;
 | 
			
		||||
import lombok.Builder;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.NoArgsConstructor;
 | 
			
		||||
import lombok.experimental.Accessors;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 退款后置处理请求 Request DTO
 | 
			
		||||
 */
 | 
			
		||||
@Data
 | 
			
		||||
@Accessors(chain = true)
 | 
			
		||||
@Builder
 | 
			
		||||
@NoArgsConstructor
 | 
			
		||||
@AllArgsConstructor
 | 
			
		||||
public class PayRefundPostReqDTO {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 渠道的通用返回结果
 | 
			
		||||
     */
 | 
			
		||||
    private PayChannelRespEnum respEnum;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private PayRefundTypeEnum refundTypeEnum;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 已退款的总金额
 | 
			
		||||
     */
 | 
			
		||||
    private Long  refundedAmount;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 本次退款金额
 | 
			
		||||
     */
 | 
			
		||||
    private Long refundAmount;
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     * 已退款次数
 | 
			
		||||
     */
 | 
			
		||||
    private Integer refundedTimes;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 订单编号
 | 
			
		||||
     */
 | 
			
		||||
    private Long  orderId;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 退款单编号
 | 
			
		||||
     */
 | 
			
		||||
    private Long refundId;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 渠道退款单号
 | 
			
		||||
     */
 | 
			
		||||
    private String channelRefundNo;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 out_trade_no
 | 
			
		||||
     * https://opendocs.alipay.com/apis alipay.trade.refund 中的 out_trade_no
 | 
			
		||||
     * 支付交易号 {PayOrderExtensionDO no字段} 和 渠道订单号 不能同时为空
 | 
			
		||||
     */
 | 
			
		||||
    private String payTradeNo;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 out_refund_no
 | 
			
		||||
     * https://opendocs.alipay.com/apis alipay.trade.refund 中的 out_request_no
 | 
			
		||||
     * 退款请求单号  同一退款请求单号多次请求只退一笔。
 | 
			
		||||
     */
 | 
			
		||||
    private String refundReqNo;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 调用异常错误信息
 | 
			
		||||
     */
 | 
			
		||||
    private String exceptionMsg;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 渠道的错误码
 | 
			
		||||
     */
 | 
			
		||||
    private String channelErrCode;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 渠道的错误描述
 | 
			
		||||
     */
 | 
			
		||||
    private String channelErrMsg;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -16,6 +16,23 @@ import lombok.experimental.Accessors;
 | 
			
		||||
@AllArgsConstructor
 | 
			
		||||
public class PayRefundRespDTO {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 渠道返回结果
 | 
			
		||||
     * 退款处理中和退款成功  返回  1
 | 
			
		||||
     * 失败和其他情况 返回 2
 | 
			
		||||
     */
 | 
			
		||||
    private Integer channelReturnResult;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 渠道返回code
 | 
			
		||||
     */
 | 
			
		||||
    private String channelReturnCode;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 渠道返回消息
 | 
			
		||||
     */
 | 
			
		||||
    private String  channelReturnMsg;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 支付退款单编号, 自增
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.util.StrUtil;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.convert.order.PayRefundCoreConvert;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
 | 
			
		||||
@@ -14,7 +13,6 @@ import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyTypeEnum;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderNotifyStatusEnum;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.notify.PayNotifyCoreService;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.notify.dto.PayNotifyTaskCreateReqDTO;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundPostReqDTO;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundReqDTO;
 | 
			
		||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundNotifyDTO;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundTypeEnum;
 | 
			
		||||
@@ -23,21 +21,18 @@ import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundStatusEnum;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayAppCoreService;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayChannelCoreService;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayRefundCoreService;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayRefundChannelPostHandler;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundRespDTO;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.util.PaySeqUtils;
 | 
			
		||||
import cn.iocoder.yudao.framework.pay.core.client.PayClient;
 | 
			
		||||
import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
 | 
			
		||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO;
 | 
			
		||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedReqDTO;
 | 
			
		||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedRespDTO;
 | 
			
		||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelRefundRespEnum;
 | 
			
		||||
import cn.iocoder.yudao.framework.pay.core.enums.PayNotifyRefundStatusEnum;
 | 
			
		||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelRespEnum;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
import org.springframework.transaction.annotation.Transactional;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.PostConstruct;
 | 
			
		||||
import javax.annotation.Resource;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
 | 
			
		||||
@@ -65,25 +60,6 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
 | 
			
		||||
    @Resource
 | 
			
		||||
    private PayClientFactory payClientFactory;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 处理渠道返回结果的后置处理器 集合
 | 
			
		||||
     */
 | 
			
		||||
    @Resource
 | 
			
		||||
    private List<PayRefundChannelPostHandler> handlerList;
 | 
			
		||||
 | 
			
		||||
    private final EnumMap<PayChannelRespEnum, PayRefundChannelPostHandler> mapHandlers = new EnumMap<>(PayChannelRespEnum.class);
 | 
			
		||||
 | 
			
		||||
    @PostConstruct
 | 
			
		||||
    public void init(){
 | 
			
		||||
        if (Objects.nonNull(handlerList)) {
 | 
			
		||||
            handlerList.forEach(handler -> {
 | 
			
		||||
                for (PayChannelRespEnum item : handler.supportHandleResp()) {
 | 
			
		||||
                    mapHandlers.put(item, handler);
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    @Transactional(rollbackFor = Exception.class)
 | 
			
		||||
    public PayRefundRespDTO submitRefundOrder(PayRefundReqDTO req) {
 | 
			
		||||
@@ -106,66 +82,89 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
 | 
			
		||||
 | 
			
		||||
        // 校验退款的条件
 | 
			
		||||
        validatePayRefund(req, order);
 | 
			
		||||
 | 
			
		||||
        // 退款类型
 | 
			
		||||
        PayRefundTypeEnum refundType = PayRefundTypeEnum.SOME;
 | 
			
		||||
        if (Objects.equals(req.getAmount(), order.getAmount())) {
 | 
			
		||||
            refundType = PayRefundTypeEnum.ALL;
 | 
			
		||||
        }
 | 
			
		||||
        // 退款单入库 退款单状态:生成,  没有和渠道产生交互
 | 
			
		||||
 | 
			
		||||
        PayOrderExtensionDO orderExtensionDO = payOrderExtensionCoreMapper.selectById(order.getSuccessExtensionId());
 | 
			
		||||
        PayRefundDO refundDO = PayRefundDO.builder().channelOrderNo(order.getChannelOrderNo())
 | 
			
		||||
                .appId(order.getAppId())
 | 
			
		||||
                .channelOrderNo(order.getChannelOrderNo())
 | 
			
		||||
                .channelCode(order.getChannelCode())
 | 
			
		||||
                .channelId(order.getChannelId())
 | 
			
		||||
                .merchantId(order.getMerchantId())
 | 
			
		||||
                .orderId(order.getId())
 | 
			
		||||
                .merchantRefundNo(req.getMerchantRefundNo())
 | 
			
		||||
                .notifyUrl(app.getRefundNotifyUrl())
 | 
			
		||||
                .payAmount(order.getAmount())
 | 
			
		||||
                .refundAmount(req.getAmount())
 | 
			
		||||
                .userIp(req.getUserIp())
 | 
			
		||||
                .merchantOrderId(order.getMerchantOrderId())
 | 
			
		||||
                .tradeNo(orderExtensionDO.getNo())
 | 
			
		||||
                .status(PayRefundStatusEnum.CREATE.getStatus())
 | 
			
		||||
                .reason(req.getReason())
 | 
			
		||||
                .notifyStatus(PayOrderNotifyStatusEnum.NO.getStatus())
 | 
			
		||||
                .reqNo(PaySeqUtils.genRefundReqNo())
 | 
			
		||||
                .type(refundType.getStatus())
 | 
			
		||||
                .build();
 | 
			
		||||
         payRefundCoreMapper.insert(refundDO);
 | 
			
		||||
 | 
			
		||||
        // 调用渠道进行退款
 | 
			
		||||
         PayRefundUnifiedReqDTO unifiedReqDTO = PayRefundUnifiedReqDTO.builder()
 | 
			
		||||
                .userIp(req.getUserIp())
 | 
			
		||||
                .channelOrderNo(refundDO.getChannelOrderNo())
 | 
			
		||||
                .payTradeNo(refundDO.getTradeNo())
 | 
			
		||||
                .refundReqNo(refundDO.getReqNo())
 | 
			
		||||
                .amount(req.getAmount())
 | 
			
		||||
                .reason(refundDO.getReason())
 | 
			
		||||
                .build();
 | 
			
		||||
         PayRefundUnifiedRespDTO refundUnifiedRespDTO = client.unifiedRefund(unifiedReqDTO);
 | 
			
		||||
         // 根据渠道返回,获取退款后置处理,由postHandler 进行处理
 | 
			
		||||
         PayRefundChannelPostHandler payRefundChannelPostHandler = mapHandlers.get(refundUnifiedRespDTO.getRespEnum());
 | 
			
		||||
         if (Objects.isNull(payRefundChannelPostHandler)) {
 | 
			
		||||
             throw exception(PAY_REFUND_POST_HANDLER_NOT_FOUND);
 | 
			
		||||
         }
 | 
			
		||||
         PayRefundPostReqDTO dto = PayRefundCoreConvert.INSTANCE.convert(refundUnifiedRespDTO);
 | 
			
		||||
         dto.setRefundAmount(req.getAmount())
 | 
			
		||||
            .setRefundedAmount(order.getRefundAmount())
 | 
			
		||||
            .setRefundedTimes(order.getRefundTimes())
 | 
			
		||||
            .setRefundId(refundDO.getId())
 | 
			
		||||
            .setOrderId(order.getId())
 | 
			
		||||
            .setRefundTypeEnum(refundType);
 | 
			
		||||
         //调用退款的后置处理
 | 
			
		||||
         payRefundChannelPostHandler.handleRefundChannelResp(dto);
 | 
			
		||||
 | 
			
		||||
         return PayRefundRespDTO.builder().refundId(refundDO.getId()).build();
 | 
			
		||||
        PayRefundDO payRefundDO = payRefundCoreMapper.selectByTradeNoAndMerchantRefundNo(orderExtensionDO.getNo(), req.getMerchantRefundNo());
 | 
			
		||||
        //构造渠道的统一的退款请求参数
 | 
			
		||||
        PayRefundUnifiedReqDTO unifiedReqDTO = new PayRefundUnifiedReqDTO();
 | 
			
		||||
        if(Objects.nonNull(payRefundDO)){
 | 
			
		||||
            //退款订单已经提交过。
 | 
			
		||||
            //TODO 校验相同退款单的金额
 | 
			
		||||
            if(Objects.equals(PayRefundStatusEnum.SUCCESS.getStatus(), payRefundDO.getStatus())
 | 
			
		||||
                || Objects.equals(PayRefundStatusEnum.CLOSE.getStatus(), payRefundDO.getStatus())){
 | 
			
		||||
                //已成功退款
 | 
			
		||||
               throw exception(PAY_REFUND_SUCCEED);
 | 
			
		||||
            }else{
 | 
			
		||||
                //保证商户退款单不变,重复向渠道发起退款。渠道保持幂等
 | 
			
		||||
                unifiedReqDTO.setUserIp(req.getUserIp())
 | 
			
		||||
                             .setAmount(payRefundDO.getRefundAmount())
 | 
			
		||||
                             .setChannelOrderNo(payRefundDO.getChannelOrderNo())
 | 
			
		||||
                             .setPayTradeNo(payRefundDO.getTradeNo())
 | 
			
		||||
                             .setRefundReqNo(payRefundDO.getMerchantRefundNo())
 | 
			
		||||
                             .setReason(payRefundDO.getReason());
 | 
			
		||||
            }
 | 
			
		||||
        }else{
 | 
			
		||||
            //新生成退款单。 退款单入库 退款单状态:生成
 | 
			
		||||
            payRefundDO = PayRefundDO.builder().channelOrderNo(order.getChannelOrderNo())
 | 
			
		||||
                    .appId(order.getAppId())
 | 
			
		||||
                    .channelOrderNo(order.getChannelOrderNo())
 | 
			
		||||
                    .channelCode(order.getChannelCode())
 | 
			
		||||
                    .channelId(order.getChannelId())
 | 
			
		||||
                    .merchantId(order.getMerchantId())
 | 
			
		||||
                    .orderId(order.getId())
 | 
			
		||||
                    .merchantRefundNo(req.getMerchantRefundNo())
 | 
			
		||||
                    .notifyUrl(app.getRefundNotifyUrl())
 | 
			
		||||
                    .payAmount(order.getAmount())
 | 
			
		||||
                    .refundAmount(req.getAmount())
 | 
			
		||||
                    .userIp(req.getUserIp())
 | 
			
		||||
                    .merchantOrderId(order.getMerchantOrderId())
 | 
			
		||||
                    .tradeNo(orderExtensionDO.getNo())
 | 
			
		||||
                    .status(PayRefundStatusEnum.CREATE.getStatus())
 | 
			
		||||
                    .reason(req.getReason())
 | 
			
		||||
                    .notifyStatus(PayOrderNotifyStatusEnum.NO.getStatus())
 | 
			
		||||
                    .type(refundType.getStatus())
 | 
			
		||||
                    .build();
 | 
			
		||||
            payRefundCoreMapper.insert(payRefundDO);
 | 
			
		||||
            unifiedReqDTO.setUserIp(req.getUserIp())
 | 
			
		||||
                    .setAmount(payRefundDO.getRefundAmount())
 | 
			
		||||
                    .setChannelOrderNo(payRefundDO.getChannelOrderNo())
 | 
			
		||||
                    .setPayTradeNo(payRefundDO.getTradeNo())
 | 
			
		||||
                    .setRefundReqNo(payRefundDO.getMerchantRefundNo())
 | 
			
		||||
                    .setReason(req.getReason());
 | 
			
		||||
        }
 | 
			
		||||
        //向渠道发起退款申请
 | 
			
		||||
        PayRefundUnifiedRespDTO refundUnifiedRespDTO = client.unifiedRefund(unifiedReqDTO);
 | 
			
		||||
        //构造退款申请返回对象
 | 
			
		||||
        PayRefundRespDTO respDTO = new PayRefundRespDTO();
 | 
			
		||||
        if(refundUnifiedRespDTO.getChannelResp() == PayChannelRefundRespEnum.SUCCESS
 | 
			
		||||
            ||refundUnifiedRespDTO.getChannelResp() == PayChannelRefundRespEnum.PROCESSING ){
 | 
			
		||||
            //成功处理, 在退款通知中处理, 这里不处理
 | 
			
		||||
            respDTO.setChannelReturnResult(PayChannelRefundRespEnum.SUCCESS.getStatus());
 | 
			
		||||
            respDTO.setRefundId(payRefundDO.getId());
 | 
			
		||||
        }else {
 | 
			
		||||
            //失败返回错误给前端,可以重新发起退款,保证退款请求号(这里是商户退款单号), 避免重复退款。
 | 
			
		||||
            respDTO.setChannelReturnResult(PayChannelRefundRespEnum.FAILURE.getStatus());
 | 
			
		||||
            //更新退款单状态
 | 
			
		||||
            PayRefundDO updatePayRefund = new PayRefundDO();
 | 
			
		||||
            updatePayRefund.setId(payRefundDO.getId())
 | 
			
		||||
                    .setChannelErrorMsg(refundUnifiedRespDTO.getChannelMsg())
 | 
			
		||||
                    .setChannelErrorCode(refundUnifiedRespDTO.getChannelCode())
 | 
			
		||||
                    .setStatus(PayRefundStatusEnum.FAILURE.getStatus());
 | 
			
		||||
            payRefundCoreMapper.updateById(updatePayRefund);
 | 
			
		||||
        }
 | 
			
		||||
        respDTO.setChannelReturnCode(refundUnifiedRespDTO.getChannelCode())
 | 
			
		||||
                .setChannelReturnMsg(refundUnifiedRespDTO.getChannelMsg());
 | 
			
		||||
        return respDTO;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    @Transactional(rollbackFor = Exception.class)
 | 
			
		||||
    public void notifyPayRefund(Long channelId, PayNotifyDataDTO notifyData) {
 | 
			
		||||
        log.info("[notifyPayRefund][channelId({}) 回调数据({})]", channelId, notifyData.getBody());
 | 
			
		||||
        // 校验支付渠道是否有效
 | 
			
		||||
@@ -178,51 +177,54 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
 | 
			
		||||
        }
 | 
			
		||||
        // 解析渠道退款通知数据, 统一处理
 | 
			
		||||
        PayRefundNotifyDTO refundNotify = client.parseRefundNotify(notifyData);
 | 
			
		||||
 | 
			
		||||
        // TODO @jason:抽一个 notifyPayRefundSuccess 方法
 | 
			
		||||
        if (Objects.equals(PayNotifyRefundStatusEnum.SUCCESS,refundNotify.getStatus())){
 | 
			
		||||
            // 退款成功。 支付宝只有退款成功才会发通知
 | 
			
		||||
            PayRefundDO refundDO = payRefundCoreMapper.selectByReqNo(refundNotify.getReqNo());
 | 
			
		||||
            if (refundDO == null) {
 | 
			
		||||
                log.error("不存在 seqNo 为{} 的支付退款单",refundNotify.getReqNo());
 | 
			
		||||
                throw exception(PAY_REFUND_NOT_FOUND);
 | 
			
		||||
            }
 | 
			
		||||
            Long refundAmount = refundDO.getRefundAmount();
 | 
			
		||||
            Integer type = refundDO.getType();
 | 
			
		||||
            PayOrderStatusEnum orderStatus = PayOrderStatusEnum.SUCCESS;
 | 
			
		||||
            if(PayRefundTypeEnum.ALL.getStatus().equals(type)){
 | 
			
		||||
                orderStatus = PayOrderStatusEnum.CLOSED;
 | 
			
		||||
            }
 | 
			
		||||
            // 更新支付订单
 | 
			
		||||
            PayOrderDO payOrderDO = payOrderCoreMapper.selectById(refundDO.getOrderId());
 | 
			
		||||
            // 需更新已退金额
 | 
			
		||||
            Long refundedAmount = payOrderDO.getRefundAmount();
 | 
			
		||||
            PayOrderDO updateOrderDO = new PayOrderDO();
 | 
			
		||||
            updateOrderDO.setId(refundDO.getOrderId())
 | 
			
		||||
                    .setRefundAmount(refundedAmount + refundAmount)
 | 
			
		||||
                    .setStatus(orderStatus.getStatus())
 | 
			
		||||
                    .setRefundStatus(type);
 | 
			
		||||
            payOrderCoreMapper.updateById(updateOrderDO);
 | 
			
		||||
 | 
			
		||||
            // 跟新退款订单
 | 
			
		||||
            PayRefundDO updateRefundDO = new PayRefundDO();
 | 
			
		||||
            updateRefundDO.setId(refundDO.getId())
 | 
			
		||||
                    .setSuccessTime(refundNotify.getRefundSuccessTime())
 | 
			
		||||
                    .setChannelRefundNo(refundNotify.getChannelOrderNo())
 | 
			
		||||
                    .setTradeNo(refundNotify.getTradeNo())
 | 
			
		||||
                    .setNotifyTime(new Date())
 | 
			
		||||
                    .setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
 | 
			
		||||
            payRefundCoreMapper.updateById(updateRefundDO);
 | 
			
		||||
 | 
			
		||||
            //插入退款通知记录
 | 
			
		||||
            // TODO 通知商户成功或者失败. 现在通知似乎没有实现, 只是回调
 | 
			
		||||
            payNotifyCoreService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder()
 | 
			
		||||
                    .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refundDO.getId()).build());
 | 
			
		||||
            payRefundSuccess(refundNotify);
 | 
			
		||||
        } else {
 | 
			
		||||
            //TODO 退款失败
 | 
			
		||||
            //TODO 支付异常, 支付宝似乎没有支付异常的通知。
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void payRefundSuccess(PayRefundNotifyDTO refundNotify) {
 | 
			
		||||
        PayRefundDO refundDO = payRefundCoreMapper.selectByTradeNoAndMerchantRefundNo(refundNotify.getTradeNo(), refundNotify.getReqNo());
 | 
			
		||||
        if (refundDO == null) {
 | 
			
		||||
            log.error("不存在 seqNo 为{} 的支付退款单",refundNotify.getReqNo());
 | 
			
		||||
            throw exception(PAY_REFUND_NOT_FOUND);
 | 
			
		||||
        }
 | 
			
		||||
        Long refundAmount = refundDO.getRefundAmount();
 | 
			
		||||
        Integer type = refundDO.getType();
 | 
			
		||||
        PayOrderStatusEnum orderStatus = PayOrderStatusEnum.SUCCESS;
 | 
			
		||||
        if(PayRefundTypeEnum.ALL.getStatus().equals(type)){
 | 
			
		||||
            orderStatus = PayOrderStatusEnum.CLOSED;
 | 
			
		||||
        }
 | 
			
		||||
        // 更新支付订单
 | 
			
		||||
        PayOrderDO payOrderDO = payOrderCoreMapper.selectById(refundDO.getOrderId());
 | 
			
		||||
        // 需更新已退金额
 | 
			
		||||
        Long refundedAmount = payOrderDO.getRefundAmount();
 | 
			
		||||
        PayOrderDO updateOrderDO = new PayOrderDO();
 | 
			
		||||
        updateOrderDO.setId(refundDO.getOrderId())
 | 
			
		||||
                .setRefundAmount(refundedAmount + refundAmount)
 | 
			
		||||
                .setStatus(orderStatus.getStatus())
 | 
			
		||||
                .setRefundTimes(payOrderDO.getRefundTimes()+1)
 | 
			
		||||
                .setRefundStatus(type);
 | 
			
		||||
 | 
			
		||||
        payOrderCoreMapper.updateById(updateOrderDO);
 | 
			
		||||
 | 
			
		||||
        // 跟新退款订单
 | 
			
		||||
        PayRefundDO updateRefundDO = new PayRefundDO();
 | 
			
		||||
        updateRefundDO.setId(refundDO.getId())
 | 
			
		||||
                .setSuccessTime(refundNotify.getRefundSuccessTime())
 | 
			
		||||
                .setChannelRefundNo(refundNotify.getChannelOrderNo())
 | 
			
		||||
                .setTradeNo(refundNotify.getTradeNo())
 | 
			
		||||
                .setNotifyTime(new Date())
 | 
			
		||||
                .setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
 | 
			
		||||
        payRefundCoreMapper.updateById(updateRefundDO);
 | 
			
		||||
 | 
			
		||||
        //插入退款通知记录
 | 
			
		||||
        // TODO 通知商户成功或者失败. 现在通知似乎没有实现, 只是回调
 | 
			
		||||
        payNotifyCoreService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder()
 | 
			
		||||
                .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refundDO.getId()).build());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 校验是否进行退款
 | 
			
		||||
     * @param req 退款申请信息
 | 
			
		||||
 
 | 
			
		||||
@@ -1,62 +0,0 @@
 | 
			
		||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl.handler;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayOrderCoreMapper;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayRefundCoreMapper;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyTypeEnum;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundStatusEnum;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.notify.PayNotifyCoreService;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.notify.dto.PayNotifyTaskCreateReqDTO;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayRefundAbstractChannelPostHandler;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundPostReqDTO;
 | 
			
		||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelRespEnum;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Resource;
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 支付退款订单渠道返回失败的后置处理类
 | 
			
		||||
 * {@link PayChannelRespEnum#CALL_EXCEPTION}
 | 
			
		||||
 * {@link PayChannelRespEnum#CAN_NOT_RETRY_FAILURE}
 | 
			
		||||
 */
 | 
			
		||||
@Service
 | 
			
		||||
public class PayRefundChannelFailedHandler extends PayRefundAbstractChannelPostHandler {
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private PayNotifyCoreService payNotifyCoreService;
 | 
			
		||||
 | 
			
		||||
    public PayRefundChannelFailedHandler(PayOrderCoreMapper payOrderCoreMapper, PayRefundCoreMapper payRefundMapper) {
 | 
			
		||||
        super(payOrderCoreMapper, payRefundMapper);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public PayChannelRespEnum[] supportHandleResp() {
 | 
			
		||||
        return new PayChannelRespEnum[] {PayChannelRespEnum.CALL_EXCEPTION, PayChannelRespEnum.CAN_NOT_RETRY_FAILURE};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void handleRefundChannelResp(PayRefundPostReqDTO req) {
 | 
			
		||||
        //退款失败
 | 
			
		||||
        //更新退款单表
 | 
			
		||||
        PayRefundDO updateRefundDO = new PayRefundDO();
 | 
			
		||||
 | 
			
		||||
        updateRefundDO.setId(req.getRefundId())
 | 
			
		||||
                .setStatus(PayRefundStatusEnum.FAILURE.getStatus())
 | 
			
		||||
                .setChannelErrorCode(req.getChannelErrCode())
 | 
			
		||||
                .setChannelErrorMsg(Optional.ofNullable(req.getChannelErrMsg())
 | 
			
		||||
                                          .orElse(req.getExceptionMsg()));
 | 
			
		||||
        updatePayRefund(updateRefundDO);
 | 
			
		||||
        PayOrderDO updateOrderDO = new PayOrderDO();
 | 
			
		||||
        //更新订单表
 | 
			
		||||
        updateOrderDO.setId(req.getOrderId())
 | 
			
		||||
                .setRefundTimes(req.getRefundedTimes() + 1);
 | 
			
		||||
        updatePayOrder(updateOrderDO);
 | 
			
		||||
        // 立刻插入退款通知记录
 | 
			
		||||
        // TODO 通知商户成功或者失败. 现在通知似乎没有实现, 只是回调
 | 
			
		||||
        payNotifyCoreService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder()
 | 
			
		||||
                .type(PayNotifyTypeEnum.REFUND.getType()).dataId(req.getRefundId()).build());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,45 +0,0 @@
 | 
			
		||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl.handler;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayOrderCoreMapper;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayRefundCoreMapper;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundStatusEnum;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayRefundAbstractChannelPostHandler;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundPostReqDTO;
 | 
			
		||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelRespEnum;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 支付退款订单渠道返回通知 {@link PayChannelRespEnum#PROCESSING_NOTIFY},后置处理类
 | 
			
		||||
 * 支付宝退款单好像没有回调, 微信会触发回调
 | 
			
		||||
 */
 | 
			
		||||
@Service
 | 
			
		||||
public class PayRefundChannelNotifyHandler extends PayRefundAbstractChannelPostHandler {
 | 
			
		||||
 | 
			
		||||
    public PayRefundChannelNotifyHandler(PayOrderCoreMapper payOrderCoreMapper,
 | 
			
		||||
                                         PayRefundCoreMapper payRefundMapper) {
 | 
			
		||||
        super(payOrderCoreMapper, payRefundMapper);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public PayChannelRespEnum[] supportHandleResp() {
 | 
			
		||||
        return new PayChannelRespEnum[] {PayChannelRespEnum.PROCESSING_NOTIFY};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void handleRefundChannelResp(PayRefundPostReqDTO req) {
 | 
			
		||||
        PayRefundDO updateRefundDO = new PayRefundDO();
 | 
			
		||||
        //更新退款单表
 | 
			
		||||
        updateRefundDO.setId(req.getRefundId())
 | 
			
		||||
                .setStatus(PayRefundStatusEnum.PROCESSING_NOTIFY.getStatus());
 | 
			
		||||
        updatePayRefund(updateRefundDO);
 | 
			
		||||
 | 
			
		||||
        PayOrderDO updateOrderDO = new PayOrderDO();
 | 
			
		||||
        //更新订单表
 | 
			
		||||
        updateOrderDO.setId(req.getOrderId())
 | 
			
		||||
                .setRefundTimes(req.getRefundedTimes() + 1);
 | 
			
		||||
        updatePayOrder(updateOrderDO);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,56 +0,0 @@
 | 
			
		||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl.handler;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayOrderCoreMapper;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayRefundCoreMapper;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundStatusEnum;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayRefundAbstractChannelPostHandler;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundPostReqDTO;
 | 
			
		||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelRespEnum;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 支付退款订单渠道返回需调用查询接口的后置处理类
 | 
			
		||||
 * {@link PayChannelRespEnum#PROCESSING_QUERY} //TODO 芋道源码 是不是微信有这样的情况
 | 
			
		||||
 * {@link PayChannelRespEnum#READ_TIME_OUT_EXCEPTION}
 | 
			
		||||
 */
 | 
			
		||||
@Service
 | 
			
		||||
public class PayRefundChannelQueryHandler extends PayRefundAbstractChannelPostHandler {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public PayRefundChannelQueryHandler(PayOrderCoreMapper payOrderCoreMapper,
 | 
			
		||||
                                        PayRefundCoreMapper payRefundMapper) {
 | 
			
		||||
        super(payOrderCoreMapper, payRefundMapper);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public PayChannelRespEnum[] supportHandleResp() {
 | 
			
		||||
        return new PayChannelRespEnum[]{PayChannelRespEnum.PROCESSING_QUERY, PayChannelRespEnum.READ_TIME_OUT_EXCEPTION};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void handleRefundChannelResp(PayRefundPostReqDTO req) {
 | 
			
		||||
        final PayChannelRespEnum respEnum = req.getRespEnum();
 | 
			
		||||
        PayRefundStatusEnum refundStatus =
 | 
			
		||||
                Objects.equals(PayChannelRespEnum.PROCESSING_QUERY, respEnum) ? PayRefundStatusEnum.PROCESSING_QUERY
 | 
			
		||||
                        : PayRefundStatusEnum.UNKNOWN_QUERY;
 | 
			
		||||
        //更新退款单表
 | 
			
		||||
        PayRefundDO updateRefundDO = new PayRefundDO();
 | 
			
		||||
        updateRefundDO.setId(req.getRefundId())
 | 
			
		||||
                .setStatus(refundStatus.getStatus())
 | 
			
		||||
                .setChannelErrorCode(req.getChannelErrCode())
 | 
			
		||||
                .setChannelErrorMsg(req.getChannelErrMsg());
 | 
			
		||||
        updatePayRefund(updateRefundDO);
 | 
			
		||||
 | 
			
		||||
        PayOrderDO updateOrderDO = new PayOrderDO();
 | 
			
		||||
        //更新订单表
 | 
			
		||||
        updateOrderDO.setId(req.getOrderId())
 | 
			
		||||
                .setRefundTimes(req.getRefundedTimes() + 1);
 | 
			
		||||
        updatePayOrder(updateOrderDO);
 | 
			
		||||
 | 
			
		||||
        //TODO 发起查询任务
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,50 +0,0 @@
 | 
			
		||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl.handler;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayOrderCoreMapper;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayRefundCoreMapper;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundStatusEnum;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayRefundAbstractChannelPostHandler;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundPostReqDTO;
 | 
			
		||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelRespEnum;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 支付退款订单渠道返回重试的后置处理类
 | 
			
		||||
 * {@link PayChannelRespEnum#RETRY_FAILURE}
 | 
			
		||||
 */
 | 
			
		||||
@Service
 | 
			
		||||
public class PayRefundChannelRetryHandler extends PayRefundAbstractChannelPostHandler {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public PayRefundChannelRetryHandler(PayOrderCoreMapper payOrderCoreMapper,
 | 
			
		||||
                                        PayRefundCoreMapper payRefundMapper) {
 | 
			
		||||
        super(payOrderCoreMapper, payRefundMapper);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public PayChannelRespEnum[] supportHandleResp() {
 | 
			
		||||
        return new PayChannelRespEnum[] {PayChannelRespEnum.RETRY_FAILURE};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void handleRefundChannelResp(PayRefundPostReqDTO req) {
 | 
			
		||||
 | 
			
		||||
        PayRefundDO updateRefundDO = new PayRefundDO();
 | 
			
		||||
        //更新退款单表
 | 
			
		||||
        updateRefundDO.setId(req.getRefundId())
 | 
			
		||||
                .setStatus(PayRefundStatusEnum.UNKNOWN_RETRY.getStatus())
 | 
			
		||||
                .setChannelErrorCode(req.getChannelErrCode())
 | 
			
		||||
                .setChannelErrorMsg(req.getChannelErrMsg());
 | 
			
		||||
        updatePayRefund(updateRefundDO);
 | 
			
		||||
 | 
			
		||||
        PayOrderDO updateOrderDO = new PayOrderDO();
 | 
			
		||||
        //更新订单表
 | 
			
		||||
        updateOrderDO.setId(req.getOrderId())
 | 
			
		||||
                .setRefundTimes(req.getRefundedTimes() + 1);
 | 
			
		||||
        updatePayOrder(updateOrderDO);
 | 
			
		||||
 | 
			
		||||
        //TODO 发起重试任务
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,64 +0,0 @@
 | 
			
		||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl.handler;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayOrderCoreMapper;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayRefundCoreMapper;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyTypeEnum;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundStatusEnum;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.notify.PayNotifyCoreService;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.notify.dto.PayNotifyTaskCreateReqDTO;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayRefundAbstractChannelPostHandler;
 | 
			
		||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundPostReqDTO;
 | 
			
		||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelRespEnum;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Resource;
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
/**
 | 
			
		||||
 * 支付退款订单渠道返回退款成功的后置处理类
 | 
			
		||||
 * {@link PayChannelRespEnum#SYNC_SUCCESS}
 | 
			
		||||
 */
 | 
			
		||||
@Service
 | 
			
		||||
public class PayRefundChannelSuccessHandler extends PayRefundAbstractChannelPostHandler {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private PayNotifyCoreService payNotifyCoreService;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public PayRefundChannelSuccessHandler(PayOrderCoreMapper payOrderCoreMapper,
 | 
			
		||||
                                          PayRefundCoreMapper payRefundMapper) {
 | 
			
		||||
        super(payOrderCoreMapper, payRefundMapper);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public PayChannelRespEnum[] supportHandleResp() {
 | 
			
		||||
        return new PayChannelRespEnum[]{PayChannelRespEnum.SYNC_SUCCESS};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void handleRefundChannelResp(PayRefundPostReqDTO req) {
 | 
			
		||||
        //退款成功
 | 
			
		||||
        PayRefundDO updateRefundDO = new PayRefundDO();
 | 
			
		||||
        //更新退款单表
 | 
			
		||||
        updateRefundDO.setId(req.getRefundId())
 | 
			
		||||
                .setStatus(PayRefundStatusEnum.SUCCESS.getStatus())
 | 
			
		||||
                .setChannelRefundNo(req.getChannelRefundNo())
 | 
			
		||||
                .setSuccessTime(new Date());
 | 
			
		||||
        updatePayRefund(updateRefundDO);
 | 
			
		||||
 | 
			
		||||
        PayOrderDO updateOrderDO = new PayOrderDO();
 | 
			
		||||
        //更新订单表
 | 
			
		||||
        updateOrderDO.setId(req.getOrderId())
 | 
			
		||||
                .setRefundTimes(req.getRefundedTimes() + 1)
 | 
			
		||||
                .setRefundStatus(req.getRefundTypeEnum().getStatus())
 | 
			
		||||
                .setRefundAmount(req.getRefundedAmount()+ req.getRefundAmount());
 | 
			
		||||
         updatePayOrder(updateOrderDO);
 | 
			
		||||
 | 
			
		||||
         // 立刻插入退款通知记录
 | 
			
		||||
        // TODO 通知商户成功或者失败. 现在通知似乎没有实现, 只是回调
 | 
			
		||||
        payNotifyCoreService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder()
 | 
			
		||||
                .type(PayNotifyTypeEnum.REFUND.getType()).dataId(req.getRefundId()).build());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user