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 javax.net.ssl.SSLContext;
|
||||
|
||||
import me.chanjar.weixin.common.bean.WxAccessToken;
|
||||
|
||||
/**
|
||||
@ -74,4 +76,5 @@ public interface WxMpConfigStorage {
|
||||
|
||||
public File getTmpDirFile();
|
||||
|
||||
public SSLContext getSSLContext();
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package me.chanjar.weixin.mp.api;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
import me.chanjar.weixin.common.bean.WxAccessToken;
|
||||
|
||||
/**
|
||||
@ -35,6 +37,8 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
|
||||
*/
|
||||
protected volatile File tmpDirFile;
|
||||
|
||||
protected volatile SSLContext sslContext;
|
||||
|
||||
public String getAccessToken() {
|
||||
return this.accessToken;
|
||||
}
|
||||
@ -219,4 +223,13 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
|
||||
this.tmpDirFile = tmpDirFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSLContext getSSLContext() {
|
||||
return sslContext;
|
||||
}
|
||||
|
||||
public void setSSLContext(SSLContext context) {
|
||||
sslContext = context;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -748,4 +748,12 @@ public interface WxMpService {
|
||||
* @return
|
||||
*/
|
||||
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.WxMpUserList;
|
||||
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.MaterialNewsInfoRequestExecutor;
|
||||
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.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||
import org.apache.http.impl.client.BasicResponseHandler;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.helpers.MessageFormatter;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
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_password = wxMpConfigStorage.getHttp_proxy_password();
|
||||
|
||||
final HttpClientBuilder builder = HttpClients.custom();
|
||||
if (StringUtils.isNotBlank(http_proxy_host)) {
|
||||
// 使用代理服务器
|
||||
if (StringUtils.isNotBlank(http_proxy_username)) {
|
||||
@ -751,18 +756,22 @@ public class WxMpServiceImpl implements WxMpService {
|
||||
credsProvider.setCredentials(
|
||||
new AuthScope(http_proxy_host, http_proxy_port),
|
||||
new UsernamePasswordCredentials(http_proxy_username, http_proxy_password));
|
||||
httpClient = HttpClients
|
||||
.custom()
|
||||
.setDefaultCredentialsProvider(credsProvider)
|
||||
.build();
|
||||
builder
|
||||
.setDefaultCredentialsProvider(credsProvider);
|
||||
} else {
|
||||
// 无需用户认证的代理服务器
|
||||
httpClient = HttpClients.createDefault();
|
||||
}
|
||||
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
|
||||
@ -941,4 +950,45 @@ public class WxMpServiceImpl implements WxMpService {
|
||||
public boolean checkJSSDKCallbackDataSignature(Map<String, String> kvm, String signature) {
|
||||
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