针对通知参数时间格式为什么是固定时间格式”YYYY-MM-DDTHH:mm:ss+TIMEZONE“,而不是时间戳的类型呢?
进行签名验证时,获取请求body里的内容只能用输入流获取,如果用一般json工具类转化的会一直签名验证失败,最后真的只是因为时间格式的问题!!
查看很多关于验签示例,其实微信支付SKDK中关于验签已经给出了具体工具类,只需要在构造该工具类时给与正确的参数即可:
引入微信支付SDK
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-apache-httpclient</artifactId>
<version>0.2.2</version>
构造微信支付相关配置
@Configuration
public class WXPayConfiguration {
@Value("${WXPay.app-id}")
private String appId;
@Value("${pay.trade.money-virtual-currency-ratio}")
private Integer ratio;
@Value("${WXPay.app-private-key}")
private String appPrivateKey;
@Value("${WXPay.api-v3-key}")
private String apiV3Key;
@Value("${WXPay.mch-serial-no}")
private String mchSerialNo;
@Value("${WXPay.charset}")
private String charset;
@Value("${WXPay.mch-id}")
private String mchId;
@Value("${WXPay.notify-url}")
private String notifyUrl;
@Value("${WXPay.native-pay-url}")
private String nativePayUrl;
@Value("${file.qrcode.logopath}")
private String logoPath;
@Bean
public HttpClient httpClient(AutoUpdateCertificatesVerifier verifier) throws IOException {
// 加载商户私钥(privateKey:私钥字符串)
PrivateKey merchantPrivateKey = PemUtil
.loadPrivateKey(new ByteArrayInputStream(appPrivateKey.getBytes(charset)));
// 初始化httpClient
return WechatPayHttpClientBuilder.create()
.withMerchant(mchId, mchSerialNo, merchantPrivateKey)
.withValidator(new WechatPay2Validator(verifier)).build();
}
@Bean
public AutoUpdateCertificatesVerifier verifier() throws UnsupportedEncodingException {
// 加载商户私钥(privateKey:私钥字符串)
PrivateKey merchantPrivateKey = PemUtil
.loadPrivateKey(new ByteArrayInputStream(appPrivateKey.getBytes(charset)));
// 加载平台证书(mchId:商户号,mchSerialNo:商户证书序列号,apiV3Key:V3秘钥)
return new AutoUpdateCertificatesVerifier(
new WechatPay2Credentials(mchId, new PrivateKeySigner(mchSerialNo, merchantPrivateKey)),apiV3Key.getBytes(charset));
}
}
验证签名
BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
String body = IOUtils.toString(reader);
//验证签名
String wechatPayTimestamp = request.getHeader("Wechatpay-Timestamp");
String wechatPayNonce = request.getHeader("Wechatpay-Nonce");
String wechatSignature = request.getHeader("Wechatpay-Signature");
String wechatPaySerial = request.getHeader("Wechatpay-Serial");
//签名信息
String signMessage = buildSignMessage(wechatPayTimestamp, wechatPayNonce, body);
// 加载平台证书(mchId:商户号,mchSerialNo:商户证书序列号,apiV3Key:V3秘钥)
boolean verify = verifier.verify(wechatPaySerial, signMessage.getBytes(StandardCharsets.UTF_8), wechatSignature);
解密数据
AesUtil aesUtil = new AesUtil(apiV3Key.getBytes(StandardCharsets.UTF_8));
String decrypt = aesUtil.decryptToString(associated_data.getBytes(StandardCharsets.UTF_8), nonce.getBytes(StandardCharsets.UTF_8), ciphertext);