🎨 #1827 微信支付分相关接口优化

1. 将原有请求模型类中一些基础数据类型改为对应的包装类,因为在用户没有显式set的情况下,这些基础数据类型序列化为json时也会以默认值的形式作为参数传到微信端,造成微信端返回错误。
2. 微信支付分相关的回调数据处理方法加上签名验证。
3. 增加方法授权/解除授权服务回调数据处理
This commit is contained in:
winter
2020-10-29 15:20:21 +08:00
committed by GitHub
parent 8bd95bcc22
commit 7eb11c8799
6 changed files with 224 additions and 22 deletions

View File

@@ -1,6 +1,8 @@
package com.github.binarywang.wxpay.service;
import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader;
import com.github.binarywang.wxpay.bean.payscore.PayScoreNotifyData;
import com.github.binarywang.wxpay.bean.payscore.UserAuthorizationStatusNotifyResult;
import com.github.binarywang.wxpay.bean.payscore.WxPayScoreRequest;
import com.github.binarywang.wxpay.bean.payscore.WxPayScoreResult;
import com.github.binarywang.wxpay.exception.WxPayException;
@@ -196,6 +198,19 @@ public interface PayScoreService {
* @throws WxPayException the wx pay exception
*/
WxPayScoreResult syncServiceOrder(WxPayScoreRequest request) throws WxPayException;
/**
* <pre>
* 授权/解除授权服务回调数据处理
* 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/payscore/chapter4_4.shtml
* </pre>
*
* @param notifyData 通知数据
* @param header 通知头部数据,不传则表示不校验头
* @return 解密后通知数据 return user authorization status notify result
* @throws WxPayException the wx pay exception
*/
UserAuthorizationStatusNotifyResult parseUserAuthorizationStatusNotifyResult(String notifyData, SignatureHeader header) throws WxPayException;
/**
* <pre>
@@ -206,7 +221,7 @@ public interface PayScoreService {
* @param data the data
* @return the wx pay score result
*/
PayScoreNotifyData parseNotifyData(String data);
PayScoreNotifyData parseNotifyData(String data,SignatureHeader header) throws WxPayException;
/**
* <pre>

View File

@@ -1,6 +1,19 @@
package com.github.binarywang.wxpay.service.impl;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.utils.URIBuilder;
import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader;
import com.github.binarywang.wxpay.bean.payscore.PayScoreNotifyData;
import com.github.binarywang.wxpay.bean.payscore.UserAuthorizationStatusNotifyResult;
import com.github.binarywang.wxpay.bean.payscore.WxPayScoreRequest;
import com.github.binarywang.wxpay.bean.payscore.WxPayScoreResult;
import com.github.binarywang.wxpay.config.WxPayConfig;
@@ -8,16 +21,11 @@ import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.PayScoreService;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.v3.util.AesUtils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.utils.URIBuilder;
import java.io.IOException;
import java.net.URISyntaxException;
import java.security.GeneralSecurityException;
import java.util.HashMap;
import java.util.Map;
/**
* @author doger.wang
@@ -25,6 +33,8 @@ import java.util.Map;
*/
@RequiredArgsConstructor
public class PayScoreServiceImpl implements PayScoreService {
private static final Gson GSON = new GsonBuilder().create();
private final WxPayService payService;
@Override
@@ -129,7 +139,7 @@ public class PayScoreServiceImpl implements PayScoreService {
@Override
public WxPayScoreResult createServiceOrder(WxPayScoreRequest request) throws WxPayException {
boolean needUserConfirm = request.isNeedUserConfirm();
boolean needUserConfirm = request.getNeedUserConfirm();
WxPayConfig config = this.payService.getConfig();
String url = this.payService.getPayBaseUrl() + "/v3/payscore/serviceorder";
request.setAppid(config.getAppId());
@@ -247,10 +257,31 @@ public class PayScoreServiceImpl implements PayScoreService {
String result = payService.postV3(url, request.toJson());
return WxPayScoreResult.fromJson(result);
}
@Override
public UserAuthorizationStatusNotifyResult parseUserAuthorizationStatusNotifyResult(String notifyData, SignatureHeader header) throws WxPayException {
PayScoreNotifyData response = parseNotifyData(notifyData,header);
PayScoreNotifyData.Resource resource = response.getResource();
String cipherText = resource.getCipherText();
String associatedData = resource.getAssociatedData();
String nonce = resource.getNonce();
String apiV3Key = this.payService.getConfig().getApiV3Key();
try {
String result = AesUtils.decryptToString(associatedData, nonce,cipherText, apiV3Key);
UserAuthorizationStatusNotifyResult notifyResult = GSON.fromJson(result, UserAuthorizationStatusNotifyResult.class);
notifyResult.setRawData(response);
return notifyResult;
} catch (GeneralSecurityException | IOException e) {
throw new WxPayException("解析报文异常!", e);
}
}
@Override
public PayScoreNotifyData parseNotifyData(String data) {
return WxGsonBuilder.create().fromJson(data, PayScoreNotifyData.class);
public PayScoreNotifyData parseNotifyData(String data,SignatureHeader header) throws WxPayException {
if(Objects.nonNull(header) && !this.verifyNotifySign(header, data)){
throw new WxPayException("非法请求,头部信息验证失败");
}
return GSON.fromJson(data, PayScoreNotifyData.class);
}
@Override
@@ -266,4 +297,19 @@ public class PayScoreServiceImpl implements PayScoreService {
throw new WxPayException("解析报文异常!", e);
}
}
/**
* 校验通知签名
* @param header 通知头信息
* @param data 通知数据
* @return true:校验通过 false:校验不通过
*/
private boolean verifyNotifySign(SignatureHeader header, String data) {
String beforeSign = String.format("%s\n%s\n%s\n",
header.getTimeStamp(),
header.getNonce(),
data);
return payService.getConfig().getVerifier().verify(header.getSerialNo(),
beforeSign.getBytes(StandardCharsets.UTF_8), header.getSigned());
}
}