mirror of
https://gitee.com/binary/weixin-java-tools.git
synced 2025-04-23 23:58:44 +08:00
commit
27ce2a2746
@ -2,6 +2,8 @@ package me.chanjar.weixin.mp.api;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
|
||||||
import me.chanjar.weixin.common.bean.WxAccessToken;
|
import me.chanjar.weixin.common.bean.WxAccessToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -74,4 +76,5 @@ public interface WxMpConfigStorage {
|
|||||||
|
|
||||||
public File getTmpDirFile();
|
public File getTmpDirFile();
|
||||||
|
|
||||||
|
public SSLContext getSSLContext();
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ package me.chanjar.weixin.mp.api;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
|
||||||
import me.chanjar.weixin.common.bean.WxAccessToken;
|
import me.chanjar.weixin.common.bean.WxAccessToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -35,6 +37,8 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
|
|||||||
*/
|
*/
|
||||||
protected volatile File tmpDirFile;
|
protected volatile File tmpDirFile;
|
||||||
|
|
||||||
|
protected volatile SSLContext sslContext;
|
||||||
|
|
||||||
public String getAccessToken() {
|
public String getAccessToken() {
|
||||||
return this.accessToken;
|
return this.accessToken;
|
||||||
}
|
}
|
||||||
@ -219,4 +223,13 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
|
|||||||
this.tmpDirFile = tmpDirFile;
|
this.tmpDirFile = tmpDirFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SSLContext getSSLContext() {
|
||||||
|
return sslContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSSLContext(SSLContext context) {
|
||||||
|
sslContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -748,4 +748,12 @@ public interface WxMpService {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public boolean checkJSSDKCallbackDataSignature(Map<String, String> kvm, String signature);
|
public boolean checkJSSDKCallbackDataSignature(Map<String, String> kvm, String signature);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送微信红包给个人用户
|
||||||
|
* @param parameters
|
||||||
|
* @return
|
||||||
|
* @throws WxErrorException
|
||||||
|
*/
|
||||||
|
public WxRedpackResult sendRedpack(Map<String, String> parameters) throws WxErrorException;
|
||||||
}
|
}
|
||||||
|
@ -66,6 +66,7 @@ import me.chanjar.weixin.mp.bean.result.WxMpUser;
|
|||||||
import me.chanjar.weixin.mp.bean.result.WxMpUserCumulate;
|
import me.chanjar.weixin.mp.bean.result.WxMpUserCumulate;
|
||||||
import me.chanjar.weixin.mp.bean.result.WxMpUserList;
|
import me.chanjar.weixin.mp.bean.result.WxMpUserList;
|
||||||
import me.chanjar.weixin.mp.bean.result.WxMpUserSummary;
|
import me.chanjar.weixin.mp.bean.result.WxMpUserSummary;
|
||||||
|
import me.chanjar.weixin.mp.bean.result.WxRedpackResult;
|
||||||
import me.chanjar.weixin.mp.util.http.MaterialDeleteRequestExecutor;
|
import me.chanjar.weixin.mp.util.http.MaterialDeleteRequestExecutor;
|
||||||
import me.chanjar.weixin.mp.util.http.MaterialNewsInfoRequestExecutor;
|
import me.chanjar.weixin.mp.util.http.MaterialNewsInfoRequestExecutor;
|
||||||
import me.chanjar.weixin.mp.util.http.MaterialUploadRequestExecutor;
|
import me.chanjar.weixin.mp.util.http.MaterialUploadRequestExecutor;
|
||||||
@ -84,13 +85,16 @@ import org.apache.http.client.config.RequestConfig;
|
|||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.client.methods.HttpPost;
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||||
import org.apache.http.entity.StringEntity;
|
import org.apache.http.entity.StringEntity;
|
||||||
import org.apache.http.impl.client.BasicCredentialsProvider;
|
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||||
import org.apache.http.impl.client.BasicResponseHandler;
|
import org.apache.http.impl.client.BasicResponseHandler;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
import org.apache.http.impl.client.HttpClients;
|
import org.apache.http.impl.client.HttpClients;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.slf4j.helpers.MessageFormatter;
|
||||||
|
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
@ -743,6 +747,7 @@ public class WxMpServiceImpl implements WxMpService {
|
|||||||
String http_proxy_username = wxMpConfigStorage.getHttp_proxy_username();
|
String http_proxy_username = wxMpConfigStorage.getHttp_proxy_username();
|
||||||
String http_proxy_password = wxMpConfigStorage.getHttp_proxy_password();
|
String http_proxy_password = wxMpConfigStorage.getHttp_proxy_password();
|
||||||
|
|
||||||
|
final HttpClientBuilder builder = HttpClients.custom();
|
||||||
if (StringUtils.isNotBlank(http_proxy_host)) {
|
if (StringUtils.isNotBlank(http_proxy_host)) {
|
||||||
// 使用代理服务器
|
// 使用代理服务器
|
||||||
if (StringUtils.isNotBlank(http_proxy_username)) {
|
if (StringUtils.isNotBlank(http_proxy_username)) {
|
||||||
@ -751,18 +756,22 @@ public class WxMpServiceImpl implements WxMpService {
|
|||||||
credsProvider.setCredentials(
|
credsProvider.setCredentials(
|
||||||
new AuthScope(http_proxy_host, http_proxy_port),
|
new AuthScope(http_proxy_host, http_proxy_port),
|
||||||
new UsernamePasswordCredentials(http_proxy_username, http_proxy_password));
|
new UsernamePasswordCredentials(http_proxy_username, http_proxy_password));
|
||||||
httpClient = HttpClients
|
builder
|
||||||
.custom()
|
.setDefaultCredentialsProvider(credsProvider);
|
||||||
.setDefaultCredentialsProvider(credsProvider)
|
|
||||||
.build();
|
|
||||||
} else {
|
} else {
|
||||||
// 无需用户认证的代理服务器
|
// 无需用户认证的代理服务器
|
||||||
httpClient = HttpClients.createDefault();
|
|
||||||
}
|
}
|
||||||
httpProxy = new HttpHost(http_proxy_host, http_proxy_port);
|
httpProxy = new HttpHost(http_proxy_host, http_proxy_port);
|
||||||
} else {
|
|
||||||
httpClient = HttpClients.createDefault();
|
|
||||||
}
|
}
|
||||||
|
if (wxConfigProvider.getSSLContext() != null){
|
||||||
|
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
|
||||||
|
wxConfigProvider.getSSLContext(),
|
||||||
|
new String[] { "TLSv1" },
|
||||||
|
null,
|
||||||
|
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
|
||||||
|
builder.setSSLSocketFactory(sslsf);
|
||||||
|
}
|
||||||
|
httpClient = builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -941,4 +950,45 @@ public class WxMpServiceImpl implements WxMpService {
|
|||||||
public boolean checkJSSDKCallbackDataSignature(Map<String, String> kvm, String signature) {
|
public boolean checkJSSDKCallbackDataSignature(Map<String, String> kvm, String signature) {
|
||||||
return signature.equals(WxCryptUtil.createSign(kvm, wxMpConfigStorage.getPartnerKey()));
|
return signature.equals(WxCryptUtil.createSign(kvm, wxMpConfigStorage.getPartnerKey()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WxRedpackResult sendRedpack(Map<String, String> parameters) throws WxErrorException {
|
||||||
|
String nonce_str = System.currentTimeMillis() + "";
|
||||||
|
|
||||||
|
SortedMap<String, String> packageParams = new TreeMap<String, String>(parameters);
|
||||||
|
packageParams.put("wxappid", wxMpConfigStorage.getAppId());
|
||||||
|
packageParams.put("mch_id", wxMpConfigStorage.getPartnerId());
|
||||||
|
packageParams.put("nonce_str", nonce_str);
|
||||||
|
|
||||||
|
String sign = WxCryptUtil.createSign(packageParams, wxMpConfigStorage.getPartnerKey());
|
||||||
|
packageParams.put("sign", sign);
|
||||||
|
|
||||||
|
StringBuilder request = new StringBuilder("<xml>");
|
||||||
|
for (Entry<String, String> para : packageParams.entrySet()) {
|
||||||
|
request.append(String.format("<%s>%s</%s>", para.getKey(), para.getValue(), para.getKey()));
|
||||||
|
}
|
||||||
|
request.append("</xml>");
|
||||||
|
|
||||||
|
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack");
|
||||||
|
if (httpProxy != null) {
|
||||||
|
RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build();
|
||||||
|
httpPost.setConfig(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringEntity entity = new StringEntity(request.toString(), Consts.UTF_8);
|
||||||
|
httpPost.setEntity(entity);
|
||||||
|
try {
|
||||||
|
CloseableHttpResponse response = getHttpclient().execute(httpPost);
|
||||||
|
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
|
||||||
|
XStream xstream = XStreamInitializer.getInstance();
|
||||||
|
xstream.processAnnotations(WxRedpackResult.class);
|
||||||
|
WxRedpackResult wxMpRedpackResult = (WxRedpackResult) xstream.fromXML(responseContent);
|
||||||
|
return wxMpRedpackResult;
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error(MessageFormatter.format("The exception was happened when sending redpack '{}'.", request.toString()).getMessage(), e);
|
||||||
|
WxError error = new WxError();
|
||||||
|
error.setErrorCode(-1);
|
||||||
|
throw new WxErrorException(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,118 @@
|
|||||||
|
package me.chanjar.weixin.mp.bean.result;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向微信用户个人发现金红包返回结果
|
||||||
|
* https://pay.weixin.qq.com/wiki/doc/api/cash_coupon.php?chapter=13_5
|
||||||
|
* @author kane
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@XStreamAlias("xml")
|
||||||
|
public class WxRedpackResult implements Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = -4837415036337132073L;
|
||||||
|
|
||||||
|
@XStreamAlias("return_code")
|
||||||
|
String returnCode;
|
||||||
|
@XStreamAlias("return_msg")
|
||||||
|
String returnMsg;
|
||||||
|
@XStreamAlias("sign")
|
||||||
|
String sign;
|
||||||
|
@XStreamAlias("result_code")
|
||||||
|
String resultCode;
|
||||||
|
|
||||||
|
@XStreamAlias("err_code")
|
||||||
|
String errCode;
|
||||||
|
@XStreamAlias("err_code_des")
|
||||||
|
String errCodeDes;
|
||||||
|
@XStreamAlias("mch_billno")
|
||||||
|
String mchBillno;
|
||||||
|
@XStreamAlias("mch_id")
|
||||||
|
String mchId;
|
||||||
|
@XStreamAlias("wxappid")
|
||||||
|
String wxappid;
|
||||||
|
@XStreamAlias("re_openid")
|
||||||
|
String reOpenid;
|
||||||
|
@XStreamAlias("total_amount")
|
||||||
|
int totalAmount;
|
||||||
|
@XStreamAlias("send_time")
|
||||||
|
String sendTime;
|
||||||
|
@XStreamAlias("send_listid")
|
||||||
|
String sendListid;
|
||||||
|
|
||||||
|
public String getErrCode() {
|
||||||
|
return errCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getErrCodeDes() {
|
||||||
|
return errCodeDes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReturnCode() {
|
||||||
|
return returnCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReturnMsg() {
|
||||||
|
return returnMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSign() {
|
||||||
|
return sign;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResultCode() {
|
||||||
|
return resultCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMchBillno() {
|
||||||
|
return mchBillno;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMchId() {
|
||||||
|
return mchId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getWxappid() {
|
||||||
|
return wxappid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReOpenid() {
|
||||||
|
return reOpenid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTotalAmount() {
|
||||||
|
return totalAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSendTime() {
|
||||||
|
return sendTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSendListid() {
|
||||||
|
return sendListid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "WxRedpackResult{" +
|
||||||
|
"returnCode=" + returnCode +
|
||||||
|
", returnMsg=" + returnMsg +
|
||||||
|
", sign=" + sign +
|
||||||
|
", errCode=" + errCode +
|
||||||
|
", errCodeDes=" + errCodeDes +
|
||||||
|
", mchBillno=" + mchBillno +
|
||||||
|
", mchId=" + mchId +
|
||||||
|
", wxappid=" + wxappid +
|
||||||
|
", reOpenid=" + reOpenid +
|
||||||
|
", totalAmount=" + totalAmount +
|
||||||
|
", sendTime=" + sendTime +
|
||||||
|
", sendListid=" + sendListid +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
package me.chanjar.weixin.mp.bean;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.thoughtworks.xstream.XStream;
|
||||||
|
|
||||||
|
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
|
||||||
|
import me.chanjar.weixin.mp.bean.result.WxRedpackResult;
|
||||||
|
|
||||||
|
public class WxRedpackResultTest {
|
||||||
|
|
||||||
|
private XStream xstream;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
xstream = XStreamInitializer.getInstance();
|
||||||
|
xstream.processAnnotations(WxRedpackResult.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void loadSuccessResult() {
|
||||||
|
final String successSample = "<xml>\n" +
|
||||||
|
"<return_code><![CDATA[SUCCESS]]></return_code>\n" +
|
||||||
|
"<return_msg><![CDATA[发放成功.]]></return_msg>\n" +
|
||||||
|
"<result_code><![CDATA[SUCCESS]]></result_code>\n" +
|
||||||
|
"<err_code><![CDATA[0]]></err_code>\n" +
|
||||||
|
"<err_code_des><![CDATA[发放成功.]]></err_code_des>\n" +
|
||||||
|
"<mch_billno><![CDATA[0010010404201411170000046545]]></mch_billno>\n" +
|
||||||
|
"<mch_id>10010404</mch_id>\n" +
|
||||||
|
"<wxappid><![CDATA[wx6fa7e3bab7e15415]]></wxappid>\n" +
|
||||||
|
"<re_openid><![CDATA[onqOjjmM1tad-3ROpncN-yUfa6uI]]></re_openid>\n" +
|
||||||
|
"<total_amount>1</total_amount>\n" +
|
||||||
|
"<send_listid>100000000020150520314766074200</send_listid>\n" +
|
||||||
|
"<send_time>20150520102602</send_time>\n" +
|
||||||
|
"</xml>";
|
||||||
|
WxRedpackResult wxMpRedpackResult = (WxRedpackResult) xstream.fromXML(successSample);
|
||||||
|
assertEquals("SUCCESS", wxMpRedpackResult.getReturnCode());
|
||||||
|
assertEquals("SUCCESS", wxMpRedpackResult.getResultCode());
|
||||||
|
assertEquals("20150520102602", wxMpRedpackResult.getSendTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void loadFailureResult() {
|
||||||
|
final String failureSample = "<xml>\n" +
|
||||||
|
"<return_code><![CDATA[FAIL]]></return_code>\n" +
|
||||||
|
"<return_msg><![CDATA[系统繁忙,请稍后再试.]]></return_msg>\n" +
|
||||||
|
"<result_code><![CDATA[FAIL]]></result_code>\n" +
|
||||||
|
"<err_code><![CDATA[268458547]]></err_code>\n" +
|
||||||
|
"<err_code_des><![CDATA[系统繁忙,请稍后再试.]]></err_code_des>\n" +
|
||||||
|
"<mch_billno><![CDATA[0010010404201411170000046542]]></mch_billno>\n" +
|
||||||
|
"<mch_id>10010404</mch_id>\n" +
|
||||||
|
"<wxappid><![CDATA[wx6fa7e3bab7e15415]]></wxappid>\n" +
|
||||||
|
"<re_openid><![CDATA[onqOjjmM1tad-3ROpncN-yUfa6uI]]></re_openid>\n" +
|
||||||
|
"<total_amount>1</total_amount>\n" +
|
||||||
|
"</xml>";
|
||||||
|
WxRedpackResult wxMpRedpackResult = (WxRedpackResult) xstream.fromXML(failureSample);
|
||||||
|
assertEquals("FAIL", wxMpRedpackResult.getReturnCode());
|
||||||
|
assertEquals("FAIL", wxMpRedpackResult.getResultCode());
|
||||||
|
assertEquals("onqOjjmM1tad-3ROpncN-yUfa6uI", wxMpRedpackResult.getReOpenid());
|
||||||
|
assertEquals(1, wxMpRedpackResult.getTotalAmount());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user