weixin4j-server:新增企业号消息服务相关类

This commit is contained in:
jinyu 2015-08-02 00:03:47 +08:00
parent 97dc88d7c7
commit 8ed7ba3f49
17 changed files with 487 additions and 44 deletions

View File

@ -412,3 +412,5 @@
+ **weixin4j-mp**: 调整群发消息接口返回类型为字符串数组[{msg_id,msg_data_id}] + **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**: 新增企业号消息服务相关类

View File

@ -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)(微信回调消息服务器)三个工程.
功能列表 功能列表
------- -------

View File

@ -2,15 +2,9 @@ package com.foxinmy.weixin4j.mp.test;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.FileReader; import java.io.FileReader;
import java.net.URL;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; 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.model.Token;
import com.foxinmy.weixin4j.mp.payment.v2.RefundRecordV2; import com.foxinmy.weixin4j.mp.payment.v2.RefundRecordV2;
import com.foxinmy.weixin4j.payment.mch.Order; import com.foxinmy.weixin4j.payment.mch.Order;
@ -105,25 +99,17 @@ public class XmlstreamTest {
com.foxinmy.weixin4j.payment.mch.RefundRecord.class)); com.foxinmy.weixin4j.payment.mch.RefundRecord.class));
} }
public static String errorXml() { /*
StringBuffer xml = new StringBuffer(); * 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"; * String url =
try { * "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"
Document doc = Jsoup.parse(new URL(url), 5000); * ; try { Document doc = Jsoup.parse(new URL(url), 5000); Elements eles =
Elements eles = doc.getElementsByTag("tr"); * doc.getElementsByTag("tr"); for (Element ele : eles) {
for (Element ele : eles) { * xml.append("<error>"); xml.append("<code>").append(ele.child(0).text())
xml.append("<error>"); * .append("</code>"); xml.append("<text>").append(ele.child(1).text())
xml.append("<code>").append(ele.child(0).text()) * .append("</text>"); xml.append("</error>"); } } catch (Exception e) {
.append("</code>"); * e.printStackTrace(); } return xml.toString(); }
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 { public static void main(String[] args) throws Exception {
// map2xml(); // map2xml();

View File

@ -171,7 +171,7 @@ public class OUserInfo implements Serializable {
/** /**
* 服务商套件中的对应应用id * 服务商套件中的对应应用id
*/ */
private String appid; private int appid;
/** /**
* 授权方应用敏感权限组目前仅有get_location表示是否有权限设置应用获取地理位置的开关 * 授权方应用敏感权限组目前仅有get_location表示是否有权限设置应用获取地理位置的开关
*/ */
@ -191,11 +191,11 @@ public class OUserInfo implements Serializable {
this.authType = null; this.authType = null;
} }
public String getAppid() { public int getAppid() {
return appid; return appid;
} }
public void setAppid(String appid) { public void setAppid(int appid) {
this.appid = appid; this.appid = appid;
} }

View File

@ -42,24 +42,19 @@ public class SuiteTicketHolder {
* @return * @return
*/ */
public String getCacheKey() { public String getCacheKey() {
return getCacheKey0(suiteId);
}
private String getCacheKey0(String suiteId) {
return String.format("qy_suite_ticket_%s", suiteId); return String.format("qy_suite_ticket_%s", suiteId);
} }
/** /**
* 缓存ticket * 缓存ticket
* *
* @param suiteTicket * @param ticket
* @throws WeixinException * @throws WeixinException
*/ */
public void cachingTicket(WeixinSuiteMessage suiteTicket) public void cachingTicket(String ticket) throws WeixinException {
throws WeixinException { Token token = new Token(ticket);
Token token = new Token(suiteTicket.getSuiteTicket());
token.setExpiresIn(-1); token.setExpiresIn(-1);
tokenStorager.caching(getCacheKey0(suiteTicket.getSuiteId()), token); tokenStorager.caching(getCacheKey(), token);
} }
public String getSuiteId() { public String getSuiteId() {

View File

@ -63,3 +63,7 @@
`WeixinServerBootstrap` 构造函数支持多个公众号 `WeixinServerBootstrap` 构造函数支持多个公众号
`MessageHandlerAdapter` 声明时限定泛型为`WeixinMessage`的子类 `MessageHandlerAdapter` 声明时限定泛型为`WeixinMessage`的子类
* 2015-08-01
新增企业号消息服务相关类

View File

@ -1,7 +1,7 @@
weixin4j-server weixin4j-server
=============== ===============
微信消息服务器 微信回调消息服务器
------------- -------------
base on netty. base on netty.

View File

@ -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;
}

View File

@ -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 + "]";
}
}

View File

@ -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
+ "]";
}
}

View File

@ -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
}

View File

@ -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;
/**
* 回调包IDuint64类型企业内唯一
*/
@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 + "]";
}
}

View File

@ -1,11 +1,14 @@
package com.foxinmy.weixin4j.qy.suite; package com.foxinmy.weixin4j.qy.suite;
import java.beans.Transient;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date;
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
/** /**
* 套件消息 * 套件消息
@ -30,7 +33,7 @@ public class WeixinSuiteMessage implements Serializable {
* 事件类型 * 事件类型
*/ */
@XmlElement(name = "InfoType") @XmlElement(name = "InfoType")
private SuiteEventType eventType; private String eventType;
/** /**
* 时间戳 * 时间戳
*/ */
@ -51,14 +54,26 @@ public class WeixinSuiteMessage implements Serializable {
return suiteId; return suiteId;
} }
public SuiteEventType getEventType() { public String getEventType() {
return eventType; return eventType;
} }
@Transient
@XmlTransient
public SuiteEventType getFormatEventType() {
return SuiteEventType.valueOf(eventType);
}
public long getTimeStamp() { public long getTimeStamp() {
return timeStamp; return timeStamp;
} }
@Transient
@XmlTransient
public Date getFormatTimeStamp() {
return timeStamp > 0l ? new Date(timeStamp * 1000l) : null;
}
public String getSuiteTicket() { public String getSuiteTicket() {
return SuiteTicket; return SuiteTicket;
} }

View File

@ -7,6 +7,8 @@ import java.util.Date;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient; import javax.xml.bind.annotation.XmlTransient;
import com.foxinmy.weixin4j.type.MessageType;
/** /**
* 微信消息基类 * 微信消息基类
* *
@ -103,6 +105,12 @@ public class WeixinMessage implements Serializable {
return msgType; return msgType;
} }
@Transient
@XmlTransient
public MessageType getFormatMsgType() {
return MessageType.valueOf(msgType);
}
public long getMsgId() { public long getMsgId() {
return msgId; return msgId;
} }

View File

@ -130,11 +130,17 @@ public final class WeixinServerBootstrap {
* @param messageMatcher * @param messageMatcher
* 消息匹配器 * 消息匹配器
* @param aesTokens * @param aesTokens
* 多个公众号 * 公众号信息
* @return * @return
*/ */
public WeixinServerBootstrap(WeixinMessageMatcher messageMatcher, public WeixinServerBootstrap(WeixinMessageMatcher messageMatcher,
AesToken... aesTokens) { 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>(); this.aesTokenMap = new HashMap<String, AesToken>();
for (AesToken aesToken : aesTokens) { for (AesToken aesToken : aesTokens) {
this.aesTokenMap.put(aesToken.getWeixinId(), aesToken); this.aesTokenMap.put(aesToken.getWeixinId(), aesToken);

View File

@ -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
}