Pārlūkot izejas kodu

支付宝退款申请通知

jason 3 gadi atpakaļ
vecāks
revīzija
dfde260ebb
13 mainītis faili ar 234 papildinājumiem un 22 dzēšanām
  1. 3 6
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/order/PayRefundMapper.java
  2. 2 2
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/PayErrorCodeCoreConstants.java
  3. 14 0
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/PayRefundCoreService.java
  4. 67 3
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/impl/PayRefundCoreServiceImpl.java
  5. 7 0
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClient.java
  6. 1 1
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayNotifyDataDTO.java
  7. 63 0
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayRefundNotifyDTO.java
  8. 6 0
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayQrPayClient.java
  9. 15 8
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClient.java
  10. 6 0
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXPubPayClient.java
  11. 20 0
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayNotifyRefundStatusEnum.java
  12. 29 2
      yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/PayOrderController.java
  13. 1 0
      yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/PayRefundController.java

+ 3 - 6
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/order/PayRefundMapper.java

@@ -1,12 +1,7 @@
 package cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order;
 
-import java.util.*;
-
 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
-
 import org.apache.ibatis.annotations.Mapper;
 
 
@@ -17,5 +12,7 @@ import org.apache.ibatis.annotations.Mapper;
 @Mapper
 public interface PayRefundMapper extends BaseMapperX<PayRefundDO> {
 
-
+    default PayRefundDO selectByReqNo(String reqNo) {
+        return selectOne("req_no", reqNo);
+    }
 }

+ 2 - 2
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/PayErrorCodeCoreConstants.java

@@ -47,8 +47,8 @@ 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(1007006002, "未找到对应的退款后置处理类");
-
+    ErrorCode PAY_REFUND_POST_HANDLER_NOT_FOUND = new ErrorCode(1007006003, "未找到对应的退款后置处理类");
+    ErrorCode PAY_REFUND_NOT_FOUND = new ErrorCode(1007006004, "支付退款单不存在");
     // TODO @aquan:下面还两个要合并上去哈。另外一般中英文之间要有空格。例如说, 新建一个 order 数据;这样可读性更好。
 
     /**

+ 14 - 0
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/PayRefundCoreService.java

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.coreservice.modules.pay.service.order;
 
 import cn.iocoder.yudao.coreservice.modules.pay.service.order.bo.PayRefundReqBO;
 import cn.iocoder.yudao.coreservice.modules.pay.service.order.bo.PayRefundRespBO;
+import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO;
 
 /**
  * 退款单 Core Service
@@ -17,4 +18,17 @@ public interface PayRefundCoreService {
      * @return 退款申请返回信息
      */
     PayRefundRespBO refund(PayRefundReqBO reqDTO);
+
+
+    /**
+     * 渠道的退款通知
+     * @param channelId  渠道编号
+     * @param channelCode 渠道编码
+     * @param notifyData  通知数据
+     * @throws Exception 退款通知异常
+     */
+    void notifyPayRefund(Long channelId, String channelCode, PayNotifyDataDTO notifyData) throws Exception;
+
+
+
 }

+ 67 - 3
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/impl/PayRefundCoreServiceImpl.java

@@ -10,7 +10,11 @@ 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.PayOrderExtensionCoreMapper;
 import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayRefundMapper;
+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.framework.pay.core.client.dto.PayRefundNotifyDTO;
 import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundTypeEnum;
 import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderStatusEnum;
 import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundStatusEnum;
@@ -24,8 +28,10 @@ import cn.iocoder.yudao.coreservice.modules.pay.service.order.bo.PayRefundRespBO
 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.PayNotifyRefundStatusEnum;
 import cn.iocoder.yudao.framework.pay.core.enums.PayChannelRespEnum;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
@@ -66,6 +72,9 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
     @Resource
     private List<PayRefundChannelPostHandler> handlerList;
 
+    @Resource
+    private PayNotifyCoreService payNotifyCoreService;
+
 
     private final EnumMap<PayChannelRespEnum, PayRefundChannelPostHandler> mapHandler = new EnumMap<>(PayChannelRespEnum.class);
 
@@ -84,7 +93,6 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
 
     }
 
-
     @Override
     @Transactional(rollbackFor = Exception.class)
     public PayRefundRespBO refund(PayRefundReqBO reqBO) {
@@ -173,6 +181,64 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
     }
 
 
+    @Override
+    public void notifyPayRefund(Long channelId, String channelCode, PayNotifyDataDTO notifyData) {
+        log.info("[notifyPayRefund][channelId({}) 回调数据({})]", channelId, notifyData.getBody());
+        // 校验支付渠道是否有效
+        PayChannelDO channel = payChannelCoreService.validPayChannel(channelId);
+        // 校验支付客户端是否正确初始化
+        PayClient client = payClientFactory.getPayClient(channel.getId());
+        if (client == null) {
+            log.error("[notifyPayOrder][渠道编号({}) 找不到对应的支付客户端]", channel.getId());
+            throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND);
+        }
+        //解析渠道退款通知数据, 统一处理
+        PayRefundNotifyDTO refundNotify = client.parseRefundNotify(notifyData);
+
+        if(Objects.equals(PayNotifyRefundStatusEnum.SUCCESS,refundNotify.getStatus())){
+            //退款成功。 支付宝只有退款成功才会发通知
+            PayRefundDO refundDO = payRefundMapper.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());
+            payRefundMapper.updateById(updateRefundDO);
+
+            //插入退款通知记录
+            // TODO 通知商户成功或者失败. 现在通知似乎没有实现, 只是回调
+            payNotifyCoreService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder()
+                    .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refundDO.getId()).build());
+        }else{
+            //TODO 退款失败
+        }
+
+    }
+
     /**
      * 校验是否进行退款
      * @param reqBO 退款申请信息
@@ -197,7 +263,5 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService {
             throw exception(PAY_REFUND_CHN_ORDER_NO_IS_NULL);
         }
         //TODO  退款的期限  退款次数的控制
-
-
     }
 }

+ 7 - 0
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClient.java

@@ -42,4 +42,11 @@ public interface PayClient {
      */
     PayRefundUnifiedRespDTO unifiedRefund(PayRefundUnifiedReqDTO reqDTO);
 
+    /**
+     * 解析支付退款通知数据
+     * @param notifyData  支付退款通知请求数据
+     * @return 支付退款通知的Notify DTO
+     */
+    PayRefundNotifyDTO parseRefundNotify(PayNotifyDataDTO notifyData);
+
 }

+ 1 - 1
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayNotifyDataDTO.java

@@ -8,7 +8,7 @@ import java.util.Map;
 
 
 /**
- * 支付订单回调,渠道的统一通知请求数据
+ * 支付订单,退款订单回调,渠道的统一通知请求数据
  */
 @Data
 @ToString

+ 63 - 0
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayRefundNotifyDTO.java

@@ -0,0 +1,63 @@
+package cn.iocoder.yudao.framework.pay.core.client.dto;
+
+import cn.iocoder.yudao.framework.pay.core.enums.PayNotifyRefundStatusEnum;
+import lombok.Builder;
+import lombok.Data;
+import lombok.ToString;
+
+import java.util.Date;
+
+/**
+ * 从渠道返回数据中解析得到的支付退款通知的Notify DTO
+ *
+ * @author jason
+ */
+@Data
+@ToString
+@Builder
+public class PayRefundNotifyDTO {
+
+    /**
+     * 支付渠道编号
+     */
+    private String channelOrderNo;
+
+
+    /**
+     * 交易订单号,根据规则生成
+     * 调用支付渠道时,使用该字段作为对接的订单号。
+     * 1. 调用微信支付 https://api.mch.weixin.qq.com/pay/unifiedorder 时,使用该字段作为 out_trade_no
+     * 2. 调用支付宝 https://opendocs.alipay.com/apis 时,使用该字段作为 out_trade_no
+     *  这里对应 pay_extension 里面的 no
+     * 例如说,P202110132239124200055
+     */
+    private String tradeNo;
+
+    /**
+     * https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 out_refund_no
+     * https://opendocs.alipay.com/apis alipay.trade.refund 中的 out_request_no
+     * 退款请求号。
+     * 标识一次退款请求,需要保证在交易号下唯一,如需部分退款,则此参数必传。
+     * 注:针对同一次退款请求,如果调用接口失败或异常了,重试时需要保证退款请求号不能变更,
+     * 防止该笔交易重复退款。支付宝会保证同样的退款请求号多次请求只会退一次。
+     * 退款单请求号,根据规则生成
+     *
+     * 例如说,RR202109181134287570000
+     */
+    private String reqNo;
+
+
+    /**
+     * 退款是否成功
+     */
+    private PayNotifyRefundStatusEnum status;
+
+
+
+    /**
+     * 退款成功时间
+     */
+    private Date refundSuccessTime;
+
+
+}

+ 6 - 0
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayQrPayClient.java

@@ -83,6 +83,12 @@ public class AlipayQrPayClient extends AbstractPayClient<AlipayPayClientConfig>
 
     }
 
+    @Override
+    public PayRefundNotifyDTO parseRefundNotify(PayNotifyDataDTO notifyData) {
+        //TODO 需要实现
+        throw new UnsupportedOperationException("需要实现");
+    }
+
     @Override
     protected PayRefundUnifiedRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable {
         //TODO 需要实现

+ 15 - 8
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClient.java

@@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult;
 import cn.iocoder.yudao.framework.pay.core.client.dto.*;
 import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
 import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
+import cn.iocoder.yudao.framework.pay.core.enums.PayNotifyRefundStatusEnum;
 import cn.iocoder.yudao.framework.pay.core.enums.PayChannelRespEnum;
 import com.alipay.api.AlipayApiException;
 import com.alipay.api.AlipayConfig;
@@ -103,7 +104,6 @@ public class AlipayWapPayClient extends AbstractPayClient<AlipayPayClientConfig>
                 .data(data.getBody()).build();
     }
 
-
     @Override
     protected PayRefundUnifiedRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO)  {
         AlipayTradeRefundModel model=new AlipayTradeRefundModel();
@@ -119,11 +119,10 @@ public class AlipayWapPayClient extends AbstractPayClient<AlipayPayClientConfig>
             AlipayTradeRefundResponse response =  client.execute(refundRequest);
             log.info("[doUnifiedRefund][response({}) 发起退款 渠道返回", toJsonString(response));
             if (response.isSuccess()) {
-                //退款成功
+                //退款成功,更新为PROCESSING_NOTIFY, 而不是 SYNC_SUCCESS 通过支付宝回调接口处理。退款导致触发的异步通知,
+                //退款导致触发的异步通知是发送到支付接口中设置的notify_url
                 //TODO 沙箱环境 返回 的tradeNo(渠道退款单号) 和 订单的tradNo 是一个值,是不是理解不对?
-                respDTO.setRespEnum(PayChannelRespEnum.SYNC_SUCCESS)
-                        .setChannelRefundNo(response.getTradeNo())
-                        .setPayTradeNo(response.getOutTradeNo());
+                respDTO.setRespEnum(PayChannelRespEnum.PROCESSING_NOTIFY);
             }else{
                 //特殊处理 sub_code  ACQ.SYSTEM_ERROR(系统错误), 需要调用重试任务
                 //沙箱环境返回的貌似是”aop.ACQ.SYSTEM_ERROR“, 用contain
@@ -153,12 +152,20 @@ public class AlipayWapPayClient extends AbstractPayClient<AlipayPayClientConfig>
                         .setChannelErrMsg(e.getErrMsg())
                         .setRespEnum(PayChannelRespEnum.CALL_EXCEPTION);
             }
-
             return respDTO;
-
         }
+    }
 
-
+    @Override
+    public PayRefundNotifyDTO parseRefundNotify(PayNotifyDataDTO notifyData) {
+        Map<String, String> params = notifyData.getParams();
+        PayRefundNotifyDTO notifyDTO = PayRefundNotifyDTO.builder().channelOrderNo(params.get("trade_no"))
+                .tradeNo(params.get("out_trade_no"))
+                .reqNo(params.get("out_biz_no"))
+                .status(PayNotifyRefundStatusEnum.SUCCESS)
+                .refundSuccessTime(DateUtil.parse(params.get("gmt_refund"), "yyyy-MM-dd HH:mm:ss"))
+                .build();
+        return notifyDTO;
     }
 
 }

+ 6 - 0
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXPubPayClient.java

@@ -141,6 +141,12 @@ public class WXPubPayClient extends AbstractPayClient<WXPayClientConfig> {
                 .data(data.getBody()).build();
     }
 
+    @Override
+    public PayRefundNotifyDTO parseRefundNotify(PayNotifyDataDTO notifyData) {
+        //TODO 需要实现
+        throw new UnsupportedOperationException("需要实现");
+    }
+
 
     @Override
     protected PayRefundUnifiedRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable {

+ 20 - 0
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayNotifyRefundStatusEnum.java

@@ -0,0 +1,20 @@
+package cn.iocoder.yudao.framework.pay.core.enums;
+
+/**
+ * 退款通知, 统一的渠道退款状态
+ *
+ * @author  jason
+ */
+public enum PayNotifyRefundStatusEnum {
+    /**
+     * 支付宝 中 全额退款 trade_status=TRADE_CLOSED, 部分退款 trade_status=TRADE_SUCCESS
+     * 退款成功
+     */
+    SUCCESS,
+
+    /**
+     * 支付宝退款通知没有这个状态
+     * 退款异常
+     */
+    ABNORMAL;
+}

+ 29 - 2
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/PayOrderController.java

@@ -3,6 +3,7 @@ package cn.iocoder.yudao.userserver.modules.pay.controller.order;
 import cn.hutool.core.bean.BeanUtil;
 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
 import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayOrderCoreService;
+import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayRefundCoreService;
 import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitReqDTO;
 import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitRespDTO;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
@@ -34,6 +35,9 @@ public class PayOrderController {
     @Resource
     private PayOrderCoreService payOrderCoreService;
 
+    @Resource
+    private PayRefundCoreService payRefundCoreService;
+
     @PostMapping("/submit")
     @ApiOperation("提交支付订单")
 //    @PreAuthenticated // TODO 暂时不加登陆验证,前端暂时没做好
@@ -85,11 +89,21 @@ public class PayOrderController {
     public String notifyAliPayWapPayOrder(@PathVariable("channelId") Long channelId,
                                           @RequestParam Map<String, String> params,
                                           @RequestBody String originData) throws Exception {
-        //TODO @jason 校验 是否支付宝调用。 payclient 中加一个校验方法
-        payOrderCoreService.notifyPayOrder(channelId, PayChannelEnum.ALIPAY_WAP.getCode(), PayNotifyDataDTO.builder().params(params).body(originData).build());
+        //TODO 校验是否支付宝调用。 payclient 中加一个校验方法
+        //支付宝退款交易也会触发支付回调接口
+        //参考 https://opensupport.alipay.com/support/helpcenter/193/201602484851
+        //判断是否为支付宝的退款交易
+        if(isAliPayRefund(params)) {
+            //退款通知
+            payRefundCoreService.notifyPayRefund(channelId,PayChannelEnum.ALIPAY_WAP.getCode(), PayNotifyDataDTO.builder().params(params).body(originData).build());
+        }else{
+            //支付通知
+            payOrderCoreService.notifyPayOrder(channelId, PayChannelEnum.ALIPAY_WAP.getCode(), PayNotifyDataDTO.builder().params(params).body(originData).build());
+        }
         return "success";
     }
 
+
     /**
      * https://opendocs.alipay.com/open/203/105285#%E5%89%8D%E5%8F%B0%E5%9B%9E%E8%B7%B3%E5%8F%82%E6%95%B0%E8%AF%B4%E6%98%8E
      * @param channelId 渠道id
@@ -102,6 +116,19 @@ public class PayOrderController {
         return "支付成功";
     }
 
+    /**
+     * 是否是支付宝的退款交易
+     * @param params http content-type application/x-www-form-urlencoded 的参数
+     * @return
+     */
+    private boolean  isAliPayRefund(Map<String, String> params) {
+        if (params.containsKey("refund_fee")) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
     @RequestMapping("/notify/test")
     @ApiOperation("通知的测试接口")
     public String notifyTest() {

+ 1 - 0
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/PayRefundController.java

@@ -37,6 +37,7 @@ public class PayRefundController {
         reqBO.setUserIp(getClientIP());
         //TODO 测试暂时模拟生成商户退款订单
         reqBO.setMerchantRefundNo(PaySeqUtils.genMerchantRefundNo());
+        //reqBO.setMerchantRefundNo("MO202111210814084370000");
         return CommonResult.success( PayRefundConvert.INSTANCE.convert(payRefundCoreService.refund(reqBO)));
     }
 }