🎨 #3056 【微信支付】优化支付/退款结果解析,增加对V3版本服务商的下单/退款支持

This commit is contained in:
Pursuer丶
2023-06-16 16:22:59 +08:00
committed by Binary Wang
parent 211f4c7f74
commit 21a95e15df
10 changed files with 1609 additions and 30 deletions

View File

@@ -169,7 +169,7 @@ public interface WxPayService {
* <p>
* 部分字段会包含敏感信息,所以在提交前需要在请求头中会包含"Wechatpay-Serial"信息
*
* @param url 请求地址
* @param url 请求地址
* @return 返回请求结果字符串 string
* @throws WxPayException the wx pay exception
*/
@@ -550,6 +550,27 @@ public interface WxPayService {
*/
<T> T createOrderV3(TradeTypeEnum tradeType, WxPayUnifiedOrderV3Request request) throws WxPayException;
/**
* 服务商模式调用统一下单接口,并组装生成支付所需参数对象.
*
* @param <T> 请使用{@link com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result}里的内部类或字段
* @param tradeType the trade type
* @param request 统一下单请求参数
* @return 返回 {@link com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result}里的内部类或字段
* @throws WxPayException the wx pay exception
*/
<T> T createPartnerOrderV3(TradeTypeEnum tradeType, WxPayPartnerUnifiedOrderV3Request request) throws WxPayException;
/**
* 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识"
*
* @param tradeType the trade type
* @param request 请求对象注意一些参数如spAppid、spMchid等不用设置方法内会自动从配置对象中获取到前提是对应配置中已经设置
* @return the wx pay unified order result
* @throws WxPayException the wx pay exception
*/
WxPayUnifiedOrderV3Result unifiedPartnerOrderV3(TradeTypeEnum tradeType, WxPayPartnerUnifiedOrderV3Request request) throws WxPayException;
/**
* 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识"
*
@@ -802,7 +823,7 @@ public interface WxPayService {
WxPayOrderNotifyResult parseOrderNotifyResult(String xmlData, String signType) throws WxPayException;
/**
* 解析支付结果v3通知.
* 解析支付结果v3通知. 直连商户模式
* 详见https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_5.shtml
*
* @param notifyData 通知数据
@@ -810,7 +831,31 @@ public interface WxPayService {
* @return the wx pay order notify result
* @throws WxPayException the wx pay exception
*/
WxPayOrderNotifyV3Result parseOrderNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException;
WxPayNotifyV3Result parseOrderNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException;
/**
* 服务商模式解析支付结果v3通知.
* 详见https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter4_1_5.shtml
*
* @param notifyData 通知数据
* @param header 通知头部数据,不传则表示不校验头
* @return the wx pay order notify result
* @throws WxPayException the wx pay exception
*/
WxPayPartnerNotifyV3Result parsePartnerOrderNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException;
/**
* 支付服务商和直连商户两种模式
* 详见https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_5.shtml
*
* @param notifyData 通知数据
* @param header 通知头部数据,不传则表示不校验头
* @param resultType 结果类型
* @param dataType 结果数据类型
* @return the wx pay order notify result
* @throws WxPayException the wx pay exception
*/
<T extends WxPayBaseNotifyV3Result<E>, E> T baseParseOrderNotifyV3Result(String notifyData, SignatureHeader header, Class<T> resultType, Class<E> dataType) throws WxPayException;
/**
* <pre>
@@ -836,7 +881,7 @@ public interface WxPayService {
WxPayRefundNotifyResult parseRefundNotifyResult(String xmlData) throws WxPayException;
/**
* 解析退款结果通知
* 解析直连商户退款结果通知
* 详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_16&index=9
*
* @param notifyData 通知数据
@@ -846,6 +891,17 @@ public interface WxPayService {
*/
WxPayRefundNotifyV3Result parseRefundNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException;
/**
* 解析服务商模式退款结果通知
* 详见https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter4_1_11.shtml
*
* @param notifyData 通知数据
* @param header 通知头部数据,不传则表示不校验头
* @return the wx pay refund notify result
* @throws WxPayException the wx pay exception
*/
WxPayPartnerRefundNotifyV3Result parsePartnerRefundNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException;
/**
* 解析扫码支付回调通知
* 详见https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4
@@ -1380,6 +1436,7 @@ public interface WxPayService {
/**
* 获取服务商支付分服务类
*
* @return the partner pay score service
*/
PartnerPayScoreService getPartnerPayScoreService();

View File

@@ -31,6 +31,7 @@ import lombok.Getter;
import lombok.Setter;
import me.chanjar.weixin.common.error.WxRuntimeException;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.ConstructorUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -343,7 +344,17 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
}
@Override
public WxPayOrderNotifyV3Result parseOrderNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException {
public WxPayNotifyV3Result parseOrderNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException {
return baseParseOrderNotifyV3Result(notifyData, header, WxPayNotifyV3Result.class, WxPayNotifyV3Result.DecryptNotifyResult.class);
}
@Override
public WxPayPartnerNotifyV3Result parsePartnerOrderNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException {
return this.baseParseOrderNotifyV3Result(notifyData, header, WxPayPartnerNotifyV3Result.class, WxPayPartnerNotifyV3Result.DecryptNotifyResult.class);
}
@Override
public <T extends WxPayBaseNotifyV3Result<E>, E> T baseParseOrderNotifyV3Result(String notifyData, SignatureHeader header, Class<T> resultType, Class<E> dataType) throws WxPayException {
if (Objects.nonNull(header) && !this.verifyNotifySign(header, notifyData)) {
throw new WxPayException("非法请求,头部信息验证失败");
}
@@ -355,12 +366,12 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
String apiV3Key = this.getConfig().getApiV3Key();
try {
String result = AesUtils.decryptToString(associatedData, nonce, cipherText, apiV3Key);
WxPayOrderNotifyV3Result.DecryptNotifyResult decryptNotifyResult = GSON.fromJson(result, WxPayOrderNotifyV3Result.DecryptNotifyResult.class);
WxPayOrderNotifyV3Result notifyResult = new WxPayOrderNotifyV3Result();
E decryptNotifyResult = GSON.fromJson(result, dataType);
T notifyResult = ConstructorUtils.invokeConstructor(resultType);
notifyResult.setRawData(response);
notifyResult.setResult(decryptNotifyResult);
return notifyResult;
} catch (GeneralSecurityException | IOException e) {
} catch (Exception e) {
throw new WxPayException("解析报文异常!", e);
}
}
@@ -409,25 +420,12 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
@Override
public WxPayRefundNotifyV3Result parseRefundNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException {
if (Objects.nonNull(header) && !this.verifyNotifySign(header, notifyData)) {
throw new WxPayException("非法请求,头部信息验证失败");
}
OriginNotifyResponse response = GSON.fromJson(notifyData, OriginNotifyResponse.class);
OriginNotifyResponse.Resource resource = response.getResource();
String cipherText = resource.getCiphertext();
String associatedData = resource.getAssociatedData();
String nonce = resource.getNonce();
String apiV3Key = this.getConfig().getApiV3Key();
try {
String result = AesUtils.decryptToString(associatedData, nonce, cipherText, apiV3Key);
WxPayRefundNotifyV3Result.DecryptNotifyResult decryptNotifyResult = GSON.fromJson(result, WxPayRefundNotifyV3Result.DecryptNotifyResult.class);
WxPayRefundNotifyV3Result notifyResult = new WxPayRefundNotifyV3Result();
notifyResult.setRawData(response);
notifyResult.setResult(decryptNotifyResult);
return notifyResult;
} catch (GeneralSecurityException | IOException e) {
throw new WxPayException("解析报文异常!", e);
}
return this.baseParseOrderNotifyV3Result(notifyData, header, WxPayRefundNotifyV3Result.class, WxPayRefundNotifyV3Result.DecryptNotifyResult.class);
}
@Override
public WxPayPartnerRefundNotifyV3Result parsePartnerRefundNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException {
return this.baseParseOrderNotifyV3Result(notifyData, header, WxPayPartnerRefundNotifyV3Result.class, WxPayPartnerRefundNotifyV3Result.DecryptNotifyResult.class);
}
@Override
@@ -665,6 +663,37 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
return result.getPayInfo(tradeType, request.getAppid(), request.getMchid(), this.getConfig().getPrivateKey());
}
@Override
public <T> T createPartnerOrderV3(TradeTypeEnum tradeType, WxPayPartnerUnifiedOrderV3Request request) throws WxPayException {
WxPayUnifiedOrderV3Result result = this.unifiedPartnerOrderV3(tradeType, request);
//获取应用ID
String appId = StringUtils.isBlank(request.getSubAppid()) ? request.getSpAppid() : request.getSubAppid();
return result.getPayInfo(tradeType, appId, request.getSubMchId(), this.getConfig().getPrivateKey());
}
@Override
public WxPayUnifiedOrderV3Result unifiedPartnerOrderV3(TradeTypeEnum tradeType, WxPayPartnerUnifiedOrderV3Request request) throws WxPayException {
if (StringUtils.isBlank(request.getSpAppid())) {
request.setSpAppid(this.getConfig().getAppId());
}
if (StringUtils.isBlank(request.getSpMchId())) {
request.setSpMchId(this.getConfig().getMchId());
}
if (StringUtils.isBlank(request.getNotifyUrl())) {
request.setNotifyUrl(this.getConfig().getNotifyUrl());
}
if (StringUtils.isBlank(request.getSubAppid())) {
request.setSubAppid(this.getConfig().getSubAppId());
}
if (StringUtils.isBlank(request.getSubMchId())) {
request.setSubMchId(this.getConfig().getSubMchId());
}
String url = this.getPayBaseUrl() + tradeType.getPartnerUrl();
String response = this.postV3(url, GSON.toJson(request));
return GSON.fromJson(response, WxPayUnifiedOrderV3Result.class);
}
@Override
public WxPayUnifiedOrderV3Result unifiedOrderV3(TradeTypeEnum tradeType, WxPayUnifiedOrderV3Request request) throws WxPayException {
if (StringUtils.isBlank(request.getAppid())) {