big update:去除被动消息实体、commons包、dom4j包
This commit is contained in:
@@ -47,30 +47,15 @@
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${commons.lang.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>${fastjson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dom4j</groupId>
|
||||
<artifactId>dom4j</artifactId>
|
||||
<version>${dom4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
<version>${jedis.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>${commons.codec.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -7,7 +7,6 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.Consts;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpEntity;
|
||||
@@ -36,7 +35,9 @@ import org.apache.http.util.EntityUtils;
|
||||
|
||||
import com.alibaba.fastjson.JSONException;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.util.ErrorUtil;
|
||||
import com.foxinmy.weixin4j.util.MapUtil;
|
||||
import com.foxinmy.weixin4j.util.StringUtil;
|
||||
import com.thoughtworks.xstream.mapper.CannotResolveClassException;
|
||||
|
||||
/**
|
||||
@@ -237,8 +238,9 @@ public class HttpRequest {
|
||||
JsonResult jsonResult = response.getAsJsonResult();
|
||||
response.setJsonResult(true);
|
||||
if (jsonResult.getCode() != 0) {
|
||||
if (StringUtils.isBlank(jsonResult.getDesc())) {
|
||||
jsonResult = response.getTextError(jsonResult.getCode());
|
||||
if (StringUtil.isBlank(jsonResult.getDesc())) {
|
||||
jsonResult.setDesc(ErrorUtil.getText(Integer
|
||||
.toString(jsonResult.getCode())));
|
||||
}
|
||||
throw new WeixinException(Integer.toString(jsonResult.getCode()),
|
||||
jsonResult.getDesc());
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
package com.foxinmy.weixin4j.http;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentException;
|
||||
import org.dom4j.Node;
|
||||
import org.dom4j.io.SAXReader;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
@@ -67,65 +60,6 @@ public class Response {
|
||||
return XmlStream.get(text, XmlResult.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* <a href=
|
||||
* "http://mp.weixin.qq.com/wiki/17/fa4e1434e57290788bde25603fa2fcbd.html"
|
||||
* >全局返回码</a> {"errcode":45009,"errmsg":"api freq out of limit"}
|
||||
*
|
||||
* @return
|
||||
* @throws DocumentException
|
||||
*/
|
||||
public JsonResult getTextError(int code) {
|
||||
JsonResult result = new JsonResult();
|
||||
result.setCode(code);
|
||||
SAXReader reader = new SAXReader();
|
||||
Document doc = null;
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = Response.class.getResourceAsStream("error.xml");
|
||||
doc = reader.read(is);
|
||||
Node node = doc.getRootElement().selectSingleNode(
|
||||
String.format("error/code[text()=%d]", code));
|
||||
if (node != null) {
|
||||
node = node.getParent();
|
||||
String desc = null;
|
||||
Node _node = node.selectSingleNode("desc");
|
||||
if (_node != null) {
|
||||
desc = _node.getStringValue();
|
||||
}
|
||||
String text = null;
|
||||
_node = node.selectSingleNode("text");
|
||||
if (_node != null) {
|
||||
text = _node.getStringValue();
|
||||
}
|
||||
if (StringUtils.isBlank(desc) && StringUtils.isNotBlank(text)) {
|
||||
desc = text;
|
||||
}
|
||||
if (StringUtils.isBlank(text) && StringUtils.isNotBlank(desc)) {
|
||||
text = desc;
|
||||
}
|
||||
result.setDesc(desc);
|
||||
result.setText(text);
|
||||
} else {
|
||||
result.setDesc("unknown error");
|
||||
result.setText("未知错误");
|
||||
}
|
||||
} catch (DocumentException e) {
|
||||
result.setDesc("unknown error");
|
||||
result.setText("未知错误");
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@@ -2,9 +2,8 @@ package com.foxinmy.weixin4j.http;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.util.StringUtil;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
@@ -53,7 +52,7 @@ public class XmlResult implements Serializable {
|
||||
}
|
||||
|
||||
public String getReturnMsg() {
|
||||
return StringUtils.isNotBlank(returnMsg) ? returnMsg : null;
|
||||
return StringUtil.isNotBlank(returnMsg) ? returnMsg : null;
|
||||
}
|
||||
|
||||
public void setReturnMsg(String returnMsg) {
|
||||
@@ -77,7 +76,7 @@ public class XmlResult implements Serializable {
|
||||
}
|
||||
|
||||
public String getErrCodeDes() {
|
||||
return StringUtils.isNotBlank(errCodeDes) ? errCodeDes : null;
|
||||
return StringUtil.isNotBlank(errCodeDes) ? errCodeDes : null;
|
||||
}
|
||||
|
||||
public void setErrCodeDes(String errCodeDes) {
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
package com.foxinmy.weixin4j.message;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 消息基类
|
||||
*
|
||||
* @className BaseMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
*/
|
||||
public class BaseMessage implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 7761192742840031607L;
|
||||
|
||||
/**
|
||||
* 开发者微信号
|
||||
*/
|
||||
@XStreamAlias("ToUserName")
|
||||
private String toUserName;
|
||||
/**
|
||||
* 发送方账号 即用户的openid
|
||||
*/
|
||||
@XStreamAlias("FromUserName")
|
||||
private String fromUserName;
|
||||
/**
|
||||
* 消息创建时间 系统毫秒数
|
||||
*/
|
||||
@XStreamAlias("CreateTime")
|
||||
private long createTime = System.currentTimeMillis();
|
||||
/**
|
||||
* 消息类型
|
||||
*
|
||||
* @see com.foxinmy.weixin4j.type.MessageType
|
||||
*/
|
||||
@XStreamAlias("MsgType")
|
||||
private String msgType;
|
||||
/**
|
||||
* 消息ID 可用于排重
|
||||
*/
|
||||
@XStreamAlias("MsgId")
|
||||
private long msgId;
|
||||
/**
|
||||
* 企业号独有的应用ID
|
||||
*/
|
||||
@XStreamAlias("AgentID")
|
||||
private String agentId;
|
||||
|
||||
public BaseMessage() {
|
||||
|
||||
}
|
||||
|
||||
public BaseMessage(String msgType) {
|
||||
this.msgType = msgType;
|
||||
}
|
||||
|
||||
public BaseMessage(String toUserName, String fromUserName) {
|
||||
this(null, toUserName, fromUserName);
|
||||
}
|
||||
|
||||
public BaseMessage(String msgType, String toUserName, String fromUserName) {
|
||||
this.msgType = msgType;
|
||||
this.toUserName = toUserName;
|
||||
this.fromUserName = fromUserName;
|
||||
}
|
||||
|
||||
public String getToUserName() {
|
||||
return toUserName;
|
||||
}
|
||||
|
||||
public void setToUserName(String toUserName) {
|
||||
this.toUserName = toUserName;
|
||||
}
|
||||
|
||||
public String getFromUserName() {
|
||||
return fromUserName;
|
||||
}
|
||||
|
||||
public void setFromUserName(String fromUserName) {
|
||||
this.fromUserName = fromUserName;
|
||||
}
|
||||
|
||||
public long getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(long createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
public String getMsgType() {
|
||||
return msgType;
|
||||
}
|
||||
|
||||
public void setMsgType(String msgType) {
|
||||
this.msgType = msgType;
|
||||
}
|
||||
|
||||
public long getMsgId() {
|
||||
return msgId;
|
||||
}
|
||||
|
||||
public String getAgentId() {
|
||||
return agentId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((agentId == null) ? 0 : agentId.hashCode());
|
||||
result = prime * result + (int) (createTime ^ (createTime >>> 32));
|
||||
result = prime * result
|
||||
+ ((fromUserName == null) ? 0 : fromUserName.hashCode());
|
||||
result = prime * result + (int) (msgId ^ (msgId >>> 32));
|
||||
result = prime * result + ((msgType == null) ? 0 : msgType.hashCode());
|
||||
result = prime * result
|
||||
+ ((toUserName == null) ? 0 : toUserName.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof BaseMessage) {
|
||||
return ((BaseMessage) obj).getMsgId() == msgId
|
||||
&& ((BaseMessage) obj).getCreateTime() == createTime;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "toUserName=" + toUserName + ", fromUserName=" + fromUserName
|
||||
+ ", createTime=" + createTime + ", msgType=" + msgType
|
||||
+ ", msgId=" + msgId + ", agentId=" + agentId;
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package com.foxinmy.weixin4j.message;
|
||||
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 图片消息
|
||||
*
|
||||
* @className ImageMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html#.E5.9B.BE.E7.89.87.E6.B6.88.E6.81.AF">订阅号、服务号的图片消息</a>
|
||||
* @see <a
|
||||
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E6%99%AE%E9%80%9A%E6%B6%88%E6%81%AF#image.E6.B6.88.E6.81.AF">企业号的图片消息</a>
|
||||
*/
|
||||
public class ImageMessage extends BaseMessage {
|
||||
|
||||
private static final long serialVersionUID = 8430800898756567016L;
|
||||
|
||||
public ImageMessage() {
|
||||
super(MessageType.image.name());
|
||||
}
|
||||
|
||||
/**
|
||||
* 图片链接
|
||||
*/
|
||||
@XStreamAlias("PicUrl")
|
||||
private String picUrl;
|
||||
/**
|
||||
* 图片消息媒体id,可以调用多媒体文件下载接口拉取数据。
|
||||
*/
|
||||
@XStreamAlias("MediaId")
|
||||
private String mediaId;
|
||||
|
||||
public String getPicUrl() {
|
||||
return picUrl;
|
||||
}
|
||||
|
||||
public String getMediaId() {
|
||||
return mediaId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ImageMessage [picUrl=" + picUrl + ", mediaId=" + mediaId + ", "
|
||||
+ super.toString() + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package com.foxinmy.weixin4j.message;
|
||||
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 链接消息
|
||||
*
|
||||
* @className LinkMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html#.E9.93.BE.E6.8E.A5.E6.B6.88.E6.81.AF">订阅号、服务号的链接消息</a>
|
||||
*/
|
||||
public class LinkMessage extends BaseMessage {
|
||||
|
||||
private static final long serialVersionUID = 754952745115497030L;
|
||||
|
||||
public LinkMessage() {
|
||||
super(MessageType.link.name());
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息标题
|
||||
*/
|
||||
@XStreamAlias("Title")
|
||||
private String title;
|
||||
/**
|
||||
* 消息描述
|
||||
*/
|
||||
@XStreamAlias("Description")
|
||||
private String description;
|
||||
/**
|
||||
* 消息链接
|
||||
*/
|
||||
@XStreamAlias("Url")
|
||||
private String url;
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LinkMessage [title=" + title + ", description=" + description
|
||||
+ ", url=" + url + ", " + super.toString() + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
package com.foxinmy.weixin4j.message;
|
||||
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 地理位置消息
|
||||
*
|
||||
* @className LocationMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html#.E5.9C.B0.E7.90.86.E4.BD.8D.E7.BD.AE.E6.B6.88.E6.81.AF">订阅号、服务号的地理位置消息</a>
|
||||
* @see <a
|
||||
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E6%99%AE%E9%80%9A%E6%B6%88%E6%81%AF#location.E6.B6.88.E6.81.AF">企业号的地理位置消息</a>
|
||||
*/
|
||||
public class LocationMessage extends BaseMessage {
|
||||
|
||||
private static final long serialVersionUID = 2866021596599237334L;
|
||||
|
||||
public LocationMessage() {
|
||||
super(MessageType.location.name());
|
||||
}
|
||||
|
||||
/**
|
||||
* 地理位置维度
|
||||
*/
|
||||
@XStreamAlias("Location_X")
|
||||
private double x;
|
||||
/**
|
||||
* 地理位置经度
|
||||
*/
|
||||
@XStreamAlias("Location_Y")
|
||||
private double y;
|
||||
/**
|
||||
* 地图缩放大小
|
||||
*/
|
||||
@XStreamAlias("Scale")
|
||||
private double scale;
|
||||
/**
|
||||
* 地理位置信息
|
||||
*/
|
||||
@XStreamAlias("Label")
|
||||
private String label;
|
||||
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public double getScale() {
|
||||
return scale;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LocationMessage [x=" + x + ", y=" + y + ", scale=" + scale
|
||||
+ ", label=" + label + ", " + super.toString() + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
普通消息
|
||||
-------
|
||||
|
||||
当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上。
|
||||
|
||||
微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次
|
||||
|
||||
关于重试的消息排重,推荐使用msgid排重。
|
||||
|
||||
假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。
|
||||
@@ -1,41 +0,0 @@
|
||||
package com.foxinmy.weixin4j.message;
|
||||
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 文本消息
|
||||
*
|
||||
* @className TextMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html#.E6.96.87.E6.9C.AC.E6.B6.88.E6.81.AF">订阅号、服务号的文本消息</a>
|
||||
* @see <a
|
||||
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E6%99%AE%E9%80%9A%E6%B6%88%E6%81%AF#text.E6.B6.88.E6.81.AF">企业号的文本消息</a>
|
||||
*/
|
||||
public class TextMessage extends BaseMessage {
|
||||
|
||||
private static final long serialVersionUID = -7018053906644190260L;
|
||||
|
||||
public TextMessage() {
|
||||
super(MessageType.text.name());
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息内容
|
||||
*/
|
||||
@XStreamAlias("Content")
|
||||
private String content;
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TextMessage [content=" + content + ", " + super.toString()
|
||||
+ "]";
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package com.foxinmy.weixin4j.message;
|
||||
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 视频消息
|
||||
*
|
||||
* @className VideoMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html#.E8.A7.86.E9.A2.91.E6.B6.88.E6.81.AF">订阅号、服务号的视频消息</a>
|
||||
* @see <a
|
||||
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E6%99%AE%E9%80%9A%E6%B6%88%E6%81%AF#video.E6.B6.88.E6.81.AF">企业号的视频消息</a>
|
||||
*/
|
||||
public class VideoMessage extends BaseMessage {
|
||||
|
||||
private static final long serialVersionUID = -1013075358679078381L;
|
||||
|
||||
public VideoMessage() {
|
||||
super(MessageType.video.name());
|
||||
}
|
||||
|
||||
/**
|
||||
* 视频消息媒体id,可以调用多媒体文件下载接口拉取数据。
|
||||
*/
|
||||
@XStreamAlias("MediaId")
|
||||
private String mediaId;
|
||||
/**
|
||||
* 视频消息缩略图的媒体id,可以调用多媒体文件下载接口拉取数据。
|
||||
*/
|
||||
@XStreamAlias("ThumbMediaId")
|
||||
private String thumbMediaId;
|
||||
|
||||
public String getMediaId() {
|
||||
return mediaId;
|
||||
}
|
||||
|
||||
public String getThumbMediaId() {
|
||||
return thumbMediaId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VideoMessage [mediaId=" + mediaId + ", thumbMediaId="
|
||||
+ thumbMediaId + ", " + super.toString() + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package com.foxinmy.weixin4j.message;
|
||||
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 语音消息
|
||||
* <p>
|
||||
* 开通语音识别功能,用户每次发送语音给公众号时,微信会在推送的语音消息XML数据包中,赋值到Recongnition字段.
|
||||
* </p>
|
||||
*
|
||||
* @className VoiceMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html#.E8.AF.AD.E9.9F.B3.E6.B6.88.E6.81.AF">订阅号、服务号的语音消息</a>
|
||||
* @see <a
|
||||
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E6%99%AE%E9%80%9A%E6%B6%88%E6%81%AF#voice.E6.B6.88.E6.81.AF">企业号的语音消息</a>
|
||||
*/
|
||||
public class VoiceMessage extends BaseMessage {
|
||||
|
||||
private static final long serialVersionUID = -7988380977182214003L;
|
||||
|
||||
public VoiceMessage() {
|
||||
super(MessageType.voice.name());
|
||||
}
|
||||
|
||||
/**
|
||||
* 语音消息媒体id,可以调用多媒体文件下载接口拉取数据。
|
||||
*/
|
||||
@XStreamAlias("MediaId")
|
||||
private String mediaId;
|
||||
/**
|
||||
* 语音格式,如amr,speex等
|
||||
*/
|
||||
@XStreamAlias("Format")
|
||||
private String format;
|
||||
/**
|
||||
* 语音识别结果,UTF8编码
|
||||
*/
|
||||
@XStreamAlias("Recognition")
|
||||
private String recognition;
|
||||
|
||||
public String getRecognition() {
|
||||
return recognition;
|
||||
}
|
||||
|
||||
public String getMediaId() {
|
||||
return mediaId;
|
||||
}
|
||||
|
||||
public String getFormat() {
|
||||
return format;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VoiceMessage [mediaId=" + mediaId + ", format=" + format
|
||||
+ ", recognition=" + recognition + ", " + super.toString()
|
||||
+ "]";
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package com.foxinmy.weixin4j.message.event;
|
||||
|
||||
import com.foxinmy.weixin4j.message.BaseMessage;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 事件消息基类
|
||||
*
|
||||
* @className EventMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/9/981d772286d10d153a3dc4286c1ee5b5.html">订阅号、服务号的事件推送</a>
|
||||
* @see <a
|
||||
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E4%BA%8B%E4%BB%B6">企业号的事件消息</a>
|
||||
*/
|
||||
public class EventMessage extends BaseMessage {
|
||||
|
||||
private static final long serialVersionUID = 7703667223814088865L;
|
||||
|
||||
public EventMessage(String eventType) {
|
||||
super(MessageType.event.name());
|
||||
this.eventType = eventType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件类型
|
||||
*
|
||||
* @see com.foxinmy.weixin4j.type.EventType
|
||||
*/
|
||||
@XStreamAlias("Event")
|
||||
private String eventType;
|
||||
|
||||
public String getEventType() {
|
||||
return eventType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "eventType=" + eventType + ", " + super.toString();
|
||||
}
|
||||
}
|
||||
-59
@@ -1,59 +0,0 @@
|
||||
package com.foxinmy.weixin4j.message.event;
|
||||
|
||||
import com.foxinmy.weixin4j.type.EventType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 上报地理位置事件
|
||||
*
|
||||
* @className LocationEventMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/2/5baf56ce4947d35003b86a9805634b1e.html#.E4.B8.8A.E6.8A.A5.E5.9C.B0.E7.90.86.E4.BD.8D.E7.BD.AE.E4.BA.8B.E4.BB.B6">订阅号、服务号的上报地理位置事件</a>
|
||||
* @see <a
|
||||
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E4%BA%8B%E4%BB%B6#.E4.B8.8A.E6.8A.A5.E5.9C.B0.E7.90.86.E4.BD.8D.E7.BD.AE.E4.BA.8B.E4.BB.B6">企业号的上报地理位置事件</a>
|
||||
*/
|
||||
public class LocationEventMessage extends EventMessage {
|
||||
|
||||
private static final long serialVersionUID = -2030716800669824861L;
|
||||
|
||||
public LocationEventMessage() {
|
||||
super(EventType.location.name());
|
||||
}
|
||||
/**
|
||||
* 地理位置纬度
|
||||
*/
|
||||
@XStreamAlias("Latitude")
|
||||
private String latitude;
|
||||
/**
|
||||
* 地理位置经度
|
||||
*/
|
||||
@XStreamAlias("Longitude")
|
||||
private String longitude;
|
||||
/**
|
||||
* 地理位置精度
|
||||
*/
|
||||
@XStreamAlias("Precision")
|
||||
private String precision;
|
||||
|
||||
public String getLatitude() {
|
||||
return latitude;
|
||||
}
|
||||
|
||||
public String getLongitude() {
|
||||
return longitude;
|
||||
}
|
||||
|
||||
public String getPrecision() {
|
||||
return precision;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LocationEventMessage [latitude=" + latitude + ", longitude="
|
||||
+ longitude + ", precision=" + precision + ", "
|
||||
+ super.toString() + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package com.foxinmy.weixin4j.message.event;
|
||||
|
||||
import com.foxinmy.weixin4j.type.EventType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 自定义菜单事件(view|click)
|
||||
*
|
||||
* @className MenuEventMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/9/981d772286d10d153a3dc4286c1ee5b5.html#.E7.82.B9.E5.87.BB.E8.8F.9C.E5.8D.95.E6.8B.89.E5.8F.96.E6.B6.88.E6.81.AF.E6.97.B6.E7.9A.84.E4.BA.8B.E4.BB.B6.E6.8E.A8.E9.80.81">订阅号、服务号的菜单事件</a>
|
||||
* @see <a
|
||||
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E4%BA%8B%E4%BB%B6#.E4.B8.8A.E6.8A.A5.E8.8F.9C.E5.8D.95.E4.BA.8B.E4.BB.B6">企业号的菜单事件</a>
|
||||
*/
|
||||
public class MenuEventMessage extends EventMessage {
|
||||
|
||||
private static final long serialVersionUID = -1049672447995366063L;
|
||||
|
||||
public MenuEventMessage() {
|
||||
super(EventType.click.name());
|
||||
}
|
||||
|
||||
public MenuEventMessage(EventType eventType) {
|
||||
super(eventType.name());
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件KEY值,与自定义菜单接口中KEY值对应
|
||||
*/
|
||||
@XStreamAlias("EventKey")
|
||||
private String eventKey;
|
||||
|
||||
public String getEventKey() {
|
||||
return eventKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MenuEventMessage [eventKey=" + eventKey + ", "
|
||||
+ super.toString() + "]";
|
||||
}
|
||||
}
|
||||
-108
@@ -1,108 +0,0 @@
|
||||
package com.foxinmy.weixin4j.message.event;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.foxinmy.weixin4j.type.EventType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 弹出地理位置选择器的事件推送
|
||||
*
|
||||
* @className MenuLocationEventMessage
|
||||
* @author jy
|
||||
* @date 2014年9月30日
|
||||
* @since JDK 1.7
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/9/981d772286d10d153a3dc4286c1ee5b5.html#location_select.EF.BC.9A.E5.BC.B9.E5.87.BA.E5.9C.B0.E7.90.86.E4.BD.8D.E7.BD.AE.E9.80.89.E6.8B.A9.E5.99.A8.E7.9A.84.E4.BA.8B.E4.BB.B6.E6.8E.A8.E9.80.81">订阅号、服务号的弹出地理位置选择事件推送</a>
|
||||
* @see <a
|
||||
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E4%BA%8B%E4%BB%B6#.E5.BC.B9.E5.87.BA.E5.9C.B0.E7.90.86.E4.BD.8D.E7.BD.AE.E9.80.89.E6.8B.A9.E5.99.A8.E7.9A.84.E4.BA.8B.E4.BB.B6.E6.8E.A8.E9.80.81">企业号的弹出地理位置选择事件推送</a>
|
||||
*/
|
||||
public class MenuLocationEventMessage extends MenuEventMessage {
|
||||
|
||||
private static final long serialVersionUID = 145223888272819563L;
|
||||
|
||||
public MenuLocationEventMessage() {
|
||||
super(EventType.location_select);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送的位置消息
|
||||
*/
|
||||
@XStreamAlias("SendLocationInfo")
|
||||
private LocationInfo locationInfo;
|
||||
|
||||
public LocationInfo getLocationInfo() {
|
||||
return locationInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 地理位置信息
|
||||
* @className LocationInfo
|
||||
* @author jy
|
||||
* @date 2015年3月29日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public static class LocationInfo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 4904181780216819965L;
|
||||
|
||||
/**
|
||||
* 地理位置维度
|
||||
*/
|
||||
@XStreamAlias("Location_X")
|
||||
private double x;
|
||||
/**
|
||||
* 地理位置经度
|
||||
*/
|
||||
@XStreamAlias("Location_Y")
|
||||
private double y;
|
||||
/**
|
||||
* 地图缩放大小
|
||||
*/
|
||||
@XStreamAlias("Scale")
|
||||
private double scale;
|
||||
/**
|
||||
* 地理位置信息
|
||||
*/
|
||||
@XStreamAlias("Label")
|
||||
private String label;
|
||||
/**
|
||||
* 朋友圈POI的名字,可能为空
|
||||
*/
|
||||
@XStreamAlias("Poiname")
|
||||
private String poiname;
|
||||
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public double getScale() {
|
||||
return scale;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public String getPoiname() {
|
||||
return poiname;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LocationInfo [x=" + x + ", y=" + y + ", scale=" + scale
|
||||
+ ", label=" + label + ", poiname=" + poiname + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MenuLocationEventMessage [locationInfo=" + locationInfo + ", "
|
||||
+ super.toString() + "]";
|
||||
}
|
||||
}
|
||||
-103
@@ -1,103 +0,0 @@
|
||||
package com.foxinmy.weixin4j.message.event;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 弹出拍照或者相册发图的事件推送(pic_sysphoto|pic_photo_or_album|pic_weixin)
|
||||
*
|
||||
* @className MenuPhotoEventMessage
|
||||
* @author jy
|
||||
* @date 2014年9月30日
|
||||
* @since JDK 1.7
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/9/981d772286d10d153a3dc4286c1ee5b5.html#pic_sysphoto.EF.BC.9A.E5.BC.B9.E5.87.BA.E7.B3.BB.E7.BB.9F.E6.8B.8D.E7.85.A7.E5.8F.91.E5.9B.BE.E7.9A.84.E4.BA.8B.E4.BB.B6.E6.8E.A8.E9.80.81">订阅号、服务号的系统发图的事件推送</a>
|
||||
* @see <a
|
||||
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E4%BA%8B%E4%BB%B6#.E5.BC.B9.E5.87.BA.E7.B3.BB.E7.BB.9F.E6.8B.8D.E7.85.A7.E5.8F.91.E5.9B.BE.E7.9A.84.E4.BA.8B.E4.BB.B6.E6.8E.A8.E9.80.81">企业号的系统发图的事件推送</a>
|
||||
*/
|
||||
public class MenuPhotoEventMessage extends MenuEventMessage {
|
||||
|
||||
private static final long serialVersionUID = 3142350663022709730L;
|
||||
|
||||
/**
|
||||
* 发送的图片信息
|
||||
*/
|
||||
@XStreamAlias("SendPicsInfo")
|
||||
private PictureInfo pictureInfo;
|
||||
|
||||
public PictureInfo getPictureInfo() {
|
||||
return pictureInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 图片信息
|
||||
*
|
||||
* @className PictureInfo
|
||||
* @author jy
|
||||
* @date 2015年3月29日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public static class PictureInfo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -3361375879168233258L;
|
||||
|
||||
/**
|
||||
* 发送的图片数量
|
||||
*/
|
||||
@XStreamAlias("Count")
|
||||
private int count;
|
||||
/**
|
||||
* 图片列表
|
||||
*/
|
||||
@XStreamAlias("PicList")
|
||||
private List<PictureItem> items;
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public List<PictureItem> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PictureInfo [count=" + count + ", items=" + items + "]";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 图片
|
||||
*
|
||||
* @className PictureItem
|
||||
* @author jy
|
||||
* @date 2015年3月29日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
@XStreamAlias("item")
|
||||
public static class PictureItem implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -7636697449096645590L;
|
||||
|
||||
/**
|
||||
* 图片的MD5值,开发者若需要,可用于验证接收到图片
|
||||
*/
|
||||
@XStreamAlias("PicMd5Sum")
|
||||
private String md5;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PictureItem [md5=" + md5 + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MenuPhotoEventMessage [pictureInfo=" + pictureInfo + ", "
|
||||
+ super.toString() + "]";
|
||||
}
|
||||
}
|
||||
-75
@@ -1,75 +0,0 @@
|
||||
package com.foxinmy.weixin4j.message.event;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 扫码推事件(scancode_push|scancode_waitmsg)
|
||||
*
|
||||
* @className MenuScanEventMessage
|
||||
* @author jy
|
||||
* @date 2014年9月30日
|
||||
* @since JDK 1.7
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/9/981d772286d10d153a3dc4286c1ee5b5.html#scancode_push.EF.BC.9A.E6.89.AB.E7.A0.81.E6.8E.A8.E4.BA.8B.E4.BB.B6.E7.9A.84.E4.BA.8B.E4.BB.B6.E6.8E.A8.E9.80.81">订阅号、服务号的扫码推事件</a>
|
||||
* @see <a
|
||||
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E4%BA%8B%E4%BB%B6#.E6.89.AB.E7.A0.81.E6.8E.A8.E4.BA.8B.E4.BB.B6.E7.9A.84.E4.BA.8B.E4.BB.B6.E6.8E.A8.E9.80.81">企业号的的扫码推事件</a>
|
||||
*/
|
||||
public class MenuScanEventMessage extends MenuEventMessage {
|
||||
|
||||
private static final long serialVersionUID = 3142350663022709730L;
|
||||
|
||||
/**
|
||||
* 扫描信息
|
||||
*/
|
||||
@XStreamAlias("ScanCodeInfo")
|
||||
private ScanInfo scanInfo;
|
||||
|
||||
public ScanInfo getScanInfo() {
|
||||
return scanInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫描信息
|
||||
*
|
||||
* @className ScanInfo
|
||||
* @author jy
|
||||
* @date 2015年3月29日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public static class ScanInfo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 2237570238164900421L;
|
||||
/**
|
||||
* 扫描类型,一般是qrcode
|
||||
*/
|
||||
@XStreamAlias("ScanType")
|
||||
private String type;
|
||||
/**
|
||||
* 扫描结果,即二维码对应的字符串信息
|
||||
*/
|
||||
@XStreamAlias("ScanResult")
|
||||
private String result;
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ScanInfo [type=" + type + ", result=" + result + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MenuScanEventMessage [scanInfo=" + scanInfo + ", "
|
||||
+ super.toString() + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
菜单事件消息
|
||||
|
||||
用户点击自定义菜单后,微信会把点击事件推送给开发者,请注意,点击菜单弹出子菜单,不会产生上报。请注意,第3个到第8个的所有事件,仅支持微信iPhone5.4.1以上版本,和Android5.4以上版本的微信用户,旧版本微信用户点击后将没有回应,开发者也不能正常接收到事件推送。
|
||||
@@ -22,6 +22,9 @@ public final class Consts {
|
||||
public static final String TLS = "TLS";
|
||||
public static final String X509 = "X.509";
|
||||
public static final String AES = "AES";
|
||||
public static final String MD5 = "MD5";
|
||||
public static final String SHA = "SHA";
|
||||
public static final String SHA1 = "SHA-1";
|
||||
public static final String PROTOCOL_FILE = "file";
|
||||
public static final String PROTOCOL_JAR = "jar";
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package com.foxinmy.weixin4j.token;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import redis.clients.jedis.Jedis;
|
||||
import redis.clients.jedis.JedisPool;
|
||||
import redis.clients.jedis.JedisPoolConfig;
|
||||
@@ -9,6 +7,7 @@ import redis.clients.jedis.exceptions.JedisException;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.model.Token;
|
||||
import com.foxinmy.weixin4j.util.StringUtil;
|
||||
|
||||
/**
|
||||
* 用REDIS保存TOKEN
|
||||
@@ -64,7 +63,7 @@ public class RedisTokenHolder implements TokenHolder {
|
||||
jedis = jedisPool.getResource();
|
||||
String cacheKey = tokenCreator.getCacheKey();
|
||||
String accessToken = jedis.get(cacheKey);
|
||||
if (StringUtils.isBlank(accessToken)) {
|
||||
if (StringUtil.isBlank(accessToken)) {
|
||||
token = tokenCreator.createToken();
|
||||
jedis.setex(cacheKey, (int) token.getExpiresIn(),
|
||||
token.getAccessToken());
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
package com.foxinmy.weixin4j.type;
|
||||
|
||||
/**
|
||||
* 事件类型
|
||||
*
|
||||
* @className EventType
|
||||
* @author jy
|
||||
* @date 2014年9月30日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public enum EventType {
|
||||
/**
|
||||
* 关注事件
|
||||
*
|
||||
*/
|
||||
subscribe,
|
||||
/**
|
||||
* 取消关注事件
|
||||
*
|
||||
*/
|
||||
unsubscribe,
|
||||
/**
|
||||
* 上报地理位置事件
|
||||
*
|
||||
* @see com.foxinmy.weixin4j.msg.event.LocationEventMessage
|
||||
*/
|
||||
location,
|
||||
/**
|
||||
* 菜单扫描事件
|
||||
*
|
||||
* @see com.foxinmy.weixin4j.msg.event.menu.MenuScanEventMessage
|
||||
*/
|
||||
scancode_push,
|
||||
/**
|
||||
* 菜单点击关键字事件
|
||||
*
|
||||
* @see com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage
|
||||
*/
|
||||
view,
|
||||
/**
|
||||
* 菜单点击链接事件
|
||||
*
|
||||
* @see com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage
|
||||
*/
|
||||
click,
|
||||
/**
|
||||
* 菜单扫描并调出等待界面事件
|
||||
*
|
||||
* @see com.foxinmy.weixin4j.msg.event.menu.MenuScanEventMessage
|
||||
*/
|
||||
scancode_waitmsg,
|
||||
/**
|
||||
* 菜单弹出拍照事件
|
||||
*
|
||||
* @see com.foxinmy.weixin4j.msg.event.menu.MenuPhotoEventMessage
|
||||
*/
|
||||
pic_sysphoto,
|
||||
/**
|
||||
* 菜单弹出发图事件
|
||||
*
|
||||
* @see com.foxinmy.weixin4j.msg.event.menu.MenuPhotoEventMessage
|
||||
*/
|
||||
pic_photo_or_album,
|
||||
/**
|
||||
* 菜单弹出发图事件
|
||||
*
|
||||
* @see com.foxinmy.weixin4j.msg.event.menu.MenuPhotoEventMessage
|
||||
*/
|
||||
pic_weixin,
|
||||
/**
|
||||
* 菜单发送地理位置事件
|
||||
*
|
||||
* @see com.foxinmy.weixin4j.msg.event.menu.MenuLocationEventMessage
|
||||
*/
|
||||
location_select;
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import com.alibaba.fastjson.JSON;
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
|
||||
/**
|
||||
* 商户配置工具类
|
||||
* 公众号配置
|
||||
*
|
||||
* @className ConfigUtil
|
||||
* @author jy
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.foxinmy.weixin4j.util;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import com.foxinmy.weixin4j.model.Consts;
|
||||
|
||||
/**
|
||||
* 签名工具类
|
||||
*
|
||||
* @className DigestUtil
|
||||
* @author jy
|
||||
* @date 2015年5月6日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public final class DigestUtil {
|
||||
|
||||
private static MessageDigest getDigest(final String algorithm) {
|
||||
try {
|
||||
return MessageDigest.getInstance(algorithm);
|
||||
} catch (final NoSuchAlgorithmException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SHA1签名
|
||||
*
|
||||
* @param content
|
||||
* 待签名字符串
|
||||
* @return 签名后的字符串
|
||||
*/
|
||||
public static String SHA1(String content) {
|
||||
byte[] data = StringUtil.getBytesUtf8(content);
|
||||
return HexUtil.encodeHexString(getDigest(Consts.SHA1).digest(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* SHA签名
|
||||
*
|
||||
* @param content
|
||||
* 待签名字符串
|
||||
* @return 签名后的字符串
|
||||
*/
|
||||
public static String SHA(String content) {
|
||||
byte[] data = StringUtil.getBytesUtf8(content);
|
||||
return HexUtil.encodeHexString(getDigest(Consts.SHA).digest(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* MD5签名
|
||||
*
|
||||
* @param content
|
||||
* 待签名字符串
|
||||
* @return 签名后的字符串
|
||||
*/
|
||||
public static String MD5(String content) {
|
||||
byte[] data = StringUtil.getBytesUtf8(content);
|
||||
return HexUtil.encodeHexString(getDigest(Consts.MD5).digest(data));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package com.foxinmy.weixin4j.util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
import com.foxinmy.weixin4j.http.Response;
|
||||
|
||||
/**
|
||||
* 接口调用错误获取
|
||||
*
|
||||
* @className ErrorUtil
|
||||
* @author jy
|
||||
* @date 2015年5月12日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public final class ErrorUtil {
|
||||
private static byte[] errorXmlByteArray;
|
||||
private final static Map<String, String> errorCacheMap;
|
||||
static {
|
||||
errorCacheMap = new HashMap<String, String>();
|
||||
try {
|
||||
errorXmlByteArray = IOUtil.toByteArray(Response.class
|
||||
.getResourceAsStream("error.xml"));
|
||||
} catch (IOException e) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ErrorTextHandler extends DefaultHandler {
|
||||
|
||||
private final String code;
|
||||
|
||||
public ErrorTextHandler(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
private String text;
|
||||
private boolean codeElement;
|
||||
private boolean textElement;
|
||||
private boolean findElement;
|
||||
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName,
|
||||
Attributes attributes) throws SAXException {
|
||||
codeElement = qName.equalsIgnoreCase("code");
|
||||
textElement = qName.equalsIgnoreCase("text");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName)
|
||||
throws SAXException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters(char[] ch, int start, int length)
|
||||
throws SAXException {
|
||||
String _text = new String(ch, start, length);
|
||||
if (codeElement && _text.equalsIgnoreCase(code)) {
|
||||
findElement = true;
|
||||
} else if (textElement && findElement) {
|
||||
text = _text;
|
||||
throw new SAXException("ENOUGH");
|
||||
}
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return StringUtil.isBlank(text) ? "未知错误" : text;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getText(String code) throws RuntimeException {
|
||||
String text = errorCacheMap.get(code);
|
||||
if (StringUtil.isBlank(text)) {
|
||||
ErrorTextHandler textHandler = new ErrorTextHandler(code);
|
||||
try {
|
||||
XMLReader xmlReader = XMLReaderFactory.createXMLReader();
|
||||
xmlReader.setContentHandler(textHandler);
|
||||
xmlReader.parse(new InputSource(new ByteArrayInputStream(
|
||||
errorXmlByteArray)));
|
||||
text = textHandler.getText();
|
||||
errorCacheMap.put(code, text);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (SAXException e) {
|
||||
text = textHandler.getText();
|
||||
errorCacheMap.put(code, text);
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(getText("40001"));
|
||||
System.out.println(getText("40001"));
|
||||
System.out.println(getText("1234"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.foxinmy.weixin4j.util;
|
||||
|
||||
public final class HexUtil {
|
||||
/**
|
||||
* Used to build output as Hex
|
||||
*/
|
||||
private static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5',
|
||||
'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
||||
|
||||
/**
|
||||
* Used to build output as Hex
|
||||
*/
|
||||
private static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5',
|
||||
'6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
|
||||
private static char[] encodeHex(final byte[] data, final char[] toDigits) {
|
||||
final int l = data.length;
|
||||
final char[] out = new char[l << 1];
|
||||
// two characters form the hex value.
|
||||
for (int i = 0, j = 0; i < l; i++) {
|
||||
out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
|
||||
out[j++] = toDigits[0x0F & data[i]];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
public static String encodeHexString(final byte[] data) {
|
||||
return new String(encodeHex(data, true));
|
||||
}
|
||||
|
||||
public static char[] encodeHex(final byte[] data, final boolean toLowerCase) {
|
||||
return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.Consts;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
@@ -65,7 +64,7 @@ public class MapUtil {
|
||||
try {
|
||||
if (encoder && lowerCase) {
|
||||
for (Map.Entry<String, String> entry : set) {
|
||||
if (StringUtils.isBlank(entry.getValue())) {
|
||||
if (StringUtil.isBlank(entry.getValue())) {
|
||||
continue;
|
||||
}
|
||||
sb.append(entry.getKey().toLowerCase())
|
||||
@@ -75,7 +74,7 @@ public class MapUtil {
|
||||
}
|
||||
} else if (encoder) {
|
||||
for (Map.Entry<String, String> entry : set) {
|
||||
if (StringUtils.isBlank(entry.getValue())) {
|
||||
if (StringUtil.isBlank(entry.getValue())) {
|
||||
continue;
|
||||
}
|
||||
sb.append(entry.getKey())
|
||||
@@ -85,7 +84,7 @@ public class MapUtil {
|
||||
}
|
||||
} else if (lowerCase) {
|
||||
for (Map.Entry<String, String> entry : set) {
|
||||
if (StringUtils.isBlank(entry.getValue())) {
|
||||
if (StringUtil.isBlank(entry.getValue())) {
|
||||
continue;
|
||||
}
|
||||
sb.append(entry.getKey().toLowerCase()).append("=")
|
||||
@@ -93,7 +92,7 @@ public class MapUtil {
|
||||
}
|
||||
} else {
|
||||
for (Map.Entry<String, String> entry : set) {
|
||||
if (StringUtils.isBlank(entry.getValue())) {
|
||||
if (StringUtil.isBlank(entry.getValue())) {
|
||||
continue;
|
||||
}
|
||||
sb.append(entry.getKey()).append("=")
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
package com.foxinmy.weixin4j.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.model.Consts;
|
||||
|
||||
/**
|
||||
* 消息工具类
|
||||
*
|
||||
* @className MessageUtil
|
||||
* @author jy
|
||||
* @date 2014年10月31日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class MessageUtil {
|
||||
|
||||
/**
|
||||
* 验证微信签名
|
||||
*
|
||||
* @param signature
|
||||
* 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数
|
||||
* @return 开发者通过检验signature对请求进行相关校验。若确认此次GET请求来自微信服务器
|
||||
* 请原样返回echostr参数内容,则接入生效 成为开发者成功,否则接入失败
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/0/61c3a8b9d50ac74f18bdf2e54ddfc4e0.html">接入指南</a>
|
||||
*/
|
||||
public static String signature(String... para) {
|
||||
Arrays.sort(para);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String str : para) {
|
||||
sb.append(str);
|
||||
}
|
||||
return DigestUtils.sha1Hex(sb.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 对xml消息加密
|
||||
*
|
||||
* @param appId 应用ID
|
||||
* @param encodingAesKey
|
||||
* 加密密钥
|
||||
* @param xmlContent
|
||||
* 原始消息体
|
||||
* @return aes加密后的消息体
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public static String aesEncrypt(String appId, String encodingAesKey,
|
||||
String xmlContent) throws WeixinException {
|
||||
byte[] randomBytes = RandomUtil.generateString(16).getBytes(
|
||||
org.apache.http.Consts.UTF_8);
|
||||
byte[] xmlBytes = xmlContent.getBytes(org.apache.http.Consts.UTF_8);
|
||||
int xmlLength = xmlBytes.length;
|
||||
byte[] orderBytes = new byte[4];
|
||||
orderBytes[3] = (byte) (xmlLength & 0xFF);
|
||||
orderBytes[2] = (byte) (xmlLength >> 8 & 0xFF);
|
||||
orderBytes[1] = (byte) (xmlLength >> 16 & 0xFF);
|
||||
orderBytes[0] = (byte) (xmlLength >> 24 & 0xFF);
|
||||
byte[] appidBytes = appId.getBytes(org.apache.http.Consts.UTF_8);
|
||||
int byteLength = randomBytes.length + xmlLength + orderBytes.length
|
||||
+ appidBytes.length;
|
||||
// ... + pad: 使用自定义的填充方式对明文进行补位填充
|
||||
byte[] padBytes = PKCS7Encoder.encode(byteLength);
|
||||
// random + endian + xml + appid + pad 获得最终的字节流
|
||||
byte[] unencrypted = new byte[byteLength + padBytes.length];
|
||||
byteLength = 0;
|
||||
// src:源数组;srcPos:源数组要复制的起始位置;dest:目的数组;destPos:目的数组放置的起始位置;length:复制的长度
|
||||
System.arraycopy(randomBytes, 0, unencrypted, byteLength,
|
||||
randomBytes.length);
|
||||
byteLength += randomBytes.length;
|
||||
System.arraycopy(orderBytes, 0, unencrypted, byteLength,
|
||||
orderBytes.length);
|
||||
byteLength += orderBytes.length;
|
||||
System.arraycopy(xmlBytes, 0, unencrypted, byteLength, xmlBytes.length);
|
||||
byteLength += xmlBytes.length;
|
||||
System.arraycopy(appidBytes, 0, unencrypted, byteLength,
|
||||
appidBytes.length);
|
||||
byteLength += appidBytes.length;
|
||||
System.arraycopy(padBytes, 0, unencrypted, byteLength, padBytes.length);
|
||||
try {
|
||||
byte[] aesKey = Base64.decodeBase64(encodingAesKey + "=");
|
||||
// 设置加密模式为AES的CBC模式
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
|
||||
SecretKeySpec keySpec = new SecretKeySpec(aesKey, Consts.AES);
|
||||
IvParameterSpec iv = new IvParameterSpec(aesKey, 0, 16);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
|
||||
// 加密
|
||||
byte[] encrypted = cipher.doFinal(unencrypted);
|
||||
// 使用BASE64对加密后的字符串进行编码
|
||||
return Base64.encodeBase64String(encrypted);
|
||||
} catch (Exception e) {
|
||||
throw new WeixinException("-40006", "AES加密失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对AES消息解密
|
||||
*
|
||||
* @param appId
|
||||
* @param encodingAesKey
|
||||
* aes加密的密钥
|
||||
* @param encryptContent
|
||||
* 加密的消息体
|
||||
* @return 解密后的字符
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public static String aesDecrypt(String appId, String encodingAesKey,
|
||||
String encryptContent) throws WeixinException {
|
||||
byte[] aesKey = Base64.decodeBase64(encodingAesKey + "=");
|
||||
byte[] original;
|
||||
try {
|
||||
// 设置解密模式为AES的CBC模式
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
|
||||
SecretKeySpec key_spec = new SecretKeySpec(aesKey, Consts.AES);
|
||||
IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey,
|
||||
0, 16));
|
||||
cipher.init(Cipher.DECRYPT_MODE, key_spec, iv);
|
||||
// 使用BASE64对密文进行解码
|
||||
byte[] encrypted = Base64.decodeBase64(encryptContent);
|
||||
// 解密
|
||||
original = cipher.doFinal(encrypted);
|
||||
} catch (Exception e) {
|
||||
throw new WeixinException("-40007", "AES解密失败:" + e.getMessage());
|
||||
}
|
||||
String xmlContent, fromAppId;
|
||||
try {
|
||||
// 去除补位字符
|
||||
byte[] bytes = PKCS7Encoder.decode(original);
|
||||
// 获取表示xml长度的字节数组
|
||||
byte[] lengthByte = Arrays.copyOfRange(bytes, 16, 20);
|
||||
// 获取xml消息主体的长度(byte[]2int)
|
||||
// http://my.oschina.net/u/169390/blog/97495
|
||||
int xmlLength = lengthByte[3] & 0xff | (lengthByte[2] & 0xff) << 8
|
||||
| (lengthByte[1] & 0xff) << 16
|
||||
| (lengthByte[0] & 0xff) << 24;
|
||||
xmlContent = new String(Arrays.copyOfRange(bytes, 20,
|
||||
20 + xmlLength), org.apache.http.Consts.UTF_8);
|
||||
fromAppId = new String(Arrays.copyOfRange(bytes, 20 + xmlLength,
|
||||
bytes.length), org.apache.http.Consts.UTF_8);
|
||||
} catch (Exception e) {
|
||||
throw new WeixinException("-40008", "公众平台发送的xml不合法:"
|
||||
+ e.getMessage());
|
||||
}
|
||||
// 校验appId是否一致
|
||||
if (!fromAppId.trim().equals(appId)) {
|
||||
throw new WeixinException("-40005", "校验AppID失败");
|
||||
}
|
||||
return xmlContent;
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,6 @@ import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* @title 反射工具类
|
||||
* @description 提供对类,字段的反射调用
|
||||
@@ -92,13 +90,13 @@ public class ReflectionUtil {
|
||||
Method getterMethod = null;
|
||||
String propertyNa = null;
|
||||
if (propertyName.contains(".")) {
|
||||
propertyNa = StringUtils.substringBefore(propertyName, ".");
|
||||
getterMethodName = "get" + StringUtils.capitalize(propertyNa);
|
||||
propertyNa = StringUtil.substringBefore(propertyName, ".");
|
||||
getterMethodName = "get" + StringUtil.capitalize(propertyNa);
|
||||
getterMethod = object.getClass().getMethod(getterMethodName);
|
||||
return invokeGetterMethod(getterMethod.invoke(object),
|
||||
StringUtils.substringAfter(propertyName, "."));
|
||||
StringUtil.substringAfter(propertyName, "."));
|
||||
} else {
|
||||
getterMethodName = "get" + StringUtils.capitalize(propertyName);
|
||||
getterMethodName = "get" + StringUtil.capitalize(propertyName);
|
||||
getterMethod = object.getClass().getMethod(getterMethodName);
|
||||
return getterMethod.invoke(object);
|
||||
}
|
||||
@@ -140,7 +138,7 @@ public class ReflectionUtil {
|
||||
*/
|
||||
public static void invokeSetterMethod(Object object, String propertyName,
|
||||
Object propertyValue, Class<?> setterMethodClass) {
|
||||
String setterMethodName = "set" + StringUtils.capitalize(propertyName);
|
||||
String setterMethodName = "set" + StringUtil.capitalize(propertyName);
|
||||
try {
|
||||
Method setterMethod = object.getClass().getMethod(setterMethodName,
|
||||
setterMethodClass);
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
package com.foxinmy.weixin4j.util;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Iterator;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.foxinmy.weixin4j.model.Consts;
|
||||
|
||||
public final class StringUtil {
|
||||
|
||||
public static final String EMPTY = "";
|
||||
public static final int INDEX_NOT_FOUND = -1;
|
||||
|
||||
private static byte[] getBytes(final String content, final Charset charset) {
|
||||
if (content == null) {
|
||||
return null;
|
||||
}
|
||||
return content.getBytes(charset);
|
||||
}
|
||||
|
||||
private static String newString(final byte[] bytes, final Charset charset) {
|
||||
return bytes == null ? null : new String(bytes, charset);
|
||||
}
|
||||
|
||||
public static byte[] getBytesUtf8(final String content) {
|
||||
return getBytes(content, Consts.UTF_8);
|
||||
}
|
||||
|
||||
public static String newStringUtf8(final byte[] bytes) {
|
||||
return newString(bytes, Consts.UTF_8);
|
||||
}
|
||||
|
||||
public static boolean isEmpty(final CharSequence cs) {
|
||||
return cs == null || cs.length() == 0;
|
||||
}
|
||||
|
||||
public static boolean isBlank(final CharSequence cs) {
|
||||
int strLen;
|
||||
if (cs == null || (strLen = cs.length()) == 0) {
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < strLen; i++) {
|
||||
if (Character.isWhitespace(cs.charAt(i)) == false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isNotBlank(final CharSequence cs) {
|
||||
return !isBlank(cs);
|
||||
}
|
||||
|
||||
public static String capitalize(final String str) {
|
||||
int strLen;
|
||||
if (str == null || (strLen = str.length()) == 0) {
|
||||
return str;
|
||||
}
|
||||
|
||||
char firstChar = str.charAt(0);
|
||||
if (Character.isTitleCase(firstChar)) {
|
||||
// already capitalized
|
||||
return str;
|
||||
}
|
||||
return new StringBuilder(strLen)
|
||||
.append(Character.toTitleCase(firstChar))
|
||||
.append(str.substring(1)).toString();
|
||||
}
|
||||
|
||||
public static String substringBefore(final String str,
|
||||
final String separator) {
|
||||
if (isEmpty(str) || separator == null) {
|
||||
return str;
|
||||
}
|
||||
if (separator.isEmpty()) {
|
||||
return EMPTY;
|
||||
}
|
||||
final int pos = str.indexOf(separator);
|
||||
if (pos == INDEX_NOT_FOUND) {
|
||||
return str;
|
||||
}
|
||||
return str.substring(0, pos);
|
||||
}
|
||||
|
||||
public static String substringAfter(final String str, final String separator) {
|
||||
if (isEmpty(str)) {
|
||||
return str;
|
||||
}
|
||||
if (separator == null) {
|
||||
return EMPTY;
|
||||
}
|
||||
final int pos = str.indexOf(separator);
|
||||
if (pos == INDEX_NOT_FOUND) {
|
||||
return EMPTY;
|
||||
}
|
||||
return str.substring(pos + separator.length());
|
||||
}
|
||||
|
||||
public static String join(final Object[] array, final char separator) {
|
||||
if (array == null) {
|
||||
return null;
|
||||
}
|
||||
return join(array, separator, 0, array.length);
|
||||
}
|
||||
|
||||
public static String join(final Object[] array, final char separator,
|
||||
final int startIndex, final int endIndex) {
|
||||
if (array == null) {
|
||||
return null;
|
||||
}
|
||||
final int noOfItems = endIndex - startIndex;
|
||||
if (noOfItems <= 0) {
|
||||
return EMPTY;
|
||||
}
|
||||
final StringBuilder buf = new StringBuilder(noOfItems * 16);
|
||||
for (int i = startIndex; i < endIndex; i++) {
|
||||
if (i > startIndex) {
|
||||
buf.append(separator);
|
||||
}
|
||||
if (array[i] != null) {
|
||||
buf.append(array[i]);
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public static String join(final Iterable<?> iterable, final char separator) {
|
||||
if (iterable == null) {
|
||||
return null;
|
||||
}
|
||||
return join(iterable.iterator(), separator);
|
||||
}
|
||||
|
||||
public static String join(final Iterator<?> iterator, final char separator) {
|
||||
|
||||
// handle null, zero and one elements before building a buffer
|
||||
if (iterator == null) {
|
||||
return null;
|
||||
}
|
||||
if (!iterator.hasNext()) {
|
||||
return EMPTY;
|
||||
}
|
||||
final Object first = iterator.next();
|
||||
if (!iterator.hasNext()) {
|
||||
String result = Objects.toString(first);
|
||||
return result;
|
||||
}
|
||||
|
||||
// two or more elements
|
||||
final StringBuilder buf = new StringBuilder(256); // Java default is 16,
|
||||
// probably too
|
||||
// small
|
||||
if (first != null) {
|
||||
buf.append(first);
|
||||
}
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
buf.append(separator);
|
||||
final Object obj = iterator.next();
|
||||
if (obj != null) {
|
||||
buf.append(obj);
|
||||
}
|
||||
}
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public static String join(final int[] array, final char separator) {
|
||||
if (array == null) {
|
||||
return null;
|
||||
}
|
||||
return join(array, separator, 0, array.length);
|
||||
}
|
||||
|
||||
public static String join(final int[] array, final char separator,
|
||||
final int startIndex, final int endIndex) {
|
||||
if (array == null) {
|
||||
return null;
|
||||
}
|
||||
final int noOfItems = endIndex - startIndex;
|
||||
if (noOfItems <= 0) {
|
||||
return EMPTY;
|
||||
}
|
||||
final StringBuilder buf = new StringBuilder(noOfItems * 16);
|
||||
for (int i = startIndex; i < endIndex; i++) {
|
||||
if (i > startIndex) {
|
||||
buf.append(separator);
|
||||
}
|
||||
buf.append(array[i]);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.foxinmy.weixin4j.util.StringUtil;
|
||||
import com.thoughtworks.xstream.converters.MarshallingContext;
|
||||
import com.thoughtworks.xstream.converters.UnmarshallingContext;
|
||||
import com.thoughtworks.xstream.converters.collections.MapConverter;
|
||||
@@ -50,7 +49,7 @@ public class Map2ObjectConverter extends MapConverter {
|
||||
continue;
|
||||
}
|
||||
String value = entry.getValue().toString();
|
||||
if (StringUtils.isBlank(value)) {
|
||||
if (StringUtil.isBlank(value)) {
|
||||
continue;
|
||||
}
|
||||
ExtendedHierarchicalStreamWriterHelper.startNode(writer, entry
|
||||
|
||||
Reference in New Issue
Block a user