diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java index d93c30804..b9b11fd73 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java @@ -118,7 +118,20 @@ public interface WxMpConfigStorage { File getTmpDirFile(); + @Deprecated SSLContext getSSLContext(); + + SSLContext getSslContext(); + + void setSslContext(SSLContext sslContext); + + /** + * 在此之前,必须将partnerId进行赋值 + * + * @param filePath + * apiclient_cert.p12的文件的绝对路径 + */ + void setSslContextFilePath(String filePath) throws Exception; /** * http client builder diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java index 61b75fbba..9fec33f84 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java @@ -1,14 +1,19 @@ package me.chanjar.weixin.mp.api; +import java.io.File; +import java.io.FileInputStream; +import java.security.KeyStore; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import javax.net.ssl.SSLContext; + +import org.apache.http.ssl.SSLContexts; + import me.chanjar.weixin.common.bean.WxAccessToken; import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder; -import javax.net.ssl.SSLContext; -import java.io.File; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - /** * 基于内存的微信配置provider,在实际生产环境中应该将这些配置持久化 * @author chanjarster @@ -300,11 +305,33 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage { public SSLContext getSSLContext() { return this.sslContext; } - - public void setSSLContext(SSLContext context) { - this.sslContext = context; + + @Override + public SSLContext getSslContext() { + return this.sslContext; } + @Override + public void setSslContextFilePath(String filePath) throws Exception { + if (null == partnerId) { + throw new Exception("请先将partnerId进行赋值"); + } + File file = new File(filePath); + if (!file.exists()) { + throw new RuntimeException(file.getPath() + ":文件不存在!在设置SSLContext的时候"); + } + FileInputStream inputStream = new FileInputStream(file); + KeyStore keystore = KeyStore.getInstance("PKCS12"); + char[] partnerId2charArray = partnerId.toCharArray(); + keystore.load(inputStream, partnerId2charArray); + this.sslContext = SSLContexts.custom().loadKeyMaterial(keystore, partnerId2charArray).build(); + } + + @Override + public void setSslContext(SSLContext context) { + this.sslContext = context; + } + @Override public ApacheHttpClientBuilder getApacheHttpClientBuilder() { return this.apacheHttpClientBuilder; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java index afe888f83..b4dd3b294 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java @@ -197,8 +197,24 @@ public interface WxMpPayService { * @param request 请求对象 * @param keyFile 证书文件对象(即apiclient_cert.p12 商户证书文件,详细参考https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3) */ + @Deprecated WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request, File keyFile) throws WxErrorException; + /** + * 发送微信红包给个人用户 + *
+ * 文档详见: + * 发送普通红包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_4&index=3 + * 接口地址:https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack + * 发送裂变红包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_5&index=4 + * 接口地址:https://api.mch.weixin.qq.com/mmpaymkttransfers/sendgroupredpack + *+ * + * @param request 请求对象 + * @param keyFile 证书文件对象(即apiclient_cert.p12 商户证书文件,详细参考https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3) + */ + WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request) throws WxErrorException; + /** *
* 查询红包记录
@@ -211,7 +227,22 @@ public interface WxMpPayService {
* @param mchBillNo 商户发放红包的商户订单号,比如10000098201411111234567890
* @param keyFile 证书文件对象(即apiclient_cert.p12 商户证书文件,详细参考https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3)
*/
+ @Deprecated
WxPayRedpackQueryResult queryRedpack(String mchBillNo, File keyFile) throws WxErrorException;
+
+ /**
+ *
+ * 查询红包记录
+ * 用于商户对已发放的红包进行查询红包的具体信息,可支持普通红包和裂变包。
+ * 请求Url https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo
+ * 是否需要证书 是(证书及使用说明详见商户证书)
+ * 请求方式 POST
+ *
+ *
+ * @param mchBillNo 商户发放红包的商户订单号,比如10000098201411111234567890
+ * @param keyFile 证书文件对象(即apiclient_cert.p12 商户证书文件,详细参考https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3)
+ */
+ WxPayRedpackQueryResult queryRedpack(String mchBillNo) throws WxErrorException;
/**
*
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java
index 9bd4dad25..8751fc6c8 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java
@@ -160,6 +160,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
@Override
+ @Deprecated
public WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request, File keyFile)
throws WxErrorException {
XStream xstream = XStreamInitializer.getInstance();
@@ -179,8 +180,30 @@ public class WxMpPayServiceImpl implements WxMpPayService {
this.checkResult(result);
return result;
}
+
+ @Override
+ public WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request)
+ throws WxErrorException {
+ XStream xstream = XStreamInitializer.getInstance();
+ xstream.processAnnotations(WxPaySendRedpackRequest.class);
+ xstream.processAnnotations(WxPaySendRedpackResult.class);
+
+ initRequest(request);
+ request.setSign(this.createSign(request));
+
+ String url = PAY_BASE_URL + "/mmpaymkttransfers/sendredpack";
+ if (request.getAmtType() != null) {
+ //裂变红包
+ url = PAY_BASE_URL + "/mmpaymkttransfers/sendgroupredpack";
+ }
+ String responseContent = this.executeRequestWithKeyFile(url, xstream.toXML(request));
+ WxPaySendRedpackResult result = (WxPaySendRedpackResult) xstream.fromXML(responseContent);
+ this.checkResult(result);
+ return result;
+ }
@Override
+ @Deprecated
public WxPayRedpackQueryResult queryRedpack(String mchBillNo, File keyFile) throws WxErrorException {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxPayRedpackQueryRequest.class);
@@ -198,6 +221,25 @@ public class WxMpPayServiceImpl implements WxMpPayService {
this.checkResult(result);
return result;
}
+
+ @Override
+ public WxPayRedpackQueryResult queryRedpack(String mchBillNo) throws WxErrorException {
+ XStream xstream = XStreamInitializer.getInstance();
+ xstream.processAnnotations(WxPayRedpackQueryRequest.class);
+ xstream.processAnnotations(WxPayRedpackQueryResult.class);
+
+ WxPayRedpackQueryRequest request = new WxPayRedpackQueryRequest();
+ request.setMchBillNo(mchBillNo);
+ request.setBillType("MCHT");
+ initRequest(request);
+ request.setSign(this.createSign(request));
+
+ String url = PAY_BASE_URL + "/mmpaymkttransfers/gethbinfo";
+ String responseContent = this.executeRequestWithKeyFile(url, xstream.toXML(request));
+ WxPayRedpackQueryResult result = (WxPayRedpackQueryResult) xstream.fromXML(responseContent);
+ this.checkResult(result);
+ return result;
+ }
@Override
public WxPayOrderQueryResult queryOrder(String transactionId, String outTradeNo) throws WxErrorException {
@@ -383,7 +425,8 @@ public class WxMpPayServiceImpl implements WxMpPayService {
httpPost.releaseConnection();
}
}
-
+
+ @Deprecated
private String executeRequestWithKeyFile(String url, File keyFile, String requestStr, String mchId) throws WxErrorException {
try (FileInputStream inputStream = new FileInputStream(keyFile)) {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
@@ -414,6 +457,37 @@ public class WxMpPayServiceImpl implements WxMpPayService {
}
}
+ private String executeRequestWithKeyFile(String url, String requestStr) throws WxErrorException {
+ try {
+
+ SSLContext sslcontext = getConfig().getSSLContext();
+ if(null==sslcontext){
+ throw new Exception("请将配置类(WxMpInMemoryConfigStorage)中的SSLContext初始化");
+ }
+ SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null,
+ new DefaultHostnameVerifier());
+
+ HttpPost httpPost = new HttpPost(url);
+ if (this.wxMpService.getHttpProxy() != null) {
+ httpPost.setConfig(RequestConfig.custom().setProxy(this.wxMpService.getHttpProxy()).build());
+ }
+
+ try (CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build()) {
+ httpPost.setEntity(new StringEntity(new String(requestStr.getBytes("UTF-8"), "ISO-8859-1")));
+ try (CloseableHttpResponse response = httpclient.execute(httpPost)) {
+ String result = EntityUtils.toString(response.getEntity(), Consts.UTF_8);
+ this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", url, requestStr, result);
+ return result;
+ }
+ } finally {
+ httpPost.releaseConnection();
+ }
+ } catch (Exception e) {
+ this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[EXCEPTION]: {}", url, requestStr, e.getMessage());
+ throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg(e.getMessage()).build(), e);
+ }
+ }
+
@Override
public String createSign(Object xmlBean) {
return createSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getPartnerKey());
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java
index ccb0bd2ec..0008e20dd 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java
@@ -20,8 +20,8 @@ import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
-import org.apache.http.conn.ssl.DefaultHostnameVerifier;
-import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+//import org.apache.http.conn.ssl.DefaultHostnameVerifier;
+//import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.CloseableHttpClient;
import org.slf4j.Logger;
@@ -33,7 +33,7 @@ import java.util.concurrent.locks.Lock;
public class WxMpServiceImpl implements WxMpService {
private static final JsonParser JSON_PARSER = new JsonParser();
-
+
protected final Logger log = LoggerFactory.getLogger(this.getClass());
private WxMpConfigStorage configStorage;
@@ -459,12 +459,12 @@ public class WxMpServiceImpl implements WxMpService {
.httpProxyUsername(this.configStorage.getHttpProxyUsername())
.httpProxyPassword(this.configStorage.getHttpProxyPassword());
- if (this.configStorage.getSSLContext() != null) {
- SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
- this.configStorage.getSSLContext(), new String[] { "TLSv1" }, null,
- new DefaultHostnameVerifier());
- apacheHttpClientBuilder.sslConnectionSocketFactory(sslsf);
- }
+ // if (this.configStorage.getSSLContext() != null) {
+ // SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
+ // this.configStorage.getSSLContext(), new String[] { "TLSv1" }, null,
+ // new DefaultHostnameVerifier());
+ // apacheHttpClientBuilder.sslConnectionSocketFactory(sslsf);
+ // }
if (this.configStorage.getHttpProxyHost() != null && this.configStorage.getHttpProxyPort() > 0) {
this.httpProxy = new HttpHost(this.configStorage.getHttpProxyHost(), this.configStorage.getHttpProxyPort());