big update:去除被动消息实体、commons包、dom4j包
This commit is contained in:
parent
165f4b3bb8
commit
3d0c3e2c9c
@ -271,8 +271,8 @@
|
|||||||
|
|
||||||
* 2015-05-07
|
* 2015-05-07
|
||||||
|
|
||||||
+**weixin4j-server**: 完成基本骨架
|
+ **weixin4j-server**: 完成基本骨架
|
||||||
|
|
||||||
* 2015-05-08
|
* 2015-05-08
|
||||||
|
|
||||||
+**weixin4j-server**: 完成消息分发器、消息处理器、消息拦截器的骨架
|
+ **weixin4j-server**: 完成消息分发器、消息处理器、消息拦截器的骨架
|
||||||
@ -47,30 +47,15 @@
|
|||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.commons</groupId>
|
|
||||||
<artifactId>commons-lang3</artifactId>
|
|
||||||
<version>${commons.lang.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba</groupId>
|
<groupId>com.alibaba</groupId>
|
||||||
<artifactId>fastjson</artifactId>
|
<artifactId>fastjson</artifactId>
|
||||||
<version>${fastjson.version}</version>
|
<version>${fastjson.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>dom4j</groupId>
|
|
||||||
<artifactId>dom4j</artifactId>
|
|
||||||
<version>${dom4j.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>redis.clients</groupId>
|
<groupId>redis.clients</groupId>
|
||||||
<artifactId>jedis</artifactId>
|
<artifactId>jedis</artifactId>
|
||||||
<version>${jedis.version}</version>
|
<version>${jedis.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>commons-codec</groupId>
|
|
||||||
<artifactId>commons-codec</artifactId>
|
|
||||||
<version>${commons.codec.version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
@ -7,7 +7,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.http.Consts;
|
import org.apache.http.Consts;
|
||||||
import org.apache.http.Header;
|
import org.apache.http.Header;
|
||||||
import org.apache.http.HttpEntity;
|
import org.apache.http.HttpEntity;
|
||||||
@ -36,7 +35,9 @@ import org.apache.http.util.EntityUtils;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.JSONException;
|
import com.alibaba.fastjson.JSONException;
|
||||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||||
|
import com.foxinmy.weixin4j.util.ErrorUtil;
|
||||||
import com.foxinmy.weixin4j.util.MapUtil;
|
import com.foxinmy.weixin4j.util.MapUtil;
|
||||||
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
import com.thoughtworks.xstream.mapper.CannotResolveClassException;
|
import com.thoughtworks.xstream.mapper.CannotResolveClassException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -237,8 +238,9 @@ public class HttpRequest {
|
|||||||
JsonResult jsonResult = response.getAsJsonResult();
|
JsonResult jsonResult = response.getAsJsonResult();
|
||||||
response.setJsonResult(true);
|
response.setJsonResult(true);
|
||||||
if (jsonResult.getCode() != 0) {
|
if (jsonResult.getCode() != 0) {
|
||||||
if (StringUtils.isBlank(jsonResult.getDesc())) {
|
if (StringUtil.isBlank(jsonResult.getDesc())) {
|
||||||
jsonResult = response.getTextError(jsonResult.getCode());
|
jsonResult.setDesc(ErrorUtil.getText(Integer
|
||||||
|
.toString(jsonResult.getCode())));
|
||||||
}
|
}
|
||||||
throw new WeixinException(Integer.toString(jsonResult.getCode()),
|
throw new WeixinException(Integer.toString(jsonResult.getCode()),
|
||||||
jsonResult.getDesc());
|
jsonResult.getDesc());
|
||||||
|
|||||||
@ -1,14 +1,7 @@
|
|||||||
package com.foxinmy.weixin4j.http;
|
package com.foxinmy.weixin4j.http;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
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.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.alibaba.fastjson.TypeReference;
|
import com.alibaba.fastjson.TypeReference;
|
||||||
@ -67,65 +60,6 @@ public class Response {
|
|||||||
return XmlStream.get(text, XmlResult.class);
|
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) {
|
public void setText(String text) {
|
||||||
this.text = text;
|
this.text = text;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,9 +2,8 @@ package com.foxinmy.weixin4j.http;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.annotation.JSONField;
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -53,7 +52,7 @@ public class XmlResult implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getReturnMsg() {
|
public String getReturnMsg() {
|
||||||
return StringUtils.isNotBlank(returnMsg) ? returnMsg : null;
|
return StringUtil.isNotBlank(returnMsg) ? returnMsg : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setReturnMsg(String returnMsg) {
|
public void setReturnMsg(String returnMsg) {
|
||||||
@ -77,7 +76,7 @@ public class XmlResult implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getErrCodeDes() {
|
public String getErrCodeDes() {
|
||||||
return StringUtils.isNotBlank(errCodeDes) ? errCodeDes : null;
|
return StringUtil.isNotBlank(errCodeDes) ? errCodeDes : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setErrCodeDes(String errCodeDes) {
|
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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() + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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() + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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() + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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 TLS = "TLS";
|
||||||
public static final String X509 = "X.509";
|
public static final String X509 = "X.509";
|
||||||
public static final String AES = "AES";
|
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_FILE = "file";
|
||||||
public static final String PROTOCOL_JAR = "jar";
|
public static final String PROTOCOL_JAR = "jar";
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
package com.foxinmy.weixin4j.token;
|
package com.foxinmy.weixin4j.token;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
import redis.clients.jedis.JedisPool;
|
import redis.clients.jedis.JedisPool;
|
||||||
import redis.clients.jedis.JedisPoolConfig;
|
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.exception.WeixinException;
|
||||||
import com.foxinmy.weixin4j.model.Token;
|
import com.foxinmy.weixin4j.model.Token;
|
||||||
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用REDIS保存TOKEN
|
* 用REDIS保存TOKEN
|
||||||
@ -64,7 +63,7 @@ public class RedisTokenHolder implements TokenHolder {
|
|||||||
jedis = jedisPool.getResource();
|
jedis = jedisPool.getResource();
|
||||||
String cacheKey = tokenCreator.getCacheKey();
|
String cacheKey = tokenCreator.getCacheKey();
|
||||||
String accessToken = jedis.get(cacheKey);
|
String accessToken = jedis.get(cacheKey);
|
||||||
if (StringUtils.isBlank(accessToken)) {
|
if (StringUtil.isBlank(accessToken)) {
|
||||||
token = tokenCreator.createToken();
|
token = tokenCreator.createToken();
|
||||||
jedis.setex(cacheKey, (int) token.getExpiresIn(),
|
jedis.setex(cacheKey, (int) token.getExpiresIn(),
|
||||||
token.getAccessToken());
|
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;
|
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商户配置工具类
|
* 公众号配置
|
||||||
*
|
*
|
||||||
* @className ConfigUtil
|
* @className ConfigUtil
|
||||||
* @author jy
|
* @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.Set;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.http.Consts;
|
import org.apache.http.Consts;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
@ -65,7 +64,7 @@ public class MapUtil {
|
|||||||
try {
|
try {
|
||||||
if (encoder && lowerCase) {
|
if (encoder && lowerCase) {
|
||||||
for (Map.Entry<String, String> entry : set) {
|
for (Map.Entry<String, String> entry : set) {
|
||||||
if (StringUtils.isBlank(entry.getValue())) {
|
if (StringUtil.isBlank(entry.getValue())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sb.append(entry.getKey().toLowerCase())
|
sb.append(entry.getKey().toLowerCase())
|
||||||
@ -75,7 +74,7 @@ public class MapUtil {
|
|||||||
}
|
}
|
||||||
} else if (encoder) {
|
} else if (encoder) {
|
||||||
for (Map.Entry<String, String> entry : set) {
|
for (Map.Entry<String, String> entry : set) {
|
||||||
if (StringUtils.isBlank(entry.getValue())) {
|
if (StringUtil.isBlank(entry.getValue())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sb.append(entry.getKey())
|
sb.append(entry.getKey())
|
||||||
@ -85,7 +84,7 @@ public class MapUtil {
|
|||||||
}
|
}
|
||||||
} else if (lowerCase) {
|
} else if (lowerCase) {
|
||||||
for (Map.Entry<String, String> entry : set) {
|
for (Map.Entry<String, String> entry : set) {
|
||||||
if (StringUtils.isBlank(entry.getValue())) {
|
if (StringUtil.isBlank(entry.getValue())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sb.append(entry.getKey().toLowerCase()).append("=")
|
sb.append(entry.getKey().toLowerCase()).append("=")
|
||||||
@ -93,7 +92,7 @@ public class MapUtil {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (Map.Entry<String, String> entry : set) {
|
for (Map.Entry<String, String> entry : set) {
|
||||||
if (StringUtils.isBlank(entry.getValue())) {
|
if (StringUtil.isBlank(entry.getValue())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sb.append(entry.getKey()).append("=")
|
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.ParameterizedType;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title 反射工具类
|
* @title 反射工具类
|
||||||
* @description 提供对类,字段的反射调用
|
* @description 提供对类,字段的反射调用
|
||||||
@ -92,13 +90,13 @@ public class ReflectionUtil {
|
|||||||
Method getterMethod = null;
|
Method getterMethod = null;
|
||||||
String propertyNa = null;
|
String propertyNa = null;
|
||||||
if (propertyName.contains(".")) {
|
if (propertyName.contains(".")) {
|
||||||
propertyNa = StringUtils.substringBefore(propertyName, ".");
|
propertyNa = StringUtil.substringBefore(propertyName, ".");
|
||||||
getterMethodName = "get" + StringUtils.capitalize(propertyNa);
|
getterMethodName = "get" + StringUtil.capitalize(propertyNa);
|
||||||
getterMethod = object.getClass().getMethod(getterMethodName);
|
getterMethod = object.getClass().getMethod(getterMethodName);
|
||||||
return invokeGetterMethod(getterMethod.invoke(object),
|
return invokeGetterMethod(getterMethod.invoke(object),
|
||||||
StringUtils.substringAfter(propertyName, "."));
|
StringUtil.substringAfter(propertyName, "."));
|
||||||
} else {
|
} else {
|
||||||
getterMethodName = "get" + StringUtils.capitalize(propertyName);
|
getterMethodName = "get" + StringUtil.capitalize(propertyName);
|
||||||
getterMethod = object.getClass().getMethod(getterMethodName);
|
getterMethod = object.getClass().getMethod(getterMethodName);
|
||||||
return getterMethod.invoke(object);
|
return getterMethod.invoke(object);
|
||||||
}
|
}
|
||||||
@ -140,7 +138,7 @@ public class ReflectionUtil {
|
|||||||
*/
|
*/
|
||||||
public static void invokeSetterMethod(Object object, String propertyName,
|
public static void invokeSetterMethod(Object object, String propertyName,
|
||||||
Object propertyValue, Class<?> setterMethodClass) {
|
Object propertyValue, Class<?> setterMethodClass) {
|
||||||
String setterMethodName = "set" + StringUtils.capitalize(propertyName);
|
String setterMethodName = "set" + StringUtil.capitalize(propertyName);
|
||||||
try {
|
try {
|
||||||
Method setterMethod = object.getClass().getMethod(setterMethodName,
|
Method setterMethod = object.getClass().getMethod(setterMethodName,
|
||||||
setterMethodClass);
|
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;
|
||||||
import java.util.Map.Entry;
|
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.MarshallingContext;
|
||||||
import com.thoughtworks.xstream.converters.UnmarshallingContext;
|
import com.thoughtworks.xstream.converters.UnmarshallingContext;
|
||||||
import com.thoughtworks.xstream.converters.collections.MapConverter;
|
import com.thoughtworks.xstream.converters.collections.MapConverter;
|
||||||
@ -50,7 +49,7 @@ public class Map2ObjectConverter extends MapConverter {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String value = entry.getValue().toString();
|
String value = entry.getValue().toString();
|
||||||
if (StringUtils.isBlank(value)) {
|
if (StringUtil.isBlank(value)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ExtendedHierarchicalStreamWriterHelper.startNode(writer, entry
|
ExtendedHierarchicalStreamWriterHelper.startNode(writer, entry
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-assembly-plugin</artifactId>
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
<finalName>weixin4j-mp-${project.version}</finalName>
|
<finalName>${project.name}-${project.version}</finalName>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
@ -42,11 +42,6 @@
|
|||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.jsoup</groupId>
|
|
||||||
<artifactId>jsoup</artifactId>
|
|
||||||
<version>${jsoup.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-api</artifactId>
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
|||||||
@ -7,8 +7,6 @@ import java.io.InputStream;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.TypeReference;
|
import com.alibaba.fastjson.TypeReference;
|
||||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||||
import com.foxinmy.weixin4j.http.Response;
|
import com.foxinmy.weixin4j.http.Response;
|
||||||
@ -19,6 +17,7 @@ import com.foxinmy.weixin4j.mp.payment.coupon.CouponDetail;
|
|||||||
import com.foxinmy.weixin4j.mp.payment.coupon.CouponResult;
|
import com.foxinmy.weixin4j.mp.payment.coupon.CouponResult;
|
||||||
import com.foxinmy.weixin4j.mp.payment.coupon.CouponStock;
|
import com.foxinmy.weixin4j.mp.payment.coupon.CouponStock;
|
||||||
import com.foxinmy.weixin4j.util.RandomUtil;
|
import com.foxinmy.weixin4j.util.RandomUtil;
|
||||||
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 代金券API
|
* 代金券API
|
||||||
@ -66,7 +65,7 @@ public class CouponApi extends MpApi {
|
|||||||
// openid记录数(目前支持num=1)
|
// openid记录数(目前支持num=1)
|
||||||
map.put("openid_count", "1");
|
map.put("openid_count", "1");
|
||||||
// 操作员帐号, 默认为商户号 可在商户平台配置操作员对应的api权限
|
// 操作员帐号, 默认为商户号 可在商户平台配置操作员对应的api权限
|
||||||
if (StringUtils.isBlank(opUserId)) {
|
if (StringUtil.isBlank(opUserId)) {
|
||||||
opUserId = weixinAccount.getMchId();
|
opUserId = weixinAccount.getMchId();
|
||||||
}
|
}
|
||||||
map.put("op_user_id", opUserId);
|
map.put("op_user_id", opUserId);
|
||||||
@ -158,10 +157,10 @@ public class CouponApi extends MpApi {
|
|||||||
map.put("appid", weixinAccount.getId());
|
map.put("appid", weixinAccount.getId());
|
||||||
map.put("mch_id", weixinAccount.getMchId());
|
map.put("mch_id", weixinAccount.getMchId());
|
||||||
map.put("nonce_str", RandomUtil.generateString(16));
|
map.put("nonce_str", RandomUtil.generateString(16));
|
||||||
if (StringUtils.isNotBlank(weixinAccount.getDeviceInfo())) {
|
if (StringUtil.isNotBlank(weixinAccount.getDeviceInfo())) {
|
||||||
map.put("device_info", weixinAccount.getDeviceInfo());
|
map.put("device_info", weixinAccount.getDeviceInfo());
|
||||||
}
|
}
|
||||||
if (StringUtils.isNotBlank(weixinAccount.getSubMchId())) {
|
if (StringUtil.isNotBlank(weixinAccount.getSubMchId())) {
|
||||||
map.put("sub_mch_id", weixinAccount.getSubMchId());
|
map.put("sub_mch_id", weixinAccount.getSubMchId());
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import java.io.IOException;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
|
||||||
import org.apache.http.entity.mime.content.ByteArrayBody;
|
import org.apache.http.entity.mime.content.ByteArrayBody;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
@ -21,6 +20,7 @@ import com.foxinmy.weixin4j.mp.model.CustomRecord;
|
|||||||
import com.foxinmy.weixin4j.mp.model.KfAccount;
|
import com.foxinmy.weixin4j.mp.model.KfAccount;
|
||||||
import com.foxinmy.weixin4j.mp.model.KfSession;
|
import com.foxinmy.weixin4j.mp.model.KfSession;
|
||||||
import com.foxinmy.weixin4j.token.TokenHolder;
|
import com.foxinmy.weixin4j.token.TokenHolder;
|
||||||
|
import com.foxinmy.weixin4j.util.DigestUtil;
|
||||||
import com.foxinmy.weixin4j.util.IOUtil;
|
import com.foxinmy.weixin4j.util.IOUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -136,7 +136,7 @@ public class CustomApi extends MpApi {
|
|||||||
JSONObject obj = new JSONObject();
|
JSONObject obj = new JSONObject();
|
||||||
obj.put("kf_account", id);
|
obj.put("kf_account", id);
|
||||||
obj.put("nickname", name);
|
obj.put("nickname", name);
|
||||||
obj.put("password", DigestUtils.md5Hex(pwd));
|
obj.put("password", DigestUtil.MD5(pwd));
|
||||||
String custom_add_uri = getRequestUri("custom_add_uri");
|
String custom_add_uri = getRequestUri("custom_add_uri");
|
||||||
Token token = tokenHolder.getToken();
|
Token token = tokenHolder.getToken();
|
||||||
Response response = request.post(
|
Response response = request.post(
|
||||||
@ -167,7 +167,7 @@ public class CustomApi extends MpApi {
|
|||||||
JSONObject obj = new JSONObject();
|
JSONObject obj = new JSONObject();
|
||||||
obj.put("kf_account", id);
|
obj.put("kf_account", id);
|
||||||
obj.put("nickname", name);
|
obj.put("nickname", name);
|
||||||
obj.put("password", DigestUtils.md5Hex(pwd));
|
obj.put("password", DigestUtil.MD5(pwd));
|
||||||
String custom_update_uri = getRequestUri("custom_update_uri");
|
String custom_update_uri = getRequestUri("custom_update_uri");
|
||||||
Token token = tokenHolder.getToken();
|
Token token = tokenHolder.getToken();
|
||||||
Response response = request.post(
|
Response response = request.post(
|
||||||
|
|||||||
@ -3,8 +3,6 @@ package com.foxinmy.weixin4j.mp.api;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||||
@ -17,6 +15,7 @@ import com.foxinmy.weixin4j.tuple.MpArticle;
|
|||||||
import com.foxinmy.weixin4j.tuple.MpNews;
|
import com.foxinmy.weixin4j.tuple.MpNews;
|
||||||
import com.foxinmy.weixin4j.tuple.Tuple;
|
import com.foxinmy.weixin4j.tuple.Tuple;
|
||||||
import com.foxinmy.weixin4j.tuple.Video;
|
import com.foxinmy.weixin4j.tuple.Video;
|
||||||
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 群发相关API
|
* 群发相关API
|
||||||
@ -132,7 +131,7 @@ public class MassApi extends MpApi {
|
|||||||
if (tuple instanceof MpNews) {
|
if (tuple instanceof MpNews) {
|
||||||
MpNews _news = (MpNews) tuple;
|
MpNews _news = (MpNews) tuple;
|
||||||
List<MpArticle> _articles = _news.getArticles();
|
List<MpArticle> _articles = _news.getArticles();
|
||||||
if (StringUtils.isBlank(_news.getMediaId())
|
if (StringUtil.isBlank(_news.getMediaId())
|
||||||
&& (_articles == null || _articles.isEmpty())) {
|
&& (_articles == null || _articles.isEmpty())) {
|
||||||
throw new WeixinException(
|
throw new WeixinException(
|
||||||
"mass fail:mediaId or articles is required");
|
"mass fail:mediaId or articles is required");
|
||||||
@ -203,7 +202,7 @@ public class MassApi extends MpApi {
|
|||||||
if (tuple instanceof MpNews) {
|
if (tuple instanceof MpNews) {
|
||||||
MpNews _news = (MpNews) tuple;
|
MpNews _news = (MpNews) tuple;
|
||||||
List<MpArticle> _articles = _news.getArticles();
|
List<MpArticle> _articles = _news.getArticles();
|
||||||
if (StringUtils.isBlank(_news.getMediaId())
|
if (StringUtil.isBlank(_news.getMediaId())
|
||||||
&& (_articles == null || _articles.isEmpty())) {
|
&& (_articles == null || _articles.isEmpty())) {
|
||||||
throw new WeixinException(
|
throw new WeixinException(
|
||||||
"mass fail:mediaId or articles is required");
|
"mass fail:mediaId or articles is required");
|
||||||
|
|||||||
@ -9,7 +9,6 @@ import java.io.UnsupportedEncodingException;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.http.entity.mime.content.ByteArrayBody;
|
import org.apache.http.entity.mime.content.ByteArrayBody;
|
||||||
import org.apache.http.entity.mime.content.StringBody;
|
import org.apache.http.entity.mime.content.StringBody;
|
||||||
|
|
||||||
@ -32,6 +31,7 @@ import com.foxinmy.weixin4j.type.MediaType;
|
|||||||
import com.foxinmy.weixin4j.util.ConfigUtil;
|
import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||||
import com.foxinmy.weixin4j.util.FileUtil;
|
import com.foxinmy.weixin4j.util.FileUtil;
|
||||||
import com.foxinmy.weixin4j.util.IOUtil;
|
import com.foxinmy.weixin4j.util.IOUtil;
|
||||||
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 素材相关API
|
* 素材相关API
|
||||||
@ -65,7 +65,7 @@ public class MediaApi extends MpApi {
|
|||||||
public String uploadMedia(File file, boolean isMaterial)
|
public String uploadMedia(File file, boolean isMaterial)
|
||||||
throws WeixinException, IOException {
|
throws WeixinException, IOException {
|
||||||
String mediaTypeKey = IOUtil.getExtension(file.getName());
|
String mediaTypeKey = IOUtil.getExtension(file.getName());
|
||||||
if (StringUtils.isBlank(mediaTypeKey)) {
|
if (StringUtil.isBlank(mediaTypeKey)) {
|
||||||
mediaTypeKey = FileUtil.getFileType(file);
|
mediaTypeKey = FileUtil.getFileType(file);
|
||||||
}
|
}
|
||||||
MediaType mediaType = MediaType.getMediaType(mediaTypeKey);
|
MediaType mediaType = MediaType.getMediaType(mediaTypeKey);
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
package com.foxinmy.weixin4j.mp.api;
|
package com.foxinmy.weixin4j.mp.api;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||||
import com.foxinmy.weixin4j.http.JsonResult;
|
import com.foxinmy.weixin4j.http.JsonResult;
|
||||||
@ -10,6 +8,7 @@ import com.foxinmy.weixin4j.model.Token;
|
|||||||
import com.foxinmy.weixin4j.mp.message.NotifyMessage;
|
import com.foxinmy.weixin4j.mp.message.NotifyMessage;
|
||||||
import com.foxinmy.weixin4j.token.TokenHolder;
|
import com.foxinmy.weixin4j.token.TokenHolder;
|
||||||
import com.foxinmy.weixin4j.tuple.NotifyTuple;
|
import com.foxinmy.weixin4j.tuple.NotifyTuple;
|
||||||
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 客服消息API
|
* 客服消息API
|
||||||
@ -70,7 +69,7 @@ public class NotifyApi extends MpApi {
|
|||||||
obj.put("touser", notify.getTouser());
|
obj.put("touser", notify.getTouser());
|
||||||
obj.put("msgtype", msgtype);
|
obj.put("msgtype", msgtype);
|
||||||
obj.put(msgtype, tuple);
|
obj.put(msgtype, tuple);
|
||||||
if (StringUtils.isNotBlank(kfAccount)) {
|
if (StringUtil.isNotBlank(kfAccount)) {
|
||||||
JSONObject kf = new JSONObject();
|
JSONObject kf = new JSONObject();
|
||||||
kf.put("kf_account", kfAccount);
|
kf.put("kf_account", kfAccount);
|
||||||
obj.put("customservice", kf);
|
obj.put("customservice", kf);
|
||||||
|
|||||||
@ -24,8 +24,6 @@ import javax.net.ssl.KeyManagerFactory;
|
|||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
|
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.http.Consts;
|
import org.apache.http.Consts;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||||
|
|
||||||
@ -52,7 +50,9 @@ import com.foxinmy.weixin4j.mp.util.ExcelUtil;
|
|||||||
import com.foxinmy.weixin4j.token.TokenHolder;
|
import com.foxinmy.weixin4j.token.TokenHolder;
|
||||||
import com.foxinmy.weixin4j.util.ConfigUtil;
|
import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||||
import com.foxinmy.weixin4j.util.DateUtil;
|
import com.foxinmy.weixin4j.util.DateUtil;
|
||||||
|
import com.foxinmy.weixin4j.util.DigestUtil;
|
||||||
import com.foxinmy.weixin4j.util.MapUtil;
|
import com.foxinmy.weixin4j.util.MapUtil;
|
||||||
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* V2支付API
|
* V2支付API
|
||||||
@ -91,7 +91,7 @@ public class Pay2Api extends PayApi {
|
|||||||
sb.append("&partner=").append(weixinAccount.getPartnerId());
|
sb.append("&partner=").append(weixinAccount.getPartnerId());
|
||||||
String part = sb.toString();
|
String part = sb.toString();
|
||||||
sb.append("&key=").append(weixinAccount.getPartnerKey());
|
sb.append("&key=").append(weixinAccount.getPartnerKey());
|
||||||
String sign = DigestUtils.md5Hex(sb.toString()).toUpperCase();
|
String sign = DigestUtil.MD5(sb.toString()).toUpperCase();
|
||||||
sb.delete(0, sb.length());
|
sb.delete(0, sb.length());
|
||||||
sb.append(part).append("&sign=").append(sign);
|
sb.append(part).append("&sign=").append(sign);
|
||||||
|
|
||||||
@ -172,7 +172,7 @@ public class Pay2Api extends PayApi {
|
|||||||
map.put("total_fee", DateUtil.formaFee2Fen(totalFee));
|
map.put("total_fee", DateUtil.formaFee2Fen(totalFee));
|
||||||
map.put("refund_fee", DateUtil.formaFee2Fen(refundFee));
|
map.put("refund_fee", DateUtil.formaFee2Fen(refundFee));
|
||||||
map.put(idQuery.getType().getName(), idQuery.getId());
|
map.put(idQuery.getType().getName(), idQuery.getId());
|
||||||
if (StringUtils.isBlank(opUserId)) {
|
if (StringUtil.isBlank(opUserId)) {
|
||||||
opUserId = weixinAccount.getPartnerId();
|
opUserId = weixinAccount.getPartnerId();
|
||||||
}
|
}
|
||||||
map.put("op_user_id", opUserId);
|
map.put("op_user_id", opUserId);
|
||||||
@ -261,7 +261,7 @@ public class Pay2Api extends PayApi {
|
|||||||
String outRefundNo, double totalFee, double refundFee,
|
String outRefundNo, double totalFee, double refundFee,
|
||||||
String opUserId, String opUserPasswd) throws WeixinException {
|
String opUserId, String opUserPasswd) throws WeixinException {
|
||||||
Map<String, String> mopara = new HashMap<String, String>();
|
Map<String, String> mopara = new HashMap<String, String>();
|
||||||
mopara.put("op_user_passwd", DigestUtils.md5Hex(opUserPasswd));
|
mopara.put("op_user_passwd", DigestUtil.MD5(opUserPasswd));
|
||||||
return refund(caFile, idQuery, outRefundNo, totalFee, refundFee,
|
return refund(caFile, idQuery, outRefundNo, totalFee, refundFee,
|
||||||
opUserId, mopara);
|
opUserId, mopara);
|
||||||
}
|
}
|
||||||
@ -301,11 +301,11 @@ public class Pay2Api extends PayApi {
|
|||||||
String opUserId, String opUserPasswd, String recvUserId,
|
String opUserId, String opUserPasswd, String recvUserId,
|
||||||
String reccvUserName, RefundType refundType) throws WeixinException {
|
String reccvUserName, RefundType refundType) throws WeixinException {
|
||||||
Map<String, String> mopara = new HashMap<String, String>();
|
Map<String, String> mopara = new HashMap<String, String>();
|
||||||
mopara.put("op_user_passwd", DigestUtils.md5Hex(opUserPasswd));
|
mopara.put("op_user_passwd", DigestUtil.MD5(opUserPasswd));
|
||||||
if (StringUtils.isNotBlank(recvUserId)) {
|
if (StringUtil.isNotBlank(recvUserId)) {
|
||||||
mopara.put("recv_user_id", recvUserId);
|
mopara.put("recv_user_id", recvUserId);
|
||||||
}
|
}
|
||||||
if (StringUtils.isNotBlank(reccvUserName)) {
|
if (StringUtil.isNotBlank(reccvUserName)) {
|
||||||
mopara.put("reccv_user_name", reccvUserName);
|
mopara.put("reccv_user_name", reccvUserName);
|
||||||
}
|
}
|
||||||
if (refundType != null) {
|
if (refundType != null) {
|
||||||
@ -389,7 +389,7 @@ public class Pay2Api extends PayApi {
|
|||||||
map.put("cft_signtype", "0");
|
map.put("cft_signtype", "0");
|
||||||
map.put("mchtype", Integer.toString(billType.getVal()));
|
map.put("mchtype", Integer.toString(billType.getVal()));
|
||||||
map.put("key", weixinAccount.getPartnerKey());
|
map.put("key", weixinAccount.getPartnerKey());
|
||||||
String sign = DigestUtils.md5Hex(MapUtil
|
String sign = DigestUtil.MD5(MapUtil
|
||||||
.toJoinString(map, false, false));
|
.toJoinString(map, false, false));
|
||||||
map.put("sign", sign.toLowerCase());
|
map.put("sign", sign.toLowerCase());
|
||||||
Response response = request.get(downloadbill_uri, map);
|
Response response = request.get(downloadbill_uri, map);
|
||||||
|
|||||||
@ -18,7 +18,6 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.http.Consts;
|
import org.apache.http.Consts;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||||
|
|
||||||
@ -45,6 +44,7 @@ import com.foxinmy.weixin4j.token.TokenHolder;
|
|||||||
import com.foxinmy.weixin4j.util.ConfigUtil;
|
import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||||
import com.foxinmy.weixin4j.util.DateUtil;
|
import com.foxinmy.weixin4j.util.DateUtil;
|
||||||
import com.foxinmy.weixin4j.util.RandomUtil;
|
import com.foxinmy.weixin4j.util.RandomUtil;
|
||||||
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* V3(商户平台版)支付API
|
* V3(商户平台版)支付API
|
||||||
@ -134,7 +134,7 @@ public class Pay3Api extends PayApi {
|
|||||||
map.put("out_refund_no", outRefundNo);
|
map.put("out_refund_no", outRefundNo);
|
||||||
map.put("total_fee", DateUtil.formaFee2Fen(totalFee));
|
map.put("total_fee", DateUtil.formaFee2Fen(totalFee));
|
||||||
map.put("refund_fee", DateUtil.formaFee2Fen(refundFee));
|
map.put("refund_fee", DateUtil.formaFee2Fen(refundFee));
|
||||||
if (StringUtils.isBlank(opUserId)) {
|
if (StringUtil.isBlank(opUserId)) {
|
||||||
opUserId = weixinAccount.getMchId();
|
opUserId = weixinAccount.getMchId();
|
||||||
}
|
}
|
||||||
map.put("op_user_id", opUserId);
|
map.put("op_user_id", opUserId);
|
||||||
@ -459,7 +459,7 @@ public class Pay3Api extends PayApi {
|
|||||||
map.put("appid", weixinAccount.getId());
|
map.put("appid", weixinAccount.getId());
|
||||||
map.put("mch_id", weixinAccount.getMchId());
|
map.put("mch_id", weixinAccount.getMchId());
|
||||||
map.put("nonce_str", RandomUtil.generateString(16));
|
map.put("nonce_str", RandomUtil.generateString(16));
|
||||||
if (StringUtils.isNotBlank(weixinAccount.getDeviceInfo())) {
|
if (StringUtil.isNotBlank(weixinAccount.getDeviceInfo())) {
|
||||||
map.put("device_info", weixinAccount.getDeviceInfo());
|
map.put("device_info", weixinAccount.getDeviceInfo());
|
||||||
}
|
}
|
||||||
if (idQuery != null) {
|
if (idQuery != null) {
|
||||||
|
|||||||
@ -1,40 +0,0 @@
|
|||||||
package com.foxinmy.weixin4j.mp.event;
|
|
||||||
|
|
||||||
import com.foxinmy.weixin4j.message.event.EventMessage;
|
|
||||||
import com.foxinmy.weixin4j.mp.type.EventType;
|
|
||||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 客服关闭会话事件
|
|
||||||
*
|
|
||||||
* @className KfCloseEventMessage
|
|
||||||
* @author jy
|
|
||||||
* @date 2015年3月22日
|
|
||||||
* @since JDK 1.7
|
|
||||||
* @see <a
|
|
||||||
* href="http://mp.weixin.qq.com/wiki/2/6c20f3e323bdf5986cfcb33cbd3b829a.html#.E4.BC.9A.E8.AF.9D.E7.8A.B6.E6.80.81.E9.80.9A.E7.9F.A5.E4.BA.8B.E4.BB.B6">会话状态通知事件</a>
|
|
||||||
*/
|
|
||||||
public class KfCloseEventMessage extends EventMessage {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 3644449346935205541L;
|
|
||||||
|
|
||||||
public KfCloseEventMessage() {
|
|
||||||
super(EventType.kf_close_session.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 客服账号
|
|
||||||
*/
|
|
||||||
@XStreamAlias("KfAccount")
|
|
||||||
private String kfAccount;
|
|
||||||
|
|
||||||
public String getKfAccount() {
|
|
||||||
return kfAccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "KfCloseEventMessage [kfAccount=" + kfAccount + ", ="
|
|
||||||
+ super.toString() + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
package com.foxinmy.weixin4j.mp.event;
|
|
||||||
|
|
||||||
import com.foxinmy.weixin4j.message.event.EventMessage;
|
|
||||||
import com.foxinmy.weixin4j.mp.type.EventType;
|
|
||||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 客服接入会话事件
|
|
||||||
*
|
|
||||||
* @className KfCreateEventMessage
|
|
||||||
* @author jy
|
|
||||||
* @date 2015年3月22日
|
|
||||||
* @since JDK 1.7
|
|
||||||
* @see <a
|
|
||||||
* href="http://mp.weixin.qq.com/wiki/2/6c20f3e323bdf5986cfcb33cbd3b829a.html#.E4.BC.9A.E8.AF.9D.E7.8A.B6.E6.80.81.E9.80.9A.E7.9F.A5.E4.BA.8B.E4.BB.B6">会话状态通知事件</a>
|
|
||||||
*/
|
|
||||||
public class KfCreateEventMessage extends EventMessage {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = -8968189700999202108L;
|
|
||||||
|
|
||||||
public KfCreateEventMessage() {
|
|
||||||
super(EventType.kf_create_session.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 客服账号
|
|
||||||
*/
|
|
||||||
@XStreamAlias("KfAccount")
|
|
||||||
private String kfAccount;
|
|
||||||
|
|
||||||
public String getKfAccount() {
|
|
||||||
return kfAccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "KfCreateEventMessage [kfAccount=" + kfAccount + ", ="
|
|
||||||
+ super.toString() + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,48 +0,0 @@
|
|||||||
package com.foxinmy.weixin4j.mp.event;
|
|
||||||
|
|
||||||
import com.foxinmy.weixin4j.message.event.EventMessage;
|
|
||||||
import com.foxinmy.weixin4j.mp.type.EventType;
|
|
||||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 客服转接会话事件
|
|
||||||
*
|
|
||||||
* @className KfSwitchEventMessage
|
|
||||||
* @author jy
|
|
||||||
* @date 2015年3月22日
|
|
||||||
* @since JDK 1.7
|
|
||||||
* @see <a
|
|
||||||
* href="http://mp.weixin.qq.com/wiki/2/6c20f3e323bdf5986cfcb33cbd3b829a.html#.E4.BC.9A.E8.AF.9D.E7.8A.B6.E6.80.81.E9.80.9A.E7.9F.A5.E4.BA.8B.E4.BB.B6">会话状态通知事件</a>
|
|
||||||
*/
|
|
||||||
public class KfSwitchEventMessage extends EventMessage {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 4319501074109623413L;
|
|
||||||
|
|
||||||
public KfSwitchEventMessage() {
|
|
||||||
super(EventType.kf_switch_session.name());
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 来自的客服账号
|
|
||||||
*/
|
|
||||||
@XStreamAlias("FromKfAccount")
|
|
||||||
private String fromKfAccount;
|
|
||||||
/**
|
|
||||||
* 转移给客服账号
|
|
||||||
*/
|
|
||||||
@XStreamAlias("ToKfAccount")
|
|
||||||
private String toKfAccount;
|
|
||||||
|
|
||||||
public String getFromKfAccount() {
|
|
||||||
return fromKfAccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getToKfAccount() {
|
|
||||||
return toKfAccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "KfSwitchEventMessage [fromKfAccount=" + fromKfAccount
|
|
||||||
+ ", toKfAccount=" + toKfAccount + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,129 +0,0 @@
|
|||||||
package com.foxinmy.weixin4j.mp.event;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.foxinmy.weixin4j.message.event.EventMessage;
|
|
||||||
import com.foxinmy.weixin4j.mp.type.EventType;
|
|
||||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
|
||||||
import com.thoughtworks.xstream.annotations.XStreamOmitField;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 群发消息事件推送
|
|
||||||
*
|
|
||||||
* @className MassEventMessage
|
|
||||||
* @author jy
|
|
||||||
* @date 2014年4月27日
|
|
||||||
* @since JDK 1.7
|
|
||||||
* @see <a
|
|
||||||
* href="http://mp.weixin.qq.com/wiki/15/5380a4e6f02f2ffdc7981a8ed7a40753.html#.E4.BA.8B.E4.BB.B6.E6.8E.A8.E9.80.81.E7.BE.A4.E5.8F.91.E7.BB.93.E6.9E.9C">群发回调</a>
|
|
||||||
*/
|
|
||||||
public class MassEventMessage extends EventMessage {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = -1660543255873723895L;
|
|
||||||
|
|
||||||
public MassEventMessage() {
|
|
||||||
super(EventType.masssendjobfinish.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 群发后的状态信息 为“send success”或“send fail”或“err(num)
|
|
||||||
*/
|
|
||||||
@XStreamAlias("Status")
|
|
||||||
private String status;
|
|
||||||
/**
|
|
||||||
* group_id下粉丝数;或者openid_list中的粉丝数
|
|
||||||
*/
|
|
||||||
@XStreamAlias("TotalCount")
|
|
||||||
private int totalCount;
|
|
||||||
/**
|
|
||||||
* 过滤(过滤是指特定地区、性别的过滤、用户设置拒收的过滤,用户接收已超4条的过滤)后,准备发送的粉丝数,原则上,FilterCount =
|
|
||||||
* SentCount + ErrorCount
|
|
||||||
*/
|
|
||||||
@XStreamAlias("FilterCount")
|
|
||||||
private int filterCount;
|
|
||||||
/**
|
|
||||||
* 发送成功的粉丝数
|
|
||||||
*/
|
|
||||||
@XStreamAlias("SentCount")
|
|
||||||
private int sentCount;
|
|
||||||
/**
|
|
||||||
* 发送失败的粉丝数
|
|
||||||
*/
|
|
||||||
@XStreamAlias("ErrorCount")
|
|
||||||
private int errorCount;
|
|
||||||
|
|
||||||
@XStreamOmitField
|
|
||||||
private final static Map<String, String> statusMap;
|
|
||||||
static {
|
|
||||||
statusMap = new HashMap<String, String>();
|
|
||||||
statusMap.put("sendsuccess", "发送成功");
|
|
||||||
statusMap.put("send_success", "发送成功");
|
|
||||||
statusMap.put("success", "发送成功");
|
|
||||||
statusMap.put("send success", "发送成功");
|
|
||||||
statusMap.put("sendfail", "发送失败");
|
|
||||||
statusMap.put("send_fail", "发送失败");
|
|
||||||
statusMap.put("fail", "发送失败");
|
|
||||||
statusMap.put("send fail", "发送失败");
|
|
||||||
statusMap.put("err(10001)", "涉嫌广告");
|
|
||||||
statusMap.put("err(20001)", "涉嫌政治");
|
|
||||||
statusMap.put("err(20004)", "涉嫌社会");
|
|
||||||
statusMap.put("err(20006)", "涉嫌违法犯罪");
|
|
||||||
statusMap.put("err(20008)", "涉嫌欺诈");
|
|
||||||
statusMap.put("err(20013)", "涉嫌版权");
|
|
||||||
statusMap.put("err(22000)", "涉嫌互推(互相宣传)");
|
|
||||||
statusMap.put("err(21000)", "涉嫌其他");
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getStatus() {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送状态描述</br> err(10001,涉嫌广告) err(20001,涉嫌政治) err(20004,涉嫌社会)</br>
|
|
||||||
* err(20002,涉嫌色情) err(20006,涉嫌违法犯罪) err(20008,涉嫌欺诈)</br> err(20013,涉嫌版权)
|
|
||||||
* err(22000,涉嫌互推(互相宣传) err(21000,涉嫌其他)
|
|
||||||
*
|
|
||||||
* @param status
|
|
||||||
* @return 中文描述
|
|
||||||
*/
|
|
||||||
public String getStatusDesc() {
|
|
||||||
return statusMap.get(status.toLowerCase());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送状态描述</br> err(10001,涉嫌广告) err(20001,涉嫌政治) err(20004,涉嫌社会)</br>
|
|
||||||
* err(20002,涉嫌色情) err(20006,涉嫌违法犯罪) err(20008,涉嫌欺诈)</br> err(20013,涉嫌版权)
|
|
||||||
* err(22000,涉嫌互推(互相宣传) err(21000,涉嫌其他)
|
|
||||||
*
|
|
||||||
* @param status
|
|
||||||
* @return 中文描述
|
|
||||||
*/
|
|
||||||
public static String getStatusDesc(String status) {
|
|
||||||
return statusMap.get(status.toLowerCase());
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTotalCount() {
|
|
||||||
return totalCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getFilterCount() {
|
|
||||||
return filterCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSentCount() {
|
|
||||||
return sentCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getErrorCount() {
|
|
||||||
return errorCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "MassEventMessage [status=" + getStatusDesc() + ", totalCount="
|
|
||||||
+ totalCount + ", filterCount=" + filterCount + ", sentCount="
|
|
||||||
+ sentCount + ", errorCount=" + errorCount + ", "
|
|
||||||
+ super.toString() + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,57 +0,0 @@
|
|||||||
package com.foxinmy.weixin4j.mp.event;
|
|
||||||
|
|
||||||
import com.foxinmy.weixin4j.message.event.EventMessage;
|
|
||||||
import com.foxinmy.weixin4j.mp.type.EventType;
|
|
||||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 扫描二维码事件
|
|
||||||
*
|
|
||||||
* @className ScanEventMessage
|
|
||||||
* @author jy.hu
|
|
||||||
* @date 2014年4月6日
|
|
||||||
* @since JDK 1.7
|
|
||||||
* @see <a
|
|
||||||
* href="http://mp.weixin.qq.com/wiki/2/5baf56ce4947d35003b86a9805634b1e.html#.E6.89.AB.E6.8F.8F.E5.B8.A6.E5.8F.82.E6.95.B0.E4.BA.8C.E7.BB.B4.E7.A0.81.E4.BA.8B.E4.BB.B6">扫描二维码事件</a>
|
|
||||||
*/
|
|
||||||
public class ScanEventMessage extends EventMessage {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 8078674062833071562L;
|
|
||||||
|
|
||||||
public ScanEventMessage() {
|
|
||||||
super(EventType.scan.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
public ScanEventMessage(String eventType) {
|
|
||||||
super(eventType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 事件KEY值,是一个32位无符号整数,即创建二维码时的二维码scene_id
|
|
||||||
*/
|
|
||||||
@XStreamAlias("EventKey")
|
|
||||||
private String eventKey;
|
|
||||||
/**
|
|
||||||
* 二维码的ticket,可用来换取二维码图片
|
|
||||||
*/
|
|
||||||
@XStreamAlias("Ticket")
|
|
||||||
private String ticket;
|
|
||||||
|
|
||||||
public String getEventKey() {
|
|
||||||
return eventKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTicket() {
|
|
||||||
return ticket;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getParameter() {
|
|
||||||
return eventKey.replace("qrscene_", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "ScanEventMessage [eventKey=" + eventKey + ", ticket=" + ticket
|
|
||||||
+ ", " + super.toString() + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
package com.foxinmy.weixin4j.mp.event;
|
|
||||||
|
|
||||||
import com.foxinmy.weixin4j.type.EventType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 关注/取消关注事件</br> <font color="red">包括直接关注与扫描关注</font>
|
|
||||||
*
|
|
||||||
* @className ScribeEventMessage
|
|
||||||
* @author jy.hu
|
|
||||||
* @date 2014年4月6日
|
|
||||||
* @since JDK 1.7
|
|
||||||
* @see <a
|
|
||||||
* href="http://mp.weixin.qq.com/wiki/2/5baf56ce4947d35003b86a9805634b1e.html#.E5.85.B3.E6.B3.A8.2F.E5.8F.96.E6.B6.88.E5.85.B3.E6.B3.A8.E4.BA.8B.E4.BB.B6">订阅号、服务号的关注/取消关注事件</a>
|
|
||||||
*/
|
|
||||||
public class ScribeEventMessage extends ScanEventMessage {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = -6846321620262204915L;
|
|
||||||
|
|
||||||
public ScribeEventMessage() {
|
|
||||||
super(EventType.subscribe.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "ScribeEventMessage [" + super.toString() + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
package com.foxinmy.weixin4j.mp.event;
|
|
||||||
|
|
||||||
import com.foxinmy.weixin4j.message.event.EventMessage;
|
|
||||||
import com.foxinmy.weixin4j.mp.type.EventType;
|
|
||||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 模板消息事件推送(公众平台)
|
|
||||||
*
|
|
||||||
* @className TemplatesendjobfinishMessage
|
|
||||||
* @author jy
|
|
||||||
* @date 2014年9月19日
|
|
||||||
* @since JDK 1.7
|
|
||||||
* @see <a
|
|
||||||
* href="http://mp.weixin.qq.com/wiki/17/304c1885ea66dbedf7dc170d84999a9d.html#.E4.BA.8B.E4.BB.B6.E6.8E.A8.E9.80.81">模板消息事件推送</a>
|
|
||||||
*/
|
|
||||||
public class TemplatesendjobfinishMessage extends EventMessage {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = -2903359365988594012L;
|
|
||||||
|
|
||||||
public TemplatesendjobfinishMessage() {
|
|
||||||
super(EventType.templatesendjobfinish.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 推送状态 如failed: system failed
|
|
||||||
*/
|
|
||||||
@XStreamAlias("Status")
|
|
||||||
private String status;
|
|
||||||
|
|
||||||
public String getStatus() {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "TemplatesendjobfinishMessage [status=" + status + ", "
|
|
||||||
+ super.toString() + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -3,12 +3,11 @@ package com.foxinmy.weixin4j.mp.model;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.annotation.JSONField;
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
import com.foxinmy.weixin4j.model.Gender;
|
import com.foxinmy.weixin4j.model.Gender;
|
||||||
import com.foxinmy.weixin4j.mp.type.FaceSize;
|
import com.foxinmy.weixin4j.mp.type.FaceSize;
|
||||||
import com.foxinmy.weixin4j.mp.type.Lang;
|
import com.foxinmy.weixin4j.mp.type.Lang;
|
||||||
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户对象
|
* 用户对象
|
||||||
@ -135,7 +134,7 @@ public class User implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getHeadimgurl(FaceSize size) {
|
public String getHeadimgurl(FaceSize size) {
|
||||||
if (StringUtils.isNotBlank(headimgurl)) {
|
if (StringUtil.isNotBlank(headimgurl)) {
|
||||||
StringBuilder sb = new StringBuilder(headimgurl);
|
StringBuilder sb = new StringBuilder(headimgurl);
|
||||||
return sb.replace(0, (headimgurl.length() - 1), size.getInt() + "")
|
return sb.replace(0, (headimgurl.length() - 1), size.getInt() + "")
|
||||||
.toString();
|
.toString();
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
package com.foxinmy.weixin4j.mp.model;
|
package com.foxinmy.weixin4j.mp.model;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||||
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 微信公众平台信息
|
* 微信公众平台信息
|
||||||
@ -101,7 +100,7 @@ public class WeixinMpAccount extends WeixinAccount {
|
|||||||
|
|
||||||
public int getVersion() {
|
public int getVersion() {
|
||||||
if (version == 0) {
|
if (version == 0) {
|
||||||
return StringUtils.isNotBlank(mchId) ? 3 : 2;
|
return StringUtil.isNotBlank(mchId) ? 3 : 2;
|
||||||
}
|
}
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,9 +3,6 @@ package com.foxinmy.weixin4j.mp.payment;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.TypeReference;
|
import com.alibaba.fastjson.TypeReference;
|
||||||
import com.foxinmy.weixin4j.exception.PayException;
|
import com.foxinmy.weixin4j.exception.PayException;
|
||||||
@ -24,8 +21,10 @@ import com.foxinmy.weixin4j.mp.type.SignType;
|
|||||||
import com.foxinmy.weixin4j.mp.type.TradeType;
|
import com.foxinmy.weixin4j.mp.type.TradeType;
|
||||||
import com.foxinmy.weixin4j.util.ConfigUtil;
|
import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||||
import com.foxinmy.weixin4j.util.DateUtil;
|
import com.foxinmy.weixin4j.util.DateUtil;
|
||||||
|
import com.foxinmy.weixin4j.util.DigestUtil;
|
||||||
import com.foxinmy.weixin4j.util.MapUtil;
|
import com.foxinmy.weixin4j.util.MapUtil;
|
||||||
import com.foxinmy.weixin4j.util.RandomUtil;
|
import com.foxinmy.weixin4j.util.RandomUtil;
|
||||||
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
import com.foxinmy.weixin4j.xml.XmlStream;
|
import com.foxinmy.weixin4j.xml.XmlStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,7 +72,7 @@ public class PayUtil {
|
|||||||
*/
|
*/
|
||||||
public static String createPayJsRequestJsonV2(PayPackageV2 payPackage,
|
public static String createPayJsRequestJsonV2(PayPackageV2 payPackage,
|
||||||
WeixinMpAccount weixinAccount) {
|
WeixinMpAccount weixinAccount) {
|
||||||
if (StringUtils.isBlank(payPackage.getPartner())) {
|
if (StringUtil.isBlank(payPackage.getPartner())) {
|
||||||
payPackage.setPartner(weixinAccount.getPartnerId());
|
payPackage.setPartner(weixinAccount.getPartnerId());
|
||||||
}
|
}
|
||||||
JsPayRequestV2 jsPayRequest = new JsPayRequestV2(weixinAccount,
|
JsPayRequestV2 jsPayRequest = new JsPayRequestV2(weixinAccount,
|
||||||
@ -115,8 +114,7 @@ public class PayUtil {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static String paysignSha(Object obj) {
|
public static String paysignSha(Object obj) {
|
||||||
return DigestUtils
|
return DigestUtil.SHA1(MapUtil.toJoinString(obj, false, true, null));
|
||||||
.sha1Hex(MapUtil.toJoinString(obj, false, true, null));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -132,8 +130,7 @@ public class PayUtil {
|
|||||||
public static String paysignSha(Object obj, String paySignKey) {
|
public static String paysignSha(Object obj, String paySignKey) {
|
||||||
Map<String, String> extra = new HashMap<String, String>();
|
Map<String, String> extra = new HashMap<String, String>();
|
||||||
extra.put("appKey", paySignKey);
|
extra.put("appKey", paySignKey);
|
||||||
return DigestUtils.sha1Hex(MapUtil
|
return DigestUtil.SHA1(MapUtil.toJoinString(obj, false, true, extra));
|
||||||
.toJoinString(obj, false, true, extra));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -154,7 +151,7 @@ public class PayUtil {
|
|||||||
// stringSignTemp 进行 md5 运算
|
// stringSignTemp 进行 md5 运算
|
||||||
// 再将得到的 字符串所有字符转换为大写 ,得到 sign 值 signValue。
|
// 再将得到的 字符串所有字符转换为大写 ,得到 sign 值 signValue。
|
||||||
sb.append("&key=").append(paySignKey);
|
sb.append("&key=").append(paySignKey);
|
||||||
return DigestUtils.md5Hex(sb.toString()).toUpperCase();
|
return DigestUtil.SHA1(sb.toString()).toUpperCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -224,7 +221,7 @@ public class PayUtil {
|
|||||||
*/
|
*/
|
||||||
public static PrePay createPrePay(PayPackageV3 payPackage, String paySignKey)
|
public static PrePay createPrePay(PayPackageV3 payPackage, String paySignKey)
|
||||||
throws PayException {
|
throws PayException {
|
||||||
if (StringUtils.isBlank(payPackage.getSign())) {
|
if (StringUtil.isBlank(payPackage.getSign())) {
|
||||||
payPackage.setSign(paysignMd5(payPackage, paySignKey));
|
payPackage.setSign(paysignMd5(payPackage, paySignKey));
|
||||||
}
|
}
|
||||||
String payJsRequestXml = XmlStream.to(payPackage).replaceAll("__", "_");
|
String payJsRequestXml = XmlStream.to(payPackage).replaceAll("__", "_");
|
||||||
|
|||||||
@ -2,14 +2,13 @@ package com.foxinmy.weixin4j.mp.payment.coupon;
|
|||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.annotation.JSONField;
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
import com.foxinmy.weixin4j.mp.payment.v3.ApiResult;
|
import com.foxinmy.weixin4j.mp.payment.v3.ApiResult;
|
||||||
import com.foxinmy.weixin4j.mp.type.CouponStatus;
|
import com.foxinmy.weixin4j.mp.type.CouponStatus;
|
||||||
import com.foxinmy.weixin4j.mp.type.CouponStockType;
|
import com.foxinmy.weixin4j.mp.type.CouponStockType;
|
||||||
import com.foxinmy.weixin4j.mp.type.CouponType;
|
import com.foxinmy.weixin4j.mp.type.CouponType;
|
||||||
import com.foxinmy.weixin4j.util.DateUtil;
|
import com.foxinmy.weixin4j.util.DateUtil;
|
||||||
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -315,7 +314,7 @@ public class CouponDetail extends ApiResult {
|
|||||||
|
|
||||||
@JSONField(deserialize = false, serialize = false)
|
@JSONField(deserialize = false, serialize = false)
|
||||||
public Date getFormatUseTime() {
|
public Date getFormatUseTime() {
|
||||||
return StringUtils.isNotBlank(useTime) ? DateUtil
|
return StringUtil.isNotBlank(useTime) ? DateUtil
|
||||||
.parse2yyyyMMddHHmmss(useTime) : null;
|
.parse2yyyyMMddHHmmss(useTime) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,10 +2,9 @@ package com.foxinmy.weixin4j.mp.payment.v2;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.annotation.JSONField;
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
import com.foxinmy.weixin4j.mp.type.SignType;
|
import com.foxinmy.weixin4j.mp.type.SignType;
|
||||||
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -68,7 +67,7 @@ public class ApiResult implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getRetMsg() {
|
public String getRetMsg() {
|
||||||
return StringUtils.isNotBlank(retMsg) ? retMsg : null;
|
return StringUtil.isNotBlank(retMsg) ? retMsg : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRetMsg(String retMsg) {
|
public void setRetMsg(String retMsg) {
|
||||||
|
|||||||
@ -2,11 +2,10 @@ package com.foxinmy.weixin4j.mp.payment.v2;
|
|||||||
|
|
||||||
import java.beans.Transient;
|
import java.beans.Transient;
|
||||||
|
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.annotation.JSONField;
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
import com.foxinmy.weixin4j.mp.model.WeixinMpAccount;
|
import com.foxinmy.weixin4j.mp.model.WeixinMpAccount;
|
||||||
import com.foxinmy.weixin4j.mp.payment.PayRequest;
|
import com.foxinmy.weixin4j.mp.payment.PayRequest;
|
||||||
|
import com.foxinmy.weixin4j.util.DigestUtil;
|
||||||
import com.foxinmy.weixin4j.util.MapUtil;
|
import com.foxinmy.weixin4j.util.MapUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,7 +47,7 @@ public class JsPayRequestV2 extends PayRequest {
|
|||||||
// 再将得到的 字符串所有字符转换为大写 ,得到 sign 值 signValue。
|
// 再将得到的 字符串所有字符转换为大写 ,得到 sign 值 signValue。
|
||||||
sb.append("&key=").append(partnerKey);
|
sb.append("&key=").append(partnerKey);
|
||||||
// c---> & d---->
|
// c---> & d---->
|
||||||
String sign = DigestUtils.md5Hex(sb.toString()).toUpperCase();
|
String sign = DigestUtil.MD5(sb.toString()).toUpperCase();
|
||||||
sb.delete(0, sb.length());
|
sb.delete(0, sb.length());
|
||||||
// c.对传入参数中所有键值对的 value 进行 urlencode 转码后重新拼接成字符串 string2
|
// c.对传入参数中所有键值对的 value 进行 urlencode 转码后重新拼接成字符串 string2
|
||||||
sb.append(MapUtil.toJoinString(payPackage, true, false, null))
|
sb.append(MapUtil.toJoinString(payPackage, true, false, null))
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
package com.foxinmy.weixin4j.mp.payment.v2;
|
package com.foxinmy.weixin4j.mp.payment.v2;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.annotation.JSONField;
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
import com.foxinmy.weixin4j.mp.type.RefundChannel;
|
import com.foxinmy.weixin4j.mp.type.RefundChannel;
|
||||||
import com.foxinmy.weixin4j.mp.type.RefundStatus;
|
import com.foxinmy.weixin4j.mp.type.RefundStatus;
|
||||||
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -123,11 +122,11 @@ public class RefundDetail extends ApiResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getRecvUserId() {
|
public String getRecvUserId() {
|
||||||
return StringUtils.isNotBlank(recvUserId) ? recvUserId : null;
|
return StringUtil.isNotBlank(recvUserId) ? recvUserId : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getReccvUserName() {
|
public String getReccvUserName() {
|
||||||
return StringUtils.isNotBlank(reccvUserName) ? reccvUserName : null;
|
return StringUtil.isNotBlank(reccvUserName) ? reccvUserName : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -2,9 +2,8 @@ package com.foxinmy.weixin4j.mp.payment.v2;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.annotation.JSONField;
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||||
import com.thoughtworks.xstream.annotations.XStreamOmitField;
|
import com.thoughtworks.xstream.annotations.XStreamOmitField;
|
||||||
|
|
||||||
@ -52,7 +51,7 @@ public class RefundRecord extends ApiResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getOutTradeNo() {
|
public String getOutTradeNo() {
|
||||||
return StringUtils.isNotBlank(outTradeNo) ? outTradeNo : null;
|
return StringUtil.isNotBlank(outTradeNo) ? outTradeNo : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCount() {
|
public int getCount() {
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
package com.foxinmy.weixin4j.mp.payment.v3;
|
package com.foxinmy.weixin4j.mp.payment.v3;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.annotation.JSONField;
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
import com.foxinmy.weixin4j.http.XmlResult;
|
import com.foxinmy.weixin4j.http.XmlResult;
|
||||||
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -83,7 +82,7 @@ public class ApiResult extends XmlResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getSubMchId() {
|
public String getSubMchId() {
|
||||||
return StringUtils.isNotBlank(subMchId) ? subMchId : null;
|
return StringUtil.isNotBlank(subMchId) ? subMchId : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSubMchId(String subMchId) {
|
public void setSubMchId(String subMchId) {
|
||||||
|
|||||||
@ -2,13 +2,12 @@ package com.foxinmy.weixin4j.mp.payment.v3;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.annotation.JSONField;
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
import com.foxinmy.weixin4j.mp.payment.coupon.CouponInfo;
|
import com.foxinmy.weixin4j.mp.payment.coupon.CouponInfo;
|
||||||
import com.foxinmy.weixin4j.mp.type.CurrencyType;
|
import com.foxinmy.weixin4j.mp.type.CurrencyType;
|
||||||
import com.foxinmy.weixin4j.mp.type.RefundChannel;
|
import com.foxinmy.weixin4j.mp.type.RefundChannel;
|
||||||
import com.foxinmy.weixin4j.mp.type.RefundStatus;
|
import com.foxinmy.weixin4j.mp.type.RefundStatus;
|
||||||
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -140,7 +139,7 @@ public class RefundDetail extends ApiResult {
|
|||||||
|
|
||||||
@JSONField(deserialize = false, serialize = false)
|
@JSONField(deserialize = false, serialize = false)
|
||||||
public RefundChannel getFormatRefundChannel() {
|
public RefundChannel getFormatRefundChannel() {
|
||||||
if (StringUtils.isNotBlank(refundChannel)) {
|
if (StringUtil.isNotBlank(refundChannel)) {
|
||||||
return RefundChannel.valueOf(refundChannel.toUpperCase());
|
return RefundChannel.valueOf(refundChannel.toUpperCase());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -170,7 +169,7 @@ public class RefundDetail extends ApiResult {
|
|||||||
|
|
||||||
@JSONField(deserialize = false, serialize = false)
|
@JSONField(deserialize = false, serialize = false)
|
||||||
public RefundStatus getFormatRefundStatus() {
|
public RefundStatus getFormatRefundStatus() {
|
||||||
if (StringUtils.isNotBlank(refundStatus)) {
|
if (StringUtil.isNotBlank(refundStatus)) {
|
||||||
return RefundStatus.valueOf(refundStatus);
|
return RefundStatus.valueOf(refundStatus);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@ -1,3 +0,0 @@
|
|||||||
模拟微信公众平台登陆
|
|
||||||
|
|
||||||
(模拟登录|启用开发者模式|修改服务器配置|修改回调地址|启用服务器配置....more)
|
|
||||||
@ -1,666 +0,0 @@
|
|||||||
package com.foxinmy.weixin4j.mp.spider;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.Base64;
|
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.http.Consts;
|
|
||||||
import org.apache.http.HttpEntity;
|
|
||||||
import org.apache.http.HttpHost;
|
|
||||||
import org.apache.http.HttpResponse;
|
|
||||||
import org.apache.http.HttpStatus;
|
|
||||||
import org.apache.http.NameValuePair;
|
|
||||||
import org.apache.http.StatusLine;
|
|
||||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
|
||||||
import org.apache.http.client.methods.HttpGet;
|
|
||||||
import org.apache.http.client.methods.HttpPost;
|
|
||||||
import org.apache.http.client.params.ClientPNames;
|
|
||||||
import org.apache.http.client.params.CookiePolicy;
|
|
||||||
import org.apache.http.cookie.Cookie;
|
|
||||||
import org.apache.http.impl.client.AbstractHttpClient;
|
|
||||||
import org.apache.http.impl.client.DefaultHttpClient;
|
|
||||||
import org.apache.http.message.BasicHeader;
|
|
||||||
import org.apache.http.message.BasicNameValuePair;
|
|
||||||
import org.jsoup.Jsoup;
|
|
||||||
import org.jsoup.nodes.Document;
|
|
||||||
import org.jsoup.nodes.Element;
|
|
||||||
import org.jsoup.select.Elements;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.foxinmy.weixin4j.util.IOUtil;
|
|
||||||
import com.foxinmy.weixin4j.util.RandomUtil;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 模拟微信公众平台登陆
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* (模拟登录|启用开发者模式|修改服务器配置|修改回调地址|启用服务器配置....more)
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @className WeixinExecutor
|
|
||||||
* @author jy
|
|
||||||
* @date 2014年8月15日
|
|
||||||
* @since JDK 1.7
|
|
||||||
* @see
|
|
||||||
*/
|
|
||||||
public class WeixinExecutor {
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
|
||||||
|
|
||||||
private final static Map<String, String> accountMap = new HashMap<String, String>() {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
{
|
|
||||||
put("名称", "name");
|
|
||||||
put("头像", "avatar");
|
|
||||||
put("登录邮箱", "loginEmail");
|
|
||||||
put("原始ID", "originalId");
|
|
||||||
put("微信号", "weixinNo");
|
|
||||||
put("类型", "accountType");
|
|
||||||
put("认证情况", "weixinVerify");
|
|
||||||
put("主体信息", "bodyInfo");
|
|
||||||
put("介绍", "introduce");
|
|
||||||
put("所在地址", "address");
|
|
||||||
put("二维码", "qrcodeUrl");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private AbstractHttpClient client;
|
|
||||||
private HttpHost host;
|
|
||||||
private JSONObject weixin;
|
|
||||||
|
|
||||||
// 服务器响应地址
|
|
||||||
private String pushurl;
|
|
||||||
// oauth授权回调地址
|
|
||||||
private String backurl;
|
|
||||||
// 服务器校验token
|
|
||||||
private String token;
|
|
||||||
|
|
||||||
// 公众号用户名
|
|
||||||
private String uname;
|
|
||||||
// 公众号密码
|
|
||||||
private String pwd;
|
|
||||||
// 登录时验证码(如果有)
|
|
||||||
private String imgcode;
|
|
||||||
// 当要求输入验证码时,cookie需带上
|
|
||||||
private String sig;
|
|
||||||
|
|
||||||
public WeixinExecutor(String backurl, String pushurl, String token,
|
|
||||||
String uname, String pwd, String imgcode, String sig) {
|
|
||||||
this.backurl = backurl;
|
|
||||||
this.pushurl = pushurl;
|
|
||||||
this.token = token;
|
|
||||||
|
|
||||||
this.uname = uname;
|
|
||||||
this.pwd = pwd;
|
|
||||||
this.imgcode = StringUtils.isBlank(imgcode) ? "" : imgcode;
|
|
||||||
this.sig = sig;
|
|
||||||
|
|
||||||
weixin = new JSONObject();
|
|
||||||
weixin.put("host", "mp.weixin.qq.com");
|
|
||||||
weixin.put("base", "https://mp.weixin.qq.com");
|
|
||||||
weixin.put("auth", "https://mp.weixin.qq.com/cgi-bin/login?lang=zh_CN");
|
|
||||||
weixin.put(
|
|
||||||
"call",
|
|
||||||
"https://mp.weixin.qq.com/advanced/callbackprofile?t=ajax-response&token=%s&lang=zh_CN");
|
|
||||||
weixin.put("start",
|
|
||||||
"https://mp.weixin.qq.com/misc/skeyform?form=advancedswitchform");
|
|
||||||
weixin.put("back",
|
|
||||||
"https://mp.weixin.qq.com/merchant/myservice?action=set_oauth_domain&f=json");
|
|
||||||
weixin.put("verifycode",
|
|
||||||
"https://mp.weixin.qq.com/cgi-bin/verifycode?username=" + uname
|
|
||||||
+ "&r=%s");
|
|
||||||
weixin.put("bedeveloper",
|
|
||||||
"https://mp.weixin.qq.com/advanced/advanced?action=agreement");
|
|
||||||
|
|
||||||
List<BasicHeader> headers = new ArrayList<BasicHeader>();
|
|
||||||
headers.add(new BasicHeader("Origin", weixin.getString("base")));
|
|
||||||
headers.add(new BasicHeader("Connection", "keep-alive"));
|
|
||||||
headers.add(new BasicHeader(
|
|
||||||
"User-Agent",
|
|
||||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36"));
|
|
||||||
|
|
||||||
client = new DefaultHttpClient();
|
|
||||||
client.getParams().setParameter(ClientPNames.COOKIE_POLICY,
|
|
||||||
CookiePolicy.BROWSER_COMPATIBILITY);
|
|
||||||
client.getParams().setBooleanParameter(
|
|
||||||
"http.protocol.single-cookie-header", true);
|
|
||||||
client.getParams().setParameter(ClientPNames.DEFAULT_HEADERS, headers);
|
|
||||||
|
|
||||||
host = new HttpHost(weixin.getString("host"), -1, "https");
|
|
||||||
}
|
|
||||||
|
|
||||||
public JSONObject process() {
|
|
||||||
// 1.登陆微信公众号
|
|
||||||
step1_login();
|
|
||||||
int code = weixin.getIntValue("code");
|
|
||||||
if (code == 0) {
|
|
||||||
// 2.收集相关信息
|
|
||||||
step2_collect();
|
|
||||||
code = weixin.getIntValue("code");
|
|
||||||
// 3.填写服务器配置
|
|
||||||
// 3-1.未初始化账号
|
|
||||||
// 3-2.已配置账号
|
|
||||||
if (code == 0) {
|
|
||||||
step3_setting();
|
|
||||||
}
|
|
||||||
code = weixin.getIntValue("code");
|
|
||||||
// 4.修改网页授权地址
|
|
||||||
if (code == 0) {
|
|
||||||
step4_back();
|
|
||||||
}
|
|
||||||
// 5.创建底部菜单 (调用封装好的API)
|
|
||||||
// 5-1.订阅号
|
|
||||||
// 5-2.服务号
|
|
||||||
// 6.完成
|
|
||||||
}
|
|
||||||
return weixin;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* step1:登录操作
|
|
||||||
*/
|
|
||||||
private void step1_login() {
|
|
||||||
HttpPost method = new HttpPost(weixin.getString("auth"));
|
|
||||||
try {
|
|
||||||
List<NameValuePair> parameters = new ArrayList<NameValuePair>();
|
|
||||||
parameters.add(new BasicNameValuePair("username", uname));
|
|
||||||
parameters.add(new BasicNameValuePair("pwd", DigestUtils.md5Hex(pwd
|
|
||||||
.getBytes(Consts.UTF_8))));
|
|
||||||
parameters.add(new BasicNameValuePair("f", "json"));
|
|
||||||
parameters.add(new BasicNameValuePair("imgcode", imgcode));
|
|
||||||
if (!StringUtils.isBlank(imgcode)) {
|
|
||||||
method.addHeader("Cookie", "sig=" + sig);
|
|
||||||
}
|
|
||||||
method.setEntity(new UrlEncodedFormEntity(parameters, Consts.UTF_8));
|
|
||||||
method.addHeader("Referer", weixin.getString("base"));
|
|
||||||
|
|
||||||
HttpResponse response = client.execute(host, method);
|
|
||||||
HttpEntity entity = response.getEntity();
|
|
||||||
Document root = Jsoup.parse(entity.getContent(),
|
|
||||||
Consts.UTF_8.name(), weixin.getString("base"));
|
|
||||||
StatusLine line = response.getStatusLine();
|
|
||||||
logger.info("step1_login--->status={},body=\n{}", line,
|
|
||||||
root.toString());
|
|
||||||
if (line.getStatusCode() == HttpStatus.SC_OK) {
|
|
||||||
JSONObject body = JSON.parseObject(root.body().text());
|
|
||||||
|
|
||||||
String msg = "";
|
|
||||||
int code = 0;
|
|
||||||
switch (body.getIntValue("ret")
|
|
||||||
+ body.getJSONObject("base_resp").getIntValue("ret")) {
|
|
||||||
case -1:
|
|
||||||
msg = "系统错误,请稍候再试。";
|
|
||||||
code = -1;
|
|
||||||
break;
|
|
||||||
case -2:
|
|
||||||
msg = "帐号或密码错误。";
|
|
||||||
code = 100;
|
|
||||||
break;
|
|
||||||
case -23:
|
|
||||||
msg = "您输入的帐号或者密码不正确,请重新输入。";
|
|
||||||
code = 101;
|
|
||||||
break;
|
|
||||||
case -21:
|
|
||||||
msg = "不存在该帐户。";
|
|
||||||
code = 102;
|
|
||||||
break;
|
|
||||||
case -7:
|
|
||||||
msg = "您目前处于访问受限状态。";
|
|
||||||
code = 103;
|
|
||||||
break;
|
|
||||||
case -8:
|
|
||||||
msg = "请输入图中的验证码";
|
|
||||||
code = 104;
|
|
||||||
break;
|
|
||||||
case -27:
|
|
||||||
msg = "您输入的验证码不正确,请重新输入";
|
|
||||||
code = 105;
|
|
||||||
break;
|
|
||||||
case -26:
|
|
||||||
msg = "该公众会议号已经过期,无法再登录使用。";
|
|
||||||
code = 106;
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
msg = "成功登录,正在跳转...";
|
|
||||||
break;
|
|
||||||
case -25:
|
|
||||||
msg = "海外帐号请在公众平台海外版登录,<a href=\"http://admin.wechat.com/\">点击登录</a>";
|
|
||||||
code = 107;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
msg = "未知错误";
|
|
||||||
code = 108;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (code == 0) {
|
|
||||||
weixin.put(
|
|
||||||
"urlToken",
|
|
||||||
getQueryMap(body.getString("redirect_url")).get(
|
|
||||||
"token"));
|
|
||||||
weixin.put("indexUrl", String.format("%s%s",
|
|
||||||
weixin.getString("base"),
|
|
||||||
body.getString("redirect_url")));
|
|
||||||
weixin.put("step", "1");
|
|
||||||
} else {
|
|
||||||
if (code == 104 || code == 105) {
|
|
||||||
// 下载验证码
|
|
||||||
HttpGet get = new HttpGet(String.format(
|
|
||||||
weixin.getString("verifycode"),
|
|
||||||
System.currentTimeMillis()));
|
|
||||||
get.setHeaders(method.getAllHeaders());
|
|
||||||
response = client.execute(host, get);
|
|
||||||
StringBuffer base64 = new StringBuffer();
|
|
||||||
base64.append("data:")
|
|
||||||
.append(response.getFirstHeader("Content-Type")
|
|
||||||
.getValue()).append(";base64,");
|
|
||||||
base64.append(new String(
|
|
||||||
Base64.encodeBase64(IOUtil.toByteArray(response
|
|
||||||
.getEntity().getContent())),
|
|
||||||
Consts.UTF_8));
|
|
||||||
weixin.put("verifydata", base64.toString());
|
|
||||||
List<Cookie> cookieList = client.getCookieStore()
|
|
||||||
.getCookies();
|
|
||||||
for (Cookie cookie : cookieList) {
|
|
||||||
if (cookie.getName().equals("sig")) {
|
|
||||||
weixin.put("sig", cookie.getValue());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
weixin.put("code", code);
|
|
||||||
weixin.put("msg", msg);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
weixin.put("code", "-3");
|
|
||||||
weixin.put("msg", "网络异常,请稍后重试!");
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
weixin.put("code", "-2");
|
|
||||||
weixin.put("msg", "服务器繁忙,请稍后重试!");
|
|
||||||
weixin.put("exception", e.getMessage());
|
|
||||||
logger.error("step1_login catch error", e);
|
|
||||||
} finally {
|
|
||||||
if (weixin.getIntValue("code") != 0) {
|
|
||||||
client.getConnectionManager().shutdown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* step2:收集信息
|
|
||||||
*/
|
|
||||||
private void step2_collect() {
|
|
||||||
String url = weixin.getString("indexUrl");
|
|
||||||
HttpGet method = new HttpGet(url);
|
|
||||||
try {
|
|
||||||
method.addHeader("Referer", weixin.getString("base"));
|
|
||||||
|
|
||||||
HttpResponse response = client.execute(host, method);
|
|
||||||
HttpEntity entity = response.getEntity();
|
|
||||||
Document root = Jsoup.parse(entity.getContent(),
|
|
||||||
Consts.UTF_8.name(), weixin.getString("base"));
|
|
||||||
StatusLine line = response.getStatusLine();
|
|
||||||
logger.info("step2_setting--->status={},body=\n{}", line,
|
|
||||||
root.toString());
|
|
||||||
if (line.getStatusCode() == HttpStatus.SC_OK) {
|
|
||||||
Element ele = root.getElementById("menuBar")
|
|
||||||
.getElementsByTag("dl").last();
|
|
||||||
url = ele.getElementsByTag("a").last().absUrl("href");
|
|
||||||
|
|
||||||
weixin.put("developerUrl", url);
|
|
||||||
|
|
||||||
method.addHeader("Referer", url);
|
|
||||||
url = ele.previousElementSibling().getElementsByTag("a")
|
|
||||||
.first().absUrl("href");
|
|
||||||
weixin.put("settingUrl", url);
|
|
||||||
method.setURI(URI.create(url));
|
|
||||||
|
|
||||||
response = client.execute(host, method);
|
|
||||||
entity = response.getEntity();
|
|
||||||
root = Jsoup.parse(entity.getContent(), Consts.UTF_8.name(),
|
|
||||||
weixin.getString("base"));
|
|
||||||
line = response.getStatusLine();
|
|
||||||
weixin.put("step", "2-1");
|
|
||||||
// 公众号配置页面
|
|
||||||
if (line.getStatusCode() == HttpStatus.SC_OK) {
|
|
||||||
Elements eles = root.getElementById("settingArea")
|
|
||||||
.getElementsByTag("li");
|
|
||||||
String key, value;
|
|
||||||
for (Element element : eles) {
|
|
||||||
key = element.getElementsByTag("h4").first().text();
|
|
||||||
ele = element.getElementsByClass("meta_content")
|
|
||||||
.first();
|
|
||||||
if (ele.children().isEmpty()) {
|
|
||||||
value = ele.text();
|
|
||||||
} else {
|
|
||||||
if (ele.child(0).tagName().equalsIgnoreCase("a")) {
|
|
||||||
value = ele.child(0).absUrl("href");
|
|
||||||
} else if (ele.child(0).tagName()
|
|
||||||
.equalsIgnoreCase("img")) {
|
|
||||||
value = ele.child(0).absUrl("src");
|
|
||||||
} else {
|
|
||||||
value = ele.text();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
weixin.put(accountMap.get(key), value);
|
|
||||||
}
|
|
||||||
weixin.put("isVerify", weixin.getString("weixinVerify")
|
|
||||||
.contains("微信认证"));
|
|
||||||
weixin.put("isService", weixin.getString("accountType")
|
|
||||||
.contains("服务号"));
|
|
||||||
weixin.put("isSubscribe", weixin.getString("accountType")
|
|
||||||
.contains("订阅号"));
|
|
||||||
value = weixin.getString("qrcodeUrl");
|
|
||||||
|
|
||||||
method.setURI(URI.create(value));
|
|
||||||
response = client.execute(host, method);
|
|
||||||
weixin.put("qrcodeData", IOUtil.toByteArray(response
|
|
||||||
.getEntity().getContent()));
|
|
||||||
|
|
||||||
weixin.put("step", "2-2");
|
|
||||||
// 开发者页面
|
|
||||||
method.addHeader("Referer", url);
|
|
||||||
method.setURI(URI.create(weixin.getString("developerUrl")));
|
|
||||||
|
|
||||||
response = client.execute(host, method);
|
|
||||||
entity = response.getEntity();
|
|
||||||
root = Jsoup.parse(entity.getContent(),
|
|
||||||
Consts.UTF_8.name(), weixin.getString("base"));
|
|
||||||
line = response.getStatusLine();
|
|
||||||
|
|
||||||
if (line.getStatusCode() == HttpStatus.SC_OK) {
|
|
||||||
// 还没有成为开发者 2014.10-06 jy.hu
|
|
||||||
// 触发成为开发者动作
|
|
||||||
ele = root.getElementById("js_toBeDeveloper");
|
|
||||||
if (ele != null && ele.hasText()) {
|
|
||||||
HttpPost post = new HttpPost(URI.create(weixin
|
|
||||||
.getString("bedeveloper")));
|
|
||||||
post.addHeader("Referer", url);
|
|
||||||
List<NameValuePair> parameters = new ArrayList<NameValuePair>();
|
|
||||||
parameters.add(new BasicNameValuePair("token",
|
|
||||||
weixin.getString("urlToken")));
|
|
||||||
parameters.add(new BasicNameValuePair("f", "json"));
|
|
||||||
parameters.add(new BasicNameValuePair("ajax", "1"));
|
|
||||||
parameters.add(new BasicNameValuePair("lang",
|
|
||||||
"zh_CN"));
|
|
||||||
parameters.add(new BasicNameValuePair("random",
|
|
||||||
System.currentTimeMillis() + ""));
|
|
||||||
|
|
||||||
post.setEntity(new UrlEncodedFormEntity(parameters,
|
|
||||||
Consts.UTF_8));
|
|
||||||
response = client.execute(host, post);
|
|
||||||
entity = response.getEntity();
|
|
||||||
root = Jsoup.parse(entity.getContent(),
|
|
||||||
Consts.UTF_8.name(),
|
|
||||||
weixin.getString("base"));
|
|
||||||
line = response.getStatusLine();
|
|
||||||
logger.info(
|
|
||||||
"step2_bedeveloper--->status={},body=\n{}",
|
|
||||||
line, root.toString());
|
|
||||||
if (line.getStatusCode() == HttpStatus.SC_OK) {
|
|
||||||
JSONObject body = JSON.parseObject(root.body()
|
|
||||||
.text());
|
|
||||||
if (body.getIntValue("ret") == 0) {
|
|
||||||
method.addHeader("Referer", url);
|
|
||||||
method.setURI(URI.create(weixin
|
|
||||||
.getString("developerUrl")));
|
|
||||||
|
|
||||||
response = client.execute(host, method);
|
|
||||||
entity = response.getEntity();
|
|
||||||
root = Jsoup.parse(entity.getContent(),
|
|
||||||
Consts.UTF_8.name(),
|
|
||||||
weixin.getString("base"));
|
|
||||||
} else {
|
|
||||||
weixin.put("code", "-100");
|
|
||||||
weixin.put("msg", "成为开发者失败!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 初始化状态
|
|
||||||
// 配置未启用状态
|
|
||||||
// 配置已启用状态
|
|
||||||
eles = root.getElementsByClass("developer_info_opr");
|
|
||||||
if (eles != null && eles.hasText()) {
|
|
||||||
weixin.put("developerModifyUrl", eles.first()
|
|
||||||
.children().first().absUrl("href"));
|
|
||||||
weixin.put("status",
|
|
||||||
eles.text().contains("启用") ? "READY"
|
|
||||||
: "RUNNING");
|
|
||||||
} else {
|
|
||||||
weixin.put("status", "INIT");
|
|
||||||
}
|
|
||||||
// appid&appsecret
|
|
||||||
if (weixin.getBooleanValue("isService")
|
|
||||||
|| (weixin.getBooleanValue("isSubscribe") && weixin
|
|
||||||
.getBooleanValue("isVerify"))) {
|
|
||||||
eles = root
|
|
||||||
.getElementsByClass("developer_info_item")
|
|
||||||
.first().children().last()
|
|
||||||
.getElementsByClass("frm_controls");
|
|
||||||
weixin.put("appId", eles.first().text());
|
|
||||||
weixin.put("appSecret",
|
|
||||||
eles.last().text().replace("重置", "").trim());
|
|
||||||
}
|
|
||||||
weixin.put("step", "2-3");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
weixin.put("code", "-3");
|
|
||||||
weixin.put("msg", "网络异常,请稍后重试!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
weixin.put("code", "-3");
|
|
||||||
weixin.put("msg", "网络异常,请稍后重试!");
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
weixin.put("code", "-2");
|
|
||||||
weixin.put("msg", "服务器繁忙,请稍后重试!");
|
|
||||||
weixin.put("exception", e.getMessage());
|
|
||||||
logger.error("step2_collect catch error", e);
|
|
||||||
} finally {
|
|
||||||
if (weixin.getIntValue("code") != 0) {
|
|
||||||
client.getConnectionManager().shutdown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* step3:填写配置
|
|
||||||
*/
|
|
||||||
private void step3_setting() {
|
|
||||||
HttpPost method = new HttpPost(String.format(weixin.getString("call"),
|
|
||||||
weixin.getString("urlToken")));
|
|
||||||
try {
|
|
||||||
List<NameValuePair> parameters = new ArrayList<NameValuePair>();
|
|
||||||
parameters.add(new BasicNameValuePair("url", pushurl));
|
|
||||||
parameters.add(new BasicNameValuePair("callback_token", token));
|
|
||||||
// EncodingAESKey | 消息加解密方式(明文0,兼容1,安全2)
|
|
||||||
parameters.add(new BasicNameValuePair("encoding_aeskey", RandomUtil
|
|
||||||
.generateString(43)));
|
|
||||||
parameters
|
|
||||||
.add(new BasicNameValuePair("callback_encrypt_mode", "0"));
|
|
||||||
parameters.add(new BasicNameValuePair("operation_seq", RandomUtil
|
|
||||||
.generateStringByNumberChar(9)));
|
|
||||||
method.setEntity(new UrlEncodedFormEntity(parameters, Consts.UTF_8));
|
|
||||||
method.addHeader("Referer", weixin.getString("developerModifyUrl"));
|
|
||||||
|
|
||||||
HttpResponse response = client.execute(host, method);
|
|
||||||
HttpEntity entity = response.getEntity();
|
|
||||||
Document root = Jsoup.parse(entity.getContent(),
|
|
||||||
Consts.UTF_8.name(), weixin.getString("base"));
|
|
||||||
StatusLine line = response.getStatusLine();
|
|
||||||
logger.info("step3_setting--->status={},body=\n{}", line,
|
|
||||||
root.toString());
|
|
||||||
if (line.getStatusCode() == HttpStatus.SC_OK) {
|
|
||||||
JSONObject body = JSON.parseObject(root.body().text());
|
|
||||||
String msg = "";
|
|
||||||
int code = 0;
|
|
||||||
switch (body.getIntValue("ret")
|
|
||||||
+ body.getJSONObject("base_resp").getIntValue("ret")) {
|
|
||||||
case -201:
|
|
||||||
msg = "无效的URL";
|
|
||||||
code = 200;
|
|
||||||
break;
|
|
||||||
case -202:
|
|
||||||
msg = "无效的Token";
|
|
||||||
code = 201;
|
|
||||||
break;
|
|
||||||
case -203:
|
|
||||||
msg = "操作频率太快,请休息一下。";
|
|
||||||
code = 202;
|
|
||||||
break;
|
|
||||||
case -204:
|
|
||||||
msg = "请先在设置页面完善当前帐号信息";
|
|
||||||
code = 203;
|
|
||||||
break;
|
|
||||||
case -205:
|
|
||||||
msg = "该URL可能存在安全风险,请检查";
|
|
||||||
code = 207;
|
|
||||||
break;
|
|
||||||
case -301:
|
|
||||||
msg = "请求URL超时";
|
|
||||||
code = 204;
|
|
||||||
break;
|
|
||||||
case -302:
|
|
||||||
msg = "服务器没有正确响应Token验证,请稍后重试";
|
|
||||||
code = 205;
|
|
||||||
break;
|
|
||||||
case -104:
|
|
||||||
msg = "参数错误,请重新填写。";
|
|
||||||
code = 206;
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
msg = "配置成功..";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
msg = "未知错误";
|
|
||||||
code = 108;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (code == 0) {
|
|
||||||
// 触发启用按钮
|
|
||||||
if (!weixin.getString("status").equals("RUNNING")) {
|
|
||||||
parameters = new ArrayList<NameValuePair>();
|
|
||||||
parameters.add(new BasicNameValuePair("token", weixin
|
|
||||||
.getString("urlToken")));
|
|
||||||
parameters.add(new BasicNameValuePair("f", "json"));
|
|
||||||
parameters.add(new BasicNameValuePair("ajax", "1"));
|
|
||||||
parameters.add(new BasicNameValuePair("flag", "1"));
|
|
||||||
parameters.add(new BasicNameValuePair("type", "2"));
|
|
||||||
parameters.add(new BasicNameValuePair("lang", "zh_CN"));
|
|
||||||
parameters.add(new BasicNameValuePair("random", System
|
|
||||||
.currentTimeMillis() + ""));
|
|
||||||
|
|
||||||
method.setEntity(new UrlEncodedFormEntity(parameters,
|
|
||||||
Consts.UTF_8));
|
|
||||||
method.setURI(URI.create(weixin.getString("start")));
|
|
||||||
|
|
||||||
response = client.execute(host, method);
|
|
||||||
entity = response.getEntity();
|
|
||||||
root = Jsoup.parse(entity.getContent(),
|
|
||||||
Consts.UTF_8.name(), weixin.getString("base"));
|
|
||||||
line = response.getStatusLine();
|
|
||||||
logger.info("step3_setting--->status={},body=\n{}",
|
|
||||||
line, root.toString());
|
|
||||||
if (line.getStatusCode() == HttpStatus.SC_OK) {
|
|
||||||
body = JSON.parseObject(root.body().text());
|
|
||||||
if (body.getIntValue("ret")
|
|
||||||
+ body.getJSONObject("base_resp")
|
|
||||||
.getIntValue("ret") != 0) {
|
|
||||||
weixin.put("code", 300);
|
|
||||||
weixin.put("msg", "启用开发者模式失败,请稍后再试!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
weixin.put("step", "3");
|
|
||||||
} else {
|
|
||||||
weixin.put("code", code);
|
|
||||||
weixin.put("msg", msg);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
weixin.put("code", "-3");
|
|
||||||
weixin.put("msg", "网络异常,请稍后重试!");
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
weixin.put("code", "-2");
|
|
||||||
weixin.put("msg", "服务器繁忙,请稍后重试!");
|
|
||||||
weixin.put("exception", e.getMessage());
|
|
||||||
logger.error("step3_setting catch error", e);
|
|
||||||
} finally {
|
|
||||||
if (weixin.getIntValue("code") != 0) {
|
|
||||||
client.getConnectionManager().shutdown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* step4:修改回调
|
|
||||||
*/
|
|
||||||
private void step4_back() {
|
|
||||||
try {
|
|
||||||
if (weixin.getBooleanValue("isVerify")) {
|
|
||||||
HttpPost method = new HttpPost(weixin.getString("back"));
|
|
||||||
|
|
||||||
List<NameValuePair> parameters = new ArrayList<NameValuePair>();
|
|
||||||
parameters.add(new BasicNameValuePair("domain", backurl));
|
|
||||||
parameters.add(new BasicNameValuePair("token", weixin
|
|
||||||
.getString("urlToken")));
|
|
||||||
parameters.add(new BasicNameValuePair("f", "json"));
|
|
||||||
parameters.add(new BasicNameValuePair("ajax", "1"));
|
|
||||||
parameters.add(new BasicNameValuePair("flag", "1"));
|
|
||||||
parameters.add(new BasicNameValuePair("lang", "zh_CN"));
|
|
||||||
parameters.add(new BasicNameValuePair("random", System
|
|
||||||
.currentTimeMillis() + ""));
|
|
||||||
method.setEntity(new UrlEncodedFormEntity(parameters,
|
|
||||||
Consts.UTF_8));
|
|
||||||
method.addHeader("Referer", weixin.getString("developerUrl"));
|
|
||||||
|
|
||||||
HttpResponse response = client.execute(host, method);
|
|
||||||
HttpEntity entity = response.getEntity();
|
|
||||||
Document root = Jsoup.parse(entity.getContent(),
|
|
||||||
Consts.UTF_8.name(), weixin.getString("base"));
|
|
||||||
StatusLine line = response.getStatusLine();
|
|
||||||
logger.info("step4_back--->status={},body=\n{}", line,
|
|
||||||
root.toString());
|
|
||||||
if (line.getStatusCode() == HttpStatus.SC_OK) {
|
|
||||||
JSONObject body = JSON.parseObject(root.body().text());
|
|
||||||
if (body.getIntValue("ret")
|
|
||||||
+ body.getJSONObject("base_resp")
|
|
||||||
.getIntValue("ret") != 0) {
|
|
||||||
weixin.put("code", "400");
|
|
||||||
weixin.put("msg", "修改授权回调地址失败!");
|
|
||||||
}
|
|
||||||
weixin.put("step", "4");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logger.info("公众号尚未认证,放弃本次修改授权回调地址操作。{}", weixin);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
weixin.put("code", "-2");
|
|
||||||
weixin.put("msg", "服务器繁忙,请稍后重试!");
|
|
||||||
weixin.put("exception", e.getMessage());
|
|
||||||
logger.error("step4_back catch error", e);
|
|
||||||
} finally {
|
|
||||||
client.getConnectionManager().shutdown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, String> getQueryMap(String query) {
|
|
||||||
String[] params = query.split("&");
|
|
||||||
Map<String, String> map = new HashMap<String, String>();
|
|
||||||
for (String param : params) {
|
|
||||||
String name = param.split("=")[0];
|
|
||||||
String value = param.split("=")[1];
|
|
||||||
map.put(name, value);
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
package com.foxinmy.weixin4j.mp.type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 公众号事件类型
|
|
||||||
*
|
|
||||||
* @className EventType
|
|
||||||
* @author jy
|
|
||||||
* @date 2014年9月30日
|
|
||||||
* @since JDK 1.7
|
|
||||||
* @see
|
|
||||||
*/
|
|
||||||
public enum EventType {
|
|
||||||
/**
|
|
||||||
* 二维码扫描事件
|
|
||||||
*
|
|
||||||
* @see com.foxinmy.weixin4j.mp.event.ScanEventMessage
|
|
||||||
*/
|
|
||||||
scan,
|
|
||||||
/**
|
|
||||||
* 群发消息事件
|
|
||||||
*
|
|
||||||
* @see com.foxinmy.weixin4j.mp.event.MassEventMessage
|
|
||||||
*/
|
|
||||||
masssendjobfinish,
|
|
||||||
/**
|
|
||||||
* 模板消息事件
|
|
||||||
*
|
|
||||||
* @see com.foxinmy.weixin4j.mp.event.TemplatesendjobfinishMessage
|
|
||||||
*/
|
|
||||||
templatesendjobfinish,
|
|
||||||
/**
|
|
||||||
* 客服接入会话事件
|
|
||||||
*
|
|
||||||
* @see com.foxinmy.weixin4j.mp.event.KfCreateEventMessage
|
|
||||||
*/
|
|
||||||
kf_create_session,
|
|
||||||
/**
|
|
||||||
* 客服关闭会话事件
|
|
||||||
*
|
|
||||||
* @see com.foxinmy.weixin4j.mp.event.KfCloseEventMessage
|
|
||||||
*/
|
|
||||||
kf_close_session,
|
|
||||||
/**
|
|
||||||
* 客服转接会话事件
|
|
||||||
*
|
|
||||||
* @see com.foxinmy.weixin4j.mp.event.KfSwitchEventMessage
|
|
||||||
*/
|
|
||||||
kf_switch_session,
|
|
||||||
/**
|
|
||||||
* 异步任务完成事件
|
|
||||||
*
|
|
||||||
* @see com.foxinmy.weixin4j.mp.event.BatchjobresultMessage
|
|
||||||
*/
|
|
||||||
batch_job_result;
|
|
||||||
}
|
|
||||||
@ -11,7 +11,6 @@ import java.util.Collection;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
|
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFFont;
|
import org.apache.poi.hssf.usermodel.HSSFFont;
|
||||||
@ -32,6 +31,7 @@ import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* excel工具类
|
* excel工具类
|
||||||
@ -55,7 +55,7 @@ public class ExcelUtil {
|
|||||||
*/
|
*/
|
||||||
public static String[][] read(File file) throws Exception {
|
public static String[][] read(File file) throws Exception {
|
||||||
String fileExt = getExtension(file.getName());
|
String fileExt = getExtension(file.getName());
|
||||||
if (StringUtils.isNotBlank(fileExt)) {
|
if (StringUtil.isNotBlank(fileExt)) {
|
||||||
if (fileExt.toLowerCase().equals("xls")) {// 2003
|
if (fileExt.toLowerCase().equals("xls")) {// 2003
|
||||||
BufferedInputStream in = new BufferedInputStream(
|
BufferedInputStream in = new BufferedInputStream(
|
||||||
new FileInputStream(file));
|
new FileInputStream(file));
|
||||||
@ -75,7 +75,7 @@ public class ExcelUtil {
|
|||||||
public static String[][] read4Special(File file, String fileName,
|
public static String[][] read4Special(File file, String fileName,
|
||||||
int columnSize) throws Exception {
|
int columnSize) throws Exception {
|
||||||
String fileExt = getExtension(fileName);
|
String fileExt = getExtension(fileName);
|
||||||
if (StringUtils.isNotBlank(fileExt)) {
|
if (StringUtil.isNotBlank(fileExt)) {
|
||||||
if (fileExt.toLowerCase().equals("xls")) {// 2003
|
if (fileExt.toLowerCase().equals("xls")) {// 2003
|
||||||
BufferedInputStream in = new BufferedInputStream(
|
BufferedInputStream in = new BufferedInputStream(
|
||||||
new FileInputStream(file));
|
new FileInputStream(file));
|
||||||
|
|||||||
@ -0,0 +1,323 @@
|
|||||||
|
package com.foxinmy.weixin4j.mp.util;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.foxinmy.weixin4j.exception.PayException;
|
||||||
|
import com.foxinmy.weixin4j.http.XmlResult;
|
||||||
|
import com.foxinmy.weixin4j.model.Consts;
|
||||||
|
import com.foxinmy.weixin4j.mp.model.WeixinMpAccount;
|
||||||
|
import com.foxinmy.weixin4j.mp.payment.JsPayNotify;
|
||||||
|
import com.foxinmy.weixin4j.mp.payment.PayPackage;
|
||||||
|
import com.foxinmy.weixin4j.mp.payment.PayUtil;
|
||||||
|
import com.foxinmy.weixin4j.mp.payment.conver.CouponConverter;
|
||||||
|
import com.foxinmy.weixin4j.mp.payment.v2.NativePayNotifyV2;
|
||||||
|
import com.foxinmy.weixin4j.mp.payment.v2.NativePayResponseV2;
|
||||||
|
import com.foxinmy.weixin4j.mp.payment.v2.PayFeedback;
|
||||||
|
import com.foxinmy.weixin4j.mp.payment.v2.PayPackageV2;
|
||||||
|
import com.foxinmy.weixin4j.mp.payment.v2.PayWarn;
|
||||||
|
import com.foxinmy.weixin4j.mp.payment.v3.NativePayNotifyV3;
|
||||||
|
import com.foxinmy.weixin4j.mp.payment.v3.NativePayResponseV3;
|
||||||
|
import com.foxinmy.weixin4j.mp.payment.v3.PayPackageV3;
|
||||||
|
import com.foxinmy.weixin4j.mp.type.TradeType;
|
||||||
|
import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||||
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
|
import com.foxinmy.weixin4j.xml.XmlStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付示例
|
||||||
|
*
|
||||||
|
* @className PayDemo
|
||||||
|
* @author jy
|
||||||
|
* @date 2014年10月28日
|
||||||
|
* @since JDK 1.7
|
||||||
|
* @see
|
||||||
|
*/
|
||||||
|
public final class PayDemo {
|
||||||
|
|
||||||
|
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JSAPI支付
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public JSONObject jsPay() {
|
||||||
|
JSONObject obj = new JSONObject();
|
||||||
|
WeixinMpAccount weixinAccount = JSON.parseObject(
|
||||||
|
ConfigUtil.getValue("account"), WeixinMpAccount.class);
|
||||||
|
// V3 支付
|
||||||
|
PayPackage payPackage = new PayPackageV3(weixinAccount, "用户openid",
|
||||||
|
"商品描述", "系统内部订单号", 1d, "IP地址", TradeType.JSAPI);
|
||||||
|
// V2 支付
|
||||||
|
payPackage = new PayPackageV2("商品描述", weixinAccount.getPartnerId(),
|
||||||
|
"系统内部订单号", 1d, "回调地址", "IP地址");
|
||||||
|
payPackage.setAttach("ID");
|
||||||
|
String jspay = null;
|
||||||
|
try {
|
||||||
|
jspay = PayUtil.createPayJsRequestJson(payPackage, weixinAccount);
|
||||||
|
} catch (PayException e) {
|
||||||
|
log.error("create jspay error,{}", weixinAccount, e);
|
||||||
|
}
|
||||||
|
if (StringUtil.isBlank(jspay)) {
|
||||||
|
obj.put("code", "-2");
|
||||||
|
obj.put("msg", "创建支付链接失败!");
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
obj.put("code", "0");
|
||||||
|
obj.put("jspay", jspay);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 编辑收货地址 SnsToken token = (SnsToken) getSession("AccessToken");
|
||||||
|
* obj.put("editaddress", PayUtil.createAddressRequestJson(
|
||||||
|
* wx.getAppId(), getFullLoction(), token.getAccess_token()));
|
||||||
|
*/
|
||||||
|
log.info("js pay....{}", obj);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JSAPI(V2)支付成功(前端)时的回调通知<br>
|
||||||
|
* <xml></br> <OpenId><![CDATA[111222]]></OpenId></br>
|
||||||
|
* <AppId><![CDATA[wwwwb4f85f3a797777]]></AppId></br>
|
||||||
|
* <IsSubscribe>1</IsSubscribe></br>
|
||||||
|
* <TimeStamp>1369743511</TimeStamp></br>
|
||||||
|
* <NonceStr><![CDATA[jALldRTHAFd5Tgs5]]></NonceStr></br>
|
||||||
|
* <AppSignature><![CDATA[bafe07f060f22dcda0bfdb4b5ff756f973aecffa]]>
|
||||||
|
* </AppSignature></br>
|
||||||
|
* <SignMethod><![CDATA[sha1]]></SignMethod></br> </xml></br>
|
||||||
|
* 参与签名的字段为: appid、appkey、timestamp、noncestr、openid、issubscribe
|
||||||
|
*
|
||||||
|
* @param 订单信息
|
||||||
|
* @param inputStream
|
||||||
|
* 用户信息
|
||||||
|
*
|
||||||
|
* @see com.foxinmy.weixin4j.mp.payment.JsPayNotify
|
||||||
|
* @return success或其他
|
||||||
|
*/
|
||||||
|
public String jsNotifyV2(InputStream inputStream) {
|
||||||
|
Map<String, String> objMap = new HashMap<String, String>();
|
||||||
|
/*
|
||||||
|
* 收集url中携带的参数 /pay/notify/back?attach=8&bank_billno=201410293351060&
|
||||||
|
* bank_type=2032&discount=0&fee_type=1&input_charset=UTF-8&
|
||||||
|
* notify_id=9fKbVf_qg6y-
|
||||||
|
* wSjtSMV0PLXeEn2oGfTM1s9dWSvR2B9U6iFQRTzmjrMWKUxvh9mpBLvnh8aqFbC_OFk1pTvFnFUO00Lln4fh
|
||||||
|
* & out_trade_no=D14102900031&partner=1221928801&product_fee=1&
|
||||||
|
* sign=B9D6E772C271C9B86B8436FC9F5DFC1A&
|
||||||
|
* sign_type=MD5&time_end=20141029183707&
|
||||||
|
* total_fee=1&trade_mode=1&trade_state=0&
|
||||||
|
* transaction_id=1221928801201410296039230054&transport_fee=0
|
||||||
|
*/
|
||||||
|
log.info("jspay_notify_orderinfo,{}", objMap);
|
||||||
|
JsPayNotify payNotify = XmlStream.get(inputStream, JsPayNotify.class);
|
||||||
|
log.info("jspay_notify_userinfo,{}", payNotify);
|
||||||
|
WeixinMpAccount weixinAccount = JSON.parseObject(
|
||||||
|
ConfigUtil.getValue("account"), WeixinMpAccount.class);
|
||||||
|
// 验证财付通签名
|
||||||
|
String sign = objMap.get("sign");
|
||||||
|
objMap.remove("sign");
|
||||||
|
String _sign = PayUtil
|
||||||
|
.paysignMd5(objMap, weixinAccount.getPartnerKey());
|
||||||
|
log.info("财付通签名----->sign={},vaild_sign={}", sign, _sign);
|
||||||
|
if (!sign.equals(_sign)) {
|
||||||
|
return "fail";
|
||||||
|
}
|
||||||
|
objMap.clear();
|
||||||
|
// 验证微信签名
|
||||||
|
sign = payNotify.getPaySign();
|
||||||
|
payNotify.setPaySign(null);
|
||||||
|
payNotify.setSignType(null);
|
||||||
|
String vaild_sign = PayUtil.paysignSha(payNotify,
|
||||||
|
weixinAccount.getPaySignKey());
|
||||||
|
log.info("微信签名----->sign={},vaild_sign={}", sign, vaild_sign);
|
||||||
|
if (!sign.equals(vaild_sign)) {
|
||||||
|
return "fail";
|
||||||
|
}
|
||||||
|
// 处理业务逻辑
|
||||||
|
return "success";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JSAPI(V3)支付成功(前端)时的回调通知
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param inputStream
|
||||||
|
* 订单回调
|
||||||
|
* @return <xml><br>
|
||||||
|
* <return_code>SUCCESS/FAIL</return_code><br>
|
||||||
|
* <return_msg>如非空,为错误 原因签名失败参数格式校验错误</return_msg><br>
|
||||||
|
* </xml>
|
||||||
|
* @throws DocumentException
|
||||||
|
* @see <a
|
||||||
|
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7">支付结果通知</a>
|
||||||
|
*/
|
||||||
|
public String jsNotifyV3(InputStream inputStream) {
|
||||||
|
String orderXml = "从inputStream中读取订单信息";
|
||||||
|
com.foxinmy.weixin4j.mp.payment.v3.Order order = CouponConverter
|
||||||
|
.fromXML(orderXml,
|
||||||
|
com.foxinmy.weixin4j.mp.payment.v3.Order.class);
|
||||||
|
log.info("jsapi_notify_order_info:", order);
|
||||||
|
String sign = order.getSign();
|
||||||
|
order.setSign(null);
|
||||||
|
WeixinMpAccount weixinAccount = JSON.parseObject(
|
||||||
|
ConfigUtil.getValue("account"), WeixinMpAccount.class);
|
||||||
|
String valid_sign = PayUtil.paysignMd5(order,
|
||||||
|
weixinAccount.getPaySignKey());
|
||||||
|
// 如果订单中存在代金券的情况并不适用
|
||||||
|
log.info("微信签名----->sign={},vaild_sign={}", sign, valid_sign);
|
||||||
|
if (!sign.equals(valid_sign)) {
|
||||||
|
return XmlStream.to(new XmlResult(Consts.FAIL, "签名错误"));
|
||||||
|
}
|
||||||
|
// 处理业务逻辑
|
||||||
|
return XmlStream.to(new XmlResult(Consts.SUCCESS, ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* V2.x版本Native支付时POST数据<br>
|
||||||
|
* <xml></br> <OpenId><![CDATA[111222]]></OpenId></br>
|
||||||
|
* <AppId><![CDATA[wwwwb4f85f3a797777]]></AppId></br>
|
||||||
|
* <IsSubscribe>1</IsSubscribe></br>
|
||||||
|
* <ProductId>[CDATA[000000]]</ProductId></br>
|
||||||
|
* <TimeStamp>1369743511</TimeStamp></br>
|
||||||
|
* <NonceStr><![CDATA[jALldRTHAFd5Tgs5]]></NonceStr></br>
|
||||||
|
* <AppSignature><![CDATA[bafe07f060f22dcda0bfdb4b5ff756f973aecffa]]>
|
||||||
|
* </AppSignature></br>
|
||||||
|
* <SignMethod><![CDATA[sha1]]></SignMethod></br> </xml></br>
|
||||||
|
* 参与签名的字段为: appid、appkey、timestamp、noncestr、openid、issubscribe、productId
|
||||||
|
*
|
||||||
|
* @param inputStream
|
||||||
|
*
|
||||||
|
* @return 必须返回一个带有Package信息的xml字符串
|
||||||
|
*/
|
||||||
|
public String nativeNotifyV2(InputStream inputStream) {
|
||||||
|
// V2.x版本
|
||||||
|
NativePayNotifyV2 payNotify = XmlStream.get(inputStream,
|
||||||
|
NativePayNotifyV2.class);
|
||||||
|
log.info("native_pay_notify,{}", payNotify);
|
||||||
|
WeixinMpAccount weixinAccount = JSON.parseObject(
|
||||||
|
ConfigUtil.getValue("account"), WeixinMpAccount.class);
|
||||||
|
String sign = payNotify.getPaySign();
|
||||||
|
payNotify.setPaySign(null);
|
||||||
|
payNotify.setSignType(null);
|
||||||
|
// 验证微信签名
|
||||||
|
String vaild_sign = PayUtil.paysignSha(payNotify,
|
||||||
|
weixinAccount.getPaySignKey());
|
||||||
|
log.info("微信签名----->sign={},vaild_sign={}", sign, vaild_sign);
|
||||||
|
if (!sign.equals(vaild_sign)) {
|
||||||
|
return "fail";
|
||||||
|
}
|
||||||
|
// 构造订单信息
|
||||||
|
PayPackageV2 payPackage = new PayPackageV2("商品描述",
|
||||||
|
weixinAccount.getPartnerId(), "系统内部订单号", 1d, "回调地址", "IP地址");
|
||||||
|
NativePayResponseV2 payResponse = new NativePayResponseV2(
|
||||||
|
weixinAccount, payPackage);
|
||||||
|
return XmlStream.to(payResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* V3.x版本native回调<br>
|
||||||
|
* <xml></br> <openid><![CDATA[111222]]></openid></br>
|
||||||
|
* <appid><![CDATA[wwwwb4f85f3a797777]]></appid></br>
|
||||||
|
* <mch_id><![CDATA[1100022]]></mch_id></br>
|
||||||
|
* <is_subscribe>1</is_subscribe></br>
|
||||||
|
* <product_id>[CDATA[000000]]</product_id></br>
|
||||||
|
* <nonce_str><![CDATA[jALldRTHAFd5Tgs5]]></nonce_str></br>
|
||||||
|
* <sign><![CDATA[bafe07f060f22dcda0bfdb4b5ff756f973aecffa]]>
|
||||||
|
* </sign></br> </xml></br>
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* @throws PayException
|
||||||
|
*/
|
||||||
|
public String nativeNotifyV3(InputStream inputStream) throws PayException {
|
||||||
|
NativePayNotifyV3 payNotify = XmlStream.get(inputStream,
|
||||||
|
NativePayNotifyV3.class);
|
||||||
|
String sign = payNotify.getSign();
|
||||||
|
payNotify.setSign(null);
|
||||||
|
WeixinMpAccount weixinAccount = JSON.parseObject(
|
||||||
|
ConfigUtil.getValue("account"), WeixinMpAccount.class);
|
||||||
|
String valid_sign = PayUtil.paysignMd5(payNotify,
|
||||||
|
weixinAccount.getPaySignKey());
|
||||||
|
log.info("微信签名----->sign={},vaild_sign={}", sign, valid_sign);
|
||||||
|
// 生成Package
|
||||||
|
PayPackageV3 payPackage = new PayPackageV3(weixinAccount, "用户openid",
|
||||||
|
"商品描述", "系统内部订单号", 1d, "IP地址", TradeType.NATIVE);
|
||||||
|
payPackage.setProductId(payNotify.getProductId());
|
||||||
|
if (!sign.equals(valid_sign)) {
|
||||||
|
// 校验失败
|
||||||
|
NativePayResponseV3 payReponse = new NativePayResponseV3("签名失败",
|
||||||
|
null);
|
||||||
|
payReponse.setSign(PayUtil.paysignMd5(payReponse,
|
||||||
|
weixinAccount.getPaySignKey()));
|
||||||
|
return XmlStream.to(payReponse);
|
||||||
|
|
||||||
|
}
|
||||||
|
// 成功返回
|
||||||
|
NativePayResponseV3 payReponse = new NativePayResponseV3(payPackage,
|
||||||
|
weixinAccount.getPaySignKey());
|
||||||
|
payReponse.setSign(PayUtil.paysignMd5(payReponse,
|
||||||
|
weixinAccount.getPaySignKey()));
|
||||||
|
return XmlStream.to(payReponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 告警通知 需要成功返回 success </br> <xml></br>
|
||||||
|
* <AppId><![CDATA[wxf8b4f85f3a794e77]]></AppId></br>
|
||||||
|
* <ErrorType>1001</ErrorType></br>
|
||||||
|
* <Description><![CDATA[错误描述]]></Description></br>
|
||||||
|
* <AlarmContent><![CDATA[错误详情]]></AlarmContent></br>
|
||||||
|
* <TimeStamp>1393860740</TimeStamp></br>
|
||||||
|
* <AppSignature><![CDATA[签名方式跟JsPayRequest中的paySign一样]]></
|
||||||
|
* AppSignature></br>
|
||||||
|
* <SignMethod><![CDATA[sha1]]></SignMethod></br>
|
||||||
|
* </xml></br>
|
||||||
|
* 参与签名字段:alarmcontent、appid、appkey、description、errortype、timestamp
|
||||||
|
*
|
||||||
|
* @param inputStream
|
||||||
|
* xml数据
|
||||||
|
* @see com.foxinmy.weixin4j.mp.payment.v2.PayWarn
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String warning(InputStream inputStream) {
|
||||||
|
PayWarn payWarn = XmlStream.get(inputStream, PayWarn.class);
|
||||||
|
log.info("pay_warning,{}", payWarn);
|
||||||
|
WeixinMpAccount weixinAccount = JSON.parseObject(
|
||||||
|
ConfigUtil.getValue("account"), WeixinMpAccount.class);
|
||||||
|
String sign = payWarn.getPaySign();
|
||||||
|
payWarn.setPaySign(null);
|
||||||
|
payWarn.setSignType(null);
|
||||||
|
// 验证微信签名
|
||||||
|
String vaild_sign = PayUtil.paysignSha(payWarn,
|
||||||
|
weixinAccount.getPaySignKey());
|
||||||
|
log.info("微信签名----->sign={},vaild_sign={}", sign, vaild_sign);
|
||||||
|
return "success";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户维权
|
||||||
|
*
|
||||||
|
* @param inputStream
|
||||||
|
* @see com.foxinmy.weixin4j.mp.payment.v2.PayFeedback
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String feedback(InputStream inputStream) {
|
||||||
|
PayFeedback feedback = XmlStream.get(inputStream, PayFeedback.class);
|
||||||
|
log.info("pay_feedback_info:{}", feedback);
|
||||||
|
WeixinMpAccount weixinAccount = JSON.parseObject(
|
||||||
|
ConfigUtil.getValue("account"), WeixinMpAccount.class);
|
||||||
|
// 验证微信签名
|
||||||
|
Map<String, String> obj = new HashMap<String, String>();
|
||||||
|
obj.put("openid", feedback.getOpenId());
|
||||||
|
obj.put("appid", feedback.getAppId());
|
||||||
|
obj.put("timestamp", feedback.getTimeStamp());
|
||||||
|
obj.put("appkey", weixinAccount.getPaySignKey());
|
||||||
|
String sign = PayUtil.paysignSha(obj);
|
||||||
|
log.info("微信签名----->sign={},vaild_sign={}", sign, feedback.getPaySign());
|
||||||
|
return "success";
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.foxinmy.weixin4j.mp.test.msg;
|
package com.foxinmy.weixin4j.mp.test;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -16,7 +16,6 @@ import com.foxinmy.weixin4j.mp.api.CustomApi;
|
|||||||
import com.foxinmy.weixin4j.mp.model.CustomRecord;
|
import com.foxinmy.weixin4j.mp.model.CustomRecord;
|
||||||
import com.foxinmy.weixin4j.mp.model.KfAccount;
|
import com.foxinmy.weixin4j.mp.model.KfAccount;
|
||||||
import com.foxinmy.weixin4j.mp.model.KfSession;
|
import com.foxinmy.weixin4j.mp.model.KfSession;
|
||||||
import com.foxinmy.weixin4j.mp.test.TokenTest;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 客服消息测试
|
* 客服消息测试
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.foxinmy.weixin4j.mp.test.msg;
|
package com.foxinmy.weixin4j.mp.test;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -13,8 +13,6 @@ import com.foxinmy.weixin4j.exception.WeixinException;
|
|||||||
import com.foxinmy.weixin4j.http.JsonResult;
|
import com.foxinmy.weixin4j.http.JsonResult;
|
||||||
import com.foxinmy.weixin4j.mp.api.MassApi;
|
import com.foxinmy.weixin4j.mp.api.MassApi;
|
||||||
import com.foxinmy.weixin4j.mp.api.MediaApi;
|
import com.foxinmy.weixin4j.mp.api.MediaApi;
|
||||||
import com.foxinmy.weixin4j.mp.event.MassEventMessage;
|
|
||||||
import com.foxinmy.weixin4j.mp.test.TokenTest;
|
|
||||||
import com.foxinmy.weixin4j.tuple.Image;
|
import com.foxinmy.weixin4j.tuple.Image;
|
||||||
import com.foxinmy.weixin4j.tuple.MpArticle;
|
import com.foxinmy.weixin4j.tuple.MpArticle;
|
||||||
import com.foxinmy.weixin4j.tuple.Text;
|
import com.foxinmy.weixin4j.tuple.Text;
|
||||||
@ -30,7 +28,7 @@ import com.foxinmy.weixin4j.type.MediaType;
|
|||||||
* @since JDK 1.7
|
* @since JDK 1.7
|
||||||
* @see
|
* @see
|
||||||
*/
|
*/
|
||||||
public class MassMsgTest extends TokenTest {
|
public class MassTest extends TokenTest {
|
||||||
private MassApi massApi;
|
private MassApi massApi;
|
||||||
private MediaApi mediaApi;
|
private MediaApi mediaApi;
|
||||||
|
|
||||||
@ -107,7 +105,6 @@ public class MassMsgTest extends TokenTest {
|
|||||||
public void getMassNews() throws WeixinException {
|
public void getMassNews() throws WeixinException {
|
||||||
String status = massApi.getMassNews("82358");
|
String status = massApi.getMassNews("82358");
|
||||||
System.out.println(status);
|
System.out.println(status);
|
||||||
System.out.println(MassEventMessage.getStatusDesc(status));
|
|
||||||
Assert.assertNotNull(status);
|
Assert.assertNotNull(status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.foxinmy.weixin4j.mp.test.msg;
|
package com.foxinmy.weixin4j.mp.test;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -12,7 +12,6 @@ import com.foxinmy.weixin4j.http.JsonResult;
|
|||||||
import com.foxinmy.weixin4j.mp.api.MediaApi;
|
import com.foxinmy.weixin4j.mp.api.MediaApi;
|
||||||
import com.foxinmy.weixin4j.mp.api.NotifyApi;
|
import com.foxinmy.weixin4j.mp.api.NotifyApi;
|
||||||
import com.foxinmy.weixin4j.mp.message.NotifyMessage;
|
import com.foxinmy.weixin4j.mp.message.NotifyMessage;
|
||||||
import com.foxinmy.weixin4j.mp.test.TokenTest;
|
|
||||||
import com.foxinmy.weixin4j.tuple.Image;
|
import com.foxinmy.weixin4j.tuple.Image;
|
||||||
import com.foxinmy.weixin4j.tuple.Music;
|
import com.foxinmy.weixin4j.tuple.Music;
|
||||||
import com.foxinmy.weixin4j.tuple.News;
|
import com.foxinmy.weixin4j.tuple.News;
|
||||||
@ -30,7 +29,7 @@ import com.foxinmy.weixin4j.type.MediaType;
|
|||||||
* @since JDK 1.7
|
* @since JDK 1.7
|
||||||
* @see
|
* @see
|
||||||
*/
|
*/
|
||||||
public class NotifyMsgTest extends TokenTest {
|
public class NotifyTest extends TokenTest {
|
||||||
|
|
||||||
private NotifyApi notifyApi;
|
private NotifyApi notifyApi;
|
||||||
private MediaApi mediaApi;
|
private MediaApi mediaApi;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.foxinmy.weixin4j.mp.test.msg;
|
package com.foxinmy.weixin4j.mp.test;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@ -8,10 +8,9 @@ import com.foxinmy.weixin4j.exception.WeixinException;
|
|||||||
import com.foxinmy.weixin4j.http.JsonResult;
|
import com.foxinmy.weixin4j.http.JsonResult;
|
||||||
import com.foxinmy.weixin4j.mp.api.TmplApi;
|
import com.foxinmy.weixin4j.mp.api.TmplApi;
|
||||||
import com.foxinmy.weixin4j.mp.message.TemplateMessage;
|
import com.foxinmy.weixin4j.mp.message.TemplateMessage;
|
||||||
import com.foxinmy.weixin4j.mp.test.TokenTest;
|
|
||||||
import com.foxinmy.weixin4j.mp.type.IndustryType;
|
import com.foxinmy.weixin4j.mp.type.IndustryType;
|
||||||
|
|
||||||
public class TemplateMsgTest extends TokenTest {
|
public class TemplateTest extends TokenTest {
|
||||||
private TmplApi tmplApi;
|
private TmplApi tmplApi;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@ -1,11 +1,5 @@
|
|||||||
package com.foxinmy.weixin4j.mp.test;
|
package com.foxinmy.weixin4j.mp.test;
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
import org.jsoup.Jsoup;
|
|
||||||
import org.jsoup.nodes.Document;
|
|
||||||
import org.jsoup.nodes.Element;
|
|
||||||
import org.jsoup.select.Elements;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -36,19 +30,4 @@ public class TokenTest {
|
|||||||
public void test() throws WeixinException {
|
public void test() throws WeixinException {
|
||||||
Assert.assertNotNull(tokenHolder.getToken());
|
Assert.assertNotNull(tokenHolder.getToken());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
String wikiUrl = "http://qydev.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";
|
|
||||||
// wikiUrl =
|
|
||||||
// "http://mp.weixin.qq.com/wiki/17/fa4e1434e57290788bde25603fa2fcbd.html";
|
|
||||||
Document doc = Jsoup.parse(new URL(wikiUrl), 5000);
|
|
||||||
Elements errors = doc.getElementsByTag("tr");
|
|
||||||
String node = "<error><code>%s</code><text>%s</text></error>";
|
|
||||||
StringBuilder xml = new StringBuilder();
|
|
||||||
for (Element error : errors) {
|
|
||||||
xml.append(String.format(node, error.child(0).text(), error
|
|
||||||
.child(1).text()));
|
|
||||||
}
|
|
||||||
System.err.println(xml);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,64 +0,0 @@
|
|||||||
package com.foxinmy.weixin4j.mp.test.msg;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
|
||||||
|
|
||||||
public class AesMsgTest extends MessagePush {
|
|
||||||
StringBuilder xmlSb = new StringBuilder();
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testValidate() throws WeixinException, IOException {
|
|
||||||
String para = "?signature=0d2366aedb4f3531cfa4297c1e4ea7eece2311d9&echostr=2143641595566077626×tamp=1415951914&nonce=165976363";
|
|
||||||
xmlSb.delete(0, xmlSb.length());
|
|
||||||
String response = get(para);
|
|
||||||
Assert.assertEquals("2143641595566077626", response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testType1() throws WeixinException, IOException {
|
|
||||||
String para = "?signature=6dd806a20a314723e78bc58742a1b98a7adfd151×tamp=1415979366&nonce=1865915590";
|
|
||||||
xmlSb.delete(0, xmlSb.length());
|
|
||||||
xmlSb.append("<xml>");
|
|
||||||
xmlSb.append("<ToUserName><![CDATA[gh_248c6f91d64f]]></ToUserName>");
|
|
||||||
xmlSb.append("<FromUserName><![CDATA[oyFLst1bqtuTcxK-ojF8hOGtLQao]]></FromUserName>");
|
|
||||||
xmlSb.append("<CreateTime>1415979365</CreateTime>");
|
|
||||||
xmlSb.append("<MsgType><![CDATA[event]]></MsgType>");
|
|
||||||
xmlSb.append("<Event><![CDATA[CLICK]]></Event>");
|
|
||||||
xmlSb.append("<EventKey><![CDATA[CHECKIN]]></EventKey>");
|
|
||||||
xmlSb.append("</xml>");
|
|
||||||
String response = push(para, xmlSb.toString());
|
|
||||||
Assert.assertNotNull(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testType2() throws WeixinException, IOException {
|
|
||||||
String para = "?signature=ad05f836772d1cbba1ff2edb7be4b9c9fb3a43d5×tamp=1415980001&nonce=1803216865&encrypt_type=raw&msg_signature=c0d38e9ca00548f7142627ec2908a4fe8481025e";
|
|
||||||
xmlSb.delete(0, xmlSb.length());
|
|
||||||
xmlSb.append("<xml>");
|
|
||||||
xmlSb.append("<ToUserName><![CDATA[gh_248c6f91d64f]]></ToUserName>");
|
|
||||||
xmlSb.append("<FromUserName><![CDATA[oyFLst1bqtuTcxK-ojF8hOGtLQao]]></FromUserName>");
|
|
||||||
xmlSb.append("<CreateTime>1415980001</CreateTime>");
|
|
||||||
xmlSb.append("<MsgType><![CDATA[event]]></MsgType>");
|
|
||||||
xmlSb.append("<Event><![CDATA[CLICK]]></Event>");
|
|
||||||
xmlSb.append("<EventKey><![CDATA[CHECKIN]]></EventKey>");
|
|
||||||
xmlSb.append("</xml>");
|
|
||||||
String response = push(para, xmlSb.toString());
|
|
||||||
Assert.assertNotNull(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testType3() throws WeixinException, IOException {
|
|
||||||
String para = "?signature=ad05f836772d1cbba1ff2edb7be4b9c9fb3a43d5×tamp=1415980001&nonce=1803216865&encrypt_type=aes&msg_signature=c0d38e9ca00548f7142627ec2908a4fe8481025e";
|
|
||||||
xmlSb.delete(0, xmlSb.length());
|
|
||||||
xmlSb.append("<xml>");
|
|
||||||
xmlSb.append("<ToUserName><![CDATA[gh_248c6f91d64f]]></ToUserName>");
|
|
||||||
xmlSb.append("<Encrypt><![CDATA[R6VQIWDR14XgSRLm25zc7V/WJYqK15gsUiMh0u/5GTMZME6jGtHkyfVN079ZPL065b+ZDq3TnoFKKtjtZlzcodY6Fm8+EujvtbTdVMMFSwdo8AwqVViAn09+DDfqPaNvbHUSiYsL3qlxArs1MH6APRUHFo7MU/piY1x2stJc8+kv28xtF+K8Aou0RuPO7PeQ18Zu/GkLnYNiI1E7UG31UYfOgVKcRjeE0PXa18iF5LBS8G/ce/l+/pH/DJWUBw5uXaqSOlo21tctlgLXu3bYUUkIu8tT49QwhHvRZILtO9icoyCNuTA7iTcHIdlAe1bD1S0ncmopIQCGmoU2/AXC2CCi6trONf3EPNKKKfDeQYHadnVZOg6kTX2cnYmHZLviYeLzjCKFSqSNkimoSKQ/Dcutpsq1D82NCwiExUZW4oo=]]></Encrypt>");
|
|
||||||
xmlSb.append("</xml>");
|
|
||||||
String response = push(para, xmlSb.toString());
|
|
||||||
Assert.assertNotNull(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,179 +0,0 @@
|
|||||||
package com.foxinmy.weixin4j.mp.test.msg;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 接收事件消息格式测试
|
|
||||||
*
|
|
||||||
* @author jy.hu
|
|
||||||
* @date 2014年3月24日
|
|
||||||
* @since JDK 1.7
|
|
||||||
*/
|
|
||||||
public class EventMsgTest extends MessagePush {
|
|
||||||
|
|
||||||
private StringBuilder xmlSb = new StringBuilder();
|
|
||||||
|
|
||||||
/***************** event message *********************/
|
|
||||||
@Test
|
|
||||||
public void scribe() throws WeixinException, IOException {
|
|
||||||
xmlSb.delete(0, xmlSb.length());
|
|
||||||
xmlSb.append("<xml>");
|
|
||||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
|
||||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
|
||||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
|
||||||
xmlSb.append("<MsgType><![CDATA[event]]></MsgType>");
|
|
||||||
xmlSb.append("<Event><![CDATA[subscribe]]></Event>");
|
|
||||||
xmlSb.append("</xml>");
|
|
||||||
String response = push(xmlSb.toString());
|
|
||||||
Assert.assertNotNull(response);
|
|
||||||
System.out.println(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void scan() throws WeixinException, IOException {
|
|
||||||
xmlSb.delete(0, xmlSb.length());
|
|
||||||
xmlSb.append("<xml>");
|
|
||||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
|
||||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
|
||||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
|
||||||
xmlSb.append("<MsgType><![CDATA[event]]></MsgType>");
|
|
||||||
xmlSb.append("<Event><![CDATA[SCAN]]></Event>");
|
|
||||||
xmlSb.append("<EventKey><![CDATA[SCENE_VALUE]]></EventKey>");
|
|
||||||
xmlSb.append("<Ticket><![CDATA[TICKET]]></Ticket>");
|
|
||||||
xmlSb.append("</xml>");
|
|
||||||
String response = push(xmlSb.toString());
|
|
||||||
Assert.assertNotNull(response);
|
|
||||||
System.out.println(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void scan_scribe() throws WeixinException, IOException {
|
|
||||||
xmlSb.delete(0, xmlSb.length());
|
|
||||||
xmlSb.append("<xml><ToUserName><![CDATA[toUser]]></ToUserName>");
|
|
||||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
|
||||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
|
||||||
xmlSb.append("<MsgType><![CDATA[event]]></MsgType>");
|
|
||||||
xmlSb.append("<Event><![CDATA[subscribe]]></Event>");
|
|
||||||
xmlSb.append("<EventKey><![CDATA[qrscene_123123]]></EventKey>");
|
|
||||||
xmlSb.append("<Ticket><![CDATA[TICKET]]></Ticket>");
|
|
||||||
xmlSb.append("</xml>");
|
|
||||||
String response = push(xmlSb.toString());
|
|
||||||
Assert.assertNotNull(response);
|
|
||||||
System.out.println(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void location() throws WeixinException, IOException {
|
|
||||||
xmlSb.delete(0, xmlSb.length());
|
|
||||||
xmlSb.append("<xml>");
|
|
||||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
|
||||||
xmlSb.append("<FromUserName><![CDATA[fromUser]]></FromUserName>");
|
|
||||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
|
||||||
xmlSb.append("<MsgType><![CDATA[event]]></MsgType>");
|
|
||||||
xmlSb.append("<Event><![CDATA[LOCATION]]></Event>");
|
|
||||||
xmlSb.append("<Latitude>23.137466</Latitude>");
|
|
||||||
xmlSb.append("<Longitude>113.352425</Longitude>");
|
|
||||||
xmlSb.append("<Precision>119.385040</Precision>");
|
|
||||||
xmlSb.append("</xml>");
|
|
||||||
String response = push(xmlSb.toString());
|
|
||||||
Assert.assertNotNull(response);
|
|
||||||
System.out.println(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void menu_click() throws WeixinException, IOException {
|
|
||||||
xmlSb.delete(0, xmlSb.length());
|
|
||||||
xmlSb.append("<xml>");
|
|
||||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
|
||||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
|
||||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
|
||||||
xmlSb.append("<MsgType><![CDATA[event]]></MsgType>");
|
|
||||||
xmlSb.append("<Event><![CDATA[CLICK]]></Event>");
|
|
||||||
xmlSb.append("<EventKey><![CDATA[EVENTKEY]]></EventKey>");
|
|
||||||
xmlSb.append("</xml>");
|
|
||||||
String response = push(xmlSb.toString());
|
|
||||||
Assert.assertNotNull(response);
|
|
||||||
System.out.println(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void menu_link() throws WeixinException, IOException {
|
|
||||||
xmlSb.delete(0, xmlSb.length());
|
|
||||||
xmlSb.append("<xml>");
|
|
||||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
|
||||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
|
||||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
|
||||||
xmlSb.append("<MsgType><![CDATA[event]]></MsgType>");
|
|
||||||
xmlSb.append("<Event><![CDATA[VIEW]]></Event>");
|
|
||||||
xmlSb.append("<EventKey><![CDATA[www.qq.com]]></EventKey>");
|
|
||||||
xmlSb.append("</xml>");
|
|
||||||
String response = push(xmlSb.toString());
|
|
||||||
Assert.assertNotNull(response);
|
|
||||||
System.out.println(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void menu_scan() throws WeixinException, IOException {
|
|
||||||
xmlSb.delete(0, xmlSb.length());
|
|
||||||
xmlSb.append("<xml>");
|
|
||||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
|
||||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
|
||||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
|
||||||
xmlSb.append("<MsgType><![CDATA[event]]></MsgType>");
|
|
||||||
xmlSb.append("<Event><![CDATA[scancode_waitmsg]]></Event>");
|
|
||||||
xmlSb.append("<EventKey><![CDATA[www.qq.com]]></EventKey>");
|
|
||||||
xmlSb.append("<ScanCodeInfo><ScanType><![CDATA[qrcode]]></ScanType>");
|
|
||||||
xmlSb.append("<ScanResult><![CDATA[1]]></ScanResult>");
|
|
||||||
xmlSb.append("</ScanCodeInfo>");
|
|
||||||
|
|
||||||
xmlSb.append("</xml>");
|
|
||||||
String response = push(xmlSb.toString());
|
|
||||||
Assert.assertNotNull(response);
|
|
||||||
System.out.println(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void menu_photo() throws WeixinException, IOException {
|
|
||||||
xmlSb.delete(0, xmlSb.length());
|
|
||||||
xmlSb.append("<xml>");
|
|
||||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
|
||||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
|
||||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
|
||||||
xmlSb.append("<MsgType><![CDATA[event]]></MsgType>");
|
|
||||||
xmlSb.append("<Event><![CDATA[pic_weixin]]></Event>");
|
|
||||||
xmlSb.append("<EventKey><![CDATA[www.qq.com]]></EventKey>");
|
|
||||||
xmlSb.append("<SendPicsInfo><Count>1</Count>");
|
|
||||||
xmlSb.append("<PicList><item><PicMd5Sum><![CDATA[1b5f7c23b5bf75682a53e7b6d163e185]]></PicMd5Sum>");
|
|
||||||
xmlSb.append("</item></PicList></SendPicsInfo>");
|
|
||||||
xmlSb.append("</xml>");
|
|
||||||
String response = push(xmlSb.toString());
|
|
||||||
Assert.assertNotNull(response);
|
|
||||||
System.out.println(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void menu_location() throws WeixinException, IOException {
|
|
||||||
xmlSb.delete(0, xmlSb.length());
|
|
||||||
xmlSb.append("<xml>");
|
|
||||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
|
||||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
|
||||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
|
||||||
xmlSb.append("<MsgType><![CDATA[event]]></MsgType>");
|
|
||||||
xmlSb.append("<Event><![CDATA[location_select]]></Event>");
|
|
||||||
xmlSb.append("<EventKey><![CDATA[www.qq.com]]></EventKey>");
|
|
||||||
xmlSb.append("<SendLocationInfo><Location_X><![CDATA[23]]></Location_X>");
|
|
||||||
xmlSb.append("<Location_Y><![CDATA[113]]></Location_Y>");
|
|
||||||
xmlSb.append("<Scale><![CDATA[15]]></Scale>");
|
|
||||||
xmlSb.append("<Label><![CDATA[ 广州市海珠区客村艺苑路 106号]]></Label>");
|
|
||||||
xmlSb.append("<Poiname><![CDATA[]]></Poiname></SendLocationInfo>");
|
|
||||||
xmlSb.append("</xml>");
|
|
||||||
String response = push(xmlSb.toString());
|
|
||||||
Assert.assertNotNull(response);
|
|
||||||
System.out.println(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,144 +0,0 @@
|
|||||||
package com.foxinmy.weixin4j.mp.test.msg;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 接受一般消息格式测试
|
|
||||||
*
|
|
||||||
* @author jy.hu
|
|
||||||
* @date 2014年3月24日
|
|
||||||
* @since JDK 1.7
|
|
||||||
*/
|
|
||||||
public class InMsgTest extends MessagePush {
|
|
||||||
|
|
||||||
private StringBuilder xmlSb = new StringBuilder();
|
|
||||||
|
|
||||||
/***************** common message *********************/
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void text() throws WeixinException, IOException {
|
|
||||||
xmlSb.delete(0, xmlSb.length());
|
|
||||||
xmlSb.append("<xml>");
|
|
||||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
|
||||||
xmlSb.append("<FromUserName><![CDATA[fromUser]]></FromUserName>");
|
|
||||||
xmlSb.append("<CreateTime>1348831860</CreateTime>");
|
|
||||||
xmlSb.append("<MsgType><![CDATA[text]]></MsgType>");
|
|
||||||
xmlSb.append("<Content><![CDATA[this is a test]]></Content>");
|
|
||||||
xmlSb.append("<MsgId>1234567890123456</MsgId>");
|
|
||||||
xmlSb.append("</xml>");
|
|
||||||
String response = push(xmlSb.toString());
|
|
||||||
Assert.assertNotNull(response);
|
|
||||||
System.out.println(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void image() throws WeixinException, IOException {
|
|
||||||
xmlSb.delete(0, xmlSb.length());
|
|
||||||
xmlSb.append("<xml>");
|
|
||||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
|
||||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
|
||||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
|
||||||
xmlSb.append("<MsgType><![CDATA[image]]></MsgType>");
|
|
||||||
xmlSb.append("<PicUrl><![CDATA[this is a url]]></PicUrl>");
|
|
||||||
xmlSb.append("<MediaId><![CDATA[media_id]]></MediaId>");
|
|
||||||
xmlSb.append("<MsgId>1234567890123456</MsgId>");
|
|
||||||
xmlSb.append("</xml>");
|
|
||||||
String response = push(xmlSb.toString());
|
|
||||||
Assert.assertNotNull(response);
|
|
||||||
System.out.println(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void voice() throws WeixinException, IOException {
|
|
||||||
xmlSb.delete(0, xmlSb.length());
|
|
||||||
xmlSb.append("<xml>");
|
|
||||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
|
||||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
|
||||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
|
||||||
xmlSb.append("<MsgType><![CDATA[voice]]></MsgType>");
|
|
||||||
xmlSb.append("<MediaId><![CDATA[media_id]]></MediaId>");
|
|
||||||
xmlSb.append("<Format><![CDATA[Format]]></Format>");
|
|
||||||
xmlSb.append("<MsgId>1234567890123456</MsgId>");
|
|
||||||
xmlSb.append("</xml>");
|
|
||||||
String response = push(xmlSb.toString());
|
|
||||||
Assert.assertNotNull(response);
|
|
||||||
System.out.println(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void re_voice() throws WeixinException, IOException {
|
|
||||||
xmlSb.delete(0, xmlSb.length());
|
|
||||||
xmlSb.append("<xml>");
|
|
||||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
|
||||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
|
||||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
|
||||||
xmlSb.append("<MsgType><![CDATA[voice]]></MsgType>");
|
|
||||||
xmlSb.append("<MediaId><![CDATA[media_id]]></MediaId>");
|
|
||||||
xmlSb.append("<Format><![CDATA[Format]]></Format>");
|
|
||||||
xmlSb.append("<Recognition><![CDATA[腾讯微信团队]]></Recognition>");
|
|
||||||
xmlSb.append("<MsgId>1234567890123456</MsgId>");
|
|
||||||
xmlSb.append("</xml>");
|
|
||||||
String response = push(xmlSb.toString());
|
|
||||||
Assert.assertNotNull(response);
|
|
||||||
System.out.println(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void video() throws WeixinException, IOException {
|
|
||||||
xmlSb.delete(0, xmlSb.length());
|
|
||||||
xmlSb.append("<xml>");
|
|
||||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
|
||||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
|
||||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
|
||||||
xmlSb.append("<MsgType><![CDATA[video]]></MsgType>");
|
|
||||||
xmlSb.append("<MediaId><![CDATA[media_id]]></MediaId>");
|
|
||||||
xmlSb.append("<ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId>");
|
|
||||||
xmlSb.append("<MsgId>1234567890123456</MsgId>");
|
|
||||||
xmlSb.append("</xml>");
|
|
||||||
String response = push(xmlSb.toString());
|
|
||||||
Assert.assertNotNull(response);
|
|
||||||
System.out.println(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void location() throws WeixinException, IOException {
|
|
||||||
xmlSb.delete(0, xmlSb.length());
|
|
||||||
xmlSb.append("<xml>");
|
|
||||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
|
||||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
|
||||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
|
||||||
xmlSb.append("<MsgType><![CDATA[location]]></MsgType>");
|
|
||||||
xmlSb.append("<Location_X>23.134521</Location_X>");
|
|
||||||
xmlSb.append("<Location_Y>113.358803</Location_Y>");
|
|
||||||
xmlSb.append("<Scale>20</Scale>");
|
|
||||||
xmlSb.append("<Label><![CDATA[位置信息]]></Label>");
|
|
||||||
xmlSb.append("<MsgId>1234567890123456</MsgId>");
|
|
||||||
xmlSb.append("</xml>");
|
|
||||||
String response = push(xmlSb.toString());
|
|
||||||
Assert.assertNotNull(response);
|
|
||||||
System.out.println(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void link() throws WeixinException, IOException {
|
|
||||||
xmlSb.delete(0, xmlSb.length());
|
|
||||||
xmlSb.append("<xml>");
|
|
||||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
|
||||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
|
||||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
|
||||||
xmlSb.append("<MsgType><![CDATA[link]]></MsgType>");
|
|
||||||
xmlSb.append("<Title><![CDATA[公众平台官网链接]]></Title>");
|
|
||||||
xmlSb.append("<Description><![CDATA[公众平台官网链接]]></Description>");
|
|
||||||
xmlSb.append("<Url><![CDATA[url]]></Url>");
|
|
||||||
xmlSb.append("<MsgId>1234567890123456</MsgId>");
|
|
||||||
xmlSb.append("</xml>");
|
|
||||||
String response = push(xmlSb.toString());
|
|
||||||
Assert.assertNotNull(response);
|
|
||||||
System.out.println(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,68 +0,0 @@
|
|||||||
package com.foxinmy.weixin4j.mp.test.msg;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
import org.apache.http.HttpResponse;
|
|
||||||
import org.apache.http.HttpStatus;
|
|
||||||
import org.apache.http.StatusLine;
|
|
||||||
import org.apache.http.client.HttpClient;
|
|
||||||
import org.apache.http.client.methods.HttpGet;
|
|
||||||
import org.apache.http.client.methods.HttpPost;
|
|
||||||
import org.apache.http.entity.StringEntity;
|
|
||||||
import org.apache.http.impl.client.DefaultHttpClient;
|
|
||||||
import org.apache.http.util.EntityUtils;
|
|
||||||
|
|
||||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
|
||||||
|
|
||||||
public class MessagePush {
|
|
||||||
|
|
||||||
private final String server = "http://localhost:8080";
|
|
||||||
private final HttpClient httpClient;
|
|
||||||
private final HttpPost httpPost;
|
|
||||||
private final HttpGet httpGet;
|
|
||||||
|
|
||||||
public MessagePush() {
|
|
||||||
httpClient = new DefaultHttpClient();
|
|
||||||
httpPost = new HttpPost();
|
|
||||||
httpPost.setURI(URI.create(server));
|
|
||||||
|
|
||||||
httpGet = new HttpGet();
|
|
||||||
httpGet.setURI(URI.create(server));
|
|
||||||
}
|
|
||||||
|
|
||||||
public String get(String para) throws WeixinException, IOException {
|
|
||||||
httpGet.setURI(URI.create(server + para));
|
|
||||||
HttpResponse httpResponse = httpClient.execute(httpGet);
|
|
||||||
return entity(httpResponse);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String push(String xml) throws WeixinException, IOException {
|
|
||||||
return push("", xml);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String push(String para, String xml) throws WeixinException,
|
|
||||||
IOException {
|
|
||||||
httpPost.setURI(URI.create(server + para));
|
|
||||||
httpPost.setEntity(new StringEntity(xml, StandardCharsets.UTF_8));
|
|
||||||
HttpResponse httpResponse = httpClient.execute(httpPost);
|
|
||||||
return entity(httpResponse);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String entity(HttpResponse httpResponse) throws WeixinException,
|
|
||||||
IOException {
|
|
||||||
StatusLine statusLine = httpResponse.getStatusLine();
|
|
||||||
|
|
||||||
int status = statusLine.getStatusCode();
|
|
||||||
if (status != HttpStatus.SC_OK) {
|
|
||||||
throw new WeixinException(Integer.toString(status), "request fail");
|
|
||||||
}
|
|
||||||
if (status == HttpStatus.SC_MOVED_PERMANENTLY
|
|
||||||
|| status == HttpStatus.SC_MOVED_TEMPORARILY) {
|
|
||||||
throw new WeixinException(Integer.toString(status), "uri moved");
|
|
||||||
}
|
|
||||||
return EntityUtils.toString(httpResponse.getEntity(),
|
|
||||||
StandardCharsets.UTF_8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -10,7 +10,6 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.http.entity.mime.content.ByteArrayBody;
|
import org.apache.http.entity.mime.content.ByteArrayBody;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
@ -30,6 +29,7 @@ import com.foxinmy.weixin4j.type.MediaType;
|
|||||||
import com.foxinmy.weixin4j.util.ConfigUtil;
|
import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||||
import com.foxinmy.weixin4j.util.FileUtil;
|
import com.foxinmy.weixin4j.util.FileUtil;
|
||||||
import com.foxinmy.weixin4j.util.IOUtil;
|
import com.foxinmy.weixin4j.util.IOUtil;
|
||||||
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 媒体相关API
|
* 媒体相关API
|
||||||
@ -62,7 +62,7 @@ public class MediaApi extends QyApi {
|
|||||||
*/
|
*/
|
||||||
public String uploadMedia(File file) throws WeixinException, IOException {
|
public String uploadMedia(File file) throws WeixinException, IOException {
|
||||||
String mediaTypeKey = IOUtil.getExtension(file.getName());
|
String mediaTypeKey = IOUtil.getExtension(file.getName());
|
||||||
if (StringUtils.isBlank(mediaTypeKey)) {
|
if (StringUtil.isBlank(mediaTypeKey)) {
|
||||||
mediaTypeKey = FileUtil.getFileType(file);
|
mediaTypeKey = FileUtil.getFileType(file);
|
||||||
}
|
}
|
||||||
MediaType mediaType = MediaType.getMediaType(mediaTypeKey);
|
MediaType mediaType = MediaType.getMediaType(mediaTypeKey);
|
||||||
@ -237,7 +237,7 @@ public class MediaApi extends QyApi {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
writer.write(StringUtils.join(column.values(), ","));
|
writer.write(StringUtil.join(column.values(), ','));
|
||||||
writer.write("\r\n");
|
writer.write("\r\n");
|
||||||
}
|
}
|
||||||
String mediaId = uploadMedia(batchName,
|
String mediaId = uploadMedia(batchName,
|
||||||
|
|||||||
@ -3,8 +3,6 @@ package com.foxinmy.weixin4j.qy.api;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
@ -16,6 +14,7 @@ import com.foxinmy.weixin4j.qy.model.User;
|
|||||||
import com.foxinmy.weixin4j.qy.type.InviteType;
|
import com.foxinmy.weixin4j.qy.type.InviteType;
|
||||||
import com.foxinmy.weixin4j.qy.type.UserStatus;
|
import com.foxinmy.weixin4j.qy.type.UserStatus;
|
||||||
import com.foxinmy.weixin4j.token.TokenHolder;
|
import com.foxinmy.weixin4j.token.TokenHolder;
|
||||||
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 成员API
|
* 成员API
|
||||||
@ -282,7 +281,7 @@ public class UserApi extends QyApi {
|
|||||||
throws WeixinException {
|
throws WeixinException {
|
||||||
JSONObject obj = new JSONObject();
|
JSONObject obj = new JSONObject();
|
||||||
obj.put("userid", userId);
|
obj.put("userid", userId);
|
||||||
if (StringUtils.isBlank(tips)) {
|
if (StringUtil.isBlank(tips)) {
|
||||||
obj.put("invite_tips", tips);
|
obj.put("invite_tips", tips);
|
||||||
}
|
}
|
||||||
String invite_user_uri = getRequestUri("invite_user_uri");
|
String invite_user_uri = getRequestUri("invite_user_uri");
|
||||||
|
|||||||
@ -1,100 +0,0 @@
|
|||||||
package com.foxinmy.weixin4j.qy.event;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
import com.foxinmy.weixin4j.message.event.EventMessage;
|
|
||||||
import com.foxinmy.weixin4j.qy.type.EventType;
|
|
||||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 异步任务事件完成通知
|
|
||||||
*
|
|
||||||
* @className BatchjobresultMessage
|
|
||||||
* @author jy
|
|
||||||
* @date 2015年3月31日
|
|
||||||
* @since JDK 1.7
|
|
||||||
* @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.82.E6.AD.A5.E4.BB.BB.E5.8A.A1.E5.AE.8C.E6.88.90.E4.BA.8B.E4.BB.B6.E6.8E.A8.E9.80.81">异步任务事件完成通知</a>
|
|
||||||
*/
|
|
||||||
public class BatchjobresultMessage extends EventMessage {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 8014540441322209657L;
|
|
||||||
|
|
||||||
public BatchjobresultMessage() {
|
|
||||||
super(EventType.batch_job_result.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 任务信息
|
|
||||||
*/
|
|
||||||
@XStreamAlias("BatchJob")
|
|
||||||
private BatchJob batchJob;
|
|
||||||
|
|
||||||
public BatchJob getBatchJob() {
|
|
||||||
return batchJob;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 任务信息
|
|
||||||
*
|
|
||||||
* @className BatchJob
|
|
||||||
* @author jy
|
|
||||||
* @date 2015年4月1日
|
|
||||||
* @since JDK 1.7
|
|
||||||
* @see
|
|
||||||
*/
|
|
||||||
public static class BatchJob implements Serializable {
|
|
||||||
private static final long serialVersionUID = -7520032656787156391L;
|
|
||||||
/**
|
|
||||||
* 异步任务id,最大长度为64字符
|
|
||||||
*/
|
|
||||||
@XStreamAlias("JobId")
|
|
||||||
private String jobId;
|
|
||||||
/**
|
|
||||||
* 操作类型,字符串,目前分别有: 1. sync_user(增量更新成员) 2. replace_user(全量覆盖成员) 3.
|
|
||||||
* invite_user(邀请成员关注) 4. replace_party(全量覆盖部门)
|
|
||||||
*
|
|
||||||
* @see com.foxinmy.weixin4j.qy.type.BatchType
|
|
||||||
*/
|
|
||||||
@XStreamAlias("JobType")
|
|
||||||
private String jobType;
|
|
||||||
/**
|
|
||||||
* 返回码
|
|
||||||
*/
|
|
||||||
@XStreamAlias("ErrCode")
|
|
||||||
private String ErrCode;
|
|
||||||
/**
|
|
||||||
* 对返回码的文本描述内容
|
|
||||||
*/
|
|
||||||
@XStreamAlias("ErrMsg")
|
|
||||||
private String errMsg;
|
|
||||||
|
|
||||||
public String getJobId() {
|
|
||||||
return jobId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getJobType() {
|
|
||||||
return jobType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getErrCode() {
|
|
||||||
return ErrCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getErrMsg() {
|
|
||||||
return errMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "[jobId=" + jobId + ", jobType=" + jobType + ", ErrCode="
|
|
||||||
+ ErrCode + ", errMsg=" + errMsg + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "BatchjobresultMessage [batchJob=" + batchJob + ", "
|
|
||||||
+ super.toString() + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
package com.foxinmy.weixin4j.qy.event;
|
|
||||||
|
|
||||||
import com.foxinmy.weixin4j.message.event.EventMessage;
|
|
||||||
import com.foxinmy.weixin4j.qy.type.EventType;
|
|
||||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户进入应用的事件推送(企业号)本事件只有在应用的回调模式中打开上报开关时上报
|
|
||||||
*
|
|
||||||
* @className EnterAgentEventMessage
|
|
||||||
* @author jy
|
|
||||||
* @date 2014年12月28日
|
|
||||||
* @since JDK 1.7
|
|
||||||
* @see <a href=
|
|
||||||
* "http://qydev.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E4%BA%8B%E4%BB%B6#.E7.94.A8.E6.88.B7.E8.BF.9B.E5.85.A5.E5.BA.94.E7.94.A8.E7.9A.84.E4.BA.8B.E4.BB.B6.E6.8E.A8.E9.80.81"
|
|
||||||
* >用户进入应用的事件推送</a>
|
|
||||||
*/
|
|
||||||
public class EnterAgentEventMessage extends EventMessage {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 7675732524832500820L;
|
|
||||||
|
|
||||||
public EnterAgentEventMessage() {
|
|
||||||
super(EventType.enter_agent.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 事件KEY值,与自定义菜单接口中KEY值对应
|
|
||||||
*/
|
|
||||||
@XStreamAlias("EventKey")
|
|
||||||
private String eventKey;
|
|
||||||
|
|
||||||
public String getEventKey() {
|
|
||||||
return eventKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "EnterAgentEventMessage [eventKey=" + eventKey + ", "
|
|
||||||
+ super.toString() + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
package com.foxinmy.weixin4j.qy.event;
|
|
||||||
|
|
||||||
import com.foxinmy.weixin4j.message.event.EventMessage;
|
|
||||||
import com.foxinmy.weixin4j.type.EventType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 关注/取消关注事件</br> <font color="red">包括直接关注与扫描关注</font>
|
|
||||||
*
|
|
||||||
* @className ScribeEventMessage
|
|
||||||
* @author jy.hu
|
|
||||||
* @date 2014年4月6日
|
|
||||||
* @since JDK 1.7
|
|
||||||
* @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.88.90.E5.91.98.E5.85.B3.E6.B3.A8.2F.E5.8F.96.E6.B6.88.E5.85.B3.E6.B3.A8.E4.BA.8B.E4.BB.B6">成员关注/取消关注事件</a>
|
|
||||||
*/
|
|
||||||
public class ScribeEventMessage extends EventMessage {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = -6846321620262204915L;
|
|
||||||
|
|
||||||
public ScribeEventMessage() {
|
|
||||||
super(EventType.subscribe.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "ScribeEventMessage [" + super.toString() + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -3,10 +3,9 @@ package com.foxinmy.weixin4j.qy.message;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.annotation.JSONField;
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
import com.foxinmy.weixin4j.tuple.NotifyTuple;
|
import com.foxinmy.weixin4j.tuple.NotifyTuple;
|
||||||
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送消息对象
|
* 发送消息对象
|
||||||
@ -29,7 +28,7 @@ public class NotifyMessage implements Serializable {
|
|||||||
|
|
||||||
private static final long serialVersionUID = 1219589414293000383L;
|
private static final long serialVersionUID = 1219589414293000383L;
|
||||||
|
|
||||||
private static final String SEPARATOR = "|";
|
private static final char SEPARATOR = '|';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UserID列表(消息接收者,多个接收者用‘|’分隔)。特殊情况:指定为@all,则向关注该企业应用的全部成员发送
|
* UserID列表(消息接收者,多个接收者用‘|’分隔)。特殊情况:指定为@all,则向关注该企业应用的全部成员发送
|
||||||
@ -65,13 +64,13 @@ public class NotifyMessage implements Serializable {
|
|||||||
public NotifyMessage(List<String> tousers, List<String> topartys,
|
public NotifyMessage(List<String> tousers, List<String> topartys,
|
||||||
List<String> totags, NotifyTuple tuple, int agentid, boolean isSafe) {
|
List<String> totags, NotifyTuple tuple, int agentid, boolean isSafe) {
|
||||||
if (tousers != null && !tousers.isEmpty()) {
|
if (tousers != null && !tousers.isEmpty()) {
|
||||||
this.touser = StringUtils.join(tousers, SEPARATOR);
|
this.touser = StringUtil.join(tousers, SEPARATOR);
|
||||||
}
|
}
|
||||||
if (topartys != null && !topartys.isEmpty()) {
|
if (topartys != null && !topartys.isEmpty()) {
|
||||||
this.toparty = StringUtils.join(topartys, SEPARATOR);
|
this.toparty = StringUtil.join(topartys, SEPARATOR);
|
||||||
}
|
}
|
||||||
if (totags != null && !totags.isEmpty()) {
|
if (totags != null && !totags.isEmpty()) {
|
||||||
this.totag = StringUtils.join(totags, SEPARATOR);
|
this.totag = StringUtil.join(totags, SEPARATOR);
|
||||||
}
|
}
|
||||||
this.agentid = agentid;
|
this.agentid = agentid;
|
||||||
this.safe = isSafe ? 1 : 0;
|
this.safe = isSafe ? 1 : 0;
|
||||||
@ -88,7 +87,7 @@ public class NotifyMessage implements Serializable {
|
|||||||
|
|
||||||
public void setTouser(List<String> tousers) {
|
public void setTouser(List<String> tousers) {
|
||||||
if (tousers != null && !tousers.isEmpty()) {
|
if (tousers != null && !tousers.isEmpty()) {
|
||||||
this.touser = StringUtils.join(tousers, SEPARATOR);
|
this.touser = StringUtil.join(tousers, SEPARATOR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +101,7 @@ public class NotifyMessage implements Serializable {
|
|||||||
|
|
||||||
public void setToparty(List<String> topartys) {
|
public void setToparty(List<String> topartys) {
|
||||||
if (topartys != null && !topartys.isEmpty()) {
|
if (topartys != null && !topartys.isEmpty()) {
|
||||||
this.toparty = StringUtils.join(topartys, SEPARATOR);
|
this.toparty = StringUtil.join(topartys, SEPARATOR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +115,7 @@ public class NotifyMessage implements Serializable {
|
|||||||
|
|
||||||
public void setTotag(List<String> totags) {
|
public void setTotag(List<String> totags) {
|
||||||
if (totags != null && !totags.isEmpty()) {
|
if (totags != null && !totags.isEmpty()) {
|
||||||
this.totag = StringUtils.join(totags, SEPARATOR);
|
this.totag = StringUtil.join(totags, SEPARATOR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import java.io.Serializable;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* id参数集
|
* id参数集
|
||||||
@ -19,6 +19,8 @@ public class IdParameter implements Serializable {
|
|||||||
|
|
||||||
private static final long serialVersionUID = -2689758682205591133L;
|
private static final long serialVersionUID = -2689758682205591133L;
|
||||||
|
|
||||||
|
private static final char SEPARATOR = '|';
|
||||||
|
|
||||||
private Map<String, String> parameterMap;
|
private Map<String, String> parameterMap;
|
||||||
|
|
||||||
public IdParameter() {
|
public IdParameter() {
|
||||||
@ -32,7 +34,7 @@ public class IdParameter implements Serializable {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public IdParameter putUseIds(String... userIds) {
|
public IdParameter putUseIds(String... userIds) {
|
||||||
parameterMap.put("touser", StringUtils.join(userIds, '|'));
|
parameterMap.put("touser", StringUtil.join(userIds, SEPARATOR));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +45,7 @@ public class IdParameter implements Serializable {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public IdParameter putUseIds(int... partyIds) {
|
public IdParameter putUseIds(int... partyIds) {
|
||||||
parameterMap.put("toparty", StringUtils.join(partyIds, '|'));
|
parameterMap.put("toparty", StringUtil.join(partyIds, SEPARATOR));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +56,7 @@ public class IdParameter implements Serializable {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public IdParameter putTagIds(int... tagIds) {
|
public IdParameter putTagIds(int... tagIds) {
|
||||||
parameterMap.put("totag", StringUtils.join(tagIds, '|'));
|
parameterMap.put("totag", StringUtil.join(tagIds, SEPARATOR));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,25 +0,0 @@
|
|||||||
package com.foxinmy.weixin4j.qy.type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 企业号事件类型
|
|
||||||
*
|
|
||||||
* @className EventType
|
|
||||||
* @author jy
|
|
||||||
* @date 2014年9月30日
|
|
||||||
* @since JDK 1.7
|
|
||||||
* @see
|
|
||||||
*/
|
|
||||||
public enum EventType {
|
|
||||||
/**
|
|
||||||
* 进入企业号应用事件
|
|
||||||
*
|
|
||||||
* @see com.foxinmy.weixin4j.qy.event.EnterAgentEventMessage
|
|
||||||
*/
|
|
||||||
enter_agent,
|
|
||||||
/**
|
|
||||||
* 异步任务完成事件
|
|
||||||
*
|
|
||||||
* @see com.foxinmy.weixin4j.msg.event.BatchjobresultMessage
|
|
||||||
*/
|
|
||||||
batch_job_result;
|
|
||||||
}
|
|
||||||
@ -1,64 +0,0 @@
|
|||||||
package com.foxinmy.weixin4j.qy.test;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
|
||||||
|
|
||||||
public class AesMsgTest extends MessagePush {
|
|
||||||
StringBuilder xmlSb = new StringBuilder();
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testValidate() throws WeixinException, IOException {
|
|
||||||
String para = "?msg_signature=33f680b72cfd87a6f8f4d751575bcc31266853a9×tamp=1416488666&nonce=1358224345&echostr=WZu9tT6KDuyhgOZ1aT%2FIoPNaUkA%2FsfVR%2F%2BDua5q84Kvhs6Fc1%2F6f2510%2BUuMByessdQWsoeak0lSIpaYOIlHrw%3D%3D";
|
|
||||||
xmlSb.delete(0, xmlSb.length());
|
|
||||||
String response = get(para);
|
|
||||||
Assert.assertEquals("2143641595566077626", response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testType1() throws WeixinException, IOException {
|
|
||||||
String para = "?signature=6dd806a20a314723e78bc58742a1b98a7adfd151×tamp=1415979366&nonce=1865915590";
|
|
||||||
xmlSb.delete(0, xmlSb.length());
|
|
||||||
xmlSb.append("<xml>");
|
|
||||||
xmlSb.append("<ToUserName><![CDATA[gh_248c6f91d64f]]></ToUserName>");
|
|
||||||
xmlSb.append("<FromUserName><![CDATA[oyFLst1bqtuTcxK-ojF8hOGtLQao]]></FromUserName>");
|
|
||||||
xmlSb.append("<CreateTime>1415979365</CreateTime>");
|
|
||||||
xmlSb.append("<MsgType><![CDATA[event]]></MsgType>");
|
|
||||||
xmlSb.append("<Event><![CDATA[CLICK]]></Event>");
|
|
||||||
xmlSb.append("<EventKey><![CDATA[CHECKIN]]></EventKey>");
|
|
||||||
xmlSb.append("</xml>");
|
|
||||||
String response = push(para, xmlSb.toString());
|
|
||||||
Assert.assertNotNull(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testType2() throws WeixinException, IOException {
|
|
||||||
String para = "?signature=ad05f836772d1cbba1ff2edb7be4b9c9fb3a43d5×tamp=1415980001&nonce=1803216865&encrypt_type=raw&msg_signature=c0d38e9ca00548f7142627ec2908a4fe8481025e";
|
|
||||||
xmlSb.delete(0, xmlSb.length());
|
|
||||||
xmlSb.append("<xml>");
|
|
||||||
xmlSb.append("<ToUserName><![CDATA[gh_248c6f91d64f]]></ToUserName>");
|
|
||||||
xmlSb.append("<FromUserName><![CDATA[oyFLst1bqtuTcxK-ojF8hOGtLQao]]></FromUserName>");
|
|
||||||
xmlSb.append("<CreateTime>1415980001</CreateTime>");
|
|
||||||
xmlSb.append("<MsgType><![CDATA[event]]></MsgType>");
|
|
||||||
xmlSb.append("<Event><![CDATA[CLICK]]></Event>");
|
|
||||||
xmlSb.append("<EventKey><![CDATA[CHECKIN]]></EventKey>");
|
|
||||||
xmlSb.append("</xml>");
|
|
||||||
String response = push(para, xmlSb.toString());
|
|
||||||
Assert.assertNotNull(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testType3() throws WeixinException, IOException {
|
|
||||||
String para = "?signature=ad05f836772d1cbba1ff2edb7be4b9c9fb3a43d5×tamp=1415980001&nonce=1803216865&encrypt_type=aes&msg_signature=c0d38e9ca00548f7142627ec2908a4fe8481025e";
|
|
||||||
xmlSb.delete(0, xmlSb.length());
|
|
||||||
xmlSb.append("<xml>");
|
|
||||||
xmlSb.append("<ToUserName><![CDATA[gh_248c6f91d64f]]></ToUserName>");
|
|
||||||
xmlSb.append("<Encrypt><![CDATA[R6VQIWDR14XgSRLm25zc7V/WJYqK15gsUiMh0u/5GTMZME6jGtHkyfVN079ZPL065b+ZDq3TnoFKKtjtZlzcodY6Fm8+EujvtbTdVMMFSwdo8AwqVViAn09+DDfqPaNvbHUSiYsL3qlxArs1MH6APRUHFo7MU/piY1x2stJc8+kv28xtF+K8Aou0RuPO7PeQ18Zu/GkLnYNiI1E7UG31UYfOgVKcRjeE0PXa18iF5LBS8G/ce/l+/pH/DJWUBw5uXaqSOlo21tctlgLXu3bYUUkIu8tT49QwhHvRZILtO9icoyCNuTA7iTcHIdlAe1bD1S0ncmopIQCGmoU2/AXC2CCi6trONf3EPNKKKfDeQYHadnVZOg6kTX2cnYmHZLviYeLzjCKFSqSNkimoSKQ/Dcutpsq1D82NCwiExUZW4oo=]]></Encrypt>");
|
|
||||||
xmlSb.append("</xml>");
|
|
||||||
String response = push(para, xmlSb.toString());
|
|
||||||
Assert.assertNotNull(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,68 +0,0 @@
|
|||||||
package com.foxinmy.weixin4j.qy.test;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
import org.apache.http.HttpResponse;
|
|
||||||
import org.apache.http.HttpStatus;
|
|
||||||
import org.apache.http.StatusLine;
|
|
||||||
import org.apache.http.client.HttpClient;
|
|
||||||
import org.apache.http.client.methods.HttpGet;
|
|
||||||
import org.apache.http.client.methods.HttpPost;
|
|
||||||
import org.apache.http.entity.StringEntity;
|
|
||||||
import org.apache.http.impl.client.DefaultHttpClient;
|
|
||||||
import org.apache.http.util.EntityUtils;
|
|
||||||
|
|
||||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
|
||||||
|
|
||||||
public class MessagePush {
|
|
||||||
|
|
||||||
private final String server = "http://localhost:8090";
|
|
||||||
private final HttpClient httpClient;
|
|
||||||
private final HttpPost httpPost;
|
|
||||||
private final HttpGet httpGet;
|
|
||||||
|
|
||||||
public MessagePush() {
|
|
||||||
httpClient = new DefaultHttpClient();
|
|
||||||
httpPost = new HttpPost();
|
|
||||||
httpPost.setURI(URI.create(server));
|
|
||||||
|
|
||||||
httpGet = new HttpGet();
|
|
||||||
httpGet.setURI(URI.create(server));
|
|
||||||
}
|
|
||||||
|
|
||||||
public String get(String para) throws WeixinException, IOException {
|
|
||||||
httpGet.setURI(URI.create(server + para));
|
|
||||||
HttpResponse httpResponse = httpClient.execute(httpGet);
|
|
||||||
return entity(httpResponse);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String push(String xml) throws WeixinException, IOException {
|
|
||||||
return push("", xml);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String push(String para, String xml) throws WeixinException,
|
|
||||||
IOException {
|
|
||||||
httpPost.setURI(URI.create(server + para));
|
|
||||||
httpPost.setEntity(new StringEntity(xml, StandardCharsets.UTF_8));
|
|
||||||
HttpResponse httpResponse = httpClient.execute(httpPost);
|
|
||||||
return entity(httpResponse);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String entity(HttpResponse httpResponse) throws WeixinException,
|
|
||||||
IOException {
|
|
||||||
StatusLine statusLine = httpResponse.getStatusLine();
|
|
||||||
|
|
||||||
int status = statusLine.getStatusCode();
|
|
||||||
if (status != HttpStatus.SC_OK) {
|
|
||||||
throw new WeixinException(Integer.toString(status), "request fail");
|
|
||||||
}
|
|
||||||
if (status == HttpStatus.SC_MOVED_PERMANENTLY
|
|
||||||
|| status == HttpStatus.SC_MOVED_TEMPORARILY) {
|
|
||||||
throw new WeixinException(Integer.toString(status), "uri moved");
|
|
||||||
}
|
|
||||||
return EntityUtils.toString(httpResponse.getEntity(),
|
|
||||||
StandardCharsets.UTF_8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -130,7 +130,7 @@ public final class WeixinServerBootstrap {
|
|||||||
new WeixinServerInitializer(aesToken,
|
new WeixinServerInitializer(aesToken,
|
||||||
messageDispatcher));
|
messageDispatcher));
|
||||||
Channel ch = b.bind(serverPort).sync().channel();
|
Channel ch = b.bind(serverPort).sync().channel();
|
||||||
System.err.println("weixin server startup OK:" + serverPort);
|
System.err.println("weixin4j server startup OK:" + serverPort);
|
||||||
ch.closeFuture().sync();
|
ch.closeFuture().sync();
|
||||||
} catch (WeixinException e) {
|
} catch (WeixinException e) {
|
||||||
throw e;
|
throw e;
|
||||||
|
|||||||
@ -16,32 +16,28 @@ public class EncryptMessageHandler extends DefaultHandler {
|
|||||||
|
|
||||||
private String encryptContent;
|
private String encryptContent;
|
||||||
|
|
||||||
private String currentQName;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startDocument() throws SAXException {
|
public void startDocument() throws SAXException {
|
||||||
encryptContent = null;
|
encryptContent = null;
|
||||||
currentQName = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startElement(String uri, String localName, String qName,
|
public void startElement(String uri, String localName, String qName,
|
||||||
Attributes attributes) throws SAXException {
|
Attributes attributes) throws SAXException {
|
||||||
this.currentQName = qName;
|
if (qName.equalsIgnoreCase("encrypt")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void endElement(String uri, String localName, String qName)
|
public void endElement(String uri, String localName, String qName)
|
||||||
throws SAXException {
|
throws SAXException {
|
||||||
this.currentQName = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void characters(char[] ch, int start, int length)
|
public void characters(char[] ch, int start, int length)
|
||||||
throws SAXException {
|
throws SAXException {
|
||||||
if (currentQName.equalsIgnoreCase("encrypt")) {
|
|
||||||
this.encryptContent = new String(ch, start, length);
|
this.encryptContent = new String(ch, start, length);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getEncryptContent() {
|
public String getEncryptContent() {
|
||||||
|
|||||||
@ -25,9 +25,9 @@ import com.foxinmy.weixin4j.startup.WeixinServerBootstrap;
|
|||||||
*/
|
*/
|
||||||
public class MessageServerStarup {
|
public class MessageServerStarup {
|
||||||
|
|
||||||
final String appid = "公众号appid";
|
final String appid = "wx0d1d598c0c03c999";
|
||||||
final String token = "开发者token";
|
final String token = "carsonliu13450438112";
|
||||||
final String aesKey = "aes加密密钥";
|
final String aesKey = "vlrw8zK2UDSV7Hbmkl8ThzSBmdC11Lw95Um9b2dg3w1";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 明文模式
|
* 明文模式
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user