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