Merge pull request #233 from videome/develop

Support sending redpack.
This commit is contained in:
Daniel Qian 2015-11-20 14:51:46 +08:00
commit 27ce2a2746
6 changed files with 262 additions and 7 deletions

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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);
}
}
}

View File

@ -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 +
'}';
}
}

View File

@ -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());
}
}