Преглед изворни кода

mall + pay:
1. 增加支付宝退款查询接口

YunaiV пре 1 година
родитељ
комит
5b066ea693

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

@@ -67,4 +67,13 @@ public interface PayClient {
      */
     PayRefundRespDTO parseRefundNotify(Map<String, String> params, String body);
 
+    /**
+     * 获得退款订单信息
+     *
+     * @param outTradeNo 外部订单号
+     * @param outRefundNo 外部退款号
+     * @return 退款订单信息
+     */
+    PayRefundRespDTO getRefund(String outTradeNo, String outRefundNo);
+
 }

+ 18 - 4
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java

@@ -94,7 +94,7 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
             throws Throwable;
 
     @Override
-    public PayOrderRespDTO parseOrderNotify(Map<String, String> params, String body) {
+    public final PayOrderRespDTO parseOrderNotify(Map<String, String> params, String body) {
         try {
             return doParseOrderNotify(params, body);
         } catch (Throwable ex) {
@@ -108,7 +108,7 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
             throws Throwable;
 
     @Override
-    public PayOrderRespDTO getOrder(String outTradeNo) {
+    public final PayOrderRespDTO getOrder(String outTradeNo) {
         try {
             return doGetOrder(outTradeNo);
         } catch (Throwable ex) {
@@ -124,7 +124,7 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
     // ============ 退款相关 ==========
 
     @Override
-    public PayRefundRespDTO unifiedRefund(PayRefundUnifiedReqDTO reqDTO) {
+    public final PayRefundRespDTO unifiedRefund(PayRefundUnifiedReqDTO reqDTO) {
         ValidationUtils.validate(reqDTO);
         // 执行统一退款
         PayRefundRespDTO resp;
@@ -145,7 +145,7 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
     protected abstract PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable;
 
     @Override
-    public PayRefundRespDTO parseRefundNotify(Map<String, String> params, String body) {
+    public final PayRefundRespDTO parseRefundNotify(Map<String, String> params, String body) {
         try {
             return doParseRefundNotify(params, body);
         } catch (Throwable ex) {
@@ -158,6 +158,20 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
     protected abstract PayRefundRespDTO doParseRefundNotify(Map<String, String> params, String body)
             throws Throwable;
 
+    @Override
+    public final PayRefundRespDTO getRefund(String outTradeNo, String outRefundNo) {
+        try {
+            return doGetRefund(outTradeNo, outRefundNo);
+        } catch (Throwable ex) {
+            log.error("[getRefund][客户端({}) outTradeNo({}) outRefundNo({}) 查询退款单异常]",
+                    getId(), outTradeNo, outRefundNo, ex);
+            throw buildPayException(ex);
+        }
+    }
+
+    protected abstract PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo)
+            throws Throwable;
+
     // ========== 各种工具方法 ==========
 
     private PayException buildPayException(Throwable ex) {

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

@@ -17,11 +17,14 @@ import com.alipay.api.AlipayApiException;
 import com.alipay.api.AlipayConfig;
 import com.alipay.api.AlipayResponse;
 import com.alipay.api.DefaultAlipayClient;
+import com.alipay.api.domain.AlipayTradeFastpayRefundQueryModel;
 import com.alipay.api.domain.AlipayTradeQueryModel;
 import com.alipay.api.domain.AlipayTradeRefundModel;
 import com.alipay.api.internal.util.AlipaySignature;
+import com.alipay.api.request.AlipayTradeFastpayRefundQueryRequest;
 import com.alipay.api.request.AlipayTradeQueryRequest;
 import com.alipay.api.request.AlipayTradeRefundRequest;
+import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
 import com.alipay.api.response.AlipayTradeQueryResponse;
 import com.alipay.api.response.AlipayTradeRefundResponse;
 import lombok.SneakyThrows;
@@ -29,6 +32,7 @@ import lombok.extern.slf4j.Slf4j;
 
 import java.nio.charset.StandardCharsets;
 import java.time.LocalDateTime;
+import java.util.Collections;
 import java.util.Map;
 import java.util.Objects;
 import java.util.function.Supplier;
@@ -102,7 +106,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
 
         // 2.1 执行请求
         AlipayTradeQueryResponse response =  client.execute(request);
-        if (!response.isSuccess()) {
+        if (!response.isSuccess()) { // 不成功,例如说订单不存在
             return PayOrderRespDTO.closedOf(response.getSubCode(), response.getSubMsg(),
                     outTradeNo, response);
         }
@@ -142,16 +146,15 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
         request.setBizModel(model);
 
         // 2.1 执行请求
-        AlipayTradeRefundResponse response =  client.execute(request);
+        AlipayTradeRefundResponse response = client.execute(request);
+        if (!response.isSuccess()) {
+            return PayRefundRespDTO.failureOf(reqDTO.getOutRefundNo(), response);
+        }
         // 2.2 创建返回结果
         // 支付宝只要退款调用返回 success,就认为退款成功,不需要回调。具体可见 parseNotify 方法的说明。
         // 另外,支付宝没有退款单号,所以不用设置
-        if (response.isSuccess()) {
-            return PayRefundRespDTO.successOf(null, LocalDateTimeUtil.of(response.getGmtRefundPay()),
-                    reqDTO.getOutRefundNo(), response);
-        } else {
-            return PayRefundRespDTO.failureOf(reqDTO.getOutRefundNo(), response);
-        }
+        return PayRefundRespDTO.successOf(null, LocalDateTimeUtil.of(response.getGmtRefundPay()),
+                reqDTO.getOutRefundNo(), response);
     }
 
     @Override
@@ -164,6 +167,35 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
         throw new UnsupportedOperationException("支付宝无退款回调");
     }
 
+    @Override
+    protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) throws AlipayApiException {
+        // 1.1 构建 AlipayTradeFastpayRefundQueryModel 请求
+        AlipayTradeFastpayRefundQueryModel model = new AlipayTradeFastpayRefundQueryModel();
+        model.setOutTradeNo(outTradeNo);
+        model.setOutRequestNo(outRefundNo);
+        model.setQueryOptions(Collections.singletonList("gmt_refund_pay"));
+        // 1.2 构建 AlipayTradeFastpayRefundQueryRequest 请求
+        AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
+        request.setBizModel(model);
+
+        // 2.1 执行请求
+        AlipayTradeFastpayRefundQueryResponse response = client.execute(request);
+        if (!response.isSuccess()) {
+            // 明确不存在的情况,应该就是失败,可进行关闭
+            if (ObjectUtils.equalsAny(response.getSubCode(), "TRADE_NOT_EXIST", "ACQ.TRADE_NOT_EXIST")) {
+                return PayRefundRespDTO.failureOf(outRefundNo, response);
+            }
+            // 可能存在“ACQ.SYSTEM_ERROR”系统错误等情况,所以返回 WAIT 继续等待
+            return PayRefundRespDTO.waitingOf(null, outRefundNo, response);
+        }
+        // 2.2 创建返回结果
+        if (Objects.equals(response.getRefundStatus(), "REFUND_SUCCESS")) {
+            return PayRefundRespDTO.successOf(null, LocalDateTimeUtil.of(response.getGmtRefundPay()),
+                    outRefundNo, response);
+        }
+        return PayRefundRespDTO.waitingOf(null, outRefundNo, response);
+    }
+
     // ========== 各种工具方法 ==========
 
     protected String formatAmount(Integer amount) {

+ 5 - 0
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java

@@ -307,6 +307,11 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
         return PayRefundRespDTO.failureOf(result.getOutRefundNo(), response);
     }
 
+    @Override
+    protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) {
+        return null;
+    }
+
     // ========== 各种工具方法 ==========
 
     static String formatDateV2(LocalDateTime time) {

+ 1 - 0
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxPubPayClient.java

@@ -4,6 +4,7 @@ import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
+import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
 import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;

+ 6 - 0
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/refund/PayRefundDO.java

@@ -70,6 +70,12 @@ public class PayRefundDO extends BaseDO {
      * 关联 {@link PayOrderDO#getId()}
      */
     private Long orderId;
+    /**
+     * 支付订单编号
+     *
+     * 冗余 {@link PayOrderDO#getNo()}
+     */
+    private String orderNo;
 
     // ========== 商户相关字段 ==========
     /**