瀏覽代碼

🎨 修复重构后的代码

dev1
Binary Wang 5 年之前
父節點
當前提交
40ab5dd402
共有 3 個文件被更改,包括 89 次插入79 次删除
  1. +5
    -0
      weixin-java-pay/pom.xml
  2. +22
    -29
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceApacheHttpImpl.java
  3. +62
    -50
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/auth/AutoUpdateCertificatesVerifier.java

+ 5
- 0
weixin-java-pay/pom.xml 查看文件

@@ -82,6 +82,11 @@
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.7</version>
</dependency>
<dependency> <dependency>
<groupId>com.google.code.gson</groupId> <groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId> <artifactId>gson</artifactId>


+ 22
- 29
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceApacheHttpImpl.java 查看文件

@@ -1,12 +1,9 @@
package com.github.binarywang.wxpay.service.impl; package com.github.binarywang.wxpay.service.impl;


import java.net.URI;
import java.nio.charset.StandardCharsets;
import javax.net.ssl.SSLContext;

import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.bean.WxPayApiData; import com.github.binarywang.wxpay.bean.WxPayApiData;
import com.github.binarywang.wxpay.exception.WxPayException; import com.github.binarywang.wxpay.exception.WxPayException;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import jodd.util.Base64; import jodd.util.Base64;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHost; import org.apache.http.HttpHost;
@@ -28,6 +25,10 @@ import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils; import org.apache.http.util.EntityUtils;


import javax.net.ssl.SSLContext;
import java.net.URI;
import java.nio.charset.StandardCharsets;

/** /**
* <pre> * <pre>
* 微信支付请求实现类,apache httpclient实现. * 微信支付请求实现类,apache httpclient实现.
@@ -37,6 +38,8 @@ import org.apache.http.util.EntityUtils;
* @author <a href="https://github.com/binarywang">Binary Wang</a> * @author <a href="https://github.com/binarywang">Binary Wang</a>
*/ */
public class WxPayServiceApacheHttpImpl extends BaseWxPayServiceImpl { public class WxPayServiceApacheHttpImpl extends BaseWxPayServiceImpl {
private final static JsonParser JSON_PARSER = new JsonParser();

@Override @Override
public byte[] postForBytes(String url, String requestStr, boolean useKey) throws WxPayException { public byte[] postForBytes(String url, String requestStr, boolean useKey) throws WxPayException {
try { try {
@@ -92,18 +95,17 @@ public class WxPayServiceApacheHttpImpl extends BaseWxPayServiceImpl {
HttpPost httpPost = this.createHttpPost(url, requestStr); HttpPost httpPost = this.createHttpPost(url, requestStr);
httpPost.addHeader("Accept", "application/json"); httpPost.addHeader("Accept", "application/json");
httpPost.addHeader("Content-Type", "application/json"); httpPost.addHeader("Content-Type", "application/json");
try (CloseableHttpResponse response = httpClient.execute(httpPost)){
try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
//v3已经改为通过状态码判断200 204 成功 //v3已经改为通过状态码判断200 204 成功
int statusCode = response.getStatusLine().getStatusCode(); int statusCode = response.getStatusLine().getStatusCode();
String responseString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); String responseString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
if (HttpStatus.SC_OK==statusCode || HttpStatus.SC_NO_CONTENT==statusCode){
if (HttpStatus.SC_OK == statusCode || HttpStatus.SC_NO_CONTENT == statusCode) {
this.log.info("\n【请求地址】:{}\n【请求数据】:{}\n【响应数据】:{}", url, requestStr, responseString); this.log.info("\n【请求地址】:{}\n【请求数据】:{}\n【响应数据】:{}", url, requestStr, responseString);
return responseString; return responseString;
}else {
} else {
//有错误提示信息返回 //有错误提示信息返回
JSONObject jsonObject = JSONObject.parseObject(responseString);
String message = jsonObject.getString("message");
throw new WxPayException(message);
JsonObject jsonObject = JSON_PARSER.parse(responseString).getAsJsonObject();
throw new WxPayException(jsonObject.get("message").getAsString());
} }
} catch (Exception e) { } catch (Exception e) {
this.log.error("\n【请求地址】:{}\n【请求数据】:{}\n【异常信息】:{}", url, requestStr, e.getMessage()); this.log.error("\n【请求地址】:{}\n【请求数据】:{}\n【异常信息】:{}", url, requestStr, e.getMessage());
@@ -113,8 +115,6 @@ public class WxPayServiceApacheHttpImpl extends BaseWxPayServiceImpl {
} }






} }


@Override @Override
@@ -123,18 +123,17 @@ public class WxPayServiceApacheHttpImpl extends BaseWxPayServiceImpl {
HttpGet httpGet = new HttpGet(url); HttpGet httpGet = new HttpGet(url);
httpGet.addHeader("Accept", "application/json"); httpGet.addHeader("Accept", "application/json");
httpGet.addHeader("Content-Type", "application/json"); httpGet.addHeader("Content-Type", "application/json");
try (CloseableHttpResponse response = httpClient.execute(httpGet)){
try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
//v3已经改为通过状态码判断200 204 成功 //v3已经改为通过状态码判断200 204 成功
int statusCode = response.getStatusLine().getStatusCode(); int statusCode = response.getStatusLine().getStatusCode();
String responseString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); String responseString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
if (HttpStatus.SC_OK==statusCode || HttpStatus.SC_NO_CONTENT==statusCode){
this.log.info("\n【请求地址】:{}\n【响应数据】:{}", url , responseString);
if (HttpStatus.SC_OK == statusCode || HttpStatus.SC_NO_CONTENT == statusCode) {
this.log.info("\n【请求地址】:{}\n【响应数据】:{}", url, responseString);
return responseString; return responseString;
}else {
} else {
//有错误提示信息返回 //有错误提示信息返回
JSONObject jsonObject = JSONObject.parseObject(responseString);
String message = jsonObject.getString("message");
throw new WxPayException(message);
JsonObject jsonObject = JSON_PARSER.parse(responseString).getAsJsonObject();
throw new WxPayException(jsonObject.get("message").getAsString());
} }
} catch (Exception e) { } catch (Exception e) {
this.log.error("\n【请求地址】:{}\n【异常信息】:{}", url, e.getMessage()); this.log.error("\n【请求地址】:{}\n【异常信息】:{}", url, e.getMessage());
@@ -142,25 +141,19 @@ public class WxPayServiceApacheHttpImpl extends BaseWxPayServiceImpl {
} finally { } finally {
httpGet.releaseConnection(); httpGet.releaseConnection();
} }


} }


private CloseableHttpClient createApiV3HttpClient() throws WxPayException { private CloseableHttpClient createApiV3HttpClient() throws WxPayException {
CloseableHttpClient apiv3HttpClient = this.getConfig().getApiV3HttpClient(); CloseableHttpClient apiv3HttpClient = this.getConfig().getApiV3HttpClient();
if (null==apiv3HttpClient){
if (null == apiv3HttpClient) {
return this.getConfig().initApiV3HttpClient(); return this.getConfig().initApiV3HttpClient();
} }
return apiv3HttpClient; return apiv3HttpClient;
} }



private StringEntity createEntry(String requestStr) { private StringEntity createEntry(String requestStr) {

return new StringEntity(requestStr, ContentType.create("application/json", "utf-8"));
//return new StringEntity(new String(requestStr.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));


return new StringEntity(requestStr, ContentType.create("application/json", "utf-8"));
//return new StringEntity(new String(requestStr.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));
} }


private HttpClientBuilder createHttpClientBuilder(boolean useKey) throws WxPayException { private HttpClientBuilder createHttpClientBuilder(boolean useKey) throws WxPayException {


+ 62
- 50
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/auth/AutoUpdateCertificatesVerifier.java 查看文件

@@ -1,8 +1,22 @@
package com.github.binarywang.wxpay.v3.auth; package com.github.binarywang.wxpay.v3.auth;


import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.binarywang.wxpay.v3.Credentials;
import com.github.binarywang.wxpay.v3.WechatPayHttpClientBuilder;
import com.github.binarywang.wxpay.v3.util.AesUtils;
import com.github.binarywang.wxpay.v3.util.PemUtils;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;


import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException; import java.security.cert.CertificateNotYetValidException;
@@ -13,57 +27,56 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;


import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.binarywang.wxpay.v3.Credentials;
import com.github.binarywang.wxpay.v3.WechatPayHttpClientBuilder;
import com.github.binarywang.wxpay.v3.util.AesUtils;
import com.github.binarywang.wxpay.v3.util.PemUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** /**
* 在原有CertificatesVerifier基础上,增加自动更新证书功能 * 在原有CertificatesVerifier基础上,增加自动更新证书功能
*
* @author doger.wang
*/ */
@Slf4j
public class AutoUpdateCertificatesVerifier implements Verifier { public class AutoUpdateCertificatesVerifier implements Verifier {
/**
* 证书下载地址
*/
private static final String CERT_DOWNLOAD_PATH = "https://api.mch.weixin.qq.com/v3/certificates";


private static final Logger log = LoggerFactory.getLogger(AutoUpdateCertificatesVerifier.class);

//证书下载地址
private static final String CertDownloadPath = "https://api.mch.weixin.qq.com/v3/certificates";

//上次更新时间
/**
* 上次更新时间
*/
private volatile Instant instant; private volatile Instant instant;


//证书更新间隔时间,单位为分钟
private int minutesInterval;
/**
* 证书更新间隔时间,单位为分钟
*/
private final int minutesInterval;


private CertificatesVerifier verifier; private CertificatesVerifier verifier;


private Credentials credentials;
private final Credentials credentials;


private byte[] apiV3Key;
private final byte[] apiV3Key;


private ReentrantLock lock = new ReentrantLock();
private final ReentrantLock lock = new ReentrantLock();


//时间间隔枚举,支持一小时、六小时以及十二小时
/**
* 时间间隔枚举,支持一小时、六小时以及十二小时
*/
@Getter
@RequiredArgsConstructor
public enum TimeInterval { public enum TimeInterval {
OneHour(60), SixHours(60 * 6), TwelveHours(60 * 12);

private int minutes;

TimeInterval(int minutes) {
this.minutes = minutes;
}

public int getMinutes() {
return minutes;
}
/**
* 一小时
*/
OneHour(60),
/**
* 六小时
*/
SixHours(60 * 6),
/**
* 十二小时
*/
TwelveHours(60 * 12);

private final int minutes;
} }


public AutoUpdateCertificatesVerifier(Credentials credentials, byte[] apiV3Key) { public AutoUpdateCertificatesVerifier(Credentials credentials, byte[] apiV3Key) {
@@ -103,11 +116,11 @@ public class AutoUpdateCertificatesVerifier implements Verifier {


private void autoUpdateCert() throws IOException, GeneralSecurityException { private void autoUpdateCert() throws IOException, GeneralSecurityException {
CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create() CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
.withCredentials(credentials)
.withValidator(verifier == null ? (response) -> true : new WechatPay2Validator(verifier))
.build();
.withCredentials(credentials)
.withValidator(verifier == null ? (response) -> true : new WechatPay2Validator(verifier))
.build();


HttpGet httpGet = new HttpGet(CertDownloadPath);
HttpGet httpGet = new HttpGet(CERT_DOWNLOAD_PATH);
httpGet.addHeader("Accept", "application/json"); httpGet.addHeader("Accept", "application/json");


CloseableHttpResponse response = httpClient.execute(httpGet); CloseableHttpResponse response = httpClient.execute(httpGet);
@@ -125,12 +138,10 @@ public class AutoUpdateCertificatesVerifier implements Verifier {
} }
} }



/** /**
* 反序列化证书并解密 * 反序列化证书并解密
*/ */
private List<X509Certificate> deserializeToCerts(byte[] apiV3Key, String body)
throws GeneralSecurityException, IOException {
private List<X509Certificate> deserializeToCerts(byte[] apiV3Key, String body) throws GeneralSecurityException, IOException {
AesUtils decryptor = new AesUtils(apiV3Key); AesUtils decryptor = new AesUtils(apiV3Key);
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
JsonNode dataNode = mapper.readTree(body).get("data"); JsonNode dataNode = mapper.readTree(body).get("data");
@@ -140,14 +151,14 @@ public class AutoUpdateCertificatesVerifier implements Verifier {
JsonNode encryptCertificateNode = dataNode.get(i).get("encrypt_certificate"); JsonNode encryptCertificateNode = dataNode.get(i).get("encrypt_certificate");
//解密 //解密
String cert = decryptor.decryptToString( String cert = decryptor.decryptToString(
encryptCertificateNode.get("associated_data").toString().replaceAll("\"", "")
.getBytes("utf-8"),
encryptCertificateNode.get("nonce").toString().replaceAll("\"", "")
.getBytes("utf-8"),
encryptCertificateNode.get("ciphertext").toString().replaceAll("\"", ""));
encryptCertificateNode.get("associated_data").toString().replaceAll("\"", "")
.getBytes(StandardCharsets.UTF_8),
encryptCertificateNode.get("nonce").toString().replaceAll("\"", "")
.getBytes(StandardCharsets.UTF_8),
encryptCertificateNode.get("ciphertext").toString().replaceAll("\"", ""));


X509Certificate x509Cert = PemUtils X509Certificate x509Cert = PemUtils
.loadCertificate(new ByteArrayInputStream(cert.getBytes("utf-8")));
.loadCertificate(new ByteArrayInputStream(cert.getBytes(StandardCharsets.UTF_8)));
try { try {
x509Cert.checkValidity(); x509Cert.checkValidity();
} catch (CertificateExpiredException | CertificateNotYetValidException e) { } catch (CertificateExpiredException | CertificateNotYetValidException e) {
@@ -156,6 +167,7 @@ public class AutoUpdateCertificatesVerifier implements Verifier {
newCertList.add(x509Cert); newCertList.add(x509Cert);
} }
} }

return newCertList; return newCertList;
} }
} }

Loading…
取消
儲存