{"id":13694686,"url":"https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient","last_synced_at":"2025-04-14T23:17:15.086Z","repository":{"id":37320956,"uuid":"189376393","full_name":"wechatpay-apiv3/wechatpay-apache-httpclient","owner":"wechatpay-apiv3","description":"微信支付 APIv3 Apache HttpClient装饰器（decorator）","archived":false,"fork":false,"pushed_at":"2025-02-11T15:12:50.000Z","size":319,"stargazers_count":699,"open_issues_count":19,"forks_count":255,"subscribers_count":20,"default_branch":"master","last_synced_at":"2025-04-14T23:17:06.931Z","etag":null,"topics":["apache-httpclient","apache-httpcomponents","decorators","java","sdk","wechatpay","wechatpay-apiv3","weixin"],"latest_commit_sha":null,"homepage":"https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pages/index.shtml","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wechatpay-apiv3.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-05-30T08:32:36.000Z","updated_at":"2025-03-09T13:25:47.000Z","dependencies_parsed_at":"2024-01-14T19:12:18.907Z","dependency_job_id":"df9cf261-e881-4dfd-8a33-3829c6145b66","html_url":"https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wechatpay-apiv3%2Fwechatpay-apache-httpclient","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wechatpay-apiv3%2Fwechatpay-apache-httpclient/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wechatpay-apiv3%2Fwechatpay-apache-httpclient/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wechatpay-apiv3%2Fwechatpay-apache-httpclient/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wechatpay-apiv3","download_url":"https://codeload.github.com/wechatpay-apiv3/wechatpay-apache-httpclient/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248975329,"owners_count":21192210,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apache-httpclient","apache-httpcomponents","decorators","java","sdk","wechatpay","wechatpay-apiv3","weixin"],"created_at":"2024-08-02T17:01:37.377Z","updated_at":"2025-04-14T23:17:15.066Z","avatar_url":"https://github.com/wechatpay-apiv3.png","language":"Java","readme":"# wechatpay-apache-httpclient\n\n## 概览\n\n[微信支付API v3](https://wechatpay-api.gitbook.io/wechatpay-api-v3/)的[Apache HttpClient](https://hc.apache.org/httpcomponents-client-ga/index.html)扩展，实现了请求签名的生成和应答签名的验证。\n\n\u003e [!IMPORTANT]\n\u003e 我们强烈建议你改为使用 [WechatPay-Java](https://github.com/wechatpay-apiv3/wechatpay-java)，该SDK同样支持 Apache HttpClient 且提供了更完善的功能，本库未来只会进行必要的修复更新。\n\n## 项目状态\n\n当前版本`0.6.0`为测试版本。请商户的专业技术人员在使用时注意系统和软件的正确性和兼容性，以及带来的风险。\n\n## 升级指引\n\n若你使用的版本为`\u003c=0.5.0`，升级前请参考[升级指南](UPGRADING.md)。\n\n## 环境要求\n\n+ Java 1.8+\n\n## 安装\n\n最新版本已经在 [Maven Central](https://search.maven.org/artifact/com.github.wechatpay-apiv3/wechatpay-apache-httpclient) 发布。\n\n### Gradle\n\n在你的`build.gradle`文件中加入如下的依赖\n\n```groovy\nimplementation 'com.github.wechatpay-apiv3:wechatpay-apache-httpclient:0.6.0'\n```\n\n### Maven\n加入以下依赖\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.github.wechatpay-apiv3\u003c/groupId\u003e\n    \u003cartifactId\u003ewechatpay-apache-httpclient\u003c/artifactId\u003e\n    \u003cversion\u003e0.6.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n## 名词解释\n\n+ **商户API证书**，是用来证实商户身份的。证书中包含商户号、证书序列号、证书有效期等信息，由证书授权机构(Certificate Authority ，简称CA)签发，以防证书被伪造或篡改。如何获取请见[商户API证书](https://wechatpay-api.gitbook.io/wechatpay-api-v3/ren-zheng/zheng-shu#shang-hu-api-zheng-shu)。\n+ **商户API私钥**。商户申请商户API证书时，会生成商户私钥，并保存在本地证书文件夹的文件apiclient_key.pem中。注：不要把私钥文件暴露在公共场合，如上传到Github，写在客户端代码等。\n+ **微信支付平台证书**。平台证书是指由微信支付负责申请的，包含微信支付平台标识、公钥信息的证书。商户可以使用平台证书中的公钥进行应答签名的验证。获取平台证书需通过[获取平台证书列表](https://wechatpay-api.gitbook.io/wechatpay-api-v3/ren-zheng/zheng-shu#ping-tai-zheng-shu)接口下载。\n+ **微信支付公钥**。由微信支付生成，商户可以使用该公钥进行应答签名、回调签名的验证，详见：[微信支付公钥](https://pay.weixin.qq.com/doc/v3/merchant/4012153196)。\n+ **证书序列号**。每个证书都有一个由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)。\n+ **API v3密钥**。为了保证安全性，微信支付在回调通知和平台证书下载接口中，对关键信息进行了AES-256-GCM加密。API v3密钥是加密时使用的对称密钥。商户可以在【商户平台】-\u003e【API安全】的页面设置该密钥。\n\n## 开始\n\n如果你使用的是`HttpClientBuilder`或者`HttpClients#custom()`来构造`HttpClient`，你可以直接替换为`WechatPayHttpClientBuilder`。\n```java\nimport com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;\n\n//...\nWechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()\n        .withMerchant(merchantId, merchantSerialNumber, merchantPrivateKey)\n        .withWechatPay(wechatpayPublicKeyId, wechatPayPublicKey);\n// ... 接下来，你仍然可以通过builder设置各种参数，来配置你的HttpClient\n\n// 通过WechatPayHttpClientBuilder构造的HttpClient，会自动的处理签名和验签\nCloseableHttpClient httpClient = builder.build();\n\n// 后面跟使用Apache HttpClient一样\nCloseableHttpResponse response = httpClient.execute(...);\n```\n\n参数说明：\n\n+ `merchantId`商户号。\n+ `merchantSerialNumber`商户API证书的证书序列号。\n+ `merchantPrivateKey`商户API私钥，如何加载商户API私钥请看[常见问题](#如何加载商户私钥)。\n+ `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)\n+ `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)\n\n### 示例：获取平台证书\n\n你可以使用`WechatPayHttpClientBuilder`构造的`HttpClient`发送请求和应答了。\n\n```java\nURIBuilder uriBuilder = new URIBuilder(\"https://api.mch.weixin.qq.com/v3/certificates\");\nHttpGet httpGet = new HttpGet(uriBuilder.build());\nhttpGet.addHeader(\"Accept\", \"application/json\");\n\nCloseableHttpResponse response = httpClient.execute(httpGet);\n\nString bodyAsString = EntityUtils.toString(response.getEntity());\nSystem.out.println(bodyAsString);\n```\n\n### 示例：JSAPI下单\n\n注：\n\n+ 我们使用了 jackson-databind 演示拼装 Json，你也可以使用自己熟悉的 Json 库\n+ 请使用你自己的测试商户号、appid 以及对应的 openid\n\n```java\nHttpPost httpPost = new HttpPost(\"https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi\");\nhttpPost.addHeader(\"Accept\", \"application/json\");\nhttpPost.addHeader(\"Content-type\",\"application/json; charset=utf-8\");\n\nByteArrayOutputStream bos = new ByteArrayOutputStream();\nObjectMapper objectMapper = new ObjectMapper();\n\nObjectNode rootNode = objectMapper.createObjectNode();\nrootNode.put(\"mchid\",\"1900009191\")\n        .put(\"appid\", \"wxd678efh567hg6787\")\n        .put(\"description\", \"Image形象店-深圳腾大-QQ公仔\")\n        .put(\"notify_url\", \"https://www.weixin.qq.com/wxpay/pay.php\")\n        .put(\"out_trade_no\", \"1217752501201407033233368018\");\nrootNode.putObject(\"amount\")\n        .put(\"total\", 1);\nrootNode.putObject(\"payer\")\n        .put(\"openid\", \"oUpF8uMuAJO_M2pxb1Q9zNjWeS6o\");\n\nobjectMapper.writeValue(bos, rootNode);\n\nhttpPost.setEntity(new StringEntity(bos.toString(\"UTF-8\"), \"UTF-8\"));\nCloseableHttpResponse response = httpClient.execute(httpPost);\n\nString bodyAsString = EntityUtils.toString(response.getEntity());\nSystem.out.println(bodyAsString);\n```\n\n### 示例：查单\n\n```java\nURIBuilder uriBuilder = new URIBuilder(\"https://api.mch.weixin.qq.com/v3/pay/transactions/id/4200000889202103303311396384?mchid=1230000109\");\nHttpGet httpGet = new HttpGet(uriBuilder.build());\nhttpGet.addHeader(\"Accept\", \"application/json\");\n\nCloseableHttpResponse response = httpClient.execute(httpGet);\n\nString bodyAsString = EntityUtils.toString(response.getEntity());\nSystem.out.println(bodyAsString);\n```\n\n### 示例：关单\n\n```java\nHttpPost httpPost = new HttpPost(\"https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/1217752501201407033233368018/close\");\nhttpPost.addHeader(\"Accept\", \"application/json\");\nhttpPost.addHeader(\"Content-type\",\"application/json; charset=utf-8\");\n\nByteArrayOutputStream bos = new ByteArrayOutputStream();\nObjectMapper objectMapper = new ObjectMapper();\n\nObjectNode rootNode = objectMapper.createObjectNode();\nrootNode.put(\"mchid\",\"1900009191\");\n\nobjectMapper.writeValue(bos, rootNode);\n\nhttpPost.setEntity(new StringEntity(bos.toString(\"UTF-8\"), \"UTF-8\"));\nCloseableHttpResponse response = httpClient.execute(httpPost);\n\nString bodyAsString = EntityUtils.toString(response.getEntity());\nSystem.out.println(bodyAsString);\n```\n\n## 定制\n\n当默认的本地签名和验签方式不适合你的系统时，你可以通过实现`Signer`或者`Verifier`来定制签名和验签。比如，你的系统把商户私钥集中存储，业务系统需通过远程调用进行签名，你可以这样做。\n\n```java\nimport com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;\nimport com.wechat.pay.contrib.apache.httpclient.Credentials;\n\n// ...\nCredentials credentials = new WechatPay2Credentials(merchantId, new Signer() {\n  @Override\n  public Signer.SignatureResult sign(byte[] message) {\n    // ... call your sign-RPC, then return sign \u0026 serial number\n  }\n});\nWechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()\n        .withCredentials(credentials)\n        .withWechatPay(wechatpayPublicKeyId, wechatPayPublicKey);\n```\n\n## 定时更新平台证书功能\n\n\u003e [!IMPORTANT]\n\u003e 新注册的商户使用「微信支付公钥」验签，不需要下载和更新平台证书。仅尚未完全迁移至「微信支付公钥」验签的旧商户才需要此能力。\n\n版本\u003e=`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）。\n\n示例代码：\n```java\n// 获取证书管理器实例\ncertificatesManager = CertificatesManager.getInstance();\n// 向证书管理器增加需要自动更新平台证书的商户信息\ncertificatesManager.putMerchant(merchantId, new WechatPay2Credentials(merchantId,\n            new PrivateKeySigner(merchantSerialNumber, merchantPrivateKey)), apiV3Key.getBytes(StandardCharsets.UTF_8));\n// ... 若有多个商户号，可继续调用putMerchant添加商户信息\n\n// 从证书管理器中获取verifier\nverifier = certificatesManager.getVerifier(merchantId);\nWechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()\n        .withMerchant(merchantId, merchantSerialNumber, merchantPrivateKey)\n        .withValidator(new WechatPay2Validator(verifier));\n// ... 接下来，你仍然可以通过builder设置各种参数，来配置你的HttpClient\n\n// 通过WechatPayHttpClientBuilder构造的HttpClient，会自动的处理签名和验签，并进行证书自动更新\nCloseableHttpClient httpClient = builder.build();\n\n// 后面跟使用Apache HttpClient一样\nCloseableHttpResponse response = httpClient.execute(...);\n```\n\n### 风险\n\n因为不需要传入微信支付平台证书，CertificatesManager 在首次更新证书时**不会验签**，也就无法确认应答身份，可能导致下载错误的证书。\n\n但下载时会通过 **HTTPS**、**AES 对称加密**来保证证书安全，所以可以认为，在使用官方 JDK、且 APIv3 密钥不泄露的情况下，CertificatesManager 是**安全**的。\n\n## 敏感信息加解密\n\n### 加密\n\n使用` RsaCryptoUtil.encryptOAEP(String, PublicKey publicKey)`进行公钥加密。示例代码如下。\n\n```java\n// 建议从Verifier中获得微信支付平台证书，或使用预先下载到本地的平台证书文件中\nPublicKey publicKey = verifier.getValidPublicKey();\ntry {\n  String ciphertext = RsaCryptoUtil.encryptOAEP(text, publicKey);\n} catch (IllegalBlockSizeException e) {\n  e.printStackTrace();\n}\n```\n\n### 解密\n\n使用`RsaCryptoUtil.decryptOAEP(String ciphertext, PrivateKey privateKey)`进行私钥解密。示例代码如下。\n\n```java\n// 使用商户私钥解密\ntry {\n  String ciphertext = RsaCryptoUtil.decryptOAEP(text, merchantPrivateKey);\n} catch (BadPaddingException e) {\n  e.printStackTrace();\n}\n```\n\n## 图片/视频上传\n\n我们对上传的参数组装和签名逻辑进行了一定的封装，只需要以下几步：\n\n1. 使用`WechatPayUploadHttpPost`构造一个上传的`HttpPost`，需设置待上传文件的文件名，SHA256摘要，文件的输入流。在`0.4.1`及以上版本，支持设置媒体文件元信息。\n2. 通过`WechatPayHttpClientBuilder`得到的`HttpClient`发送请求。\n\n示例请参考下列代码。\n\n```java\nString filePath = \"/your/home/hellokitty.png\";\nURI uri = new URI(\"https://api.mch.weixin.qq.com/v3/merchant/media/upload\");\nFile file = new File(filePath);\n\ntry (FileInputStream ins1 = new FileInputStream(file)) {\n  String sha256 = DigestUtils.sha256Hex(ins1);\n  try (InputStream ins2 = new FileInputStream(file)) {\n    HttpPost request = new WechatPayUploadHttpPost.Builder(uri)\n// 如需直接设置媒体文件元信息，可使用withFile代替withImage\n        .withImage(file.getName(), sha256, ins2)\n        .build();\n    CloseableHttpResponse response1 = httpClient.execute(request);\n  }\n}\n```\n\n[AutoUpdateVerifierTest.uploadImageTest](/src/test/java/com/wechat/pay/contrib/apache/httpclient/AutoUpdateVerifierTest.java#90)是一个更完整的示例。\n\n## 回调通知的验签与解密\n版本\u003e=`0.4.2`可使用 `NotificationHandler.parse(request)` 对回调通知验签和解密：\n\n1. 使用`NotificationRequest`构造一个回调通知请求体，需设置应答平台证书序列号、应答随机串、应答时间戳、应答签名串、应答主体。\n2. 使用`NotificationHandler`构造一个回调通知处理器，需设置验证器、apiV3密钥。调用`parse(request)`得到回调通知`notification`。\n\n示例请参考下列代码。\n\n```java\n// 构建request，传入必要参数\nNotificationRequest request = new NotificationRequest.Builder().withSerialNumber(wechatPaySerial)\n        .withNonce(nonce)\n        .withTimestamp(timestamp)\n        .withSignature(signature)\n        .withBody(body)\n        .build();\n\n// 如果已经初始化了 NotificationHandler 则直接使用，否则根据具体情况创建一个\n\n// 1. 如果你使用的是微信支付公私钥，则使用公钥初始化 Verifier 以创建 NotificationHandler\nNotificationHandler handler = new NotificationHandler(\n        new PublicKeyVerifier(wechatPayPublicKeyId, wechatPayPublicKey),\n        apiV3Key.getBytes(StandardCharsets.UTF_8)\n);\n\n// 2. 如果你使用的事微信支付平台证书，则从 CertificatesManager 获取 Verifier 以创建 NotificationHandler\nNotificationHandler handler = new NotificationHandler(\n        certificatesManager.getVerifier(merchantId),\n        apiV3Key.getBytes(StandardCharsets.UTF_8)\n);\n\n// 3. 如果你正在进行微信支付平台证书到微信支付公私钥的灰度切换，希望保持切换兼容，则需要使用 MixVerifier 创建 NotificationHandler\nVerifier mixVerifier = new MixVerifier(\n        new PublicKeyVerifier(wechatPayPublicKeyId, wechatPayPublicKey),\n        certificatesManager.getVerifier(merchantId)\n);\nNotificationHandler handler = new NotificationHandler(\n        mixVerifier,\n        apiV3Key.getBytes(StandardCharsets.UTF_8)\n);\n\n// 验签和解析请求体\nNotification notification = handler.parse(request);\n// 从notification中获取解密报文\nSystem.out.println(notification.getDecryptData());\n```\n\n[NotificationHandlerTest](src/test/java/com/wechat/pay/contrib/apache/httpclient/NotificationHandlerTest.java#105)是一个更完整的示例。\n\n### 异常处理\n`parse(request)`可能返回以下异常，推荐对异常打日志或上报监控。\n- 抛出`ValidationException`时，请先检查传入参数是否与回调通知参数一致。若一致，说明参数可能被恶意篡改导致验签失败。\n- 抛出`ParseException`时，请先检查传入包体是否与回调通知包体一致。若一致，请检查AES密钥是否正确设置。若正确，说明包体可能被恶意篡改导致解析失败。\n\n## 常见问题\n\n### 如何加载商户私钥\n\n商户申请商户API证书时，会生成商户私钥，并保存在本地证书文件夹的文件`apiclient_key.pem`中。商户开发者可以使用方法`PemUtil.loadPrivateKey()`加载证书。\n\n```java\n// 示例：私钥存储在文件\nPrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(\n        new FileInputStream(\"/path/to/apiclient_key.pem\"));\n\n// 示例：私钥为String字符串\nPrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(\n        new ByteArrayInputStream(privateKey.getBytes(\"utf-8\")));\n```\n\n### 如何下载平台证书？\n\n使用`WechatPayHttpClientBuilder`需要调用`withWechatPay`设置[微信支付平台证书](https://wechatpay-api.gitbook.io/wechatpay-api-v3/ren-zheng/zheng-shu#ping-tai-zheng-shu)，而平台证书又只能通过调用[获取平台证书接口](https://wechatpay-api.gitbook.io/wechatpay-api-v3/jie-kou-wen-dang/ping-tai-zheng-shu#huo-qu-ping-tai-zheng-shu-lie-biao)下载。为了解开\"死循环\"，你可以在第一次下载平台证书时，按照下述方法临时\"跳过”应答签名的验证。\n\n```java\nCloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()\n  .withMerchant(merchantId, merchantSerialNumber, merchantPrivateKey)\n  .withValidator(response -\u003e true) // NOTE: 设置一个空的应答签名验证器，**不要**用在业务请求\n  .build();\n```\n\n**注意**：业务请求请使用标准的初始化流程，务必验证应答签名。\n\n### 如何下载账单\n\n因为下载的账单文件可能会很大，为了平衡系统性能和签名验签的实现成本，[账单下载API](https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/bill/chapter3_3.shtml)被分成了两个步骤：\n\n1. `/v3/bill/tradebill` 获取账单下载链接和账单摘要\n2. `/v3/billdownload/file` 账单文件下载，请求需签名但应答不签名\n\n因为第二步不包含应答签名，我们可以参考上一个问题下载平台证书的方法，使用`withValidator(response -\u003e true)`“跳过”应答的签名校验。\n\n**注意**：开发者在下载文件之后，应使用第一步获取的账单摘要校验文件的完整性。\n\n### 证书和回调解密需要的AesGcm解密在哪里？\n\n请参考[AesUtil.Java](https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient/blob/master/src/main/java/com/wechat/pay/contrib/apache/httpclient/util/AesUtil.java)。\n\n### 我想使用以前的版本，要怎么办\n\n之前的版本可以从 [jitpack](https://jitpack.io/#wechatpay-apiv3/wechatpay-apache-httpclient) 获取。例如希望使用0.1.6版本，gradle中可以使用以下的方式。\n\n```groovy\nrepositories {\n    ...\n    maven { url 'https://jitpack.io' }\n}\n...\ndependencies {\n    implementation 'com.github.wechatpay-apiv3:wechatpay-apache-httpclient:0.1.6'\n    ...\n}\n```\n\n### 如何解决Jackson NoSuchMethodError报错\n\n在之前的版本中，我们出于安全考虑升级 Jackson 到`2.12`，并使用了`2.11`版本中新增的方法`readValue(String src, Class\u003cT\u003e valueType)`。如果你的项目所依赖的其他组件又依赖了低于`2.11`版本的 Jackson ，可能会出现依赖冲突。\n\n我们建议有能力的开发者，升级冲突组件至较新的兼容版本。例如，issue [#125](https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient/issues/125) 版本 \u003c`2.3.x` 的 SpringBoot 官方已不再维护，继续使用可能会有安全隐患。\n\n如果难以升级，你可以用下面的方式引入 [jackson-bom](https://github.com/FasterXML/jackson-bom) 来升级 Jackson 版本。根据[通用漏洞披露信息](https://cve.mitre.org/)，我们推荐升级到`2.13.2.20220328`版本。\n\n#### Gradle\n```groovy\nimplementation(platform(\"com.fasterxml.jackson:jackson-bom:2.13.2.20220328\"))\n```\n#### Maven\n```xml\n\u003cparent\u003e\n    \u003cgroupId\u003ecom.fasterxml.jackson\u003c/groupId\u003e\n    \u003cartifactId\u003ejackson-bom\u003c/artifactId\u003e\n    \u003cversion\u003e2.13.2.20220328\u003c/version\u003e\n\u003c/parent\u003e\n```\n\n如果出现其他组件的 `NoSuchMethodError` 报错，一般是依赖冲突导致。我们可以参考下面的解决思路：\n1. 从报错信息中找到出现问题的组件（如上面的 Jackson ）。根据你的项目的构建方式，选择 [Gradle](https://docs.gradle.org/current/userguide/viewing_debugging_dependencies.html#sec:listing_dependencies) 或 [Maven](https://maven.apache.org/plugins/maven-dependency-plugin/tree-mojo.html) 工具列出项目的依赖关系树，找到问题组件的所有版本号。\n2. 从报错信息中找到正确的组件版本号。一般来说，导致报错的原因是使用的组件版本太低，所以我们可以找组件在依赖关系树中最新的版本号。\n3. 指定组件版本。如果组件提供了 bom 依赖，可以使用上述方式引入 bom 依赖来指定版本。否则，根据你的项目的构建方式，选择 [Gradle](https://docs.gradle.org/current/userguide/dependency_constraints.html#sec:adding-constraints-transitive-deps) 或 [Maven](https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html) 的方式来指定版本。\n\n### 更多常见问题\n\n请看商户平台的[常见问题](https://pay.weixin.qq.com/wiki/doc/apiv3_partner/wechatpay/wechatpay7_0.shtml)，或者[这里](https://wechatpay-api.gitbook.io/wechatpay-api-v3/chang-jian-wen-ti)。\n\n## 联系我们\n\n如果你发现了**BUG**或者有任何疑问、建议，请通过issue进行反馈。\n\n也欢迎访问我们的[开发者社区](https://developers.weixin.qq.com/community/pay)。\n","funding_links":[],"categories":["Java"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwechatpay-apiv3%2Fwechatpay-apache-httpclient","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwechatpay-apiv3%2Fwechatpay-apache-httpclient","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwechatpay-apiv3%2Fwechatpay-apache-httpclient/lists"}