Skip to content

Commit

Permalink
Merge pull request chanjarster#233 from videome/develop
Browse files Browse the repository at this point in the history
Support sending redpack.
  • Loading branch information
chanjarster committed Nov 20, 2015
2 parents d0a4529 + 30f2289 commit 27ce2a2
Show file tree
Hide file tree
Showing 6 changed files with 262 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import java.io.File;

import javax.net.ssl.SSLContext;

import me.chanjar.weixin.common.bean.WxAccessToken;

/**
Expand Down Expand Up @@ -74,4 +76,5 @@ public interface WxMpConfigStorage {

public File getTmpDirFile();

public SSLContext getSSLContext();
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import java.io.File;

import javax.net.ssl.SSLContext;

import me.chanjar.weixin.common.bean.WxAccessToken;

/**
Expand Down Expand Up @@ -35,6 +37,8 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
*/
protected volatile File tmpDirFile;

protected volatile SSLContext sslContext;

public String getAccessToken() {
return this.accessToken;
}
Expand Down Expand Up @@ -219,4 +223,13 @@ public void setTmpDirFile(File tmpDirFile) {
this.tmpDirFile = tmpDirFile;
}

@Override
public SSLContext getSSLContext() {
return sslContext;
}

public void setSSLContext(SSLContext context) {
sslContext = context;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
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;
Expand All @@ -84,13 +85,16 @@
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;
Expand Down Expand Up @@ -743,6 +747,7 @@ public void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider) {
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)) {
Expand All @@ -751,18 +756,22 @@ public void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider) {
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
Expand Down Expand Up @@ -941,4 +950,45 @@ public WxMpPayCallback getJSSDKCallbackData(String xmlData) {
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);
}
}
}
Original file line number Diff line number Diff line change
@@ -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 +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -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());
}
}

0 comments on commit 27ce2a2

Please sign in to comment.