mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-04 12:18:42 +08:00 
			
		
		
		
	mall + pay:
1. 增加支付宝 Client 的查询订单接口
This commit is contained in:
		@@ -27,7 +27,7 @@ public interface PayClient {
 | 
			
		||||
     * 调用支付渠道,统一下单
 | 
			
		||||
     *
 | 
			
		||||
     * @param reqDTO 下单信息
 | 
			
		||||
     * @return 各支付渠道的返回结果
 | 
			
		||||
     * @return 支付订单信息
 | 
			
		||||
     */
 | 
			
		||||
    PayOrderRespDTO unifiedOrder(PayOrderUnifiedReqDTO reqDTO);
 | 
			
		||||
 | 
			
		||||
@@ -40,6 +40,14 @@ public interface PayClient {
 | 
			
		||||
     */
 | 
			
		||||
    PayOrderRespDTO parseOrderNotify(Map<String, String> params, String body);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获得支付订单信息
 | 
			
		||||
     *
 | 
			
		||||
     * @param outTradeNo 外部订单号
 | 
			
		||||
     * @return 支付订单信息
 | 
			
		||||
     */
 | 
			
		||||
    PayOrderRespDTO getOrder(String outTradeNo);
 | 
			
		||||
 | 
			
		||||
    // ============ 退款相关 ==========
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -94,38 +94,40 @@ public class PayOrderRespDTO {
 | 
			
		||||
    /**
 | 
			
		||||
     * 创建【SUCCESS】状态的订单返回
 | 
			
		||||
     */
 | 
			
		||||
    public PayOrderRespDTO(String channelOrderNo, String channelUserId, LocalDateTime successTime,
 | 
			
		||||
                           String outTradeNo, Object rawData) {
 | 
			
		||||
        this.status = PayOrderStatusRespEnum.SUCCESS.getStatus();
 | 
			
		||||
        this.channelOrderNo = channelOrderNo;
 | 
			
		||||
        this.channelUserId = channelUserId;
 | 
			
		||||
        this.successTime = successTime;
 | 
			
		||||
    public static PayOrderRespDTO successOf(String channelOrderNo, String channelUserId, LocalDateTime successTime,
 | 
			
		||||
                                            String outTradeNo, Object rawData) {
 | 
			
		||||
        PayOrderRespDTO respDTO = new PayOrderRespDTO();
 | 
			
		||||
        respDTO.status = PayOrderStatusRespEnum.SUCCESS.getStatus();
 | 
			
		||||
        respDTO.channelOrderNo = channelOrderNo;
 | 
			
		||||
        respDTO.channelUserId = channelUserId;
 | 
			
		||||
        respDTO.successTime = successTime;
 | 
			
		||||
        // 相对通用的字段
 | 
			
		||||
        this.outTradeNo = outTradeNo;
 | 
			
		||||
        this.rawData = rawData;
 | 
			
		||||
        respDTO.outTradeNo = outTradeNo;
 | 
			
		||||
        respDTO.rawData = rawData;
 | 
			
		||||
        return respDTO;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 创建【SUCCESS】或【CLOSED】状态的订单返回,适合支付渠道回调时
 | 
			
		||||
     * 创建指定状态的订单返回,适合支付渠道回调时
 | 
			
		||||
     */
 | 
			
		||||
    public PayOrderRespDTO(Integer status, String channelOrderNo, String channelUserId, LocalDateTime successTime,
 | 
			
		||||
                           String outTradeNo, Object rawData) {
 | 
			
		||||
        this.status = status;
 | 
			
		||||
        this.channelOrderNo = channelOrderNo;
 | 
			
		||||
        this.channelUserId = channelUserId;
 | 
			
		||||
        this.successTime = successTime;
 | 
			
		||||
    public static PayOrderRespDTO of(Integer status, String channelOrderNo, String channelUserId, LocalDateTime successTime,
 | 
			
		||||
                                     String outTradeNo, Object rawData) {
 | 
			
		||||
        PayOrderRespDTO respDTO = new PayOrderRespDTO();
 | 
			
		||||
        respDTO.status = status;
 | 
			
		||||
        respDTO.channelOrderNo = channelOrderNo;
 | 
			
		||||
        respDTO.channelUserId = channelUserId;
 | 
			
		||||
        respDTO.successTime = successTime;
 | 
			
		||||
        // 相对通用的字段
 | 
			
		||||
        this.outTradeNo = outTradeNo;
 | 
			
		||||
        this.rawData = rawData;
 | 
			
		||||
        respDTO.outTradeNo = outTradeNo;
 | 
			
		||||
        respDTO.rawData = rawData;
 | 
			
		||||
        return respDTO;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 创建【CLOSED】状态的订单返回,适合调用支付渠道失败时
 | 
			
		||||
     *
 | 
			
		||||
     * 参数和 {@link #PayOrderRespDTO(String, String, String, Object)} 冲突,所以独立个方法出来
 | 
			
		||||
     */
 | 
			
		||||
    public static PayOrderRespDTO build(String channelErrorCode, String channelErrorMsg,
 | 
			
		||||
                                        String outTradeNo, Object rawData) {
 | 
			
		||||
    public static PayOrderRespDTO closedOf(String channelErrorCode, String channelErrorMsg,
 | 
			
		||||
                                           String outTradeNo, Object rawData) {
 | 
			
		||||
        PayOrderRespDTO respDTO = new PayOrderRespDTO();
 | 
			
		||||
        respDTO.status = PayOrderStatusRespEnum.CLOSED.getStatus();
 | 
			
		||||
        respDTO.channelErrorCode = channelErrorCode;
 | 
			
		||||
 
 | 
			
		||||
@@ -107,6 +107,20 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
 | 
			
		||||
    protected abstract PayOrderRespDTO doParseOrderNotify(Map<String, String> params, String body)
 | 
			
		||||
            throws Throwable;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public PayOrderRespDTO getOrder(String outTradeNo) {
 | 
			
		||||
        try {
 | 
			
		||||
            return doGetOrder(outTradeNo);
 | 
			
		||||
        } catch (Throwable ex) {
 | 
			
		||||
            log.error("[getOrder][客户端({}) outTradeNo({}) 查询支付单异常]",
 | 
			
		||||
                    getId(), outTradeNo, ex);
 | 
			
		||||
            throw buildPayException(ex);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected abstract PayOrderRespDTO doGetOrder(String outTradeNo)
 | 
			
		||||
            throws Throwable;
 | 
			
		||||
 | 
			
		||||
    // ============ 退款相关 ==========
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
 
 | 
			
		||||
@@ -17,9 +17,12 @@ 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.AlipayTradeQueryModel;
 | 
			
		||||
import com.alipay.api.domain.AlipayTradeRefundModel;
 | 
			
		||||
import com.alipay.api.internal.util.AlipaySignature;
 | 
			
		||||
import com.alipay.api.request.AlipayTradeQueryRequest;
 | 
			
		||||
import com.alipay.api.request.AlipayTradeRefundRequest;
 | 
			
		||||
import com.alipay.api.response.AlipayTradeQueryResponse;
 | 
			
		||||
import com.alipay.api.response.AlipayTradeRefundResponse;
 | 
			
		||||
import lombok.SneakyThrows;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
@@ -63,7 +66,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
 | 
			
		||||
     */
 | 
			
		||||
    protected PayOrderRespDTO buildClosedPayOrderRespDTO(PayOrderUnifiedReqDTO reqDTO, AlipayResponse response) {
 | 
			
		||||
        Assert.isFalse(response.isSuccess());
 | 
			
		||||
        return PayOrderRespDTO.build(response.getSubCode(), response.getSubMsg(),
 | 
			
		||||
        return PayOrderRespDTO.closedOf(response.getSubCode(), response.getSubMsg(),
 | 
			
		||||
                reqDTO.getOutTradeNo(), response);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -76,10 +79,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
 | 
			
		||||
 | 
			
		||||
        // 2. 解析订单的状态
 | 
			
		||||
        // 额外说明:支付宝不仅仅支付成功会回调,再各种触发支付单数据变化时,都会进行回调,所以这里 status 的解析会写的比较复杂
 | 
			
		||||
        String tradeStatus = bodyObj.get("trade_status");
 | 
			
		||||
        Integer status = Objects.equals("WAIT_BUYER_PAY", tradeStatus) ? PayOrderStatusRespEnum.WAITING.getStatus()
 | 
			
		||||
                : ObjectUtils.equalsAny(tradeStatus, "TRADE_FINISHED", "TRADE_SUCCESS") ? PayOrderStatusRespEnum.SUCCESS.getStatus()
 | 
			
		||||
                : Objects.equals("TRADE_CLOSED", tradeStatus) ? PayOrderStatusRespEnum.CLOSED.getStatus() : null;
 | 
			
		||||
        Integer status = parseStatus(bodyObj.get("trade_status"));
 | 
			
		||||
        // 特殊逻辑: 支付宝没有退款成功的状态,所以,如果有退款金额,我们认为是退款成功
 | 
			
		||||
        if (MapUtil.getDouble(bodyObj, "refund_fee", 0D) > 0) {
 | 
			
		||||
            status = PayOrderStatusRespEnum.REFUND.getStatus();
 | 
			
		||||
@@ -87,10 +87,40 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
 | 
			
		||||
        Assert.notNull(status, (Supplier<Throwable>) () -> {
 | 
			
		||||
            throw new IllegalArgumentException(StrUtil.format("body({}) 的 trade_status 不正确", body));
 | 
			
		||||
        });
 | 
			
		||||
        return new PayOrderRespDTO(status, bodyObj.get("trade_no"), bodyObj.get("seller_id"), parseTime(params.get("gmt_payment")),
 | 
			
		||||
        return PayOrderRespDTO.of(status, bodyObj.get("trade_no"), bodyObj.get("seller_id"), parseTime(params.get("gmt_payment")),
 | 
			
		||||
                bodyObj.get("out_trade_no"), body);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected PayOrderRespDTO doGetOrder(String outTradeNo) throws Throwable {
 | 
			
		||||
        // 1.1 构建 AlipayTradeRefundModel 请求
 | 
			
		||||
        AlipayTradeQueryModel model = new AlipayTradeQueryModel();
 | 
			
		||||
        model.setOutTradeNo(outTradeNo);
 | 
			
		||||
        // 1.2 构建 AlipayTradeQueryRequest 请求
 | 
			
		||||
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
 | 
			
		||||
        request.setBizModel(model);
 | 
			
		||||
 | 
			
		||||
        // 2.1 执行请求
 | 
			
		||||
        AlipayTradeQueryResponse response =  client.execute(request);
 | 
			
		||||
        if (!response.isSuccess()) {
 | 
			
		||||
            return PayOrderRespDTO.closedOf(response.getSubCode(), response.getSubMsg(),
 | 
			
		||||
                    outTradeNo, response);
 | 
			
		||||
        }
 | 
			
		||||
        // 2.2 解析订单的状态
 | 
			
		||||
        Integer status = parseStatus(response.getTradeStatus());
 | 
			
		||||
        Assert.notNull(status, (Supplier<Throwable>) () -> {
 | 
			
		||||
            throw new IllegalArgumentException(StrUtil.format("body({}) 的 trade_status 不正确", response.getBody()));
 | 
			
		||||
        });
 | 
			
		||||
        return PayOrderRespDTO.of(status, response.getTradeNo(), response.getBuyerUserId(), LocalDateTimeUtil.of(response.getSendPayDate()),
 | 
			
		||||
                outTradeNo, response);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private Integer parseStatus(String tradeStatus) {
 | 
			
		||||
        return Objects.equals("WAIT_BUYER_PAY", tradeStatus) ? PayOrderStatusRespEnum.WAITING.getStatus()
 | 
			
		||||
                : ObjectUtils.equalsAny(tradeStatus, "TRADE_FINISHED", "TRADE_SUCCESS") ? PayOrderStatusRespEnum.SUCCESS.getStatus()
 | 
			
		||||
                : Objects.equals("TRADE_CLOSED", tradeStatus) ? PayOrderStatusRespEnum.CLOSED.getStatus() : null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // ============ 退款相关 ==========
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -90,7 +90,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
 | 
			
		||||
        } catch (WxPayException e) {
 | 
			
		||||
            String errorCode = getErrorCode(e);
 | 
			
		||||
            String errorMessage = getErrorMessage(e);
 | 
			
		||||
            return PayOrderRespDTO.build(errorCode, errorMessage,
 | 
			
		||||
            return PayOrderRespDTO.closedOf(errorCode, errorMessage,
 | 
			
		||||
                    reqDTO.getOutTradeNo(), e.getXmlString());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -133,7 +133,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
 | 
			
		||||
        // 微信支付的回调,只有 SUCCESS 支付成功、CLOSED 支付失败两种情况,无需像支付宝一样解析的比较复杂
 | 
			
		||||
        Integer status = Objects.equals(response.getResultCode(), "SUCCESS") ?
 | 
			
		||||
                PayOrderStatusRespEnum.SUCCESS.getStatus() : PayOrderStatusRespEnum.CLOSED.getStatus();
 | 
			
		||||
        return new PayOrderRespDTO(status, response.getTransactionId(), response.getOpenid(), parseDateV2(response.getTimeEnd()),
 | 
			
		||||
        return PayOrderRespDTO.of(status, response.getTransactionId(), response.getOpenid(), parseDateV2(response.getTimeEnd()),
 | 
			
		||||
                response.getOutTradeNo(), body);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -146,10 +146,15 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
 | 
			
		||||
        Integer status = Objects.equals(result.getTradeState(), "SUCCESS") ?
 | 
			
		||||
                PayOrderStatusRespEnum.SUCCESS.getStatus() : PayOrderStatusRespEnum.CLOSED.getStatus();
 | 
			
		||||
        String openid = result.getPayer() != null ? result.getPayer().getOpenid() : null;
 | 
			
		||||
        return new PayOrderRespDTO(status, result.getTransactionId(), openid, parseDateV3(result.getSuccessTime()),
 | 
			
		||||
        return PayOrderRespDTO.of(status, result.getTransactionId(), openid, parseDateV3(result.getSuccessTime()),
 | 
			
		||||
                result.getOutTradeNo(), body);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected PayOrderRespDTO doGetOrder(String outTradeNo) throws Throwable {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // ============ 退款相关 ==========
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
 
 | 
			
		||||
@@ -68,7 +68,7 @@ public class WxBarPayClient extends AbstractWxPayClient {
 | 
			
		||||
            try {
 | 
			
		||||
                WxPayMicropayResult response = client.micropay(request);
 | 
			
		||||
                // 支付成功,例如说:1)用户输入了密码;2)用户免密支付
 | 
			
		||||
                return new PayOrderRespDTO(response.getTransactionId(), response.getOpenid(), parseDateV2(response.getTimeEnd()),
 | 
			
		||||
                return PayOrderRespDTO.successOf(response.getTransactionId(), response.getOpenid(), parseDateV2(response.getTimeEnd()),
 | 
			
		||||
                        response.getOutTradeNo(), response)
 | 
			
		||||
                        .setDisplayMode(PayOrderDisplayModeEnum.BAR_CODE.getMode());
 | 
			
		||||
            } catch (WxPayException ex) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user