diff --git a/.github/workflows/sonarcloud-scan.yml b/.github/workflows/sonarcloud-scan.yml index 489de321..706a2eb0 100644 --- a/.github/workflows/sonarcloud-scan.yml +++ b/.github/workflows/sonarcloud-scan.yml @@ -18,10 +18,10 @@ jobs: - uses: actions/checkout@v2 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v1 with: - java-version: 11 + java-version: 17 - name: Cache SonarCloud packages uses: actions/cache@v1 with: diff --git a/README.md b/README.md index 3435d8d2..f27528a3 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![JavaDoc](http://img.shields.io/badge/javadoc-reference-blue.svg)](https://www.javadoc.io/doc/com.github.wechatpay-apiv3/wechatpay-java/latest/index.html) -![Maven Central](https://img.shields.io/maven-central/v/com.github.wechatpay-apiv3/wechatpay-java?versionPrefix=0.2.10) +![Maven Central](https://img.shields.io/maven-central/v/com.github.wechatpay-apiv3/wechatpay-java?versionPrefix=0.2.11) [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=wechatpay-apiv3_wechatpay-java&metric=security_rating)](https://sonarcloud.io/summary/overall?id=wechatpay-apiv3_wechatpay-java) [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=wechatpay-apiv3_wechatpay-java&metric=sqale_rating)](https://sonarcloud.io/summary/overall?id=wechatpay-apiv3_wechatpay-java) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=wechatpay-apiv3_wechatpay-java&metric=coverage)](https://sonarcloud.io/summary/overall?id=wechatpay-apiv3_wechatpay-java) @@ -36,7 +36,7 @@ 在你的 build.gradle 文件中加入如下的依赖 ```groovy -implementation 'com.github.wechatpay-apiv3:wechatpay-java:0.2.10' +implementation 'com.github.wechatpay-apiv3:wechatpay-java:0.2.11' ``` #### Maven @@ -47,7 +47,7 @@ implementation 'com.github.wechatpay-apiv3:wechatpay-java:0.2.10' com.github.wechatpay-apiv3 wechatpay-java - 0.2.10 + 0.2.11 ``` @@ -233,7 +233,7 @@ Config config = .build(); ``` -## 回调通知验签和解密 +## 回调通知 首先,你需要在你的服务器上创建一个公开的 HTTP 端点,接受来自微信支付的回调通知。 当接收到回调通知,使用 [notification](core/src/main/java/com/wechat/pay/java/core/notification) 中的 `NotificationParser` 解析回调通知。 @@ -241,23 +241,24 @@ Config config = 具体步骤如下: 1. 使用回调通知请求的数据,构建 `RequestParam`。 - - HTTP 头 `Wechatpay-Signature` - - HTTP 头 `Wechatpay-Nonce` - - HTTP 头 `Wechatpay-Timestamp` - - HTTP 头 `Wechatpay-Serial` - - HTTP 头 `Wechatpay-Signature-Type` - - HTTP 请求体 body。切记使用原始报文,不要用 JSON 对象序列化后的字符串,避免验签的 body 和原文不一致。 -2. 初始化 `RSAAutoCertificateConfig`。微信支付平台证书由 SDK 的自动更新平台能力提供,也可以使用本地证书。 -3. 初始化 `NotificationParser`。 -4. 调用 `NotificationParser.parse()` 验签、解密并将 JSON 转换成具体的通知回调对象。 + - HTTP 请求体 body。**切记使用原始报文**,不要用 JSON 对象序列化后的字符串,避免验签的 body 和原文不一致。 + - HTTP 头 `Wechatpay-Signature`。应答的微信支付签名。 + - HTTP 头 `Wechatpay-Serial`。微信支付平台证书的序列号,验签必须使用序列号对应的微信支付平台证书。 + - HTTP 头 `Wechatpay-Nonce`。签名中的随机数。 + - HTTP 头 `Wechatpay-Timestamp`。签名中的时间戳。 + - HTTP 头 `Wechatpay-Signature-Type`。签名类型。 +1. 初始化 `RSAAutoCertificateConfig`。微信支付平台证书由 SDK 的自动更新平台能力提供,也可以使用本地证书。 +1. 初始化 `NotificationParser`。 +1. 调用 `NotificationParser.parse()` 验签、解密并将 JSON 转换成具体的通知回调对象。如果验签失败,SDK 会抛出 `ValidationException`。 +1. 接下来可以执行你的业务逻辑了。如果执行成功,你应返回 `200 OK` 的状态码。如果执行失败,你应返回 `4xx` 或者 `5xx`的状态码,例如数据库操作失败建议返回 `500 Internal Server Error`。 ```java // 构造 RequestParam RequestParam requestParam = new RequestParam.Builder() - .serialNumber(wechatPayCertificateSerialNumber) - .nonce(nonce) - .signature(signature) - .timestamp(timestamp) + .serialNumber(wechatPaySerial) + .nonce(wechatpayNonce) + .signature(wechatSignature) + .timestamp(wechatTimestamp) .body(requestBody) .build(); @@ -273,11 +274,25 @@ NotificationConfig config = new RSAAutoCertificateConfig.Builder() // 初始化 NotificationParser NotificationParser parser = new NotificationParser(config); -// 以支付通知回调为例,验签、解密并转换成 Transaction -Transaction transaction = parser.parse(requestParam, Transaction.class); +try { + // 以支付通知回调为例,验签、解密并转换成 Transaction + Transaction transaction = parser.parse(requestParam, Transaction.class); +} catch (ValidationException e) { + // 签名验证失败,返回 401 UNAUTHORIZED 状态码 + logger.error("sign verification failed", e); + return ResponseEntity.status(HttpStatus.UNAUTHORIZED); +} + +// 如果处理失败,应返回 4xx/5xx 的状态码,例如 500 INTERNAL_SERVER_ERROR +if (/* process error */) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR); +} + +// 处理成功,返回 200 OK 状态码 +return ResponseEntity.status(HttpStatus.OK); ``` -常用的通知回调对象类型: +常用的通知回调调对象类型有: - 支付 `Transaction` - 退款 `RefundNotification` @@ -293,8 +308,8 @@ Transaction transaction = parser.parse(requestParam, Transaction.class); 发送请求步骤如下: 1. 初始化 `OkHttpClientAdapter`,建议使用 `DefaultHttpClientBuilder` 构建。 -2. 构建请求 `HttpRequest`。 -3. 调用 `httpClient.execute` 或者 `httpClient.get` 等方法来发送 HTTP 请求。`httpClient.execute` 支持发送 GET、PUT、POST、PATCH、DELETE 请求,也可以调用指定的 HTTP 方法发送请求。 +1. 构建请求 `HttpRequest`。 +1. 调用 `httpClient.execute` 或者 `httpClient.get` 等方法来发送 HTTP 请求。`httpClient.execute` 支持发送 GET、PUT、POST、PATCH、DELETE 请求,也可以调用指定的 HTTP 方法发送请求。 [OkHttpClientAdapterTest](core/src/test/java/com/wechat/pay/java/core/http/OkHttpClientAdapterTest.java) 中演示了如何构造和发送 HTTP 请求。如果现有的 `OkHttpClientAdapter` 实现类不满足你的需求,可以继承 [AbstractHttpClient](core/src/main/java/com/wechat/pay/java/core/http/AbstractHttpClient.java) 拓展实现。 diff --git a/gradle.properties b/gradle.properties index dc2d8dac..15bdbc0f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ projectPropGroup=com.github.wechatpay-apiv3 -projectPropVersion=0.2.10 +projectPropVersion=0.2.11 slf4jVersion=1.7.36 junitVersion=4.13.2