微信支付服务器验证的java_关于java:Java中的微信支付3API-V3对微信服务器响应进行签名验证...

1. 前言

牢记一句话:公钥加密,私钥解密;私钥加签,公钥验签。

微信领取V3版本前两篇别离讲了如何对申请做签名和如何获取并刷新微信平台公钥,本篇将持续开展如何对微信领取响应后果的验签。

2. 为什么要对响应验签

微信领取会在回调的HTTP头部中包含回调报文的签名。商户必须验证响应的签名,保障响应的确来自微信领取服务器,防止中间人攻打。而验证响应签名除了须要微信平台的公钥外还须要从申请头的其它参数。

假如以下就是微信领取服务器的响应:

HTTP/1.1 200 OK

Server: nginx

Date: Tue, 02 Apr 2019 12:59:40 GMT

Content-Type: application/json; charset=utf-8

Content-Length: 2204

Connection: keep-alive

Keep-Alive: timeout=8

Content-Language: zh-CN

Request-ID: e2762b10-b6b9-5108-a42c-16fe2422fc8a

Wechatpay-Nonce: c5ac7061fccab6bf3e254dcf98995b8c

Wechatpay-Signature: CtcbzwtQjN8rnOXItEBJ5aQFSnIXESeV28Pr2YEmf9wsDQ8Nx25ytW6FXBCAFdrr0mgqngX3AD9gNzjnNHzSGTPBSsaEkIfhPF4b8YRRTpny88tNLyprXA0GU5ID3DkZHpjFkX1hAp/D0fva2GKjGRLtvYbtUk/OLYqFuzbjt3yOBzJSKQqJsvbXILffgAmX4pKql+Ln+6UPvSCeKwznvtPaEx+9nMBmKu7Wpbqm/+2ksc0XwjD+xlvlECkCxfD/OJ4gN3IurE0fpjxIkvHDiinQmk51BI7zQD8k1znU7r/spPqB+vZjc5ep6DC5wZUpFu5vJ8MoNKjCu8wnzyCFdA==

Wechatpay-Timestamp: 1554209980

Wechatpay-Serial: 5157F09EFDC096DE15EBE81A47057A7232F1B8E1

Cache-Control: no-cache, must-revalidate

{"prepay_id":"wx2922034726858082fbd40b511c67630000"}

查看平台证书序列号

微信领取响应的时候会携带一个微信平台证书序列号,从响应头中的Wechatpay-Serial字段中获取值,用来提醒咱们要应用该序列号的证书来进行验签,如果不存在就须要咱们刷新证书,而上一文咱们将平台证书序列号和证书以键值对存在HashMap中,咱们只须要查看是否存在即可,不存在就刷新。

结构验签名串

从响应后果中获取对应上面办法的三个参数就能够结构出验签名串。

/**

* 结构验签名串.

*

* @param wechatpayTimestamp HTTP头 Wechatpay-Timestamp 中的应答工夫戳。

* @param wechatpayNonce HTTP头 Wechatpay-Nonce 中的应答随机串

* @param body 响应体

* @return the string

*/

public String responseSign(String wechatpayTimestamp, String wechatpayNonce, String body) {

return Stream.of(wechatpayTimestamp, wechatpayNonce, body)

.collect(Collectors.joining("\n", "", "\n"));

}

验证签名

待验证的签名从响应头中的Wechatpay-Signature字段中获取,咱们应用微信领取平台公钥对验签名串和签名进行SHA256 with RSA签名验证。

// 结构验签名串

final String signatureStr = responseSign(wechatpayTimestamp, wechatpayNonce, body);

// 加载SHA256withRSA签名器

Signature signer = Signature.getInstance("SHA256withRSA");

// 用微信平台公钥对签名器进行初始化

signer.initVerify(certificate);

// 把咱们结构的验签名串更新到签名器中

signer.update(signatureStr.getBytes(StandardCharsets.UTF_8));

// 把申请头中微信服务器返回的签名用Base64解码 并应用签名器进行验证

boolean result = signer.verify(Base64Utils.decodeFromString(wechatpaySignature));

残缺的验签代码

/**

* 我方对响应验签,和应答签名做比拟,应用微信平台证书.

*

* @param wechatpaySerial response.headers['Wechatpay-Serial'] 以后应用的微信平台证书序列号

* @param wechatpaySignature response.headers['Wechatpay-Signature'] 微信平台签名

* @param wechatpayTimestamp response.headers['Wechatpay-Timestamp'] 微信服务器的工夫戳

* @param wechatpayNonce response.headers['Wechatpay-Nonce'] 微信服务器提供的随机串

* @param body response.body 微信服务器的响应体

* @return the boolean

*/

@SneakyThrows

public boolean responseSignVerify(String wechatpaySerial, String wechatpaySignature, String wechatpayTimestamp, String wechatpayNonce, String body) {

if (CERTIFICATE_MAP.isEmpty() || !CERTIFICATE_MAP.containsKey(wechatpaySerial)) {

refreshCertificate();

}

Certificate certificate = CERTIFICATE_MAP.get(wechatpaySerial);

final String signatureStr = createSign(wechatpayTimestamp, wechatpayNonce, body);

Signature signer = Signature.getInstance("SHA256withRSA");

signer.initVerify(certificate);

signer.update(signatureStr.getBytes(StandardCharsets.UTF_8));

return signer.verify(Base64Utils.decodeFromString(wechatpaySignature));

}

CERTIFICATE_MAP 平台证书容器可参考上一篇文章。

3. 总结

验签通过就阐明咱们申请的响应来自微信服务器就能够针对后果进行对应的逻辑解决了,微信领取API无论是V2还是V3都蕴含了应用Api证书对申请进行加签,对响应后果进行验签的流程,非常考验对明码摘要算法的应用,其它就是组织参数调用Http申请。如果你可能把握这一能力就会在面试中和工作中占到劣势。好了明天分享就到这里,多多关注: 码农小胖哥 获取更多实用的编程干货。

关注公众号:Felordcn 获取更多资讯

集体博客:https://felord.cn

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值