weixin4j-server:新增企业号消息服务相关类
This commit is contained in:
parent
97dc88d7c7
commit
8ed7ba3f49
@ -411,4 +411,6 @@
|
||||
|
||||
+ **weixin4j-mp**: 调整群发消息接口返回类型为字符串数组[{msg_id,msg_data_id}]
|
||||
|
||||
+ **weixin4j-qy**: 新增聊天服务接口[ChatApi](./weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/ChatApi.java)
|
||||
+ **weixin4j-qy**: 新增聊天服务接口[ChatApi](./weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/ChatApi.java)
|
||||
|
||||
+ **weixin4j-server**: 新增企业号消息服务相关类
|
||||
@ -3,7 +3,7 @@ weixin4j
|
||||
|
||||
微信开发工具包
|
||||
-------------
|
||||
> `weixin4j`是一个用java编写针对微信开发的工具包,包含[weixin4j-mp](./weixin4j-mp)(微信公众平台API)、[weixin4j-qy](./weixin4j-qy)(微信企业号API)以及[weixin4j-server](./weixin4j-server)(微信被动消息服务器)三个工程.
|
||||
> `weixin4j`是一个用java编写针对微信开发的工具包,包含[weixin4j-mp](./weixin4j-mp)(微信公众平台API)、[weixin4j-qy](./weixin4j-qy)(微信企业号API)以及[weixin4j-server](./weixin4j-server)(微信回调消息服务器)三个工程.
|
||||
|
||||
功能列表
|
||||
-------
|
||||
|
||||
@ -2,15 +2,9 @@ package com.foxinmy.weixin4j.mp.test;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
|
||||
import com.foxinmy.weixin4j.model.Token;
|
||||
import com.foxinmy.weixin4j.mp.payment.v2.RefundRecordV2;
|
||||
import com.foxinmy.weixin4j.payment.mch.Order;
|
||||
@ -105,25 +99,17 @@ public class XmlstreamTest {
|
||||
com.foxinmy.weixin4j.payment.mch.RefundRecord.class));
|
||||
}
|
||||
|
||||
public static String errorXml() {
|
||||
StringBuffer xml = new StringBuffer();
|
||||
String url = "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";
|
||||
try {
|
||||
Document doc = Jsoup.parse(new URL(url), 5000);
|
||||
Elements eles = doc.getElementsByTag("tr");
|
||||
for (Element ele : eles) {
|
||||
xml.append("<error>");
|
||||
xml.append("<code>").append(ele.child(0).text())
|
||||
.append("</code>");
|
||||
xml.append("<text>").append(ele.child(1).text())
|
||||
.append("</text>");
|
||||
xml.append("</error>");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return xml.toString();
|
||||
}
|
||||
/*
|
||||
* public static String errorXml() { StringBuffer xml = new StringBuffer();
|
||||
* String url =
|
||||
* "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"
|
||||
* ; try { Document doc = Jsoup.parse(new URL(url), 5000); Elements eles =
|
||||
* doc.getElementsByTag("tr"); for (Element ele : eles) {
|
||||
* xml.append("<error>"); xml.append("<code>").append(ele.child(0).text())
|
||||
* .append("</code>"); xml.append("<text>").append(ele.child(1).text())
|
||||
* .append("</text>"); xml.append("</error>"); } } catch (Exception e) {
|
||||
* e.printStackTrace(); } return xml.toString(); }
|
||||
*/
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// map2xml();
|
||||
|
||||
@ -171,7 +171,7 @@ public class OUserInfo implements Serializable {
|
||||
/**
|
||||
* 服务商套件中的对应应用id
|
||||
*/
|
||||
private String appid;
|
||||
private int appid;
|
||||
/**
|
||||
* 授权方应用敏感权限组,目前仅有get_location,表示是否有权限设置应用获取地理位置的开关
|
||||
*/
|
||||
@ -191,11 +191,11 @@ public class OUserInfo implements Serializable {
|
||||
this.authType = null;
|
||||
}
|
||||
|
||||
public String getAppid() {
|
||||
public int getAppid() {
|
||||
return appid;
|
||||
}
|
||||
|
||||
public void setAppid(String appid) {
|
||||
public void setAppid(int appid) {
|
||||
this.appid = appid;
|
||||
}
|
||||
|
||||
|
||||
@ -42,24 +42,19 @@ public class SuiteTicketHolder {
|
||||
* @return
|
||||
*/
|
||||
public String getCacheKey() {
|
||||
return getCacheKey0(suiteId);
|
||||
}
|
||||
|
||||
private String getCacheKey0(String suiteId) {
|
||||
return String.format("qy_suite_ticket_%s", suiteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存ticket
|
||||
*
|
||||
* @param suiteTicket
|
||||
* @param ticket
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public void cachingTicket(WeixinSuiteMessage suiteTicket)
|
||||
throws WeixinException {
|
||||
Token token = new Token(suiteTicket.getSuiteTicket());
|
||||
public void cachingTicket(String ticket) throws WeixinException {
|
||||
Token token = new Token(ticket);
|
||||
token.setExpiresIn(-1);
|
||||
tokenStorager.caching(getCacheKey0(suiteTicket.getSuiteId()), token);
|
||||
tokenStorager.caching(getCacheKey(), token);
|
||||
}
|
||||
|
||||
public String getSuiteId() {
|
||||
|
||||
@ -62,4 +62,8 @@
|
||||
|
||||
`WeixinServerBootstrap` 构造函数支持多个公众号
|
||||
|
||||
`MessageHandlerAdapter` 声明时限定泛型为`WeixinMessage`的子类
|
||||
`MessageHandlerAdapter` 声明时限定泛型为`WeixinMessage`的子类
|
||||
|
||||
* 2015-08-01
|
||||
|
||||
新增企业号消息服务相关类
|
||||
@ -1,7 +1,7 @@
|
||||
weixin4j-server
|
||||
===============
|
||||
|
||||
微信消息服务器
|
||||
微信回调消息服务器
|
||||
-------------
|
||||
base on netty.
|
||||
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
package com.foxinmy.weixin4j.qy.chat;
|
||||
|
||||
/**
|
||||
* 会话事件
|
||||
*
|
||||
* @className ChatEventType
|
||||
* @author jy
|
||||
* @date 2015年8月1日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public enum ChatEventType {
|
||||
/**
|
||||
* 创建会话
|
||||
*/
|
||||
create_chat,
|
||||
/**
|
||||
* 修改会话
|
||||
*/
|
||||
update_chat,
|
||||
/**
|
||||
* 退出会话
|
||||
*/
|
||||
quit_chat,
|
||||
/**
|
||||
* 订阅事件
|
||||
*/
|
||||
subscribe,
|
||||
/**
|
||||
* 取消订阅事件
|
||||
*/
|
||||
unsubscribe;
|
||||
}
|
||||
@ -0,0 +1,216 @@
|
||||
package com.foxinmy.weixin4j.qy.chat;
|
||||
|
||||
import java.beans.Transient;
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
|
||||
/**
|
||||
* 会话事件或消息
|
||||
*
|
||||
* @className ChatItem
|
||||
* @author jy
|
||||
* @date 2015年8月1日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class ChatItem implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -5921235260175596270L;
|
||||
|
||||
public final String LIST_SEPARATOR = "|";
|
||||
|
||||
/**
|
||||
* 操作成员UserID
|
||||
*/
|
||||
@XmlElement(name = "FromUserName")
|
||||
private String operatorId;
|
||||
/**
|
||||
* 消息创建时间(整型)
|
||||
*/
|
||||
@XmlElement(name = "CreateTime")
|
||||
private long createTime;
|
||||
/**
|
||||
* 消息类型
|
||||
*
|
||||
*/
|
||||
@XmlElement(name = "MsgType")
|
||||
private String msgType;
|
||||
/**
|
||||
* 事件类型
|
||||
*/
|
||||
@XmlElement(name = "Event")
|
||||
private String eventType;
|
||||
/**
|
||||
* 会话id
|
||||
*/
|
||||
@XmlElement(name = "ChatId")
|
||||
private String chatId;
|
||||
/**
|
||||
* 会话标题
|
||||
*/
|
||||
@XmlElement(name = "Name")
|
||||
private String chatName;
|
||||
/**
|
||||
* 管理员userid
|
||||
*/
|
||||
@XmlElement(name = "Owner")
|
||||
private String ownerId;
|
||||
/**
|
||||
* 会话成员列表
|
||||
*/
|
||||
@XmlElement(name = "UserList")
|
||||
private String members;
|
||||
/**
|
||||
* 会话新增成员列表
|
||||
*/
|
||||
@XmlElement(name = "AddUserList")
|
||||
private String addMembers;
|
||||
/**
|
||||
* 会话删除成员列表
|
||||
*/
|
||||
@XmlElement(name = "DelUserList")
|
||||
private String deleteMembers;
|
||||
/**
|
||||
* 消息ID 64位整型
|
||||
*/
|
||||
@XmlElement(name = "MsgId")
|
||||
private long msgId;
|
||||
/**
|
||||
* 接收人
|
||||
*/
|
||||
@XmlElement(name = "Receiver")
|
||||
private ChatReceiver receiver;
|
||||
/**
|
||||
* 文本消息内容
|
||||
*/
|
||||
@XmlElement(name = "Content")
|
||||
private String content;
|
||||
/**
|
||||
* 图片链接
|
||||
*/
|
||||
@XmlElement(name = "PicUrl")
|
||||
private String picUrl;
|
||||
/**
|
||||
* 图片媒体文件id,可以调用获取媒体文件接口拉取数据
|
||||
*/
|
||||
@XmlElement(name = "MediaId")
|
||||
private String mediaId;
|
||||
|
||||
public String getOperatorId() {
|
||||
return operatorId;
|
||||
}
|
||||
|
||||
public long getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
@Transient
|
||||
@XmlTransient
|
||||
public Date getFormatCreateTime() {
|
||||
return createTime > 0l ? new Date(createTime * 1000l) : null;
|
||||
}
|
||||
|
||||
public String getMsgType() {
|
||||
return msgType;
|
||||
}
|
||||
|
||||
@Transient
|
||||
@XmlTransient
|
||||
public MessageType getFormatMsgType() {
|
||||
return msgType != null ? MessageType.valueOf(msgType) : null;
|
||||
}
|
||||
|
||||
public String getEventType() {
|
||||
return eventType;
|
||||
}
|
||||
|
||||
@Transient
|
||||
@XmlTransient
|
||||
public ChatEventType getFormatEventType() {
|
||||
return eventType != null ? ChatEventType.valueOf(eventType) : null;
|
||||
}
|
||||
|
||||
public String getChatId() {
|
||||
return chatId;
|
||||
}
|
||||
|
||||
public String getChatName() {
|
||||
return chatName;
|
||||
}
|
||||
|
||||
public String getOwnerId() {
|
||||
return ownerId;
|
||||
}
|
||||
|
||||
public String getMembers() {
|
||||
return members;
|
||||
}
|
||||
|
||||
@Transient
|
||||
@XmlTransient
|
||||
public List<String> getFormatMembers() {
|
||||
return members != null ? Arrays.asList(members.split(LIST_SEPARATOR))
|
||||
: null;
|
||||
}
|
||||
|
||||
public String getAddMembers() {
|
||||
return addMembers;
|
||||
}
|
||||
|
||||
@Transient
|
||||
@XmlTransient
|
||||
public List<String> getFormatAddMembers() {
|
||||
return addMembers != null ? Arrays.asList(addMembers
|
||||
.split(LIST_SEPARATOR)) : null;
|
||||
}
|
||||
|
||||
public String getDeleteMembers() {
|
||||
return deleteMembers;
|
||||
}
|
||||
|
||||
@Transient
|
||||
@XmlTransient
|
||||
public List<String> getFormatDeleteMembers() {
|
||||
return deleteMembers != null ? Arrays.asList(deleteMembers
|
||||
.split(LIST_SEPARATOR)) : null;
|
||||
}
|
||||
|
||||
public long getMsgId() {
|
||||
return msgId;
|
||||
}
|
||||
|
||||
public ChatReceiver getReceiver() {
|
||||
return receiver;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public String getPicUrl() {
|
||||
return picUrl;
|
||||
}
|
||||
|
||||
public String getMediaId() {
|
||||
return mediaId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ChatItem [operatorId=" + operatorId + ", createTime="
|
||||
+ createTime + ", msgType=" + msgType + ", eventType="
|
||||
+ eventType + ", chatId=" + chatId + ", chatName=" + chatName
|
||||
+ ", ownerId=" + ownerId + ", members=" + members
|
||||
+ ", addMembers=" + addMembers + ", deleteMembers="
|
||||
+ deleteMembers + ", msgId=" + msgId + ", receiver=" + receiver
|
||||
+ ", content=" + content + ", picUrl=" + picUrl + ", mediaId="
|
||||
+ mediaId + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
package com.foxinmy.weixin4j.qy.chat;
|
||||
|
||||
import java.beans.Transient;
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
|
||||
/**
|
||||
* 接收人
|
||||
*
|
||||
* @className ChatReceiver
|
||||
* @author jy
|
||||
* @date 2015年8月1日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class ChatReceiver implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -3870813624685620828L;
|
||||
/**
|
||||
* 成员id|会话id
|
||||
*/
|
||||
@XmlElement(name = "id")
|
||||
private String targetId;
|
||||
/**
|
||||
* 群聊|单聊
|
||||
*/
|
||||
@XmlElement(name = "type")
|
||||
private String chatType;
|
||||
|
||||
public String getTargetId() {
|
||||
return targetId;
|
||||
}
|
||||
|
||||
public String getChatType() {
|
||||
return chatType;
|
||||
}
|
||||
|
||||
@Transient
|
||||
@XmlTransient
|
||||
public ChatType getFormatChatType() {
|
||||
return ChatType.valueOf(chatType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ChatReceiver [targetId=" + targetId + ", chatType=" + chatType
|
||||
+ "]";
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package com.foxinmy.weixin4j.qy.chat;
|
||||
|
||||
/**
|
||||
* 会话类型
|
||||
*
|
||||
* @className ChatType
|
||||
* @author jy
|
||||
* @date 2015年7月31日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public enum ChatType {
|
||||
/**
|
||||
* 单聊
|
||||
*/
|
||||
single,
|
||||
/**
|
||||
* 群聊
|
||||
*/
|
||||
group
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
package com.foxinmy.weixin4j.qy.chat;
|
||||
|
||||
import java.beans.Transient;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
|
||||
import com.foxinmy.weixin4j.type.AgentType;
|
||||
|
||||
/**
|
||||
* 企业号聊天服务回调消息
|
||||
*
|
||||
* @className WeixinChatMessage
|
||||
* @author jy
|
||||
* @date 2015年8月1日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
@XmlRootElement(name = "xml")
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class WeixinChatMessage implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 6788124387186831643L;
|
||||
|
||||
/**
|
||||
* 企业号CorpID
|
||||
*/
|
||||
@XmlElement(name = "ToUserName")
|
||||
private String corpId;
|
||||
/**
|
||||
* 应用类型
|
||||
*/
|
||||
@XmlElement(name = "AgentType")
|
||||
private String agentType;
|
||||
/**
|
||||
* 消息数量
|
||||
*/
|
||||
@XmlElement(name = "ItemCount")
|
||||
private int itemCount;
|
||||
/**
|
||||
* 会话事件或消息
|
||||
*/
|
||||
@XmlElement(name = "Item")
|
||||
public List<ChatItem> items;
|
||||
/**
|
||||
* 回调包ID,uint64类型,企业内唯一
|
||||
*/
|
||||
@XmlElement(name = "PackageId")
|
||||
private String packageId;
|
||||
|
||||
public String getCorpId() {
|
||||
return corpId;
|
||||
}
|
||||
|
||||
public String getAgentType() {
|
||||
return agentType;
|
||||
}
|
||||
|
||||
@Transient
|
||||
@XmlTransient
|
||||
public AgentType getFormatAgentType() {
|
||||
return AgentType.valueOf(agentType);
|
||||
}
|
||||
|
||||
public int getItemCount() {
|
||||
return itemCount;
|
||||
}
|
||||
|
||||
public List<ChatItem> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
public String getPackageId() {
|
||||
return packageId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WeixinChatMessage [corpId=" + corpId + ", agentType="
|
||||
+ agentType + ", itemCount=" + itemCount + ", items=" + items
|
||||
+ ", packageId=" + packageId + "]";
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,14 @@
|
||||
package com.foxinmy.weixin4j.qy.suite;
|
||||
|
||||
import java.beans.Transient;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
|
||||
/**
|
||||
* 套件消息
|
||||
@ -30,7 +33,7 @@ public class WeixinSuiteMessage implements Serializable {
|
||||
* 事件类型
|
||||
*/
|
||||
@XmlElement(name = "InfoType")
|
||||
private SuiteEventType eventType;
|
||||
private String eventType;
|
||||
/**
|
||||
* 时间戳
|
||||
*/
|
||||
@ -51,14 +54,26 @@ public class WeixinSuiteMessage implements Serializable {
|
||||
return suiteId;
|
||||
}
|
||||
|
||||
public SuiteEventType getEventType() {
|
||||
public String getEventType() {
|
||||
return eventType;
|
||||
}
|
||||
|
||||
@Transient
|
||||
@XmlTransient
|
||||
public SuiteEventType getFormatEventType() {
|
||||
return SuiteEventType.valueOf(eventType);
|
||||
}
|
||||
|
||||
public long getTimeStamp() {
|
||||
return timeStamp;
|
||||
}
|
||||
|
||||
@Transient
|
||||
@XmlTransient
|
||||
public Date getFormatTimeStamp() {
|
||||
return timeStamp > 0l ? new Date(timeStamp * 1000l) : null;
|
||||
}
|
||||
|
||||
public String getSuiteTicket() {
|
||||
return SuiteTicket;
|
||||
}
|
||||
@ -7,6 +7,8 @@ import java.util.Date;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
|
||||
/**
|
||||
* 微信消息基类
|
||||
*
|
||||
@ -103,6 +105,12 @@ public class WeixinMessage implements Serializable {
|
||||
return msgType;
|
||||
}
|
||||
|
||||
@Transient
|
||||
@XmlTransient
|
||||
public MessageType getFormatMsgType() {
|
||||
return MessageType.valueOf(msgType);
|
||||
}
|
||||
|
||||
public long getMsgId() {
|
||||
return msgId;
|
||||
}
|
||||
|
||||
@ -130,11 +130,17 @@ public final class WeixinServerBootstrap {
|
||||
* @param messageMatcher
|
||||
* 消息匹配器
|
||||
* @param aesTokens
|
||||
* 多个公众号
|
||||
* 公众号信息
|
||||
* @return
|
||||
*/
|
||||
public WeixinServerBootstrap(WeixinMessageMatcher messageMatcher,
|
||||
AesToken... aesTokens) {
|
||||
if (messageMatcher == null) {
|
||||
throw new IllegalArgumentException("MessageMatcher not be null");
|
||||
}
|
||||
if (aesTokens == null) {
|
||||
throw new IllegalArgumentException("AesToken not be null");
|
||||
}
|
||||
this.aesTokenMap = new HashMap<String, AesToken>();
|
||||
for (AesToken aesToken : aesTokens) {
|
||||
this.aesTokenMap.put(aesToken.getWeixinId(), aesToken);
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
package com.foxinmy.weixin4j.type;
|
||||
|
||||
/**
|
||||
* 应用类型
|
||||
*
|
||||
* @className AgentType
|
||||
* @author jy
|
||||
* @date 2015年8月1日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public enum AgentType {
|
||||
/**
|
||||
* 聊天应用
|
||||
*/
|
||||
chat
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user