切分weixin.properties
This commit is contained in:
@@ -1,5 +1,13 @@
|
||||
package com.foxinmy.weixin4j.exception;
|
||||
|
||||
/**
|
||||
* 调用微信支付抛出的异常
|
||||
* @className PayException
|
||||
* @author jy
|
||||
* @date 2014年10月28日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class PayException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 7148145661883468514L;
|
||||
|
||||
@@ -13,14 +13,10 @@ public class WeixinException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 7148145661883468514L;
|
||||
|
||||
private int errorCode;
|
||||
private String errorCode;
|
||||
private String errorMsg;
|
||||
|
||||
public WeixinException(int errorCode) {
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
public WeixinException(int errorCode, String errorMsg) {
|
||||
public WeixinException(String errorCode, String errorMsg) {
|
||||
this.errorCode = errorCode;
|
||||
this.errorMsg = errorMsg;
|
||||
}
|
||||
@@ -29,7 +25,7 @@ public class WeixinException extends Exception {
|
||||
this.errorMsg = errorMsg;
|
||||
}
|
||||
|
||||
public int getErrorCode() {
|
||||
public String getErrorCode() {
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.foxinmy.weixin4j.http;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 调用接口响应值
|
||||
*
|
||||
@@ -12,12 +14,15 @@ import java.io.Serializable;
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%85%A8%E5%B1%80%E8%BF%94%E5%9B%9E%E7%A0%81%E8%AF%B4%E6%98%8E">全局返回码</a>
|
||||
*/
|
||||
@XStreamAlias("xml")
|
||||
public class BaseResult implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -6185313616955051150L;
|
||||
|
||||
private int errcode;
|
||||
private String errmsg;
|
||||
@XStreamAlias("return_code")
|
||||
private String errcode = "0";
|
||||
@XStreamAlias("return_msg")
|
||||
private String errmsg = "";
|
||||
private String msgid;
|
||||
private String text;
|
||||
|
||||
@@ -25,13 +30,11 @@ public class BaseResult implements Serializable {
|
||||
|
||||
}
|
||||
|
||||
public BaseResult(int errcode, String errmsg, String text) {
|
||||
this.errcode = errcode;
|
||||
this.errmsg = errmsg;
|
||||
this.text = text;
|
||||
public BaseResult(String errcode, String errmsg, String text) {
|
||||
this(errcode, errmsg, null, text);
|
||||
}
|
||||
|
||||
public BaseResult(int errcode, String errmsg, String msgid, String text) {
|
||||
public BaseResult(String errcode, String errmsg, String msgid, String text) {
|
||||
this.errcode = errcode;
|
||||
this.errmsg = errmsg;
|
||||
this.msgid = msgid;
|
||||
@@ -46,11 +49,11 @@ public class BaseResult implements Serializable {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public int getErrcode() {
|
||||
public String getErrcode() {
|
||||
return errcode;
|
||||
}
|
||||
|
||||
public void setErrcode(int errcode) {
|
||||
public void setErrcode(String errcode) {
|
||||
this.errcode = errcode;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@ package com.foxinmy.weixin4j.http;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.Consts;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpEntity;
|
||||
@@ -33,6 +33,7 @@ import org.apache.http.params.CoreConnectionPNames;
|
||||
import org.apache.http.params.CoreProtocolPNames;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
import com.alibaba.fastjson.JSONException;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
|
||||
/**
|
||||
@@ -155,12 +156,12 @@ public class HttpRequest {
|
||||
|
||||
int status = statusLine.getStatusCode();
|
||||
if (status != HttpStatus.SC_OK) {
|
||||
throw new WeixinException(status, "request fail");
|
||||
throw new WeixinException(status + "", "request fail");
|
||||
}
|
||||
// 301或者302
|
||||
if (status == HttpStatus.SC_MOVED_PERMANENTLY
|
||||
|| status == HttpStatus.SC_MOVED_TEMPORARILY) {
|
||||
throw new WeixinException(status, String.format(
|
||||
throw new WeixinException(status + "", String.format(
|
||||
"the page was redirected to %s",
|
||||
httpResponse.getFirstHeader("location")));
|
||||
}
|
||||
@@ -170,7 +171,7 @@ public class HttpRequest {
|
||||
response.setStatusCode(status);
|
||||
response.setStatusText(statusLine.getReasonPhrase());
|
||||
response.setStream(new ByteArrayInputStream(data));
|
||||
response.setText(StringUtils.join(data));
|
||||
response.setText(new String(data, StandardCharsets.UTF_8));
|
||||
|
||||
Header contentType = httpResponse
|
||||
.getFirstHeader(HttpHeaders.CONTENT_TYPE);
|
||||
@@ -178,18 +179,25 @@ public class HttpRequest {
|
||||
ContentType.APPLICATION_JSON.getMimeType())
|
||||
|| contentType.getValue().contains(
|
||||
ContentType.TEXT_PLAIN.getMimeType())) {
|
||||
BaseResult result = response.getAsResult();
|
||||
if (result.getErrcode() != 0) {
|
||||
throw new WeixinException(result.getErrcode(),
|
||||
result.getErrmsg());
|
||||
BaseResult result = null;
|
||||
try {
|
||||
result = response.getAsResult();
|
||||
} catch (JSONException e) {
|
||||
result = response.getAsXml(BaseResult.class);
|
||||
}
|
||||
if (result.getErrcode().equals("0")
|
||||
|| result.getErrcode().equalsIgnoreCase("success")) {
|
||||
EntityUtils.consume(httpEntity);
|
||||
return response;
|
||||
}
|
||||
throw new WeixinException(result.getErrcode(),
|
||||
result.getErrmsg());
|
||||
}
|
||||
EntityUtils.consume(httpEntity);
|
||||
return response;
|
||||
} catch (IOException e) {
|
||||
throw new WeixinException(e.getMessage());
|
||||
} finally {
|
||||
request.releaseConnection();
|
||||
}
|
||||
throw new WeixinException("-1", "request fail");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.foxinmy.weixin4j.http;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentException;
|
||||
@@ -10,7 +9,7 @@ import org.dom4j.io.SAXReader;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
import com.foxinmy.weixin4j.xml.XStream;
|
||||
|
||||
public class Response {
|
||||
|
||||
@@ -39,15 +38,14 @@ public class Response {
|
||||
return JSON.parseObject(text);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getAsObject(Class<? extends Serializable> clazz) {
|
||||
public <T> T getAsObject(Class<T> clazz) {
|
||||
return (T) JSON.parseObject(text, clazz);
|
||||
}
|
||||
|
||||
public Object getAsXml() {
|
||||
XStream xs = new XStream();
|
||||
xs.autodetectAnnotations(true);
|
||||
return xs.fromXML(text);
|
||||
public <T> T getAsXml(Class<T> clazz) {
|
||||
XStream xStream = XStream.get();
|
||||
xStream.processAnnotations(clazz);
|
||||
return xStream.fromXML(text, clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,12 +58,11 @@ public class Response {
|
||||
*/
|
||||
public BaseResult getBaseError() throws DocumentException {
|
||||
BaseResult result = getAsResult();
|
||||
if (result.getErrcode() != 0) {
|
||||
if (!result.getErrcode().equals("0")) {
|
||||
SAXReader reader = new SAXReader();
|
||||
Document doc = reader.read(Thread.currentThread()
|
||||
.getContextClassLoader().getResourceAsStream("error.xml"));
|
||||
Document doc = reader.read(Response.class.getResourceAsStream("error.xml"));
|
||||
Node node = doc.getRootElement().selectSingleNode(
|
||||
String.format("error[@code='%d']", result.getErrcode()));
|
||||
String.format("error[@code='%s']", result.getErrcode()));
|
||||
if (node != null) {
|
||||
result.setText(node.getStringValue());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- http://mp.weixin.qq.com/wiki/index.php?title=%E5%85%A8%E5%B1%80%E8%BF%94%E5%9B%9E%E7%A0%81%E8%AF%B4%E6%98%8E -->
|
||||
<errors>
|
||||
<error code="-1">系统繁忙</error>
|
||||
<error code="40001">获取access_token时AppSecret错误,或者access_token无效</error>
|
||||
<error code="40002">不合法的凭证类型</error>
|
||||
<error code="40003">不合法的OpenID</error>
|
||||
<error code="40004">不合法的媒体文件类型</error>
|
||||
<error code="40005">不合法的文件类型</error>
|
||||
<error code="40006">不合法的文件大小</error>
|
||||
<error code="40007">不合法的媒体文件id</error>
|
||||
<error code="40008">不合法的消息类型</error>
|
||||
<error code="40009">不合法的图片文件大小</error>
|
||||
<error code="40010">不合法的语音文件大小</error>
|
||||
<error code="40011">不合法的视频文件大小</error>
|
||||
<error code="40012">不合法的缩略图文件大小</error>
|
||||
<error code="40013">不合法的APPID</error>
|
||||
<error code="40014">不合法的access_token</error>
|
||||
<error code="40015">不合法的菜单类型</error>
|
||||
<error code="40016">不合法的按钮个数</error>
|
||||
<error code="40017">不合法的按钮个数</error>
|
||||
<error code="40018">不合法的按钮名字长度</error>
|
||||
<error code="40019">不合法的按钮KEY长度</error>
|
||||
<error code="40020">不合法的按钮URL长度</error>
|
||||
<error code="40021">不合法的菜单版本号</error>
|
||||
<error code="40022">不合法的子菜单级数</error>
|
||||
<error code="40023">不合法的子菜单按钮个数</error>
|
||||
<error code="40024">不合法的子菜单按钮类型</error>
|
||||
<error code="40025">不合法的子菜单按钮名字长度</error>
|
||||
<error code="40026">不合法的子菜单按钮KEY长度</error>
|
||||
<error code="40027">不合法的子菜单按钮URL长度</error>
|
||||
<error code="40028">不合法的自定义菜单使用用户</error>
|
||||
<error code="40029">不合法的oauth_code</error>
|
||||
<error code="40030">不合法的refresh_token</error>
|
||||
<error code="40031">不合法的openid列表</error>
|
||||
<error code="40032">不合法的openid列表长度</error>
|
||||
<error code="40033">不合法的请求字符,不能包含\uxxxx格式的字符</error>
|
||||
<error code="40035">不合法的参数</error>
|
||||
<error code="40038">不合法的请求格式</error>
|
||||
<error code="40039">不合法的URL长度</error>
|
||||
<error code="40050">不合法的分组id</error>
|
||||
<error code="40051">分组名字不合法</error>
|
||||
<error code="41001">缺少access_token参数</error>
|
||||
<error code="41002">缺少appid参数</error>
|
||||
<error code="41003">缺少refresh_token参数</error>
|
||||
<error code="41004">缺少secret参数</error>
|
||||
<error code="41005">缺少多媒体文件数据</error>
|
||||
<error code="41006">缺少media_id参数</error>
|
||||
<error code="41007">缺少子菜单数据</error>
|
||||
<error code="41008">缺少oauth code</error>
|
||||
<error code="41009">缺少openid</error>
|
||||
<error code="42001">access_token超时</error>
|
||||
<error code="42002">refresh_token超时</error>
|
||||
<error code="42003">oauth_code超时</error>
|
||||
<error code="43001">需要GET请求</error>
|
||||
<error code="43002">需要POST请求</error>
|
||||
<error code="43003">需要HTTPS请求</error>
|
||||
<error code="43004">需要接收者关注</error>
|
||||
<error code="43005">需要好友关系</error>
|
||||
<error code="44001">多媒体文件为空</error>
|
||||
<error code="44002">POST的数据包为空</error>
|
||||
<error code="44003">图文消息内容为空</error>
|
||||
<error code="44004">文本消息内容为空</error>
|
||||
<error code="45001">多媒体文件大小超过限制</error>
|
||||
<error code="45002">消息内容超过限制</error>
|
||||
<error code="45003">标题字段超过限制</error>
|
||||
<error code="45004">描述字段超过限制</error>
|
||||
<error code="45005">链接字段超过限制</error>
|
||||
<error code="45006">图片链接字段超过限制</error>
|
||||
<error code="45007">语音播放时间超过限制</error>
|
||||
<error code="45008">图文消息超过限制</error>
|
||||
<error code="45009">接口调用超过限制</error>
|
||||
<error code="45010">创建菜单个数超过限制</error>
|
||||
<error code="45015">回复时间超过限制</error>
|
||||
<error code="45016">系统分组,不允许修改</error>
|
||||
<error code="45017">分组名字过长</error>
|
||||
<error code="45018">分组数量超过上限</error>
|
||||
<error code="46001">不存在媒体数据</error>
|
||||
<error code="46002">不存在的菜单版本</error>
|
||||
<error code="46003">不存在的菜单数据</error>
|
||||
<error code="46004">不存在的用户</error>
|
||||
<error code="47001">解析JSON/XML内容错误</error>
|
||||
<error code="48001">api功能未授权</error>
|
||||
<error code="50001">用户未授权该api</error>
|
||||
<error code="SYSTEMERROR">接口后台错误</error>
|
||||
<error code="INVALID_TRANSACTIONID">无效 transaction_id</error>
|
||||
<error code="PARAM_ERROR">提交参数错误</error>
|
||||
<error code="ORDERPAID">订单已支付</error>
|
||||
<error code="OUT_TRADE_NO_USED">商户订单号重复</error>
|
||||
<error code="NOAUTH">商户无权限</error>
|
||||
<error code="NOTENOUGH">余额不足</error>
|
||||
<error code="NOTSUPORTCARD">不支持卡类型</error>
|
||||
<error code="ORDERCLOSED">订单已关闭</error>
|
||||
<error code="BANKERROR">银行系统异常</error>
|
||||
<error code="REFUND_FEE_INVALID">退款金额大于支付金额</error>
|
||||
<error code="ORDERNOTEXIST">订单不存在</error>
|
||||
</errors>
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.foxinmy.weixin4j.model;
|
||||
|
||||
/**
|
||||
* 微信账户信息
|
||||
*
|
||||
* @className WeixinAccountV2
|
||||
* @author jy
|
||||
* @date 2014年8月17日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class WeixinAccount extends WeixinAccountV2 {
|
||||
private static final long serialVersionUID = 3689999353867189585L;
|
||||
// 是否已经认证
|
||||
private boolean isAlive;
|
||||
// 是否是服务号
|
||||
private boolean isService;
|
||||
// 是否是订阅号
|
||||
private boolean isSubscribe = true;
|
||||
// 微信支付商户号
|
||||
private String mchId;
|
||||
|
||||
public boolean getIsAlive() {
|
||||
return isAlive;
|
||||
}
|
||||
|
||||
public void setIsAlive(Boolean isAlive) {
|
||||
this.isAlive = isAlive;
|
||||
}
|
||||
|
||||
public boolean getIsService() {
|
||||
return isService;
|
||||
}
|
||||
|
||||
public void setIsService(Boolean isService) {
|
||||
this.isService = isService;
|
||||
}
|
||||
|
||||
public boolean getIsSubscribe() {
|
||||
return isSubscribe;
|
||||
}
|
||||
public String getMchId() {
|
||||
return mchId;
|
||||
}
|
||||
public void setMchId(String mchId) {
|
||||
this.mchId = mchId;
|
||||
}
|
||||
public void setIsSubscribe(Boolean isSubscribe) {
|
||||
this.isSubscribe = isSubscribe;
|
||||
}
|
||||
|
||||
public WeixinAccount() {
|
||||
}
|
||||
|
||||
public WeixinAccount(boolean isAlive, boolean isService,
|
||||
boolean isSubscribe, String token, String openId) {
|
||||
super.setToken(token);
|
||||
super.setOpenId(openId);
|
||||
this.isAlive = isAlive;
|
||||
this.isService = isService;
|
||||
this.isSubscribe = isSubscribe;
|
||||
}
|
||||
|
||||
public WeixinAccount(boolean isAlive, boolean isService,
|
||||
boolean isSubscribe, String token, String openId, String appId,
|
||||
String appSecret) {
|
||||
super.setToken(token);
|
||||
super.setOpenId(openId);
|
||||
super.setAppId(appId);
|
||||
super.setAppSecret(appSecret);
|
||||
this.isAlive = isAlive;
|
||||
this.isService = isService;
|
||||
this.isSubscribe = isSubscribe;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WeixinAccount [isAlive=" + isAlive + ", isService=" + isService
|
||||
+ ", isSubscribe=" + isSubscribe + ", mchId=" + mchId
|
||||
+ ", getIsAlive()=" + getIsAlive() + ", getIsService()="
|
||||
+ getIsService() + ", getIsSubscribe()=" + getIsSubscribe()
|
||||
+ ", getMchId()=" + getMchId() + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.foxinmy.weixin4j.model;
|
||||
|
||||
/**
|
||||
* 微信支付V2.7
|
||||
*
|
||||
* @className WeixinAccountV2
|
||||
* @author jy
|
||||
* @date 2014年8月17日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class WeixinAccountV2 extends WeixinConfig {
|
||||
private static final long serialVersionUID = 3689999353867189585L;
|
||||
// 公众号支付请求中用于加密的密钥 Key,可验证商户唯一身份,PaySignKey 对应于支付场景中的 appKey 值
|
||||
private String paySignKey;
|
||||
// 财付通商户身份的标识
|
||||
private String partnerId;
|
||||
// 财付通商户权限密钥Key
|
||||
private String partnerKey;
|
||||
|
||||
public String getPaySignKey() {
|
||||
return paySignKey;
|
||||
}
|
||||
public void setPaySignKey(String paySignKey) {
|
||||
this.paySignKey = paySignKey;
|
||||
}
|
||||
public String getPartnerId() {
|
||||
return partnerId;
|
||||
}
|
||||
public void setPartnerId(String partnerId) {
|
||||
this.partnerId = partnerId;
|
||||
}
|
||||
public String getPartnerKey() {
|
||||
return partnerKey;
|
||||
}
|
||||
public void setPartnerKey(String partnerKey) {
|
||||
this.partnerKey = partnerKey;
|
||||
}
|
||||
|
||||
public WeixinAccountV2() {
|
||||
}
|
||||
public WeixinAccountV2(String openId, String appId, String appSecret,
|
||||
String paySignKey, String partnerId, String partnerKey) {
|
||||
super(null, openId, appId, appSecret);
|
||||
this.paySignKey = paySignKey;
|
||||
this.partnerId = partnerId;
|
||||
this.partnerKey = partnerKey;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WeixinAccountV2 [paySignKey=" + paySignKey + ", partnerId="
|
||||
+ partnerId + ", partnerKey=" + partnerKey
|
||||
+ ", getPaySignKey()=" + getPaySignKey() + ", getPartnerId()="
|
||||
+ getPartnerId() + ", getPartnerKey()=" + getPartnerKey() + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.foxinmy.weixin4j.model;
|
||||
|
||||
/**
|
||||
* 微信支付V3.3.6
|
||||
*
|
||||
* @className WeixinConfig
|
||||
* @author jy
|
||||
* @date 2014年8月17日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class WeixinAccountV3 extends WeixinConfig {
|
||||
private static final long serialVersionUID = 3689999353867189585L;
|
||||
// 公众号支付请求中用于加密的密钥 Key,可验证商户唯一身份,PaySignKey 对应于支付场景中的 appKey 值
|
||||
private String paySignKey;
|
||||
// 微信支付商户号
|
||||
private String mchId;
|
||||
|
||||
public String getPaySignKey() {
|
||||
return paySignKey;
|
||||
}
|
||||
public void setPaySignKey(String paySignKey) {
|
||||
this.paySignKey = paySignKey;
|
||||
}
|
||||
public String getMchId() {
|
||||
return mchId;
|
||||
}
|
||||
public void setMchId(String mchId) {
|
||||
this.mchId = mchId;
|
||||
}
|
||||
public WeixinAccountV3() {
|
||||
}
|
||||
|
||||
public WeixinAccountV3(String appId, String appSecret, String paySignKey,
|
||||
String mchId, String openId) {
|
||||
super(null, openId, appId, appSecret);
|
||||
this.mchId = mchId;
|
||||
this.paySignKey = paySignKey;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WeixinAccountV3 [paySignKey=" + paySignKey + ", mchId=" + mchId
|
||||
+ ", getPaySignKey()=" + getPaySignKey() + ", getMchId()="
|
||||
+ getMchId() + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.foxinmy.weixin4j.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class WeixinConfig implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -3454743453282851243L;
|
||||
|
||||
private String token;
|
||||
// 支付场景下为用户的openid 其余情况可能是公众号的原始ID
|
||||
private String openId;
|
||||
// 公众号身份的唯一标识
|
||||
private String appId;
|
||||
// 除了支付请求需要用到 paySignKey,公众平台接口 API 的权限获取所需密 钥 Key
|
||||
private String appSecret;
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
public String getOpenId() {
|
||||
return openId;
|
||||
}
|
||||
public void setOpenId(String openId) {
|
||||
this.openId = openId;
|
||||
}
|
||||
public String getAppId() {
|
||||
return appId;
|
||||
}
|
||||
public void setAppId(String appId) {
|
||||
this.appId = appId;
|
||||
}
|
||||
public String getAppSecret() {
|
||||
return appSecret;
|
||||
}
|
||||
public void setAppSecret(String appSecret) {
|
||||
this.appSecret = appSecret;
|
||||
}
|
||||
public WeixinConfig() {
|
||||
|
||||
}
|
||||
public WeixinConfig(String token, String openId, String appId,
|
||||
String appSecret) {
|
||||
this.token = token;
|
||||
this.openId = openId;
|
||||
this.appId = appId;
|
||||
this.appSecret = appSecret;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WeixinConfig [token=" + token + ", openId=" + openId
|
||||
+ ", appId=" + appId + ", appSecret=" + appSecret + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,7 +26,7 @@ import com.thoughtworks.xstream.io.json.JsonWriter;
|
||||
public class BaseMessage implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 7761192742840031607L;
|
||||
private final static XStream xmlStream = new XStream();
|
||||
private final static XStream xmlStream = XStream.get();
|
||||
private final static XStream jsonStream = new XStream(
|
||||
new JsonHierarchicalStreamDriver() {
|
||||
public HierarchicalStreamWriter createWriter(Writer writer) {
|
||||
@@ -49,8 +49,6 @@ public class BaseMessage implements Serializable {
|
||||
Class<?>[] classes = ClassUtil.getClasses(
|
||||
TextMessage.class.getPackage()).toArray(new Class[0]);
|
||||
|
||||
xmlStream.ignoreUnknownElements();
|
||||
xmlStream.autodetectAnnotations(true);
|
||||
xmlStream.processAnnotations(classes);
|
||||
xmlStream.omitField(BaseMessage.class, "msgId");
|
||||
|
||||
@@ -123,20 +121,16 @@ public class BaseMessage implements Serializable {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected XStream getXStream() {
|
||||
Class<? extends BaseMessage> targetClass = getMsgType()
|
||||
.getMessageClass();
|
||||
xmlStream.alias("xml", targetClass);
|
||||
return xmlStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息对象转换为微信服务器接受的xml格式消息
|
||||
*
|
||||
* @return xml字符串
|
||||
*/
|
||||
public String toXml() {
|
||||
return getXStream().toXML(this);
|
||||
Class<? extends BaseMessage> targetClass = getMsgType()
|
||||
.getMessageClass();
|
||||
xmlStream.alias("xml", targetClass);
|
||||
return xmlStream.toXML(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
package com.foxinmy.weixin4j.token;
|
||||
|
||||
import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||
|
||||
/**
|
||||
* 获取config.properties中的appid&appsecret信息
|
||||
*
|
||||
* @className AbstractTokenApi
|
||||
* @author jy
|
||||
* @date 2014年10月6日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public abstract class AbstractTokenApi implements TokenApi {
|
||||
|
||||
protected String getAppid() {
|
||||
return ConfigUtil.getValue("app_id");
|
||||
}
|
||||
|
||||
protected String getAppsecret() {
|
||||
return ConfigUtil.getValue("app_secret");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.foxinmy.weixin4j.token;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.foxinmy.weixin4j.http.HttpRequest;
|
||||
import com.foxinmy.weixin4j.model.WeixinConfig;
|
||||
import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||
|
||||
/**
|
||||
* 获取config.properties中的appid&appsecret信息
|
||||
*
|
||||
* @className AbstractTokenApi
|
||||
* @author jy
|
||||
* @date 2014年10月6日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public abstract class AbstractTokenHolder implements TokenHolder {
|
||||
protected final String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
|
||||
protected final HttpRequest request = new HttpRequest();
|
||||
private final WeixinConfig weixinConfig;
|
||||
|
||||
public AbstractTokenHolder() {
|
||||
weixinConfig = JSON.parseObject(ConfigUtil.getValue("account"),
|
||||
WeixinConfig.class);
|
||||
}
|
||||
|
||||
protected String getAppid() {
|
||||
return weixinConfig.getAppId();
|
||||
}
|
||||
|
||||
protected String getAppsecret() {
|
||||
return weixinConfig.getAppSecret();
|
||||
}
|
||||
}
|
||||
+10
-15
@@ -8,7 +8,6 @@ import java.util.Calendar;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.HttpRequest;
|
||||
import com.foxinmy.weixin4j.http.Response;
|
||||
import com.foxinmy.weixin4j.model.Token;
|
||||
import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||
@@ -17,7 +16,7 @@ import com.foxinmy.weixin4j.xml.XStream;
|
||||
/**
|
||||
* 基于文件保存的Token获取类
|
||||
*
|
||||
* @className FileTokenApi
|
||||
* @className FileTokenHolder
|
||||
* @author jy.hu
|
||||
* @date 2014年9月27日
|
||||
* @since JDK 1.7
|
||||
@@ -25,19 +24,17 @@ import com.foxinmy.weixin4j.xml.XStream;
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96access_token">获取token说明</a>
|
||||
* @see com.foxinmy.weixin4j.model.Token
|
||||
*/
|
||||
public class FileTokenApi extends AbstractTokenApi {
|
||||
|
||||
private final HttpRequest request = new HttpRequest();
|
||||
public class FileTokenHolder extends AbstractTokenHolder {
|
||||
|
||||
private final String appid;
|
||||
private final String appsecret;
|
||||
|
||||
public FileTokenApi() {
|
||||
public FileTokenHolder() {
|
||||
this.appid = getAppid();
|
||||
this.appsecret = getAppsecret();
|
||||
}
|
||||
|
||||
public FileTokenApi(String appid, String appsecret) {
|
||||
public FileTokenHolder(String appid, String appsecret) {
|
||||
this.appid = appid;
|
||||
this.appsecret = appsecret;
|
||||
}
|
||||
@@ -60,8 +57,7 @@ public class FileTokenApi extends AbstractTokenApi {
|
||||
throw new IllegalArgumentException(
|
||||
"appid or appsecret not be null!");
|
||||
}
|
||||
XStream xstream = new XStream();
|
||||
xstream.autodetectAnnotations(true);
|
||||
XStream xstream = XStream.get();
|
||||
xstream.processAnnotations(Token.class);
|
||||
File token_file = new File(String.format("%s/token_%s.xml",
|
||||
ConfigUtil.getValue("token_path"), appid));
|
||||
@@ -69,9 +65,6 @@ public class FileTokenApi extends AbstractTokenApi {
|
||||
Calendar ca = Calendar.getInstance();
|
||||
long now_time = ca.getTimeInMillis();
|
||||
try {
|
||||
String api_token_uri = String.format(
|
||||
ConfigUtil.getValue("api_token_uri"), appid, appsecret);
|
||||
Response response = null;
|
||||
if (token_file.exists()) {
|
||||
token = (Token) xstream.fromXML(token_file);
|
||||
|
||||
@@ -80,22 +73,24 @@ public class FileTokenApi extends AbstractTokenApi {
|
||||
if (expise_time > now_time) {
|
||||
return token;
|
||||
}
|
||||
response = request.get(api_token_uri);
|
||||
} else {
|
||||
response = request.get(api_token_uri);
|
||||
try {
|
||||
token_file.createNewFile();
|
||||
} catch (IOException e) {
|
||||
token_file.getParentFile().mkdirs();
|
||||
}
|
||||
}
|
||||
String api_token_uri = String.format(
|
||||
tokenUrl, appid, appsecret);
|
||||
Response response = request.get(api_token_uri);
|
||||
token = response.getAsObject(Token.class);
|
||||
token.setTime(now_time);
|
||||
token.setOpenid(appid);
|
||||
xstream.toXML(token, new FileOutputStream(token_file));
|
||||
return token;
|
||||
} catch (IOException e) {
|
||||
;
|
||||
}
|
||||
return token;
|
||||
throw new WeixinException("-1", "request fail");
|
||||
}
|
||||
}
|
||||
+8
-11
@@ -7,14 +7,12 @@ import redis.clients.jedis.JedisPool;
|
||||
import redis.clients.jedis.JedisPoolConfig;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.HttpRequest;
|
||||
import com.foxinmy.weixin4j.model.Token;
|
||||
import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||
|
||||
/**
|
||||
* 基于redis保存的Token获取类
|
||||
*
|
||||
* @className RedisTokenApi
|
||||
* @className RedisTokenHolder
|
||||
* @author jy.hu
|
||||
* @date 2014年9月27日
|
||||
* @since JDK 1.7
|
||||
@@ -22,24 +20,23 @@ import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96access_token">获取token说明</a>
|
||||
* @see com.foxinmy.weixin4j.model.Token
|
||||
*/
|
||||
public class RedisTokenApi extends AbstractTokenApi {
|
||||
|
||||
private final HttpRequest request = new HttpRequest();
|
||||
public class RedisTokenHolder extends AbstractTokenHolder {
|
||||
|
||||
private final String appid;
|
||||
private final String appsecret;
|
||||
private JedisPool jedisPool;
|
||||
|
||||
public RedisTokenApi() {
|
||||
public RedisTokenHolder() {
|
||||
this.appid = getAppid();
|
||||
this.appsecret = getAppsecret();
|
||||
}
|
||||
|
||||
public RedisTokenApi(String appid, String appsecret) {
|
||||
public RedisTokenHolder(String appid, String appsecret) {
|
||||
this(appid, appsecret, "localhost", 6379);
|
||||
}
|
||||
|
||||
public RedisTokenApi(String appid, String appsecret, String host, int port) {
|
||||
public RedisTokenHolder(String appid, String appsecret, String host,
|
||||
int port) {
|
||||
this.appid = appid;
|
||||
this.appsecret = appsecret;
|
||||
JedisPoolConfig poolConfig = new JedisPoolConfig();
|
||||
@@ -64,8 +61,8 @@ public class RedisTokenApi extends AbstractTokenApi {
|
||||
String key = String.format("token:%s", appid);
|
||||
String accessToken = jedis.get(key);
|
||||
if (StringUtils.isBlank(accessToken)) {
|
||||
String api_token_uri = String.format(
|
||||
ConfigUtil.getValue("api_token_uri"), appid, appsecret);
|
||||
String api_token_uri = String
|
||||
.format(tokenUrl, appid, appsecret);
|
||||
token = request.get(api_token_uri).getAsObject(Token.class);
|
||||
jedis.setex(key, token.getExpiresIn() - 3,
|
||||
token.getAccessToken());
|
||||
+5
-5
@@ -6,15 +6,15 @@ import com.foxinmy.weixin4j.model.Token;
|
||||
/**
|
||||
* 获取Token接口
|
||||
*
|
||||
* @className TokenApi
|
||||
* @className TokenHolder
|
||||
* @author jy.hu
|
||||
* @date 2014年9月27日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.model.Token
|
||||
* @see com.foxinmy.weixin4j.token.AbstractTokenApi
|
||||
* @see com.foxinmy.weixin4j.token.FileTokenApi
|
||||
* @see com.foxinmy.weixin4j.token.RedisTokenApi
|
||||
* @see com.foxinmy.weixin4j.token.AbstractTokenHolder
|
||||
* @see com.foxinmy.weixin4j.token.FileTokenHolder
|
||||
* @see com.foxinmy.weixin4j.token.RedisTokenHolder
|
||||
*/
|
||||
public interface TokenApi {
|
||||
public interface TokenHolder {
|
||||
public Token getToken() throws WeixinException;
|
||||
}
|
||||
@@ -3,13 +3,8 @@ package com.foxinmy.weixin4j.util;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class ConfigUtil {
|
||||
public ConfigUtil() {
|
||||
}
|
||||
|
||||
private static Properties props = new Properties();
|
||||
static {
|
||||
try {
|
||||
@@ -23,18 +18,7 @@ public class ConfigUtil {
|
||||
}
|
||||
|
||||
public static String getValue(String key) {
|
||||
String url = props.getProperty(key);
|
||||
Pattern p = Pattern.compile("(\\{[^\\}]*\\})");
|
||||
Matcher m = p.matcher(url);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
String sub = null;
|
||||
while (m.find()) {
|
||||
sub = m.group();
|
||||
m.appendReplacement(sb,
|
||||
getValue(sub.substring(1, sub.length() - 1)));
|
||||
}
|
||||
m.appendTail(sb);
|
||||
return sb.toString();
|
||||
return props.getProperty(key);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
@@ -111,9 +111,7 @@ public class MessageUtil {
|
||||
messageClass = EventType.valueOf(type.toLowerCase())
|
||||
.getEventClass();
|
||||
}
|
||||
XStream xstream = new XStream();
|
||||
xstream.ignoreUnknownElements();
|
||||
xstream.autodetectAnnotations(true);
|
||||
XStream xstream = XStream.get();
|
||||
xstream.processAnnotations(messageClass);
|
||||
xstream.alias("xml", messageClass);
|
||||
return xstream.fromXML(xmlMsg, messageClass);
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.foxinmy.weixin4j.xml;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import com.thoughtworks.xstream.converters.MarshallingContext;
|
||||
import com.thoughtworks.xstream.converters.collections.MapConverter;
|
||||
import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
||||
import com.thoughtworks.xstream.mapper.Mapper;
|
||||
|
||||
public class Map2ObjectConverter extends MapConverter {
|
||||
|
||||
public Map2ObjectConverter(Mapper mapper) {
|
||||
super(mapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void marshal(Object source, HierarchicalStreamWriter writer,
|
||||
MarshallingContext context) {
|
||||
Map<?, ?> map = (Map<?, ?>) source;
|
||||
for (Iterator<?> iterator = map.entrySet().iterator(); iterator
|
||||
.hasNext();) {
|
||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) iterator.next();
|
||||
ExtendedHierarchicalStreamWriterHelper.startNode(writer, entry
|
||||
.getKey().toString(), entry.getClass());
|
||||
writer.setValue(entry.getValue().toString());
|
||||
writer.endNode();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,9 +29,11 @@ public class XStream extends com.thoughtworks.xstream.XStream {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public XStream(HierarchicalStreamDriver hierarchicalStreamDriver) {
|
||||
super(hierarchicalStreamDriver);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T fromXML(String xml, Class<T> t) {
|
||||
return (T) super.fromXML(xml);
|
||||
@@ -41,4 +43,11 @@ public class XStream extends com.thoughtworks.xstream.XStream {
|
||||
public <T> T fromXML(InputStream inputStream, Class<T> t) {
|
||||
return (T) super.fromXML(inputStream);
|
||||
}
|
||||
|
||||
public static XStream get() {
|
||||
XStream xstream = new XStream();
|
||||
xstream.ignoreUnknownElements();
|
||||
xstream.autodetectAnnotations(true);
|
||||
return xstream;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user