4
4
5
5
[ 微信支付API v3] ( https://wechatpay-api.gitbook.io/wechatpay-api-v3/ ) 的[ Apache HttpClient] ( https://hc.apache.org/httpcomponents-client-ga/index.html ) 扩展,实现了请求签名的生成和应答签名的验证。
6
6
7
- 如果你是使用Apache HttpClient的商户开发者,可以使用它构造` HttpClient ` 。得到的` HttpClient ` 在执行请求时将自动携带身份认证信息,并检查应答的微信支付签名。
7
+ > [ !IMPORTANT]
8
+ > 我们强烈建议你改为使用 [ WechatPay-Java] ( https://github.com/wechatpay-apiv3/wechatpay-java ) ,该SDK同样支持 Apache HttpClient 且提供了更完善的功能,本库未来只会进行必要的修复更新。
8
9
9
10
## 项目状态
10
11
11
- 当前版本` 0.5 .0 ` 为测试版本。请商户的专业技术人员在使用时注意系统和软件的正确性和兼容性,以及带来的风险。
12
+ 当前版本` 0.6 .0 ` 为测试版本。请商户的专业技术人员在使用时注意系统和软件的正确性和兼容性,以及带来的风险。
12
13
13
14
## 升级指引
14
15
15
- 若你使用的版本为` 0.3 .0` ,升级前请参考[ 升级指南] ( UPGRADING.md ) 。
16
+ 若你使用的版本为` <=0.5 .0` ,升级前请参考[ 升级指南] ( UPGRADING.md ) 。
16
17
17
18
## 环境要求
18
19
27
28
在你的` build.gradle ` 文件中加入如下的依赖
28
29
29
30
``` groovy
30
- implementation 'com.github.wechatpay-apiv3:wechatpay-apache-httpclient:0.5 .0'
31
+ implementation 'com.github.wechatpay-apiv3:wechatpay-apache-httpclient:0.6 .0'
31
32
```
32
33
33
34
### Maven
@@ -37,17 +38,18 @@ implementation 'com.github.wechatpay-apiv3:wechatpay-apache-httpclient:0.5.0'
37
38
<dependency >
38
39
<groupId >com.github.wechatpay-apiv3</groupId >
39
40
<artifactId >wechatpay-apache-httpclient</artifactId >
40
- <version >0.5 .0</version >
41
+ <version >0.6 .0</version >
41
42
</dependency >
42
43
```
43
44
44
45
## 名词解释
45
46
46
- + 商户API证书,是用来证实商户身份的。证书中包含商户号、证书序列号、证书有效期等信息,由证书授权机构(Certificate Authority ,简称CA)签发,以防证书被伪造或篡改。如何获取请见[ 商户API证书] ( https://wechatpay-api.gitbook.io/wechatpay-api-v3/ren-zheng/zheng-shu#shang-hu-api-zheng-shu ) 。
47
- + 商户API私钥。商户申请商户API证书时,会生成商户私钥,并保存在本地证书文件夹的文件apiclient_key.pem中。注:不要把私钥文件暴露在公共场合,如上传到Github,写在客户端代码等。
48
- + 微信支付平台证书。平台证书是指由微信支付负责申请的,包含微信支付平台标识、公钥信息的证书。商户可以使用平台证书中的公钥进行应答签名的验证。获取平台证书需通过[ 获取平台证书列表] ( https://wechatpay-api.gitbook.io/wechatpay-api-v3/ren-zheng/zheng-shu#ping-tai-zheng-shu ) 接口下载。
49
- + 证书序列号。每个证书都有一个由CA颁发的唯一编号,即证书序列号。如何查看证书序列号请看[ 这里] ( https://wechatpay-api.gitbook.io/wechatpay-api-v3/chang-jian-wen-ti/zheng-shu-xiang-guan#ru-he-cha-kan-zheng-shu-xu-lie-hao ) 。
50
- + API v3密钥。为了保证安全性,微信支付在回调通知和平台证书下载接口中,对关键信息进行了AES-256-GCM加密。API v3密钥是加密时使用的对称密钥。商户可以在【商户平台】->【API安全】的页面设置该密钥。
47
+ + ** 商户API证书** ,是用来证实商户身份的。证书中包含商户号、证书序列号、证书有效期等信息,由证书授权机构(Certificate Authority ,简称CA)签发,以防证书被伪造或篡改。如何获取请见[ 商户API证书] ( https://wechatpay-api.gitbook.io/wechatpay-api-v3/ren-zheng/zheng-shu#shang-hu-api-zheng-shu ) 。
48
+ + ** 商户API私钥** 。商户申请商户API证书时,会生成商户私钥,并保存在本地证书文件夹的文件apiclient_key.pem中。注:不要把私钥文件暴露在公共场合,如上传到Github,写在客户端代码等。
49
+ + ** 微信支付平台证书** 。平台证书是指由微信支付负责申请的,包含微信支付平台标识、公钥信息的证书。商户可以使用平台证书中的公钥进行应答签名的验证。获取平台证书需通过[ 获取平台证书列表] ( https://wechatpay-api.gitbook.io/wechatpay-api-v3/ren-zheng/zheng-shu#ping-tai-zheng-shu ) 接口下载。
50
+ + ** 微信支付公钥** 。由微信支付生成,商户可以使用该公钥进行应答签名、回调签名的验证,详见:[ 微信支付公钥] ( https://pay.weixin.qq.com/doc/v3/merchant/4012153196 ) 。
51
+ + ** 证书序列号** 。每个证书都有一个由CA颁发的唯一编号,即证书序列号。如何查看证书序列号请看[ 这里] ( https://wechatpay-api.gitbook.io/wechatpay-api-v3/chang-jian-wen-ti/zheng-shu-xiang-guan#ru-he-cha-kan-zheng-shu-xu-lie-hao ) 。
52
+ + ** API v3密钥** 。为了保证安全性,微信支付在回调通知和平台证书下载接口中,对关键信息进行了AES-256-GCM加密。API v3密钥是加密时使用的对称密钥。商户可以在【商户平台】->【API安全】的页面设置该密钥。
51
53
52
54
## 开始
53
55
@@ -58,7 +60,7 @@ import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
58
60
// ...
59
61
WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder . create()
60
62
.withMerchant(merchantId, merchantSerialNumber, merchantPrivateKey)
61
- .withWechatPay(wechatPayCertificates );
63
+ .withWechatPay(wechatpayPublicKeyId, wechatPayPublicKey );
62
64
// ... 接下来,你仍然可以通过builder设置各种参数,来配置你的HttpClient
63
65
64
66
// 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签
@@ -73,7 +75,8 @@ CloseableHttpResponse response = httpClient.execute(...);
73
75
+ ` merchantId ` 商户号。
74
76
+ ` merchantSerialNumber ` 商户API证书的证书序列号。
75
77
+ ` merchantPrivateKey ` 商户API私钥,如何加载商户API私钥请看[ 常见问题] ( #如何加载商户私钥 ) 。
76
- + ` wechatPayCertificates ` 微信支付平台证书列表。你也可以使用后面章节提到的“[ 定时更新平台证书功能] ( #定时更新平台证书功能 ) ”,而不需要关心平台证书的来龙去脉。
78
+ + ` wechatpayPublicKeyId ` 微信支付公钥ID,登录商户平台可获取,详见:[ 获取微信支付公钥] ( https://pay.weixin.qq.com/doc/v3/merchant/4013053249#1.-%E8%8E%B7%E5%8F%96%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98%E5%85%AC%E9%92%A5 )
79
+ + ` wechatPayPublicKey ` 微信支付公钥,登录商户平台可获取,详见:[ 获取微信支付公钥] ( https://pay.weixin.qq.com/doc/v3/merchant/4013053249#1.-%E8%8E%B7%E5%8F%96%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98%E5%85%AC%E9%92%A5 )
77
80
78
81
### 示例:获取平台证书
79
82
@@ -177,11 +180,14 @@ Credentials credentials = new WechatPay2Credentials(merchantId, new Signer() {
177
180
});
178
181
WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder . create()
179
182
.withCredentials(credentials)
180
- .withWechatPay(wechatPayCertificates );
183
+ .withWechatPay(wechatpayPublicKeyId, wechatPayPublicKey );
181
184
```
182
185
183
186
## 定时更新平台证书功能
184
187
188
+ > [ !IMPORTANT]
189
+ > 新注册的商户使用「微信支付公钥」验签,不需要下载和更新平台证书。仅尚未完全迁移至「微信支付公钥」验签的旧商户才需要此能力。
190
+
185
191
版本>=` 0.4.0 ` 可使用 CertificatesManager.getVerifier(merchantId) 得到的验签器替代默认的验签器。它会定时下载和更新商户对应的[ 微信支付平台证书] ( https://wechatpay-api.gitbook.io/wechatpay-api-v3/ren-zheng/zheng-shu#ping-tai-zheng-shu ) (默认下载间隔为UPDATE_INTERVAL_MINUTE)。
186
192
187
193
示例代码:
@@ -197,7 +203,7 @@ certificatesManager.putMerchant(merchantId, new WechatPay2Credentials(merchantId
197
203
verifier = certificatesManager. getVerifier(merchantId);
198
204
WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder . create()
199
205
.withMerchant(merchantId, merchantSerialNumber, merchantPrivateKey)
200
- .withValidator(new WechatPay2Validator (verifier))
206
+ .withValidator(new WechatPay2Validator (verifier));
201
207
// ... 接下来,你仍然可以通过builder设置各种参数,来配置你的HttpClient
202
208
203
209
// 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
@@ -217,13 +223,13 @@ CloseableHttpResponse response = httpClient.execute(...);
217
223
218
224
### 加密
219
225
220
- 使用` RsaCryptoUtil.encryptOAEP(String, X509Certificate ) ` 进行公钥加密。示例代码如下。
226
+ 使用` RsaCryptoUtil.encryptOAEP(String, PublicKey publicKey ) ` 进行公钥加密。示例代码如下。
221
227
222
228
``` java
223
229
// 建议从Verifier中获得微信支付平台证书,或使用预先下载到本地的平台证书文件中
224
- X509Certificate certificate = verifier. getValidCertificate ();
230
+ PublicKey publicKey = verifier. getValidPublicKey ();
225
231
try {
226
- String ciphertext = RsaCryptoUtil . encryptOAEP(text, certificate );
232
+ String ciphertext = RsaCryptoUtil . encryptOAEP(text, publicKey );
227
233
} catch (IllegalBlockSizeException e) {
228
234
e. printStackTrace();
229
235
}
@@ -277,15 +283,40 @@ try (FileInputStream ins1 = new FileInputStream(file)) {
277
283
2 . 使用` NotificationHandler ` 构造一个回调通知处理器,需设置验证器、apiV3密钥。调用` parse(request) ` 得到回调通知` notification ` 。
278
284
279
285
示例请参考下列代码。
286
+
280
287
``` java
281
288
// 构建request,传入必要参数
282
- NotificationRequest request = new NotificationRequest .Builder (). withSerialNumber(wechatPaySerial)
289
+ NotificationRequest request = new NotificationRequest .Builder (). withSerialNumber(wechatPaySerial)
283
290
.withNonce(nonce)
284
291
.withTimestamp(timestamp)
285
292
.withSignature(signature)
286
293
.withBody(body)
287
294
.build();
288
- NotificationHandler handler = new NotificationHandler (verifier, apiV3Key. getBytes(StandardCharsets . UTF_8 ));
295
+
296
+ // 如果已经初始化了 NotificationHandler 则直接使用,否则根据具体情况创建一个
297
+
298
+ // 1. 如果你使用的是微信支付公私钥,则使用公钥初始化 Verifier 以创建 NotificationHandler
299
+ NotificationHandler handler = new NotificationHandler (
300
+ new PublicKeyVerifier (wechatPayPublicKeyId, wechatPayPublicKey),
301
+ apiV3Key. getBytes(StandardCharsets . UTF_8 )
302
+ );
303
+
304
+ // 2. 如果你使用的事微信支付平台证书,则从 CertificatesManager 获取 Verifier 以创建 NotificationHandler
305
+ NotificationHandler handler = new NotificationHandler (
306
+ certificatesManager. getVerifier(merchantId),
307
+ apiV3Key. getBytes(StandardCharsets . UTF_8 )
308
+ );
309
+
310
+ // 3. 如果你正在进行微信支付平台证书到微信支付公私钥的灰度切换,希望保持切换兼容,则需要使用 MixVerifier 创建 NotificationHandler
311
+ Verifier mixVerifier = new MixVerifier (
312
+ new PublicKeyVerifier (wechatPayPublicKeyId, wechatPayPublicKey),
313
+ certificatesManager. getVerifier(merchantId)
314
+ );
315
+ NotificationHandler handler = new NotificationHandler (
316
+ mixVerifier,
317
+ apiV3Key. getBytes(StandardCharsets . UTF_8 )
318
+ );
319
+
289
320
// 验签和解析请求体
290
321
Notification notification = handler. parse(request);
291
322
// 从notification中获取解密报文
@@ -306,11 +337,11 @@ System.out.println(notification.getDecryptData());
306
337
商户申请商户API证书时,会生成商户私钥,并保存在本地证书文件夹的文件` apiclient_key.pem ` 中。商户开发者可以使用方法` PemUtil.loadPrivateKey() ` 加载证书。
307
338
308
339
``` java
309
- # 示例:私钥存储在文件
340
+ // 示例:私钥存储在文件
310
341
PrivateKey merchantPrivateKey = PemUtil . loadPrivateKey(
311
342
new FileInputStream (" /path/to/apiclient_key.pem" ));
312
343
313
- # 示例:私钥为String 字符串
344
+ // 示例:私钥为String字符串
314
345
PrivateKey merchantPrivateKey = PemUtil . loadPrivateKey(
315
346
new ByteArrayInputStream (privateKey. getBytes(" utf-8" )));
316
347
```
0 commit comments