在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称:wechatpay-apiv3/wechatpay-apache-httpclient开源软件地址:https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient开源编程语言:Java 100.0%开源软件介绍:wechatpay-apache-httpclient概览微信支付API v3的Apache HttpClient扩展,实现了请求签名的生成和应答签名的验证。 如果你是使用Apache HttpClient的商户开发者,可以使用它构造 项目状态当前版本 升级指引若你使用的版本为 环境要求
安装最新版本已经在 Maven Central 发布。 Gradle在你的 implementation 'com.github.wechatpay-apiv3:wechatpay-apache-httpclient:0.4.7' Maven加入以下依赖 <dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-apache-httpclient</artifactId>
<version>0.4.7</version>
</dependency> 名词解释
开始如果你使用的是 import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
//...
WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
.withMerchant(merchantId, merchantSerialNumber, merchantPrivateKey)
.withWechatPay(wechatPayCertificates);
// ... 接下来,你仍然可以通过builder设置各种参数,来配置你的HttpClient
// 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签
CloseableHttpClient httpClient = builder.build();
// 后面跟使用Apache HttpClient一样
CloseableHttpResponse response = httpClient.execute(...); 参数说明:
示例:获取平台证书你可以使用 URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/certificates");
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.addHeader("Accept", "application/json");
CloseableHttpResponse response = httpClient.execute(httpGet);
String bodyAsString = EntityUtils.toString(response.getEntity());
System.out.println(bodyAsString); 示例:JSAPI下单注:
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");
httpPost.addHeader("Accept", "application/json");
httpPost.addHeader("Content-type","application/json; charset=utf-8");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode rootNode = objectMapper.createObjectNode();
rootNode.put("mchid","1900009191")
.put("appid", "wxd678efh567hg6787")
.put("description", "Image形象店-深圳腾大-QQ公仔")
.put("notify_url", "https://www.weixin.qq.com/wxpay/pay.php")
.put("out_trade_no", "1217752501201407033233368018");
rootNode.putObject("amount")
.put("total", 1);
rootNode.putObject("payer")
.put("openid", "oUpF8uMuAJO_M2pxb1Q9zNjWeS6o");
objectMapper.writeValue(bos, rootNode);
httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
CloseableHttpResponse response = httpClient.execute(httpPost);
String bodyAsString = EntityUtils.toString(response.getEntity());
System.out.println(bodyAsString); 示例:查单URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/pay/transactions/id/4200000889202103303311396384?mchid=1230000109");
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.addHeader("Accept", "application/json");
CloseableHttpResponse response = httpClient.execute(httpGet);
String bodyAsString = EntityUtils.toString(response.getEntity());
System.out.println(bodyAsString); 示例:关单HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/1217752501201407033233368018/close");
httpPost.addHeader("Accept", "application/json");
httpPost.addHeader("Content-type","application/json; charset=utf-8");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode rootNode = objectMapper.createObjectNode();
rootNode.put("mchid","1900009191");
objectMapper.writeValue(bos, rootNode);
httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
CloseableHttpResponse response = httpClient.execute(httpPost);
String bodyAsString = EntityUtils.toString(response.getEntity());
System.out.println(bodyAsString); 定制当默认的本地签名和验签方式不适合你的系统时,你可以通过实现 import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.Credentials;
// ...
Credentials credentials = new WechatPay2Credentials(merchantId, new Signer() {
@Override
public Signer.SignatureResult sign(byte[] message) {
// ... call your sign-RPC, then return sign & serial number
}
});
WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
.withCredentials(credentials)
.withWechatPay(wechatPayCertificates); 定时更新平台证书功能版本>= 示例代码: // 获取证书管理器实例
certificatesManager = CertificatesManager.getInstance();
// 向证书管理器增加需要自动更新平台证书的商户信息
certificatesManager.putMerchant(merchantId, new WechatPay2Credentials(merchantId,
new PrivateKeySigner(merchantSerialNumber, merchantPrivateKey)), apiV3Key.getBytes(StandardCharsets.UTF_8));
// ... 若有多个商户号,可继续调用putMerchant添加商户信息
// 从证书管理器中获取verifier
verifier = certificatesManager.getVerifier(merchantId);
WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
.withMerchant(merchantId, merchantSerialNumber, merchantPrivateKey)
.withValidator(new WechatPay2Validator(verifier))
// ... 接下来,你仍然可以通过builder设置各种参数,来配置你的HttpClient
// 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
CloseableHttpClient httpClient = builder.build();
// 后面跟使用Apache HttpClient一样
CloseableHttpResponse response = httpClient.execute(...); 风险因为不需要传入微信支付平台证书,CertificatesManager 在首次更新证书时不会验签,也就无法确认应答身份,可能导致下载错误的证书。 但下载时会通过 HTTPS、AES 对称加密来保证证书安全,所以可以认为,在使用官方 JDK、且 APIv3 密钥不泄露的情况下,CertificatesManager 是安全的。 敏感信息加解密加密使用 // 建议从Verifier中获得微信支付平台证书,或使用预先下载到本地的平台证书文件中
X509Certificate certificate = verifier.getValidCertificate();
try {
String ciphertext = RsaCryptoUtil.encryptOAEP(text, certificate);
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} 解密使用 // 使用商户私钥解密
try {
String ciphertext = RsaCryptoUtil.decryptOAEP(text, merchantPrivateKey);
} catch (BadPaddingException e) {
e.printStackTrace();
} 图片/视频上传我们对上传的参数组装和签名逻辑进行了一定的封装,只需要以下几步:
示例请参考下列代码。 String filePath = "/your/home/hellokitty.png";
URI uri = new URI("https://api.mch.weixin.qq.com/v3/merchant/media/upload");
File file = new File(filePath);
try (FileInputStream ins1 = new FileInputStream(file)) {
String sha256 = DigestUtils.sha256Hex(ins1);
try (InputStream ins2 = new FileInputStream(file)) {
HttpPost request = new WechatPayUploadHttpPost.Builder(uri)
// 如需直接设置媒体文件元信息,可使用withFile代替withImage
.withImage(file.getName(), sha256, ins2)
.build();
CloseableHttpResponse response1 = httpClient.execute(request);
}
} AutoUpdateVerifierTest.uploadImageTest是一个更完整的示例。 回调通知的验签与解密版本>=
示例请参考下列代码。 // 构建request,传入必要参数
NotificationRequest request = new NotificationRequest.Builder().withSerialNumber(wechatPaySerial)
.withNonce(nonce)
.withTimestamp(timestamp)
.withSignature(signature)
.withBody(body)
.build();
NotificationHandler handler = new NotificationHandler(verifier, apiV3Key.getBytes(StandardCharsets.UTF_8));
// 验签和解析请求体
Notification notification = handler.parse(request);
// 从notification中获取解密报文
System.out.println(notification.getDecryptData()); NotificationHandlerTest是一个更完整的示例。 异常处理
常见问题如何加载商户私钥商户申请商户API证书时,会生成商户私钥,并保存在本地证书文件夹的文件 # 示例:私钥存储在文件
PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(
new FileInputStream("/path/to/apiclient_key.pem"));
# 示例:私钥为String字符串
PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(
new ByteArrayInputStream(privateKey.getBytes("utf-8"))); 如何下载平台证书?使用 CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
.withMerchant(merchantId, merchantSerialNumber, merchantPrivateKey)
.withValidator(response -> true) // NOTE: 设置一个空的应答签名验证器,**不要**用在业务请求
.build(); 注意:业务请求请使用标准的初始化流程,务必验证应答签名。 如何下载账单因为下载的账单文件可能会很大,为了平衡系统性能和签名验签的实现成本,账单下载API被分成了两个步骤:
因为第二步不包含应答签名,我们可以参考上一个问题下载平台证书的方法,使用 注意:开发者在下载文件之后,应使用第一步获取的账单摘要校验文件的完整性。 证书和回调解密需要的AesGcm解密在哪里?请参考AesUtil.Java。 我想使用以前的版本,要怎么办之前的版本可以从 jitpack 获取。例如希望使用0.1.6版本,gradle中可以使用以下的方式。 repositories {
...
maven { url 'https://jitpack.io' }
}
...
dependencies {
implementation 'com.github.wechatpay-apiv3:wechatpay-apache-httpclient:0.1.6'
...
} 如何解决Jackson NoSuchMethodError报错在之前的版本中,我们出于安全考虑升级 Jackson 到 我们建议有能力的开发者,升级冲突组件至较新的兼容版本。例如,issue #125 版本 < 如果难以升级,你可以用下面的方式引入 jackson-bom 来升级 Jackson 版本。根据通用漏洞披露信息,我们推荐升级到 Gradleimplementation(platform("com.fasterxml.jackson:jackson-bom:2.13.2.20220328")) Maven<parent>
<groupId>com.fasterxml.jackson</groupId>
<artifactId>jackson-bom</artifactId>
<version>2.13.2.20220328</version>
</parent> 如果出现其他组件的
|
请发表评论