feat:【PAY 支付】AbstractAlipayPayClient,支付宝增加回调解析

This commit is contained in:
YunaiV 2025-05-08 13:57:49 +08:00
parent 7653be9d48
commit f81dc105a2

View File

@ -81,24 +81,11 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
@Override
public PayOrderRespDTO doParseOrderNotify(Map<String, String> params, String body, Map<String, String> headers) throws Throwable {
// 1. 校验回调数据
Map<String, String> bodyObj = HttpUtil.decodeParamMap(body, StandardCharsets.UTF_8);
boolean verify;
if (Objects.equals(config.getMode(), MODE_PUBLIC_KEY)) {
verify = AlipaySignature.rsaCheckV1(params, config.getAlipayPublicKey(),
StandardCharsets.UTF_8.name(), config.getSignType());
} else if (Objects.equals(config.getMode(), MODE_CERTIFICATE)) {
// 由于 rsaCertCheckV1 的第二个参数是 path所以不能这么调用通过阅读源码发现可以采用如下方式
X509Certificate cert = AntCertificationUtil.getCertFromContent(config.getAlipayPublicCertContent());
String publicKey = Base64.encodeBase64String(cert.getEncoded());
verify = AlipaySignature.rsaCheckV1(bodyObj, publicKey,
StandardCharsets.UTF_8.name(), config.getSignType());
} else {
throw new IllegalArgumentException("未知的公钥类型:" + config.getMode());
}
Assert.isTrue(verify, "验签结果不通过");
verifyNotifyData(params);
// 2. 解析订单的状态
// 额外说明支付宝不仅仅支付成功会回调再各种触发支付单数据变化时都会进行回调所以这里 status 的解析会写的比较复杂
Map<String, String> bodyObj = HttpUtil.decodeParamMap(body, StandardCharsets.UTF_8);
Integer status = parseStatus(bodyObj.get("trade_status"));
// 特殊逻辑: 支付宝没有退款成功的状态所以如果有退款金额我们认为是退款成功
if (MapUtil.getDouble(bodyObj, "refund_fee", 0D) > 0) {
@ -324,10 +311,55 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
response.getOutBizNo(), response);
}
// TODO @chihuo这里是不是也要实现支付宝的
// TODO @芋艿由于支付宝一直没触发回调这个方法暂时没办法测试
@Override
protected PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body, Map<String, String> headers) {
throw new UnsupportedOperationException("未实现");
protected PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body, Map<String, String> headers)
throws Throwable {
// 1. 校验回调数据
verifyNotifyData(params);
// 2. 解析转账状态
Map<String, String> bodyObj = HttpUtil.decodeParamMap(body, StandardCharsets.UTF_8);
String status = bodyObj.get("status");
String outBizNo = bodyObj.get("out_biz_no");
String orderId = bodyObj.get("order_id");
String payDate = bodyObj.get("pay_date");
// 3. 根据状态返回对应的结果
if (Objects.equals(status, "SUCCESS")) {
return PayTransferRespDTO.successOf(orderId, parseTime(payDate), outBizNo, bodyObj);
}
if (Objects.equals(status, "DEALING")) {
return PayTransferRespDTO.processingOf(orderId, outBizNo, bodyObj);
}
if (ObjectUtils.equalsAny(status, "REFUND", "FAIL")) {
return PayTransferRespDTO.closedOf(bodyObj.get("sub_code"), bodyObj.get("sub_msg"),
outBizNo, bodyObj);
}
return PayTransferRespDTO.waitingOf(orderId, outBizNo, bodyObj);
}
/**
* 校验回调数据
*
* @param params 回调参数
* @throws Throwable 验签失败时抛出异常
*/
protected void verifyNotifyData(Map<String, String> params) throws Throwable {
boolean verify;
if (Objects.equals(config.getMode(), MODE_PUBLIC_KEY)) {
verify = AlipaySignature.rsaCheckV1(params, config.getAlipayPublicKey(),
StandardCharsets.UTF_8.name(), config.getSignType());
} else if (Objects.equals(config.getMode(), MODE_CERTIFICATE)) {
// 由于 rsaCertCheckV1 的第二个参数是 path所以不能这么调用通过阅读源码发现可以采用如下方式
X509Certificate cert = AntCertificationUtil.getCertFromContent(config.getAlipayPublicCertContent());
String publicKey = Base64.encodeBase64String(cert.getEncoded());
verify = AlipaySignature.rsaCheckV1(params, publicKey,
StandardCharsets.UTF_8.name(), config.getSignType());
} else {
throw new IllegalArgumentException("未知的公钥类型:" + config.getMode());
}
Assert.isTrue(verify, "验签结果不通过");
}
// ========== 各种工具方法 ==========