大重构:weixin4j精简为weixin4j-base、weixin4j-mp、weixin4j-qy、weixin4j-server四个子工程

This commit is contained in:
jinyu
2015-04-27 21:02:51 +08:00
parent 69c9bdffa4
commit 784d1f33ea
221 changed files with 24504 additions and 0 deletions
+31
View File
@@ -0,0 +1,31 @@
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>full</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>target/classes</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>/**</include>
</includes>
<excludes>
<exclude>*.properties</exclude>
<exclude>*.xml</exclude>
</excludes>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<unpack>true</unpack>
<includes>
<include>com.foxinmy:weixin4j-base</include>
</includes>
</dependencySet>
</dependencySets>
</assembly>
@@ -0,0 +1,807 @@
package com.foxinmy.weixin4j.qy;
import java.io.File;
import java.io.IOException;
import java.util.List;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.JsonResult;
import com.foxinmy.weixin4j.model.Button;
import com.foxinmy.weixin4j.qy.api.AgentApi;
import com.foxinmy.weixin4j.qy.api.BatchApi;
import com.foxinmy.weixin4j.qy.api.HelperApi;
import com.foxinmy.weixin4j.qy.api.MediaApi;
import com.foxinmy.weixin4j.qy.api.MenuApi;
import com.foxinmy.weixin4j.qy.api.NotifyApi;
import com.foxinmy.weixin4j.qy.api.PartyApi;
import com.foxinmy.weixin4j.qy.api.TagApi;
import com.foxinmy.weixin4j.qy.api.UserApi;
import com.foxinmy.weixin4j.qy.message.NotifyMessage;
import com.foxinmy.weixin4j.qy.model.AgentInfo;
import com.foxinmy.weixin4j.qy.model.AgentOverview;
import com.foxinmy.weixin4j.qy.model.AgentSetter;
import com.foxinmy.weixin4j.qy.model.BatchResult;
import com.foxinmy.weixin4j.qy.model.Callback;
import com.foxinmy.weixin4j.qy.model.IdParameter;
import com.foxinmy.weixin4j.qy.model.Party;
import com.foxinmy.weixin4j.qy.model.Tag;
import com.foxinmy.weixin4j.qy.model.User;
import com.foxinmy.weixin4j.qy.token.WeixinTokenCreator;
import com.foxinmy.weixin4j.qy.type.InviteType;
import com.foxinmy.weixin4j.qy.type.UserStatus;
import com.foxinmy.weixin4j.token.FileTokenHolder;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.type.MediaType;
/**
* 微信企业号接口实现
*
* @className WeixinProxy
* @author jy
* @date 2014年11月19日
* @since JDK 1.7
* @see <a href="http://qydev.weixin.qq.com/wiki/index.php">api文档</a>
*/
public class WeixinProxy {
private final MediaApi mediaApi;
private final MenuApi menuApi;
private final NotifyApi notifyApi;
private final PartyApi partyApi;
private final UserApi userApi;
private final TagApi tagApi;
private final HelperApi helperApi;
private final AgentApi agentApi;
private final BatchApi batchApi;
/**
* 默认采用文件存放Token信息
*/
public WeixinProxy() {
this(new FileTokenHolder(new WeixinTokenCreator()));
}
/**
* appid,appsecret
*
* @param corpid
* @param corpsecret
*/
public WeixinProxy(String corpid, String corpsecret) {
this(new FileTokenHolder(new WeixinTokenCreator(corpid, corpsecret)));
}
/**
* TokenHolder对象
*
* @see com.foxinmy.weixin4j.token.TokenHolder
* @param tokenHolder
*/
public WeixinProxy(TokenHolder tokenHolder) {
this.partyApi = new PartyApi(tokenHolder);
this.userApi = new UserApi(tokenHolder);
this.tagApi = new TagApi(tokenHolder);
this.helperApi = new HelperApi(tokenHolder);
this.agentApi = new AgentApi(tokenHolder);
this.batchApi = new BatchApi(tokenHolder);
this.notifyApi = new NotifyApi(tokenHolder);
this.menuApi = new MenuApi(tokenHolder);
this.mediaApi = new MediaApi(tokenHolder);
}
/**
* 发送消息(需要管理员对应用有使用权限,对收件人touser、toparty、totag有查看权限,否则本次调用失败)
* <p>
* 1) 发送人员列表存在错误的userid:执行发送,开发者需注意返回结果说明</br>
* 2)发送人员不在通讯录权限范围内:不执行发送任务,返回首个出错的userid</br>
* 3)发送人员不在应用可见范围内:不执行发送任务,返回首个出错的userid</br>
* </p>
*
* @param notify
* 客服消息对象
* @return
* 如果对应用或收件人、部门、标签任何一个无权限,则本次发送失败;如果收件人、部门或标签不存在,发送仍然执行,但返回无效的部分</br>
* { "errcode": 0, "errmsg": "ok", "invaliduser": "UserID1",
* "invalidparty":"PartyID1", "invalidtag":"TagID1" }
* @throws WeixinException
* @see com.foxinmy.weixin4j.qy.api.NotifyApi
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E">发送接口说明</a>
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E6%B6%88%E6%81%AF%E7%B1%BB%E5%9E%8B%E5%8F%8A%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F">发送格式说明</a>
* @see com.foxinmy.weixin4j.tuple.Text
* @see com.foxinmy.weixin4j.tuple.Image
* @see com.foxinmy.weixin4j.tuple.Voice
* @see com.foxinmy.weixin4j.tuple.Video
* @see com.foxinmy.weixin4j.tuple.File
* @see com.foxinmy.weixin4j.tuple.News
* @see com.foxinmy.weixin4j.tuple.MpNews
* @see com.foxinmy.weixin4j.qy.message.NotifyMessage
*/
public JSONObject sendNotify(NotifyMessage notify) throws WeixinException {
return notifyApi.sendNotify(notify);
}
/**
* 自定义菜单(管理员须拥有应用的管理权限 并且应用必须设置在回调模式)
*
* @param btnList
* 菜单列表
* @param agentid
* 应用ID
* @throws WeixinException
* @see com.foxinmy.weixin4j.qy.api.MenuApi
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%88%9B%E5%BB%BA%E5%BA%94%E7%94%A8%E8%8F%9C%E5%8D%95">创建自定义菜单</a>
* @see com.foxinmy.weixin4j.model.Button
*/
public JsonResult createMenu(List<Button> btnList, int agentid)
throws WeixinException {
return menuApi.createMenu(btnList, agentid);
}
/**
* 查询菜单(管理员须拥有应用的管理权限 并且应用必须设置在回调模式。)
*
* @param agentid
* 应用ID
* @return 菜单集合
* @throws WeixinException
* @see com.foxinmy.weixin4j.qy.api.MenuApi
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E8%8F%9C%E5%8D%95%E5%88%97%E8%A1%A8">查询菜单</a>
* @see com.foxinmy.weixin4j.model.Button
*/
public List<Button> getMenu(int agentid) throws WeixinException {
return menuApi.getMenu(agentid);
}
/**
* 删除菜单(管理员须拥有应用的管理权限 并且应用必须设置在回调模式)
*
* @param agentid
* 应用ID
* @throws WeixinException
* @see com.foxinmy.weixin4j.qy.api.MenuApi
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%88%A0%E9%99%A4%E8%8F%9C%E5%8D%95">删除菜单</a>
* @return 处理结果
*/
public JsonResult deleteMenu(int agentid) throws WeixinException {
return menuApi.deleteMenu(agentid);
}
/**
* 上传媒体文件
*
* @param file
* 媒体对象
* @return 上传到微信服务器返回的媒体标识
* @see com.foxinmy.weixin4j.qy.api.MediaApi
* @see {@link com.foxinmy.weixin4j.qy.WeixinProxy.MediaApi#uploadMedia(File, MediaType)}
* @throws WeixinException
* @throws IOException
*/
public String uploadMedia(File file) throws WeixinException, IOException {
return mediaApi.uploadMedia(file);
}
/**
* 上传媒体文件
*
* @param file
* 文件对象
* @param mediaType
* 媒体类型
* @return 上传到微信服务器返回的媒体标识
* @throws WeixinException
* @throws IOException
* @see com.foxinmy.weixin4j.qy.api.MediaApi
* @see com.foxinmy.weixin4j.type.MediaType
* @see {@link com.foxinmy.weixin4j.qy.WeixinProxy#uploadMedia(String, byte[],String)}
*/
public String uploadMedia(File file, MediaType mediaType)
throws WeixinException, IOException {
return mediaApi.uploadMedia(file, mediaType);
}
/**
* 上传媒体文件(完全公开。所有管理员均可调用,media_id可以共享)
* <p>
* 正常情况下返回{"type":"TYPE","media_id":"MEDIA_ID","created_at":123456789},
* 否则抛出异常.
* </p>
*
* @param bytes
* 媒体数据包
* @param mediaType
* 媒体类型
* @return 上传到微信服务器返回的媒体标识
* @see com.foxinmy.weixin4j.qy.api.MediaApi
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E4%B8%8A%E4%BC%A0%E5%AA%92%E4%BD%93%E6%96%87%E4%BB%B6">上传媒体文件说明</a>
* @throws WeixinException
*/
public String uploadMedia(String fileName, byte[] bytes, String mediaType)
throws WeixinException {
return mediaApi.uploadMedia(fileName, bytes, mediaType);
}
/**
* 下载媒体文件(完全公开。所有管理员均可调用,media_id可以共享)
*
* @param mediaId
* 媒体ID
* @return 二进制数据包
* @see com.foxinmy.weixin4j.qy.api.MediaApi
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E5%AA%92%E4%BD%93%E6%96%87%E4%BB%B6">获取媒体说明</a>
* @throws WeixinException
*/
public byte[] downloadMedia(String mediaId) throws WeixinException {
return mediaApi.downloadMedia(mediaId);
}
/**
* 下载媒体文件(完全公开。所有管理员均可调用,media_id可以共享)
* <p>
* 正常情况下返回表头如Content-Type: image/jpeg,否则抛出异常.
* </p>
*
* @param mediaId
* 存储在微信服务器上的媒体标识
* @param extension
* 媒体后缀名
* @return 写入硬盘后的文件对象
* @throws WeixinException
* @throws IOException
* @see com.foxinmy.weixin4j.qy.api.MediaApi
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E5%AA%92%E4%BD%93%E6%96%87%E4%BB%B6">获取媒体说明</a>
* @see com.foxinmy.weixin4j.type.MediaType
* @see {@link com.foxinmy.weixin4j.WeixinProxy.MediaApi#downloadMedia(String)}
*/
public File downloadMedia(String mediaId, String extension)
throws WeixinException {
return mediaApi.downloadMedia(mediaId, extension);
}
/**
* 创建部门(根部门的parentid为1)
*
* @param party
* 部门对象
* @see com.foxinmy.weixin4j.qy.model.Party
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E9%83%A8%E9%97%A8#.E5.88.9B.E5.BB.BA.E9.83.A8.E9.97.A8">创建部门说明</a>
* @see com.foxinmy.weixin4j.qy.api.PartyApi
* @return 部门ID
* @throws WeixinException
*/
public int createParty(Party party) throws WeixinException {
return partyApi.createParty(party);
}
/**
* 更新部门(如果非必须的字段未指定 则不更新该字段之前的设置值)
*
* @param party
* 部门对象
* @see com.foxinmy.weixin4j.qy.model.Party
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E9%83%A8%E9%97%A8#.E6.9B.B4.E6.96.B0.E9.83.A8.E9.97.A8">更新部门说明</a>
* @see com.foxinmy.weixin4j.qy.api.PartyApi
* @return 处理结果
* @throws WeixinException
*/
public JsonResult updateParty(Party party) throws WeixinException {
return partyApi.updateParty(party);
}
/**
* 查询部门列表(以部门的order字段从小到大排列)
*
* @param partyId
* 部门ID。获取指定部门ID下的子部门
* @see com.foxinmy.weixin4j.qy.model.Party
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E9%83%A8%E9%97%A8#.E8.8E.B7.E5.8F.96.E9.83.A8.E9.97.A8.E5.88.97.E8.A1.A8">获取部门列表</a>
* @see com.foxinmy.weixin4j.qy.api.PartyApi
* @return 部门列表
* @throws WeixinException
*/
public List<Party> listParty(int partyId) throws WeixinException {
return partyApi.listParty(partyId);
}
/**
* 删除部门(不能删除根部门;不能删除含有子部门、成员的部门)
*
* @param partyId
* 部门ID
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E9%83%A8%E9%97%A8#.E5.88.A0.E9.99.A4.E9.83.A8.E9.97.A8">删除部门说明</a>
* @see com.foxinmy.weixin4j.qy.api.PartyApi
* @return 处理结果
* @throws WeixinException
*/
public JsonResult deleteParty(int partyId) throws WeixinException {
return partyApi.deleteParty(partyId);
}
/**
* 批量上传部门
*
* @param parties
* 部门列表
* @see com.foxinmy.weixin4j.qy.api.MediaApi
* @see com.foxinmy.weixin4j.qy.api.BatchApi
* @see {@link com.foxinmy.weixin4j.qy.WeixinProxy#replaceparty(String,Callback)}
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%BC%82%E6%AD%A5%E4%BB%BB%E5%8A%A1%E6%8E%A5%E5%8F%A3#.E9.80.9A.E8.AE.AF.E5.BD.95.E6.9B.B4.E6.96.B0">批量任务</a>
* @return 上传后的mediaId
* @throws WeixinException
*/
public String batchUploadParties(List<Party> parties)
throws WeixinException {
return mediaApi.batchUploadParties(parties);
}
/**
* 创建成员
*
* @param user
* 成员对象
* @see com.foxinmy.weixin4j.qy.model.User
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%88%90%E5%91%98#.E5.88.9B.E5.BB.BA.E6.88.90.E5.91.98">创建成员说明</a>
* @see com.foxinmy.weixin4j.qy.api.UserApi
* @return 处理结果
* @throws WeixinException
*/
public JsonResult createUser(User user) throws WeixinException {
return userApi.createUser(user);
}
/**
* 更新用户(如果非必须的字段未指定 则不更新该字段之前的设置值)
*
* @param user
* 成员对象
* @see com.foxinmy.weixin4j.qy.model.User
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%88%90%E5%91%98#.E6.9B.B4.E6.96.B0.E6.88.90.E5.91.98">更新成员说明</a>
* @see com.foxinmy.weixin4j.qy.api.UserApi
* @return 处理结果
* @throws WeixinException
*/
public JsonResult updateUser(User user) throws WeixinException {
return userApi.updateUser(user);
}
/**
* 获取成员
*
* @param userid
* 成员唯一ID
* @see com.foxinmy.weixin4j.qy.model.User
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%88%90%E5%91%98#.E8.8E.B7.E5.8F.96.E6.88.90.E5.91.98">获取成员说明</a>
* @see com.foxinmy.weixin4j.qy.api.UserApi
* @return 成员对象
* @throws WeixinException
*/
public User getUser(String userid) throws WeixinException {
return userApi.getUser(userid);
}
/**
* code获取userid(管理员须拥有agent的使用权限;agentid必须和跳转链接时所在的企业应用ID相同。)
*
* @param code
* 通过员工授权获取到的code,每次员工授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期
* @param agentid
* 跳转链接时所在的企业应用ID
* @see com.foxinmy.weixin4j.qy.api.UserApi
* @return 成员对象
* @see {@link com.foxinmy.weixin4j.qy.WeixinProxy#getUser(String)}
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E4%BC%81%E4%B8%9A%E8%8E%B7%E5%8F%96code">企业获取code</a>
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E6%A0%B9%E6%8D%AEcode%E8%8E%B7%E5%8F%96%E6%88%90%E5%91%98%E4%BF%A1%E6%81%AF">根据code获取成员信息</a>
* @throws WeixinException
*/
public User getUserByCode(String code, int agentid) throws WeixinException {
return userApi.getUserByCode(code, agentid);
}
/**
* 获取部门成员
*
* @param partyId
* 部门ID 必须
* @param fetchChild
* 是否递归获取子部门下面的成员 非必须
* @param userStatus
* 成员状态 status可叠加 非必须
* @param findDetail
* 是否获取详细信息
* @see com.foxinmy.weixin4j.qy.model.User
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%88%90%E5%91%98#.E8.8E.B7.E5.8F.96.E9.83.A8.E9.97.A8.E6.88.90.E5.91.98">获取部门成员说明</a>
* @see com.foxinmy.weixin4j.qy.api.UserApi
* @return 成员列表
* @throws WeixinException
*/
public List<User> listUser(int partyId, boolean fetchChild,
UserStatus userStatus, boolean findDetail) throws WeixinException {
return userApi.listUser(partyId, fetchChild, userStatus, findDetail);
}
/**
* 获取部门下所有状态成员(不进行递归)
*
* @param departId
* 部门ID
* @see {@link com.foxinmy.weixin4j.qy.WeixinProxy#listUser(int, boolean,UserStatus)}
* @see com.foxinmy.weixin4j.qy.api.UserApi
* @return 成员列表
* @throws WeixinException
*/
public List<User> listUser(int departId) throws WeixinException {
return userApi.listUser(departId);
}
/**
* 删除成员
*
* @param userid
* 成员ID
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%88%90%E5%91%98#.E5.88.A0.E9.99.A4.E6.88.90.E5.91.98">删除成员说明</a>
* @see com.foxinmy.weixin4j.qy.api.UserApi
* @return 处理结果
* @throws WeixinException
*/
public JsonResult deleteUser(String userid) throws WeixinException {
return userApi.deleteUser(userid);
}
/**
* 批量删除成员
*
* @param userIds
* 成员列表
* @see <a href=
* "http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%88%90%E5%91%98#.E6.89.B9.E9.87.8F.E5.88.A0.E9.99.A4.E6.88.90.E5.91.98"
* >批量删除成员说明</a
* @see com.foxinmy.weixin4j.qy.api.UserApi
* @return 处理结果
* @throws WeixinException
*/
public JsonResult batchDeleteUser(List<String> userIds)
throws WeixinException {
return userApi.batchDeleteUser(userIds);
}
/**
* 邀请成员关注(管理员须拥有该成员的查看权限)
*
* @param userId
* 成员ID
* @param tips
* 推送到微信上的提示语(只有认证号可以使用)。当使用微信推送时,该字段默认为“请关注XXX企业号”,邮件邀请时,该字段无效。
* @see com.foxinmy.weixin4j.qy.api.UserApi
* @return 调用结果
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%88%90%E5%91%98#.E9.82.80.E8.AF.B7.E6.88.90.E5.91.98.E5.85.B3.E6.B3.A8">邀请成员关注说明</a>
* @throws WeixinException
*/
public InviteType inviteUser(String userId, String tips)
throws WeixinException {
return userApi.inviteUser(userId, tips);
}
/**
* 创建标签(创建的标签属于管理组;默认为未加锁状态)
*
* @param tagName
* 标签名称
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%A0%87%E7%AD%BE#.E5.88.9B.E5.BB.BA.E6.A0.87.E7.AD.BE">创建标签说明</a>
* @see com.foxinmy.weixin4j.qy.api.TagApi
* @return 标签ID
* @throws WeixinException
*/
public int createTag(String tagName) throws WeixinException {
return tagApi.createTag(tagName);
}
/**
* 更新标签(管理组必须是指定标签的创建者)
*
* @param tag
* 标签信息
* @see <a href=
* "http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%A0%87%E7%AD%BE#.E6.9B.B4.E6.96.B0.E6.A0.87.E7.AD.BE.E5.90.8D.E5.AD.97"
* >更新标签说明</a>
* @see com.foxinmy.weixin4j.qy.model.Tag
* @see com.foxinmy.weixin4j.qy.api.TagApi
* @return 处理结果
* @throws WeixinException
*/
public JsonResult updateTag(Tag tag) throws WeixinException {
return tagApi.updateTag(tag);
}
/**
* 删除标签(管理组必须是指定标签的创建者 并且标签的成员列表为空)
*
* @param tagId
* 标签ID
* @return 处理结果
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%A0%87%E7%AD%BE#.E5.88.A0.E9.99.A4.E6.A0.87.E7.AD.BE">删除标签说明</a>
* @see com.foxinmy.weixin4j.qy.api.TagApi
* @throws WeixinException
*/
public JsonResult deleteTag(int tagId) throws WeixinException {
return tagApi.deleteTag(tagId);
}
/**
* 获取标签列表
*
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%A0%87%E7%AD%BE#.E8.8E.B7.E5.8F.96.E6.A0.87.E7.AD.BE.E5.88.97.E8.A1.A8">获取标签列表说明</a>
* @see com.foxinmy.weixin4j.qy.model.Tag
* @see com.foxinmy.weixin4j.qy.api.TagApi
* @return 标签列表
* @throws WeixinException
*/
public List<Tag> listTag() throws WeixinException {
return tagApi.listTag();
}
/**
* 获取标签成员(管理组须拥有“获取标签成员”的接口权限,标签须对管理组可见;返回列表仅包含管理组管辖范围的成员)
*
* @param tagId
* 标签ID
* @see com.foxinmy.weixin4j.qy.model.User
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%A0%87%E7%AD%BE#.E8.8E.B7.E5.8F.96.E6.A0.87.E7.AD.BE.E6.88.90.E5.91.98">获取标签成员说明</a>
* @see com.foxinmy.weixin4j.qy.api.TagApi
* @return 成员列表
* @throws WeixinException
*/
public List<User> getTagUsers(int tagId) throws WeixinException {
return tagApi.getTagUsers(tagId);
}
/**
* 新增标签成员(标签对管理组可见且未加锁,成员属于管理组管辖范围)<br>
* <font color="red">若部分userid非法,则在text中体现</font>
*
* @param tagId
* 标签ID
* @param userIds
* 成员ID
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%A0%87%E7%AD%BE#.E5.A2.9E.E5.8A.A0.E6.A0.87.E7.AD.BE.E6.88.90.E5.91.98">新增标签成员说明</a>
* @see com.foxinmy.weixin4j.qy.api.TagApi
* @return 处理结果
* @throws WeixinException
*/
public JsonResult addTagUsers(int tagId, List<String> userIds)
throws WeixinException {
return tagApi.addTagUsers(tagId, userIds);
}
/**
* 删除标签成员(标签对管理组可见且未加锁,成员属于管理组管辖范围)<br>
* <font color="red">若部分userid非法,则在text中体现</font>
*
* @param tagId
* 标签ID
* @param userIds
* 成员ID
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%A0%87%E7%AD%BE#.E5.88.A0.E9.99.A4.E6.A0.87.E7.AD.BE.E6.88.90.E5.91.98">删除标签成员说明</a>
* @see com.foxinmy.weixin4j.qy.api.TagApi
* @return 处理结果
* @throws WeixinException
*/
public JsonResult deleteTagUsers(int tagId, List<String> userIds)
throws WeixinException {
return tagApi.deleteTagUsers(tagId, userIds);
}
/**
* 获取微信服务器IP地址
*
* @return IP地址
* @see com.foxinmy.weixin4j.qy.api.HelperApi
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%9B%9E%E8%B0%83%E6%A8%A1%E5%BC%8F#.E8.8E.B7.E5.8F.96.E5.BE.AE.E4.BF.A1.E6.9C.8D.E5.8A.A1.E5.99.A8.E7.9A.84ip.E6.AE.B5">获取IP地址</a>
* @throws WeixinException
*/
public List<String> getcallbackip() throws WeixinException {
return helperApi.getcallbackip();
}
/**
* 获取企业号某个应用的基本信息,包括头像、昵称、帐号类型、认证类型、可见范围等信息
*
* @param agentid
* 授权方应用id
* @return 应用信息
* @see com.foxinmy.weixin4j.qy.model.AgentInfo
* @see com.foxinmy.weixin4j.qy.api.AgentApi
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E4%BC%81%E4%B8%9A%E5%8F%B7%E5%BA%94%E7%94%A8">企业号应用的信息</a>
* @throws WeixinException
*/
public AgentInfo getAgent(int agentid) throws WeixinException {
return agentApi.getAgent(agentid);
}
/**
* 设置企业应用的选项设置信息,如:地理位置上报等
*
* @param agentSet
* 设置参数
* @see com.foxinmy.weixin4j.qy.model.AgentSetter
* @see com.foxinmy.weixin4j.qy.api.AgentApi
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E8%AE%BE%E7%BD%AE%E4%BC%81%E4%B8%9A%E5%8F%B7%E5%BA%94%E7%94%A8">设置企业号信息</a>
* @return 处理结果
* @throws WeixinException
*/
public JsonResult setAgent(AgentSetter agentSet) throws WeixinException {
return agentApi.setAgent(agentSet);
}
/**
* 获取应用概况列表
*
* @see com.foxinmy.weixin4j.qy.model.AgentOverview
* @see com.foxinmy.weixin4j.qy.api.AgentApi
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E5%BA%94%E7%94%A8%E6%A6%82%E5%86%B5%E5%88%97%E8%A1%A8">获取应用概况</a>
* @return 应用概况列表
* @throws WeixinException
*/
public List<AgentOverview> listAgentOverview() throws WeixinException {
return agentApi.listAgentOverview();
}
/**
* 批量邀请成员关注
*
* @param parameter
* 成员ID,标签ID,部门ID
* @param callback
* 接收任务执行结果的回调地址等信息
* @param tips
* 推送到微信上的提示语(只有认证号可以使用)。当使用微信推送时,该字段默认为“请关注XXX企业号”,邮件邀请时,该字段无效。
* @return 异步任务id,最大长度为64字符
* @see com.foxinmy.weixin4j.qy.model.IdParameter
* @see com.foxinmy.weixin4j.qy.model.Callback
* @see com.foxinmy.weixin4j.qy.api.BatchApi
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%BC%82%E6%AD%A5%E4%BB%BB%E5%8A%A1%E6%8E%A5%E5%8F%A3#.E9.82.80.E8.AF.B7.E6.88.90.E5.91.98.E5.85.B3.E6.B3.A8">邀请成员关注</a>
* @throws WeixinException
*/
public String inviteuser(IdParameter parameter, Callback callback,
String tips) throws WeixinException {
return batchApi.inviteuser(parameter, callback, tips);
}
/**
* 批量更新成员,本接口以userid为主键,增量更新企业号通讯录成员。
* <p>
* 1.模板中的部门需填写部门ID,多个部门用分号分隔,部门ID必须为数字</br>
* 2.文件中存在、通讯录中也存在的成员,更新成员在文件中指定的字段值 </br> 3.文件中存在、通讯录中不存在的成员,执行添加操作</br>
* 4.通讯录中存在、文件中不存在的成员,保持不变</br>
* </p>
*
* @param mediaId
* 带user信息的cvs文件上传后的media_id
* @param callback
* 接收任务执行结果的回调地址等信息
* @return 异步任务id,最大长度为64字符
* @see com.foxinmy.weixin4j.qy.model.Callback
* @see com.foxinmy.weixin4j.qy.api.BatchApi
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%BC%82%E6%AD%A5%E4%BB%BB%E5%8A%A1%E6%8E%A5%E5%8F%A3#.E5.A2.9E.E9.87.8F.E6.9B.B4.E6.96.B0.E6.88.90.E5.91.98">批量更新成员</a>
* @throws WeixinException
*/
public String syncuser(String mediaId, Callback callback)
throws WeixinException {
return batchApi.syncuser(mediaId, callback);
}
/**
* 批量覆盖成员,本接口以userid为主键,全量覆盖企业号通讯录成员,任务完成后企业号通讯录成员与提交的文件完全保持一致。
* <p>
* 1.模板中的部门需填写部门ID,多个部门用分号分隔,部门ID必须为数字</br> 2.文件中存在、通讯录中也存在的成员,完全以文件为准</br>
* 3.文件中存在、通讯录中不存在的成员,执行添加操作</br>
* 4.通讯录中存在、文件中不存在的成员,执行删除操作。出于安全考虑,如果需要删除的成员多于50人,
* 且多于现有人数的20%以上,系统将中止导入并返回相应的错误码
* </p>
*
* @param mediaId
* 带userid信息的cvs文件上传后的media_id
* @param callback
* 接收任务执行结果的回调地址等信息
* @return 异步任务id,最大长度为64字符
* @see com.foxinmy.weixin4j.qy.model.Callback
* @see com.foxinmy.weixin4j.qy.api.BatchApi
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%BC%82%E6%AD%A5%E4%BB%BB%E5%8A%A1%E6%8E%A5%E5%8F%A3#.E5.85.A8.E9.87.8F.E8.A6.86.E7.9B.96.E6.88.90.E5.91.98">批量覆盖成员</a>
* @throws WeixinException
*/
public String replaceuser(String mediaId, Callback callback)
throws WeixinException {
return batchApi.replaceuser(mediaId, callback);
}
/**
* 批量上传成员
*
* @param users
* 成员列表
* @see com.foxinmy.weixin4j.qy.api.MediaApi
* @see com.foxinmy.weixin4j.qy.api.BatchApi
* @see {@link com.foxinmy.weixin4j.qy.WeixinProxy#syncuser(String,Callback)}
* @see {@link com.foxinmy.weixin4j.qy.WeixinProxy#replaceuser(String,Callback)}
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%BC%82%E6%AD%A5%E4%BB%BB%E5%8A%A1%E6%8E%A5%E5%8F%A3#.E9.80.9A.E8.AE.AF.E5.BD.95.E6.9B.B4.E6.96.B0">批量任务</a>
* @return 上传后的mediaId
* @throws WeixinException
*/
public String batchUploadUsers(List<User> users) throws WeixinException {
return mediaApi.batchUploadUsers(users);
}
/**
* 批量覆盖部门,本接口以partyid为键,全量覆盖企业号通讯录组织架构,任务完成后企业号通讯录组织架构与提交的文件完全保持一致。
* <p>
* 1.文件中存在、通讯录中也存在的部门,执行修改操作</br> 2.文件中存在、通讯录中不存在的部门,执行添加操作</br>
* 3.文件中不存在、通讯录中存在的部门,当部门为空时,执行删除操作</br>
* 4.CSV文件中,部门名称、部门ID、父部门ID为必填字段,部门ID必须为数字;排序为可选字段,置空或填0不修改排序
* </p>
*
* @param mediaId
* 带partyid信息的cvs文件上传后的media_id
* @param callback
* 接收任务执行结果的回调地址等信息
* @return 异步任务id,最大长度为64字符
* @see com.foxinmy.weixin4j.qy.model.Callback
* @see com.foxinmy.weixin4j.qy.api.BatchApi
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%BC%82%E6%AD%A5%E4%BB%BB%E5%8A%A1%E6%8E%A5%E5%8F%A3#.E5.85.A8.E9.87.8F.E8.A6.86.E7.9B.96.E9.83.A8.E9.97.A8">批量覆盖部门</a>
* @throws WeixinException
*/
public String replaceparty(String mediaId, Callback callback)
throws WeixinException {
return batchApi.replaceparty(mediaId, callback);
}
/**
* 获取异步任务执行的结果
*
* @param jobId
* 任务ID
* @return 效果信息
* @see com.foxinmy.weixin4j.qy.model.BatchResult
* @see com.foxinmy.weixin4j.qy.api.BatchApi
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%BC%82%E6%AD%A5%E4%BB%BB%E5%8A%A1%E6%8E%A5%E5%8F%A3#.E8.8E.B7.E5.8F.96.E5.BC.82.E6.AD.A5.E4.BB.BB.E5.8A.A1.E7.BB.93.E6.9E.9C">获取异步任务执行结果</a>
* @throws WeixinException
*/
public BatchResult getresult(String jobId) throws WeixinException {
return batchApi.getresult(jobId);
}
}
@@ -0,0 +1,118 @@
package com.foxinmy.weixin4j.qy.api;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.ValueFilter;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.JsonResult;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.qy.model.AgentInfo;
import com.foxinmy.weixin4j.qy.model.AgentOverview;
import com.foxinmy.weixin4j.qy.model.AgentSetter;
import com.foxinmy.weixin4j.qy.model.User;
import com.foxinmy.weixin4j.token.TokenHolder;
/**
* 管理应用接口
*
* @className AgentApi
* @author jy
* @date 2015年3月16日
* @since JDK 1.7
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E4%BC%81%E4%B8%9A%E5%8F%B7%E5%BA%94%E7%94%A8">管理应用接口说明</a>
*/
public class AgentApi extends QyApi {
private final TokenHolder tokenHolder;
public AgentApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
}
/**
* 获取企业号某个应用的基本信息,包括头像、昵称、帐号类型、认证类型、可见范围等信息
*
* @param agentid
* 授权方应用id
* @return 应用信息
* @see com.foxinmy.weixin4j.qy.model.AgentInfo
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E4%BC%81%E4%B8%9A%E5%8F%B7%E5%BA%94%E7%94%A8">企业号应用的信息</a>
* @throws WeixinException
*/
public AgentInfo getAgent(int agentid) throws WeixinException {
String agent_get_uri = getRequestUri("agent_get_uri");
Token token = tokenHolder.getToken();
Response response = request.post(String.format(agent_get_uri,
token.getAccessToken(), agentid));
JSONObject jsonObj = response.getAsJson();
AgentInfo agent = JSON.toJavaObject(jsonObj, AgentInfo.class);
agent.setAllowUsers(JSON.parseArray(
jsonObj.getJSONObject("allow_userinfos").getString("user"),
User.class));
agent.setAllowPartys(JSON.parseArray(
jsonObj.getJSONObject("allow_partys").getString("partyid"),
Integer.class));
agent.setAllowTags(JSON.parseArray(jsonObj.getJSONObject("allow_tags")
.getString("tagid"), Integer.class));
return agent;
}
/**
* 设置企业应用的选项设置信息,如:地理位置上报等
*
* @param agentSet
* 设置参数
* @see com.foxinmy.weixin4j.qy.model.AgentSetter
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E8%AE%BE%E7%BD%AE%E4%BC%81%E4%B8%9A%E5%8F%B7%E5%BA%94%E7%94%A8">设置企业号信息</a>
* @return 处理结果
* @throws WeixinException
*/
public JsonResult setAgent(AgentSetter agentSet) throws WeixinException {
String agent_set_uri = getRequestUri("agent_set_uri");
Token token = tokenHolder.getToken();
Response response = request.post(
String.format(agent_set_uri, token.getAccessToken()),
JSON.toJSONString(agentSet, typeFilter));
return response.getAsJsonResult();
}
private static ValueFilter typeFilter;
static {
typeFilter = new ValueFilter() {
@Override
public Object process(Object object, String name, Object value) {
if (value instanceof Boolean) {
return ((Boolean) value) ? 1 : 0;
}
if (value instanceof Enum) {
return ((Enum<?>) value).ordinal();
}
return value;
}
};
}
/**
* 获取应用概况列表
*
* @see com.foxinmy.weixin4j.qy.model.AgentOverview
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E5%BA%94%E7%94%A8%E6%A6%82%E5%86%B5%E5%88%97%E8%A1%A8">获取应用概况</a>
* @return 应用概况列表
* @throws WeixinException
*/
public List<AgentOverview> listAgentOverview() throws WeixinException {
String agent_list_uri = getRequestUri("agent_list_uri");
Token token = tokenHolder.getToken();
Response response = request.get(String.format(agent_list_uri,
token.getAccessToken()));
return JSON.parseArray(response.getAsJson().getString("agentlist"),
AgentOverview.class);
}
}
@@ -0,0 +1,172 @@
package com.foxinmy.weixin4j.qy.api;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.qy.model.BatchResult;
import com.foxinmy.weixin4j.qy.model.Callback;
import com.foxinmy.weixin4j.qy.model.IdParameter;
import com.foxinmy.weixin4j.token.TokenHolder;
/**
* 批量异步任务API
* <p>
* 异步任务接口用于大批量数据的处理,提交后接口即返回,企业号会在后台继续执行任务。执行完成后,通过任务事件通知企业获取结果
* </p>
*
* @className BatchApi
* @author jy
* @date 2015年3月30日
* @since JDK 1.7
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%BC%82%E6%AD%A5%E4%BB%BB%E5%8A%A1%E6%8E%A5%E5%8F%A3">批量任务</a>
*/
public class BatchApi extends QyApi {
private final TokenHolder tokenHolder;
public BatchApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
}
/**
* 批量邀请成员关注
*
* @param parameter
* 成员ID,标签ID,部门ID
* @param callback
* 接收任务执行结果的回调地址等信息
* @param tips
* 推送到微信上的提示语(只有认证号可以使用)。当使用微信推送时,该字段默认为“请关注XXX企业号”,邮件邀请时,该字段无效。
* @return 异步任务id,最大长度为64字符
* @see com.foxinmy.weixin4j.qy.model.IdParameter
* @see com.foxinmy.weixin4j.qy.model.Callback
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%BC%82%E6%AD%A5%E4%BB%BB%E5%8A%A1%E6%8E%A5%E5%8F%A3#.E9.82.80.E8.AF.B7.E6.88.90.E5.91.98.E5.85.B3.E6.B3.A8">邀请成员关注</a>
* @throws WeixinException
*/
public String inviteuser(IdParameter parameter, Callback callback,
String tips) throws WeixinException {
String batch_inviteuser_uri = getRequestUri("batch_inviteuser_uri");
Token token = tokenHolder.getToken();
JSONObject obj = new JSONObject();
obj.putAll(parameter.getParameter());
obj.put("callback", callback);
obj.put("invite_tips", tips);
Response response = request.post(
String.format(batch_inviteuser_uri, token.getAccessToken()),
obj.toJSONString());
return response.getAsJson().getString("jobid");
}
/**
* 批量更新成员,本接口以userid为主键,增量更新企业号通讯录成员。
*
* <p>
* 1.模板中的部门需填写部门ID,多个部门用分号分隔,部门ID必须为数字</br>
* 2.文件中存在、通讯录中也存在的成员,更新成员在文件中指定的字段值 </br> 3.文件中存在、通讯录中不存在的成员,执行添加操作</br>
* 4.通讯录中存在、文件中不存在的成员,保持不变</br>
* </p>
*
* @param mediaId
* 带user信息的cvs文件上传后的media_id
* @param callback
* 接收任务执行结果的回调地址等信息
* @return 异步任务id,最大长度为64字符
* @see {@link com.foxinmy.weixin4j.qy.api.MediaApi#batchUploadUsers(List)}
* @see com.foxinmy.weixin4j.qy.model.Callback
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%BC%82%E6%AD%A5%E4%BB%BB%E5%8A%A1%E6%8E%A5%E5%8F%A3#.E5.A2.9E.E9.87.8F.E6.9B.B4.E6.96.B0.E6.88.90.E5.91.98">批量更新成员</a>
* @throws WeixinException
*/
public String syncuser(String mediaId, Callback callback)
throws WeixinException {
String batch_syncuser_uri = getRequestUri("batch_syncuser_uri");
return batch(batch_syncuser_uri, mediaId, callback);
}
private String batch(String batchUrl, String mediaId, Callback callback)
throws WeixinException {
Token token = tokenHolder.getToken();
JSONObject obj = new JSONObject();
obj.put("media_id", mediaId);
obj.put("callback", callback);
Response response = request.post(
String.format(batchUrl, token.getAccessToken()),
obj.toJSONString());
return response.getAsJson().getString("jobid");
}
/**
* 批量覆盖成员,本接口以userid为主键,全量覆盖企业号通讯录成员,任务完成后企业号通讯录成员与提交的文件完全保持一致。
* <p>
* 1.模板中的部门需填写部门ID,多个部门用分号分隔,部门ID必须为数字</br> 2.文件中存在、通讯录中也存在的成员,完全以文件为准</br>
* 3.文件中存在、通讯录中不存在的成员,执行添加操作</br>
* 4.通讯录中存在、文件中不存在的成员,执行删除操作。出于安全考虑,如果需要删除的成员多于50人,
* 且多于现有人数的20%以上,系统将中止导入并返回相应的错误码
* </p>
*
* @param mediaId
* 带userid信息的cvs文件上传后的media_id
* @param callback
* 接收任务执行结果的回调地址等信息
* @return 异步任务id,最大长度为64字符
* @see {@link com.foxinmy.weixin4j.qy.api.MediaApi#batchUploadUsers(List)}
* @see com.foxinmy.weixin4j.qy.model.Callback
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%BC%82%E6%AD%A5%E4%BB%BB%E5%8A%A1%E6%8E%A5%E5%8F%A3#.E5.85.A8.E9.87.8F.E8.A6.86.E7.9B.96.E6.88.90.E5.91.98">批量覆盖成员</a>
* @throws WeixinException
*/
public String replaceuser(String mediaId, Callback callback)
throws WeixinException {
String batch_replaceuser_uri = getRequestUri("batch_replaceuser_uri");
return batch(batch_replaceuser_uri, mediaId, callback);
}
/**
* 批量覆盖部门,本接口以partyid为键,全量覆盖企业号通讯录组织架构,任务完成后企业号通讯录组织架构与提交的文件完全保持一致。
* <p>
* 1.文件中存在、通讯录中也存在的部门,执行修改操作</br> 2.文件中存在、通讯录中不存在的部门,执行添加操作</br>
* 3.文件中不存在、通讯录中存在的部门,当部门为空时,执行删除操作</br>
* 4.CSV文件中,部门名称、部门ID、父部门ID为必填字段,部门ID必须为数字;排序为可选字段,置空或填0不修改排序
* </p>
*
* @param mediaId
* 带partyid信息的cvs文件上传后的media_id
* @param callback
* 接收任务执行结果的回调地址等信息
* @return 异步任务id,最大长度为64字符
* @see {@link com.foxinmy.weixin4j.qy.api.MediaApi#batchUploadParties(List)}
* @see com.foxinmy.weixin4j.qy.model.Callback
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%BC%82%E6%AD%A5%E4%BB%BB%E5%8A%A1%E6%8E%A5%E5%8F%A3#.E5.85.A8.E9.87.8F.E8.A6.86.E7.9B.96.E9.83.A8.E9.97.A8">批量覆盖部门</a>
* @throws WeixinException
*/
public String replaceparty(String mediaId, Callback callback)
throws WeixinException {
String batch_replaceparty_uri = getRequestUri("batch_replaceparty_uri");
return batch(batch_replaceparty_uri, mediaId, callback);
}
/**
* 获取异步任务执行的结果
*
* @param jobId
* 任务ID
* @return 效果信息
* @see com.foxinmy.weixin4j.qy.model.BatchResult
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%BC%82%E6%AD%A5%E4%BB%BB%E5%8A%A1%E6%8E%A5%E5%8F%A3#.E8.8E.B7.E5.8F.96.E5.BC.82.E6.AD.A5.E4.BB.BB.E5.8A.A1.E7.BB.93.E6.9E.9C">获取异步任务执行结果</a>
* @throws WeixinException
*/
public BatchResult getresult(String jobId) throws WeixinException {
Token token = tokenHolder.getToken();
String batch_getresult_uri = getRequestUri("batch_getresult_uri");
Response response = request.get(String.format(batch_getresult_uri,
token.getAccessToken(), jobId));
return response.getAsObject(new TypeReference<BatchResult>() {
});
}
}
@@ -0,0 +1,43 @@
package com.foxinmy.weixin4j.qy.api;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.token.TokenHolder;
/**
* 辅助API
*
* @className HelperApi
* @author jy
* @date 2014年12月28日
* @since JDK 1.7
* @see
*/
public class HelperApi extends QyApi {
private final TokenHolder tokenHolder;
public HelperApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
}
/**
* 获取微信服务器IP地址
*
* @return IP地址
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%9B%9E%E8%B0%83%E6%A8%A1%E5%BC%8F#.E8.8E.B7.E5.8F.96.E5.BE.AE.E4.BF.A1.E6.9C.8D.E5.8A.A1.E5.99.A8.E7.9A.84ip.E6.AE.B5">获取IP地址</a>
* @throws WeixinException
*/
public List<String> getcallbackip() throws WeixinException {
String getcallbackip_uri = getRequestUri("getcallbackip_uri");
Token token = tokenHolder.getToken();
Response response = request.post(String.format(getcallbackip_uri,
token.getAccessToken()));
return JSON.parseArray(response.getAsJson().getString("ip_list"),
String.class);
}
}
@@ -0,0 +1,252 @@
package com.foxinmy.weixin4j.qy.api;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.StringWriter;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.entity.mime.content.ByteArrayBody;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.PropertyFilter;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.PartParameter;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.qy.model.Callback;
import com.foxinmy.weixin4j.qy.model.Party;
import com.foxinmy.weixin4j.qy.model.User;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.type.MediaType;
import com.foxinmy.weixin4j.util.ConfigUtil;
import com.foxinmy.weixin4j.util.FileUtil;
import com.foxinmy.weixin4j.util.IOUtil;
/**
* 媒体相关API
*
* @className MediaApi
* @author jy.hu
* @date 2014年9月25日
* @since JDK 1.7
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E5%A4%9A%E5%AA%92%E4%BD%93%E6%96%87%E4%BB%B6">管理多媒体文件</a>
* @see com.foxinmy.weixin4j.type.MediaType
*/
public class MediaApi extends QyApi {
private final TokenHolder tokenHolder;
public MediaApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
}
/**
* 上传媒体文件
*
* @param file
* 媒体对象
* @return 上传到微信服务器返回的媒体标识
* @see {@link com.foxinmy.weixin4j.qy.api.MediaApi#uploadMedia(File, MediaType)}
* @throws WeixinException
* @throws IOException
*/
public String uploadMedia(File file) throws WeixinException, IOException {
String mediaTypeKey = IOUtil.getExtension(file.getName());
if (StringUtils.isBlank(mediaTypeKey)) {
mediaTypeKey = FileUtil.getFileType(file);
}
MediaType mediaType = MediaType.getMediaType(mediaTypeKey);
return uploadMedia(file, mediaType);
}
/**
* 上传媒体文件
*
* @param file
* 文件对象
* @param mediaType
* 媒体类型
* @return 上传到微信服务器返回的媒体标识
* @throws WeixinException
* @throws IOException
* @see com.foxinmy.weixin4j.type.MediaType
* @see {@link com.foxinmy.weixin4j.qy.api.MediaApi#uploadMedia(String, byte[],String)}
*/
public String uploadMedia(File file, MediaType mediaType)
throws WeixinException, IOException {
byte[] datas = IOUtil.toByteArray(new FileInputStream(file));
return uploadMedia(file.getName(), datas, mediaType.name());
}
/**
* 上传媒体文件(完全公开。所有管理员均可调用,media_id可以共享)
* <p>
* 正常情况下返回{"type":"TYPE","media_id":"MEDIA_ID","created_at":123456789},
* 否则抛出异常.
* </p>
*
* @param bytes
* 媒体数据包
* @param mediaType
* 媒体类型
* @return 上传到微信服务器返回的媒体标识
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E4%B8%8A%E4%BC%A0%E5%AA%92%E4%BD%93%E6%96%87%E4%BB%B6">上传媒体文件说明</a>
* @throws WeixinException
*/
public String uploadMedia(String fileName, byte[] bytes, String mediaType)
throws WeixinException {
Token token = tokenHolder.getToken();
String file_upload_uri = getRequestUri("file_upload_uri");
Response response = request.post(String.format(file_upload_uri,
token.getAccessToken(), mediaType), new PartParameter("media",
new ByteArrayBody(bytes, fileName)));
return response.getAsJson().getString("media_id");
}
/**
* 下载媒体文件(完全公开。所有管理员均可调用,media_id可以共享)
* <p>
* 正常情况下返回表头如Content-Type: image/jpeg,否则抛出异常.
* </p>
*
* @param mediaId
* 存储在微信服务器上的媒体标识
* @param extension
* 媒体后缀名
* @return 写入硬盘后的文件对象
* @throws WeixinException
* @throws IOException
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E5%AA%92%E4%BD%93%E6%96%87%E4%BB%B6">获取媒体说明</a>
* @see com.foxinmy.weixin4j.type.MediaType
* @see {@link com.foxinmy.weixin4j.qy.api.MediaApi#downloadMedia(String)}
*/
public File downloadMedia(String mediaId, String extension)
throws WeixinException {
String media_path = ConfigUtil.getValue("media_path");
File file = new File(media_path + File.separator + mediaId + "."
+ extension);
if (file.exists()) {
return file;
}
byte[] datas = downloadMedia(mediaId);
OutputStream os = null;
try {
boolean flag = file.createNewFile();
if (flag) {
os = new FileOutputStream(file);
os.write(datas);
} else {
throw new WeixinException(String.format("create file fail:%s",
file.getAbsolutePath()));
}
} catch (IOException e) {
throw new WeixinException(e.getMessage());
} finally {
try {
if (os != null) {
os.close();
}
} catch (IOException ignore) {
;
}
}
return file;
}
/**
* 下载媒体文件(完全公开。所有管理员均可调用,media_id可以共享)
*
* @param mediaId
* 媒体ID
* @return 二进制数据包
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E5%AA%92%E4%BD%93%E6%96%87%E4%BB%B6">获取媒体说明</a>
* @throws WeixinException
*/
public byte[] downloadMedia(String mediaId) throws WeixinException {
Token token = tokenHolder.getToken();
String file_download_uri = getRequestUri("file_download_uri");
Response response = request.get(String.format(file_download_uri,
token.getAccessToken(), mediaId));
return response.getBody();
}
/**
* 批量上传成员
*
* @param users
* 成员列表
* @see {@link com.foxinmy.weixin4j.qy.api.BatchApi#syncuser(String,Callback)}
* @see {@link com.foxinmy.weixin4j.qy.api.BatchApi#replaceuser(String,Callback)}
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%BC%82%E6%AD%A5%E4%BB%BB%E5%8A%A1%E6%8E%A5%E5%8F%A3#.E9.80.9A.E8.AE.AF.E5.BD.95.E6.9B.B4.E6.96.B0">批量任务</a>
* @return 上传后的mediaId
* @throws WeixinException
*/
public String batchUploadUsers(List<User> users) throws WeixinException {
return batchUpload("batch_syncuser.cvs", users);
}
/**
* 批量上传部门
*
* @param parties
* 部门列表
* @see {@link com.foxinmy.weixin4j.qy.api.BatchApi#replaceparty(String,Callback)}
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%BC%82%E6%AD%A5%E4%BB%BB%E5%8A%A1%E6%8E%A5%E5%8F%A3#.E9.80.9A.E8.AE.AF.E5.BD.95.E6.9B.B4.E6.96.B0">批量任务</a>
* @return 上传后的mediaId
* @throws WeixinException
*/
public String batchUploadParties(List<Party> parties)
throws WeixinException {
return batchUpload("batch_replaceparty.cvs", parties);
}
private <T> String batchUpload(String batchName, List<T> models)
throws WeixinException {
JSONObject csvObj = JSON.parseObject(getConfigValue(batchName));
JSONArray columns = csvObj.getJSONArray("column");
StringWriter writer = new StringWriter();
writer.write(csvObj.getString("header"));
final Map<String, Object> column = new LinkedHashMap<String, Object>();
for (Object col : columns) {
column.put(col.toString(), "");
}
writer.write("\r\n");
for (T model : models) {
JSON.toJSONString(model, new PropertyFilter() {
@Override
public boolean apply(Object object, String name, Object value) {
if (column.containsKey(name)) {
column.put(name, value);
}
return true;
}
});
writer.write(StringUtils.join(column.values(), ","));
writer.write("\r\n");
}
String mediaId = uploadMedia(batchName,
writer.toString().getBytes(Consts.UTF_8), MediaType.file.name());
try {
writer.close();
} catch (IOException e) {
;
}
return mediaId;
}
}
@@ -0,0 +1,121 @@
package com.foxinmy.weixin4j.qy.api;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.NameFilter;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.JsonResult;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Button;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.type.ButtonType;
/**
* 菜单相关API
*
* @className MenuApi
* @author jy.hu
* @date 2014年9月25日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.model.Button
*/
public class MenuApi extends QyApi {
private final TokenHolder tokenHolder;
public MenuApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
}
/**
* 自定义菜单(管理员须拥有应用的管理权限 并且应用必须设置在回调模式)
*
* @param btnList
* 菜单列表
* @param agentid
* 应用ID
* @throws WeixinException
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%88%9B%E5%BB%BA%E5%BA%94%E7%94%A8%E8%8F%9C%E5%8D%95">创建自定义菜单</a>
* @see com.foxinmy.weixin4j.model.Button
*/
public JsonResult createMenu(List<Button> btnList, int agentid)
throws WeixinException {
String menu_create_uri = getRequestUri("menu_create_uri");
Token token = tokenHolder.getToken();
JSONObject obj = new JSONObject();
obj.put("button", btnList);
Response response = request
.post(String.format(menu_create_uri, token.getAccessToken(),
agentid), JSON.toJSONString(obj, new NameFilter() {
@Override
public String process(Object object, String name,
Object value) {
if (object instanceof Button && name.equals("content")) {
if (((Button) object).getFormatType() == ButtonType.view) {
return "url";
} else {
return "key";
}
}
return name;
}
}));
return response.getAsJsonResult();
}
/**
* 查询菜单(管理员须拥有应用的管理权限 并且应用必须设置在回调模式。)
*
* @param agentid
* 应用ID
* @return 菜单集合
* @throws WeixinException
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E8%8F%9C%E5%8D%95%E5%88%97%E8%A1%A8">查询菜单</a>
* @see com.foxinmy.weixin4j.model.Button
*/
public List<Button> getMenu(int agentid) throws WeixinException {
String menu_get_uri = getRequestUri("menu_get_uri");
Token token = tokenHolder.getToken();
Response response = request.get(String.format(menu_get_uri,
token.getAccessToken(), agentid));
String text = JSON.toJSONString(
response.getAsJson().getJSONObject("menu")
.getJSONArray("button"), new NameFilter() {
@Override
public String process(Object object, String name,
Object value) {
if (name.equals("url") || name.equals("key")) {
return "content";
}
return name;
}
});
return JSON.parseArray(text, Button.class);
}
/**
* 删除菜单(管理员须拥有应用的管理权限 并且应用必须设置在回调模式)
*
* @param agentid
* 应用ID
* @throws WeixinException
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%88%A0%E9%99%A4%E8%8F%9C%E5%8D%95">删除菜单</a>
* @return 处理结果
*/
public JsonResult deleteMenu(int agentid) throws WeixinException {
String menu_delete_uri = getRequestUri("menu_delete_uri");
Token token = tokenHolder.getToken();
Response response = request.get(String.format(menu_delete_uri,
token.getAccessToken(), agentid));
return response.getAsJsonResult();
}
}
@@ -0,0 +1,81 @@
package com.foxinmy.weixin4j.qy.api;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.qy.message.NotifyMessage;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.tuple.NotifyTuple;
/**
* 发送消息API
*
* @className NotifyApi
* @author jy.hu
* @date 2014年11月21日
* @since JDK 1.7
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E">发送接口说明</a>
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E6%B6%88%E6%81%AF%E7%B1%BB%E5%9E%8B%E5%8F%8A%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F">发送格式说明</a>
* @see com.foxinmy.weixin4j.tuple.Text
* @see com.foxinmy.weixin4j.tuple.Image
* @see com.foxinmy.weixin4j.tuple.Voice
* @see com.foxinmy.weixin4j.tuple.Video
* @see com.foxinmy.weixin4j.tuple.File
* @see com.foxinmy.weixin4j.tuple.News
* @see com.foxinmy.weixin4j.tuple.MpNews
*/
public class NotifyApi extends QyApi {
private final TokenHolder tokenHolder;
public NotifyApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
}
/**
* 发送消息(需要管理员对应用有使用权限,对收件人touser、toparty、totag有查看权限,否则本次调用失败)
* <p>
* 1) 发送人员列表存在错误的userid:执行发送,开发者需注意返回结果说明</br>
* 2)发送人员不在通讯录权限范围内:不执行发送任务,返回首个出错的userid</br>
* 3)发送人员不在应用可见范围内:不执行发送任务,返回首个出错的userid</br>
* </p>
*
* @param notify
* 客服消息对象
* @return
* 如果对应用或收件人、部门、标签任何一个无权限,则本次发送失败;如果收件人、部门或标签不存在,发送仍然执行,但返回无效的部分</br>
* { "errcode": 0, "errmsg": "ok", "invaliduser": "UserID1",
* "invalidparty":"PartyID1", "invalidtag":"TagID1" }
* @throws WeixinException
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E">发送接口说明</a>
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E6%B6%88%E6%81%AF%E7%B1%BB%E5%9E%8B%E5%8F%8A%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F">发送格式说明</a>
* @see com.foxinmy.weixin4j.tuple.Text
* @see com.foxinmy.weixin4j.tuple.Image
* @see com.foxinmy.weixin4j.tuple.Voice
* @see com.foxinmy.weixin4j.tuple.Video
* @see com.foxinmy.weixin4j.tuple.File
* @see com.foxinmy.weixin4j.tuple.News
* @see com.foxinmy.weixin4j.tuple.MpNews
* @see com.foxinmy.weixin4j.qy.message.NotifyMessage
*/
public JSONObject sendNotify(NotifyMessage notify) throws WeixinException {
NotifyTuple tuple = notify.getTuple();
String msgtype = tuple.getMessageType();
JSONObject obj = (JSONObject) JSON.toJSON(notify);
obj.put("msgtype", msgtype);
obj.put(msgtype, tuple);
String message_send_uri = getRequestUri("message_send_uri");
Token token = tokenHolder.getToken();
Response response = request.post(
String.format(message_send_uri, token.getAccessToken()),
obj.toJSONString());
return response.getAsJson();
}
}
@@ -0,0 +1,111 @@
package com.foxinmy.weixin4j.qy.api;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.JsonResult;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.qy.model.Party;
import com.foxinmy.weixin4j.token.TokenHolder;
/**
* 部门API
*
* @className PartyApi
* @author jy
* @date 2014年11月18日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.qy.model.Party
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E9%83%A8%E9%97%A8">管理部门说明</a>
*/
public class PartyApi extends QyApi {
private final TokenHolder tokenHolder;
public PartyApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
}
/**
* 创建部门(根部门的parentid为1)
*
* @param depart
* 部门对象
* @see com.foxinmy.weixin4j.qy.model.Party
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E9%83%A8%E9%97%A8#.E5.88.9B.E5.BB.BA.E9.83.A8.E9.97.A8">创建部门说明</a>
* @return 部门ID
* @throws WeixinException
*/
public int createParty(Party depart) throws WeixinException {
String department_create_uri = getRequestUri("department_create_uri");
JSONObject obj = (JSONObject) JSON.toJSON(depart);
obj.remove("id");
Token token = tokenHolder.getToken();
Response response = request.post(
String.format(department_create_uri, token.getAccessToken()),
obj.toJSONString());
return response.getAsJson().getIntValue("id");
}
/**
* 更新部门(如果非必须的字段未指定 则不更新该字段之前的设置值)
*
* @param depart
* 部门对象
* @see com.foxinmy.weixin4j.qy.model.Party
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E9%83%A8%E9%97%A8#.E6.9B.B4.E6.96.B0.E9.83.A8.E9.97.A8">更新部门说明</a>
* @return 处理结果
* @throws WeixinException
*/
public JsonResult updateParty(Party party) throws WeixinException {
String department_update_uri = getRequestUri("department_update_uri");
JSONObject obj = (JSONObject) JSON.toJSON(party);
Token token = tokenHolder.getToken();
Response response = request.post(
String.format(department_update_uri, token.getAccessToken()),
obj.toJSONString());
return response.getAsJsonResult();
}
/**
* 查询部门列表(以部门的order字段从小到大排列)
*
* @param partId 部门ID。获取指定部门ID下的子部门
* @see com.foxinmy.weixin4j.qy.model.Party
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E9%83%A8%E9%97%A8#.E8.8E.B7.E5.8F.96.E9.83.A8.E9.97.A8.E5.88.97.E8.A1.A8">获取部门列表</a>
* @return 部门列表
* @throws WeixinException
*/
public List<Party> listParty(int partId) throws WeixinException {
String department_list_uri = getRequestUri("department_list_uri");
Token token = tokenHolder.getToken();
Response response = request.post(String.format(department_list_uri,
token.getAccessToken()));
return JSON.parseArray(response.getAsJson().getString("department"),
Party.class);
}
/**
* 删除部门(不能删除根部门;不能删除含有子部门、成员的部门)
*
* @param partId
* 部门ID
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E9%83%A8%E9%97%A8#.E5.88.A0.E9.99.A4.E9.83.A8.E9.97.A8">删除部门说明</a>
* @return 处理结果
* @throws WeixinException
*/
public JsonResult deleteParty(int partId) throws WeixinException {
String department_delete_uri = getRequestUri("department_delete_uri");
Token token = tokenHolder.getToken();
Response response = request.post(String.format(department_delete_uri,
token.getAccessToken(), partId));
return response.getAsJsonResult();
}
}
@@ -0,0 +1,28 @@
package com.foxinmy.weixin4j.qy.api;
import java.util.ResourceBundle;
import com.foxinmy.weixin4j.api.BaseApi;
/**
* 微信企业号API
*
* @className QyApi
* @author jy.hu
* @date 2014年11月18日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.api.BaseApi
* @see <a href="http://qydev.weixin.qq.com/wiki/index.php">api文档</a>
*/
public class QyApi extends BaseApi {
private final static ResourceBundle weixinBundle;
static {
weixinBundle = ResourceBundle
.getBundle("com/foxinmy/weixin4j/qy/api/weixin");
}
@Override
protected ResourceBundle getWeixinBundle() {
return weixinBundle;
}
}
@@ -0,0 +1,178 @@
package com.foxinmy.weixin4j.qy.api;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.JsonResult;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.qy.model.Tag;
import com.foxinmy.weixin4j.qy.model.User;
import com.foxinmy.weixin4j.token.TokenHolder;
/**
* 标签API
*
* @className TagApi
* @author jy
* @date 2014年11月19日
* @since JDK 1.7
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%A0%87%E7%AD%BE">管理标签</a>
*/
public class TagApi extends QyApi {
private final TokenHolder tokenHolder;
public TagApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
}
/**
* 创建标签(创建的标签属于管理组;默认为未加锁状态)
*
* @param tagName
* 标签名称
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%A0%87%E7%AD%BE#.E5.88.9B.E5.BB.BA.E6.A0.87.E7.AD.BE">创建标签说明</a>
* @return 标签ID
* @throws WeixinException
*/
public int createTag(String tagName) throws WeixinException {
String tag_create_uri = getRequestUri("tag_create_uri");
Token token = tokenHolder.getToken();
Response response = request.post(
String.format(tag_create_uri, token.getAccessToken()),
String.format("{\"tagname\":\"%s\"}", tagName));
return response.getAsJson().getIntValue("tagid");
}
/**
* 更新标签(管理组必须是指定标签的创建者)
*
* @param tag 标签信息
* @see <a href=
* "http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%A0%87%E7%AD%BE#.E6.9B.B4.E6.96.B0.E6.A0.87.E7.AD.BE.E5.90.8D.E5.AD.97"
* >更新标签说明</a>
* @return 处理结果
* @see com.foxinmy.weixin4j.qy.model.Tag
* @throws WeixinException
*/
public JsonResult updateTag(Tag tag) throws WeixinException {
String tag_update_uri = getRequestUri("tag_update_uri");
Token token = tokenHolder.getToken();
Response response = request.post(
String.format(tag_update_uri, token.getAccessToken()),
JSON.toJSONString(tag));
return response.getAsJsonResult();
}
/**
* 删除标签(管理组必须是指定标签的创建者 并且标签的成员列表为空)
*
* @param tagId
* 标签ID
* @return 处理结果
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%A0%87%E7%AD%BE#.E5.88.A0.E9.99.A4.E6.A0.87.E7.AD.BE">删除标签说明</a>
* @throws WeixinException
*/
public JsonResult deleteTag(int tagId) throws WeixinException {
String tag_delete_uri = getRequestUri("tag_delete_uri");
Token token = tokenHolder.getToken();
Response response = request.post(String.format(tag_delete_uri,
token.getAccessToken(), tagId));
return response.getAsJsonResult();
}
/**
* 获取标签列表
*
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%A0%87%E7%AD%BE#.E8.8E.B7.E5.8F.96.E6.A0.87.E7.AD.BE.E5.88.97.E8.A1.A8">获取标签列表说明</a>
* @return 标签列表
* @see com.foxinmy.weixin4j.qy.model.Tag
* @throws WeixinException
*/
public List<Tag> listTag() throws WeixinException {
String tag_list_uri = getRequestUri("tag_list_uri");
Token token = tokenHolder.getToken();
Response response = request.post(String.format(tag_list_uri,
token.getAccessToken()));
return JSON.parseArray(response.getAsJson().getString("taglist"),
Tag.class);
}
/**
* 获取标签成员(管理组须拥有“获取标签成员”的接口权限,标签须对管理组可见;返回列表仅包含管理组管辖范围的成员)
*
* @param tagId
* 标签ID
* @see com.foxinmy.weixin4j.qy.model.User
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%A0%87%E7%AD%BE#.E8.8E.B7.E5.8F.96.E6.A0.87.E7.AD.BE.E6.88.90.E5.91.98">获取标签成员说明</a>
* @return 成员列表
* @throws WeixinException
*/
public List<User> getTagUsers(int tagId) throws WeixinException {
String tag_get_user_uri = getRequestUri("tag_get_user_uri");
Token token = tokenHolder.getToken();
Response response = request.post(String.format(tag_get_user_uri,
token.getAccessToken(), tagId));
return JSON.parseArray(response.getAsJson().getString("userlist"),
User.class);
}
/**
* 新增标签成员(标签对管理组可见且未加锁,成员属于管理组管辖范围)<br>
* <font color="red">若部分userid非法,则在text中体现</font>
*
* @param tagId
* 标签ID
* @param userIds
* 成员ID
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%A0%87%E7%AD%BE#.E5.A2.9E.E5.8A.A0.E6.A0.87.E7.AD.BE.E6.88.90.E5.91.98">新增标签成员说明</a>
* @return 处理结果
* @throws WeixinException
*/
public JsonResult addTagUsers(int tagId, List<String> userIds)
throws WeixinException {
String tag_add_user_uri = getRequestUri("tag_add_user_uri");
return excuteUsers(tag_add_user_uri, tagId, userIds);
}
/**
* 删除标签成员(标签对管理组可见且未加锁,成员属于管理组管辖范围)<br>
* <font color="red">若部分userid非法,则在text中体现</font>
*
* @param tagId
* 标签ID
* @param userIds
* 成员ID
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%A0%87%E7%AD%BE#.E5.88.A0.E9.99.A4.E6.A0.87.E7.AD.BE.E6.88.90.E5.91.98">删除标签成员说明</a>
* @return 处理结果
* @throws WeixinException
*/
public JsonResult deleteTagUsers(int tagId, List<String> userIds)
throws WeixinException {
String tag_delete_user_uri = getRequestUri("tag_delete_user_uri");
return excuteUsers(tag_delete_user_uri, tagId, userIds);
}
private JsonResult excuteUsers(String uri, int tagId, List<String> userIds)
throws WeixinException {
JSONObject obj = new JSONObject();
obj.put("tagid", tagId);
obj.put("userlist", userIds);
Token token = tokenHolder.getToken();
Response response = request.post(
String.format(uri, token.getAccessToken()), obj.toJSONString());
obj = response.getAsJson();
JsonResult result = JSON.toJavaObject(obj, JsonResult.class);
result.setText(obj.getString("invalidlist"));
return result;
}
}
@@ -0,0 +1,281 @@
package com.foxinmy.weixin4j.qy.api;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.JsonResult;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.qy.model.User;
import com.foxinmy.weixin4j.qy.type.InviteType;
import com.foxinmy.weixin4j.qy.type.UserStatus;
import com.foxinmy.weixin4j.token.TokenHolder;
/**
* 成员API
*
* @className UserApi
* @author jy
* @date 2014年11月19日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.qy.model.User
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%88%90%E5%91%98">管理成员说明</a>
*/
public class UserApi extends QyApi {
private final TokenHolder tokenHolder;
public UserApi(TokenHolder tokenHolder) {
this.tokenHolder = tokenHolder;
}
/**
* 创建成员
*
* @param user
* 成员对象
* @see com.foxinmy.weixin4j.qy.model.User
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%88%90%E5%91%98#.E5.88.9B.E5.BB.BA.E6.88.90.E5.91.98">创建成员说明</a>
* @return 处理结果
* @throws WeixinException
*/
public JsonResult createUser(User user) throws WeixinException {
String user_create_uri = getRequestUri("user_create_uri");
return excute(user_create_uri, user);
}
/**
* 更新用户(如果非必须的字段未指定 则不更新该字段之前的设置值)
*
* @param user
* 成员对象
* @see com.foxinmy.weixin4j.qy.model.User
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%88%90%E5%91%98#.E6.9B.B4.E6.96.B0.E6.88.90.E5.91.98">更新成员说明</a>
* @return 处理结果
* @throws WeixinException
*/
public JsonResult updateUser(User user) throws WeixinException {
String user_update_uri = getRequestUri("user_update_uri");
return excute(user_update_uri, user);
}
private JsonResult excute(String uri, User user) throws WeixinException {
JSONObject obj = (JSONObject) JSON.toJSON(user);
Object extattr = obj.remove("extattr");
if (extattr != null) {
JSONObject attrs = new JSONObject();
attrs.put("attrs", extattr);
obj.put("extattr", attrs);
}
Token token = tokenHolder.getToken();
Response response = request.post(
String.format(uri, token.getAccessToken()), obj.toJSONString());
return response.getAsJsonResult();
}
/**
* 获取成员
*
* @param userid
* 成员唯一ID
* @see com.foxinmy.weixin4j.qy.model.User
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%88%90%E5%91%98#.E8.8E.B7.E5.8F.96.E6.88.90.E5.91.98">获取成员说明</a>
* @return 成员对象
* @throws WeixinException
*/
public User getUser(String userid) throws WeixinException {
String user_get_uri = getRequestUri("user_get_uri");
Token token = tokenHolder.getToken();
Response response = request.post(String.format(user_get_uri,
token.getAccessToken(), userid));
JSONObject obj = response.getAsJson();
Object attrs = obj.getJSONObject("extattr").remove("attrs");
if (attrs != null) {
obj.put("extattr", attrs);
}
return JSON.toJavaObject(obj, User.class);
}
/**
* code获取userid(管理员须拥有agent的使用权限;agentid必须和跳转链接时所在的企业应用ID相同。)
*
* @param code
* 通过员工授权获取到的code,每次员工授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期
* @param agentid
* 跳转链接时所在的企业应用ID
* @see com.foxinmy.weixin4j.qy.api.UserApi
* @return 成员对象
* @see {@link com.foxinmy.weixin4j.qy.api.UserApi#getUser(String)}
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E4%BC%81%E4%B8%9A%E8%8E%B7%E5%8F%96code">企业获取code</a>
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E6%A0%B9%E6%8D%AEcode%E8%8E%B7%E5%8F%96%E6%88%90%E5%91%98%E4%BF%A1%E6%81%AF">根据code获取成员信息</a>
* @throws WeixinException
*/
public User getUserByCode(String code, int agentid) throws WeixinException {
String user_getid_uri = getRequestUri("user_getid_uri");
Token token = tokenHolder.getToken();
Response response = request.post(String.format(user_getid_uri,
token.getAccessToken(), code, agentid));
return getUser(response.getAsJson().getString("UserId"));
}
/**
* 获取部门成员
*
* @param departId
* 部门ID 必须
* @param fetchChild
* 是否递归获取子部门下面的成员 非必须
* @param userStatus
* 成员状态 status可叠加 非必须
* @param findDetail
* 是否获取详细信息
* @see com.foxinmy.weixin4j.qy.model.User
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%88%90%E5%91%98#.E8.8E.B7.E5.8F.96.E9.83.A8.E9.97.A8.E6.88.90.E5.91.98">获取部门成员说明</a>
* @return 成员列表
* @throws WeixinException
*/
public List<User> listUser(int departId, boolean fetchChild,
UserStatus userStatus, boolean findDetail) throws WeixinException {
String user_list_uri = findDetail ? getRequestUri("user_list_uri")
: getRequestUri("user_slist_uri");
Token token = tokenHolder.getToken();
Response response = request.post(String.format(user_list_uri,
token.getAccessToken(), departId, fetchChild ? 1 : 0,
userStatus.getVal()));
List<User> list = null;
if (findDetail) {
JSONArray arrays = response.getAsJson().getJSONArray("userlist");
list = new ArrayList<User>(arrays.size());
for (int i = 0; i < arrays.size(); i++) {
JSONObject obj = arrays.getJSONObject(i);
JSONObject ex = obj.getJSONObject("extattr");
Object attrs = null;
if (ex != null && (attrs = ex.remove("attrs")) != null) {
obj.put("extattr", attrs);
}
list.add(JSON.toJavaObject(obj, User.class));
}
} else {
list = JSON.parseArray(response.getAsJson().getString("userlist"),
User.class);
}
return list;
}
/**
* 获取部门下所有状态成员(不进行递归)
*
* @param departId
* 部门ID
* @see {@link com.foxinmy.weixin4j.qy.api.UserApi#listUser(int, boolean,UserStatus)}
* @return 成员列表
* @throws WeixinException
*/
public List<User> listUser(int departId) throws WeixinException {
return listUser(departId, false, UserStatus.BOTH, false);
}
/**
* 删除成员
*
* @param userid
* 成员ID
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%88%90%E5%91%98#.E5.88.A0.E9.99.A4.E6.88.90.E5.91.98">删除成员说明</a>
* @return 处理结果
* @throws WeixinException
*/
public JsonResult deleteUser(String userid) throws WeixinException {
String user_delete_uri = getRequestUri("user_delete_uri");
Token token = tokenHolder.getToken();
Response response = request.post(String.format(user_delete_uri,
token.getAccessToken(), userid));
return response.getAsJsonResult();
}
/**
* 批量删除成员
*
* @param userIds
* 成员列表
* @see <a href=
* "http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%88%90%E5%91%98#.E6.89.B9.E9.87.8F.E5.88.A0.E9.99.A4.E6.88.90.E5.91.98"
* >批量删除成员说明</a
* @return 处理结果
* @throws WeixinException
*/
public JsonResult batchDeleteUser(List<String> userIds)
throws WeixinException {
JSONObject obj = new JSONObject();
obj.put("useridlist", userIds);
String user_delete_uri = getRequestUri("user_batchdelete_uri");
Token token = tokenHolder.getToken();
Response response = request.post(String.format(user_delete_uri,
token.getAccessToken(), obj.toJSONString()));
return response.getAsJsonResult();
}
/**
* 开启二次验证成功时调用(管理员须拥有userid对应员工的管理权限)
*
* @param userid
* 成员ID
* @return 调用结果
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%85%B3%E6%B3%A8%E4%B8%8E%E5%8F%96%E6%B6%88%E5%85%B3%E6%B3%A8">二次验证说明</a>
* @throws WeixinException
*/
public JsonResult authsucc(String userId) throws WeixinException {
String user_authsucc_uri = getRequestUri("user_authsucc_uri");
Token token = tokenHolder.getToken();
Response response = request.post(String.format(user_authsucc_uri,
token.getAccessToken(), userId));
return response.getAsJsonResult();
}
/**
* 邀请成员关注(管理员须拥有该成员的查看权限)
*
* @param userId
* 成员ID
* @param tips
* 推送到微信上的提示语(只有认证号可以使用)。当使用微信推送时,该字段默认为“请关注XXX企业号”,邮件邀请时,该字段无效。
* @return 邀请类型
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%88%90%E5%91%98#.E9.82.80.E8.AF.B7.E6.88.90.E5.91.98.E5.85.B3.E6.B3.A8">邀请成员关注说明</a>
* @throws WeixinException
*/
public InviteType inviteUser(String userId, String tips)
throws WeixinException {
JSONObject obj = new JSONObject();
obj.put("userid", userId);
if (StringUtils.isBlank(tips)) {
obj.put("invite_tips", tips);
}
String invite_user_uri = getRequestUri("invite_user_uri");
Token token = tokenHolder.getToken();
Response response = request.post(
String.format(invite_user_uri, token.getAccessToken()),
obj.toJSONString());
int type = response.getAsJson().getIntValue("type");
if (type == 1) {
return InviteType.WEIXIN;
} else if (type == 2) {
return InviteType.EMAIL;
} else {
return null;
}
}
}
@@ -0,0 +1,81 @@
# ----------------------------------------------------------------------------
# api\u9996\u9875
# http://qydev.weixin.qq.com/wiki/index.php
# ----------------------------------------------------------------------------
api_base_url=https://qyapi.weixin.qq.com/cgi-bin
# \u521b\u5efa\u90e8\u95e8
department_create_uri={api_base_url}/department/create?access_token=%s
# \u66f4\u65b0\u90e8\u95e8
department_update_uri={api_base_url}/department/update?access_token=%s
# \u90e8\u95e8\u5217\u8868
department_list_uri={api_base_url}/department/list?access_token=%s
# \u5220\u9664\u90e8\u95e8
department_delete_uri={api_base_url}/department/delete?access_token=%s&id=%d
# \u521b\u5efa\u6210\u5458
user_create_uri={api_base_url}/user/create?access_token=%s
# \u66f4\u65b0\u6210\u5458\u4fe1\u606f
user_update_uri={api_base_url}/user/update?access_token=%s
# \u83b7\u53d6\u6210\u5458\u4fe1\u606f
user_get_uri={api_base_url}/user/get?access_token=%s&userid=%s
# code\u83b7\u53d6\u6210\u5458\u4fe1\u606f
user_getid_uri={api_base_url}/user/getuserinfo?access_token=%s&code=%s&agentid=%d
# \u83b7\u53d6\u90e8\u95e8\u6210\u5458
user_slist_uri={api_base_url}/user/simplelist?access_token=%s&department_id=%d&fetch_child=%d&status=%d
# \u83b7\u53d6\u90e8\u95e8\u6210\u5458(\u8be6\u60c5)
user_list_uri={api_base_url}/user/list?access_token=%s&department_id=%d&fetch_child=%d&status=%d
# \u5220\u9664\u6210\u5458
user_delete_uri={api_base_url}/user/delete?access_token=%s&userid=%s
# \u6279\u91cf\u5220\u9664\u6210\u5458
user_batchdelete_uri={api_base_url}/user/batchdelete?access_token=%s
# \u6210\u5458\u4e8c\u6b21\u9a8c\u8bc1\u6210\u529f\u65f6\u8c03\u7528
user_authsucc_uri={api_base_url}/user/authsucc?access_token=%s&userid=%s
# \u521b\u5efa\u6807\u7b7e
tag_create_uri={api_base_url}/tag/create?access_token=%s
# \u66f4\u65b0\u6807\u7b7e
tag_update_uri={api_base_url}/tag/update?access_token=%s
# \u5220\u9664\u6807\u7b7e
tag_delete_uri={api_base_url}/tag/delete?access_token=%s&tagid=%d
# \u83b7\u53d6\u6807\u7b7e
tag_list_uri={api_base_url}/tag/list?access_token=%s
# \u83b7\u53d6\u6807\u7b7e\u6210\u5458
tag_get_user_uri={api_base_url}/tag/get?access_token=%s&tagid=%d
# \u6dfb\u52a0\u6807\u7b7e\u6210\u5458
tag_add_user_uri={api_base_url}/tag/addtagusers?access_token=%s
# \u5220\u9664\u6807\u7b7e\u6210\u5458
tag_delete_user_uri={api_base_url}/tag/deltagusers?access_token=%s
# \u9080\u8bf7\u6210\u5458\u5173\u6ce8
invite_user_uri={api_base_url}/invite/send?access_token=%s
# \u4e0a\u4f20\u5a92\u4f53\u6587\u4ef6
file_upload_uri={api_base_url}/media/upload?access_token=%s&type=%s
# \u4e0b\u8f7d\u5a92\u4f53\u6587\u4ef6
file_download_uri={api_base_url}/media/get?access_token=%s&media_id=%s
# \u81ea\u5b9a\u4e49\u83dc\u5355
menu_create_uri={api_base_url}/menu/create?access_token=%s&agentid=%d
# \u5220\u9664\u83dc\u5355
menu_delete_uri={api_base_url}/menu/delete?access_token=%s&agentid=%d
# \u67e5\u8be2\u83dc\u5355
menu_get_uri={api_base_url}/menu/get?access_token=%s&agentid=%d
# \u53d1\u9001\u6d88\u606f
message_send_uri={api_base_url}/message/send?access_token=%s
# \u83b7\u53d6\u5fae\u4fe1IP\u5730\u5740
getcallbackip_uri={api_base_url}/getcallbackip?access_token=%s
# \u83b7\u53d6\u4f01\u4e1a\u53f7\u5e94\u7528\u4fe1\u606f
agent_get_uri={api_base_url}/agent/get?access_token=%s&agentid=%d
# \u8bbe\u7f6e\u4f01\u4e1a\u53f7\u5e94\u7528\u4fe1\u606f
agent_set_uri={api_base_url}/agent/set?access_token=%s
# \u83b7\u53d6\u5e94\u7528\u5217\u8868
agent_list_uri={api_base_url}/agent/list?access_token=%s
# \u6279\u91cf\u9080\u8bf7\u6210\u5458\u5173\u6ce8
batch_inviteuser_uri={api_base_url}/batch/inviteuser?access_token=%s
# \u6279\u91cf\u66f4\u65b0\u6210\u5458
batch_syncuser_uri={api_base_url}/batch/syncuser?access_token=%s
batch_syncuser.cvs={"header":"\u59d3\u540d,\u8d26\u53f7,\u5fae\u4fe1\u53f7,\u624b\u673a\u53f7,\u90ae\u7bb1,\u6240\u5728\u90e8\u95e8,\u804c\u4f4d","column":["name","userid","weixinid","mobile","email","department","position"]}
# \u6279\u91cf\u8986\u76d6\u6210\u5458
batch_replaceuser_uri={api_base_url}/batch/replaceuser?access_token=%s
# \u6279\u91cf\u8986\u76d6\u90e8\u95e8
batch_replaceparty_uri={api_base_url}/batch/replaceparty?access_token=%s
batch_replaceparty.cvs={"header":"\u90e8\u95e8\u540d\u79f0,\u90e8\u95e8ID,\u7236\u90e8\u95e8ID,\u6392\u5e8f","column":["name","id","parentid","order"]}
# \u83b7\u53d6\u5f02\u6b65\u4efb\u52a1\u6267\u884c\u7ed3\u679c
batch_getresult_uri={api_base_url}/batch/getresult?access_token=%s&jobid=%s
@@ -0,0 +1,28 @@
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() + "]";
}
}
@@ -0,0 +1,157 @@
package com.foxinmy.weixin4j.qy.message;
import java.io.Serializable;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.tuple.NotifyTuple;
/**
* 发送消息对象
*
* @className NotifyMessage
* @author jy
* @date 2014年11月22日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.tuple.Text
* @see com.foxinmy.weixin4j.tuple.Image
* @see com.foxinmy.weixin4j.tuple.Voice
* @see com.foxinmy.weixin4j.tuple.Video
* @see com.foxinmy.weixin4j.tuple.File
* @see com.foxinmy.weixin4j.tuple.News
* @see com.foxinmy.weixin4j.tuple.MpNews
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E6%B6%88%E6%81%AF%E7%B1%BB%E5%9E%8B%E5%8F%8A%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F">消息说明</a>
*/
public class NotifyMessage implements Serializable {
private static final long serialVersionUID = 1219589414293000383L;
private static final String SEPARATOR = "|";
/**
* UserID列表(消息接收者,多个接收者用‘|’分隔)。特殊情况:指定为@all,则向关注该企业应用的全部成员发送
*/
private String touser;
/**
* PartyID列表,多个接受者用‘|’分隔。当touser为@all时忽略本参数
*/
private String toparty;
/**
* TagID列表,多个接受者用‘|’分隔。当touser为@all时忽略本参数
*/
private String totag;
/**
* 企业应用的id,整型。可在应用的设置页面查看
*/
private int agentid;
/**
* 表示是否是保密消息,0表示否,1表示是,默认0
*/
private int safe;
/**
* 消息对象
*/
@JSONField(serialize = false)
private NotifyTuple tuple;
public NotifyMessage(NotifyTuple tuple, int agentid) {
this(null, null, null, tuple, agentid, false);
this.touser = "@all";
}
public NotifyMessage(List<String> tousers, List<String> topartys,
List<String> totags, NotifyTuple tuple, int agentid, boolean isSafe) {
if (tousers != null && !tousers.isEmpty()) {
this.touser = StringUtils.join(tousers, SEPARATOR);
}
if (topartys != null && !topartys.isEmpty()) {
this.toparty = StringUtils.join(topartys, SEPARATOR);
}
if (totags != null && !totags.isEmpty()) {
this.totag = StringUtils.join(totags, SEPARATOR);
}
this.agentid = agentid;
this.safe = isSafe ? 1 : 0;
this.tuple = tuple;
}
public String getTouser() {
return touser;
}
public void setTouser(String touser) {
this.touser = touser;
}
public void setTouser(List<String> tousers) {
if (tousers != null && !tousers.isEmpty()) {
this.touser = StringUtils.join(tousers, SEPARATOR);
}
}
public String getToparty() {
return toparty;
}
public void setToparty(String toparty) {
this.toparty = toparty;
}
public void setToparty(List<String> topartys) {
if (topartys != null && !topartys.isEmpty()) {
this.toparty = StringUtils.join(topartys, SEPARATOR);
}
}
public String getTotag() {
return totag;
}
public void setTotag(String totag) {
this.totag = totag;
}
public void setTotag(List<String> totags) {
if (totags != null && !totags.isEmpty()) {
this.totag = StringUtils.join(totags, SEPARATOR);
}
}
public int getAgentid() {
return agentid;
}
public void setAgentid(int agentid) {
this.agentid = agentid;
}
public int getSafe() {
return safe;
}
public void setSafe(int safe) {
this.safe = safe;
}
public void setSafe(boolean isSafe) {
this.safe = isSafe ? 1 : 0;
}
public NotifyTuple getTuple() {
return tuple;
}
public void setTuple(NotifyTuple tuple) {
this.tuple = tuple;
}
@Override
public String toString() {
return "NotifyMessage [touser=" + touser + ", toparty=" + toparty
+ ", totag=" + totag + ", agentid=" + agentid + ", safe="
+ safe + ", tuple=" + tuple + "]";
}
}
@@ -0,0 +1,109 @@
package com.foxinmy.weixin4j.qy.model;
import java.util.List;
import com.alibaba.fastjson.annotation.JSONField;
/**
* 企业号应用的设置信息
*
* @className AgentInfo
* @author jy
* @date 2015年3月17日
* @since JDK 1.7
* @see
*/
public class AgentInfo extends AgentSetter {
private static final long serialVersionUID = -8975132919768696174L;
/**
* 企业应用方形头像
*/
@JSONField(name = "square_logo_url")
private String squareLogoUrl;
/**
* 企业应用圆形头像
*/
@JSONField(name = "round_logo_url")
private String roundLogoUrl;
/**
* 企业应用可见范围(人员),其中包括userid和关注状态state
*/
@JSONField(serialize = false)
private List<User> allowUsers;
/**
* 企业应用可见范围(部门)
*/
@JSONField(serialize = false)
private List<Integer> allowPartys;
/**
* 企业应用可见范围(标签)
*/
@JSONField(serialize = false)
private List<Integer> allowTags;
/**
* 企业应用是否被禁用
*/
private boolean close;
public AgentInfo() {
super(0);
}
public String getSquareLogoUrl() {
return squareLogoUrl;
}
public void setSquareLogoUrl(String squareLogoUrl) {
this.squareLogoUrl = squareLogoUrl;
}
public String getRoundLogoUrl() {
return roundLogoUrl;
}
public void setRoundLogoUrl(String roundLogoUrl) {
this.roundLogoUrl = roundLogoUrl;
}
public List<User> getAllowUsers() {
return allowUsers;
}
public void setAllowUsers(List<User> allowUsers) {
this.allowUsers = allowUsers;
}
public List<Integer> getAllowPartys() {
return allowPartys;
}
public void setAllowPartys(List<Integer> allowPartys) {
this.allowPartys = allowPartys;
}
public List<Integer> getAllowTags() {
return allowTags;
}
public void setAllowTags(List<Integer> allowTags) {
this.allowTags = allowTags;
}
public boolean isClose() {
return close;
}
public void setClose(boolean close) {
this.close = close;
}
@Override
public String toString() {
return "AgentInfo [squareLogoUrl=" + squareLogoUrl + ", roundLogoUrl="
+ roundLogoUrl + ", allowUsers=" + allowUsers
+ ", allowPartys=" + allowPartys + ", allowTags=" + allowTags
+ ", close=" + close + ", " + super.toString() + "]";
}
}
@@ -0,0 +1,67 @@
package com.foxinmy.weixin4j.qy.model;
import java.io.Serializable;
import com.alibaba.fastjson.annotation.JSONField;
/**
* 企业号应用的概况信息
* @className AgentOverview
* @author jy
* @date 2015年4月9日
* @since JDK 1.7
* @see
*/
public class AgentOverview implements Serializable {
private static final long serialVersionUID = 5459274811502476460L;
/**
* 企业应用的id
*/
private int agentid;
/**
* 企业应用名称
*/
private String name;
/**
* 企业应用方形头像
*/
@JSONField(name = "square_logo_url")
private String squareLogoUrl;
/**
* 企业应用圆形头像
*/
@JSONField(name = "round_logo_url")
private String roundLogoUrl;
public int getAgentid() {
return agentid;
}
public void setAgentid(int agentid) {
this.agentid = agentid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSquareLogoUrl() {
return squareLogoUrl;
}
public void setSquareLogoUrl(String squareLogoUrl) {
this.squareLogoUrl = squareLogoUrl;
}
public String getRoundLogoUrl() {
return roundLogoUrl;
}
public void setRoundLogoUrl(String roundLogoUrl) {
this.roundLogoUrl = roundLogoUrl;
}
@Override
public String toString() {
return "AgentOverview [agentid=" + agentid + ", name=" + name
+ ", squareLogoUrl=" + squareLogoUrl + ", roundLogoUrl="
+ roundLogoUrl + "]";
}
}
@@ -0,0 +1,135 @@
package com.foxinmy.weixin4j.qy.model;
import java.io.Serializable;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.qy.type.ReportLocationType;
/**
* 设置企业号应用
*
* @className AgentSetter
* @author jy
* @date 2015年3月16日
* @since JDK 1.7
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E8%AE%BE%E7%BD%AE%E4%BC%81%E4%B8%9A%E5%8F%B7%E5%BA%94%E7%94%A8">设置企业号应用</a>
*/
public class AgentSetter implements Serializable {
private static final long serialVersionUID = 5420335232308079801L;
/**
* 企业应用的id
*/
private int agentid;
/**
* 企业应用是否打开地理位置上报
*/
@JSONField(name = "report_location_flag")
private ReportLocationType reportLocationType;
/**
* 企业应用头像的mediaid,通过多媒体接口上传图片获得mediaid,上传后会自动裁剪成方形和圆形两个头像
*/
@JSONField(name = "logo_mediaid")
private String logoMediaid;
/**
* 企业应用名称
*/
private String name;
/**
* 企业应用详情
*/
private String description;
/**
* 企业应用可信域名
*/
@JSONField(name = "redirect_domain")
private String redirectDomain;
/**
* 是否接收用户变更通知。0:不接收;1:接收
*/
@JSONField(name = "isreportuser")
private int isReportUser;
/**
* 是否上报用户进入应用事件。0:不接收;1:接收
*/
@JSONField(name = "isreportenter")
private int isReportEnter;
public AgentSetter(int agentid) {
this.agentid = agentid;
}
public int getAgentid() {
return agentid;
}
public void setAgentid(int agentid) {
this.agentid = agentid;
}
public ReportLocationType getReportLocationType() {
return reportLocationType;
}
public void setReportLocationType(ReportLocationType reportLocationType) {
this.reportLocationType = reportLocationType;
}
public String getLogoMediaid() {
return logoMediaid;
}
public void setLogoMediaid(String logoMediaid) {
this.logoMediaid = logoMediaid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getRedirectDomain() {
return redirectDomain;
}
public void setRedirectDomain(String redirectDomain) {
this.redirectDomain = redirectDomain;
}
public boolean getIsReportUser() {
return isReportUser == 1;
}
public void setIsReportUser(boolean isReportUser) {
this.isReportUser = isReportUser ? 1 : 0;
}
public boolean getIsReportEnter() {
return isReportEnter == 1;
}
public void setIsReportEnter(boolean isReportEnter) {
this.isReportEnter = isReportEnter ? 1 : 0;
}
@Override
public String toString() {
return "agentid=" + agentid + ", reportLocationType="
+ reportLocationType + ", logoMediaid=" + logoMediaid
+ ", name=" + name + ", description=" + description
+ ", redirectDomain=" + redirectDomain + ", isReportUser="
+ isReportUser + ", isReportEnter=" + isReportEnter;
}
}
@@ -0,0 +1,99 @@
package com.foxinmy.weixin4j.qy.model;
import com.alibaba.fastjson.JSONArray;
import com.foxinmy.weixin4j.http.JsonResult;
import com.foxinmy.weixin4j.qy.type.BatchStatus;
import com.foxinmy.weixin4j.qy.type.BatchType;
/**
* 异步任务执行结果
*
* @className BatchResult
* @author jy
* @date 2015年3月31日
* @since JDK 1.7
* @see
*/
public class BatchResult extends JsonResult {
private static final long serialVersionUID = 4985338631992208903L;
/**
* 任务状态
*/
private int status;
/**
* 任务类型
*/
private String type;
/**
* 任务运行总条数
*/
private int total;
/**
* 目前运行百分比,当任务完成时为100
*/
private int percentage;
/**
* 预估剩余时间(单位:分钟),当任务完成时为0
*/
private int remaintime;
/**
* 详细的处理结果 TODO
*/
private JSONArray result;
public BatchStatus getStatus() {
return BatchStatus.values()[status - 1];
}
public void setStatus(int status) {
this.status = status;
}
public BatchType getType() {
return BatchType.valueOf(type.toUpperCase());
}
public void setType(String type) {
this.type = type;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public int getPercentage() {
return percentage;
}
public void setPercentage(int percentage) {
this.percentage = percentage;
}
public int getRemaintime() {
return remaintime;
}
public void setRemaintime(int remaintime) {
this.remaintime = remaintime;
}
public JSONArray getResult() {
return result;
}
public void setResult(JSONArray result) {
this.result = result;
}
@Override
public String toString() {
return "BatchResult [status=" + getStatus() + ", type=" + getType() + ", total="
+ total + ", percentage=" + percentage + ", remaintime="
+ remaintime + ", result=" + result + "]";
}
}
@@ -0,0 +1,52 @@
package com.foxinmy.weixin4j.qy.model;
import java.io.Serializable;
import com.alibaba.fastjson.annotation.JSONField;
/**
* 调用某些接口时填入的回调信息
*
* @className Callback
* @author jy
* @date 2015年3月30日
* @since JDK 1.7
* @see
*/
public class Callback implements Serializable {
private static final long serialVersionUID = 8575808461248605317L;
/**
* 企业应用接收企业号推送请求的访问协议和地址,支持http或https协议
*/
private String url;
/**
* 用于生成签名
*/
private String token;
/**
* 用于消息体的加密,是AES密钥的Base64编码
*/
@JSONField(name = "encodingaeskey")
private String aesKey;
public Callback(String url, String token, String aesKey) {
this.url = url;
this.token = token;
this.aesKey = aesKey;
}
public String getUrl() {
return url;
}
public String getToken() {
return token;
}
public String getAesKey() {
return aesKey;
}
}
@@ -0,0 +1,64 @@
package com.foxinmy.weixin4j.qy.model;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
/**
* id参数集
*
* @className IdParameter
* @author jy
* @date 2015年3月30日
* @since JDK 1.7
* @see
*/
public class IdParameter implements Serializable {
private static final long serialVersionUID = -2689758682205591133L;
private Map<String, String> parameterMap;
public IdParameter() {
this.parameterMap = new HashMap<String, String>();
}
/**
* 成员ID列表,最多支持1000个
*
* @param userIds
* @return
*/
public IdParameter putUseIds(String... userIds) {
parameterMap.put("touser", StringUtils.join(userIds, '|'));
return this;
}
/**
* 部门ID列表,最多支持100个
*
* @param partyIds
* @return
*/
public IdParameter putUseIds(int... partyIds) {
parameterMap.put("toparty", StringUtils.join(partyIds, '|'));
return this;
}
/**
* 标签ID列表
*
* @param tagIds
* @return
*/
public IdParameter putTagIds(int... tagIds) {
parameterMap.put("totag", StringUtils.join(tagIds, '|'));
return this;
}
public Map<String, String> getParameter() {
return parameterMap;
}
}
@@ -0,0 +1,48 @@
package com.foxinmy.weixin4j.qy.model;
import java.io.Serializable;
/**
* name-value
* @className NameValue
* @author jy
* @date 2015年3月29日
* @since JDK 1.7
* @see
*/
public class NameValue implements Serializable {
private static final long serialVersionUID = -348620146718819093L;
private String name;
private String value;
public NameValue() {
}
public NameValue(String name, String value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public String getValue() {
return value;
}
public void setName(String name) {
this.name = name;
}
public void setValue(String value) {
this.value = value;
}
@Override
public String toString() {
return "NameValue [name=" + name + ", value=" + value + "]";
}
}
@@ -0,0 +1,87 @@
package com.foxinmy.weixin4j.qy.model;
import java.io.Serializable;
/**
* 部门对象
*
* @className Party
* @author jy
* @date 2014年11月18日
* @since JDK 1.7
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E9%83%A8%E9%97%A8">管理部门说明</a>
*/
public class Party implements Serializable {
private static final long serialVersionUID = -2567893218591084288L;
/**
* 部门ID
*/
private int id;
/**
* 部门名称。长度限制为1~64个字符
*/
private String name;
/**
* 父亲部门id。根部门id为1
*/
private int parentid;
/**
* 在父部门中的次序。从1开始,数字越大排序越靠后
*/
private int order;
public Party() {
}
public Party(String name) {
this(0, name, 1, 1);
}
public Party(int id, String name, int parentid, int order) {
this.id = id;
this.name = name;
this.parentid = parentid;
this.order = order;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getParentid() {
return parentid;
}
public void setParentid(int parentid) {
this.parentid = parentid;
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
@Override
public String toString() {
return "Party [id=" + id + ", name=" + name + ", parentid=" + parentid
+ ", order=" + order + "]";
}
}
@@ -0,0 +1,60 @@
package com.foxinmy.weixin4j.qy.model;
import java.io.Serializable;
import com.alibaba.fastjson.annotation.JSONField;
/**
* 标签对象
*
* @className Tag
* @author jy
* @date 2014年11月24日
* @since JDK 1.7
* @see
*/
public class Tag implements Serializable {
private static final long serialVersionUID = 5204620476267654921L;
/**
* 标签ID
*/
@JSONField(name = "tagid")
private int id;
/**
* 标签名称
*/
@JSONField(name = "tagname")
private String name;
public Tag() {
}
public Tag(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Tag [id=" + id + ", name=" + name + "]";
}
}
@@ -0,0 +1,262 @@
package com.foxinmy.weixin4j.qy.model;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.model.Gender;
import com.foxinmy.weixin4j.qy.type.UserStatus;
/**
* 部门成员对象
*
* @className User
* @author jy
* @date 2014年11月19日
* @since JDK 1.7
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%88%90%E5%91%98">管理成员说明</a>
*/
public class User implements Serializable {
private static final long serialVersionUID = 4747301605060801611L;
/**
* 必须 员工UserID。对应管理端的帐号,企业内必须唯一。长度为1~64个字符
*/
private String userid;
/**
* 必须 成员名称。长度为1~64个字符
*/
private String name;
/**
* 非必须 成员所属部门id列表。注意,每个部门的直属员工上限为1000个
*/
private List<Integer> department;
/**
* 非必须 职位信息。长度为0~64个字符
*/
private String position;
/**
* 非必须 手机号码。企业内必须唯一,mobile/weixinid/email三者不能同时为空
*/
private String mobile;
/**
* 非必须 性别。gender=0表示男,=1表示女。默认gender=0
*/
private int gender;
/**
* 非必须 办公电话。长度为0~64个字符
*/
private String tel;
/**
* 非必须 邮箱。长度为0~64个字符。企业内必须唯一
*/
private String email;
/**
* 非必须 微信号。企业内必须唯一
*/
private String weixinid;
/**
* 头像url。注:如果要获取小图将url最后的"/0"改成"/64"即可
*/
private String avatar;
/**
* 关注状态: 1=已关注,2=已冻结,4=未关注
*/
private int status;
/**
* 启用/禁用成员。1表示启用成员,0表示禁用成员
*/
private int enable;
/**
* 非必须 扩展属性。扩展属性需要在WEB管理端创建后才生效,否则忽略未知属性的赋值
*/
private List<NameValue> extattr;
public User() {
this.extattr = new ArrayList<NameValue>();
}
public User(String userid, String name) {
this(userid, name, null, null, null);
}
/**
* mobile/weixinid/email三者不能同时为空
*
* @param userid
* 用户ID
* @param name
* 用户昵称
* @param tel
* 号码
* @param email
* 邮箱
* @param weixinid
* 微信ID
*/
public User(String userid, String name, String tel, String email,
String weixinid) {
this.userid = userid;
this.name = name;
this.tel = tel;
this.email = email;
this.weixinid = weixinid;
this.extattr = new ArrayList<NameValue>();
}
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Integer> getDepartment() {
return department;
}
public void setDepartment(List<Integer> department) {
this.department = department;
}
public void setDepartment(Integer... department) {
this.department = Arrays.asList(department);
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public int getGender() {
return gender;
}
@JSONField(serialize = false)
public Gender getFormatGender() {
if (gender == 0) {
return Gender.male;
} else if (gender == 1) {
return Gender.female;
} else {
return Gender.unknown;
}
}
public void setGender(int gender) {
this.gender = gender;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getWeixinid() {
return weixinid;
}
public void setWeixinid(String weixinid) {
this.weixinid = weixinid;
}
@JSONField(serialize = false)
public String getAvatar() {
return avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
@JSONField(serialize = false, deserialize = false)
public UserStatus getFormatStatus() {
for (UserStatus userStatus : UserStatus.values()) {
if (userStatus.getVal() == status) {
return userStatus;
}
}
return null;
}
public void setStatus(int status) {
this.status = status;
}
public int getEnable() {
return enable;
}
@JSONField(serialize = false, deserialize = false)
public boolean getFormatEnable() {
return enable == 1;
}
public void setEnable(int enable) {
this.enable = enable;
}
public List<NameValue> getExtattr() {
return extattr;
}
public void setExtattr(List<NameValue> extattr) {
this.extattr = extattr;
}
public void setExtattr(NameValue... extattr) {
this.extattr = Arrays.asList(extattr);
}
public void pushExattr(String name, String value) {
pushExattr(new NameValue(name, value));
}
public void pushExattr(NameValue nameValue) {
extattr.add(nameValue);
}
@Override
public String toString() {
return "User [userid=" + userid + ", name=" + name + ", department="
+ department + ", position=" + position + ", mobile=" + mobile
+ ", gender=" + getFormatGender() + ", tel=" + tel + ", email="
+ email + ", weixinid=" + weixinid + ", avatar=" + avatar
+ ", status=" + getFormatStatus() + ", enable="
+ getFormatEnable() + ", extattr=" + extattr + "]";
}
}
@@ -0,0 +1,55 @@
package com.foxinmy.weixin4j.qy.token;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.HttpRequest;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.token.TokenCreator;
import com.foxinmy.weixin4j.token.TokenHolder;
/**
* 微信企业号JSTICKET创建者
*
* @className WeixinJSTicketCreator
* @author jy
* @date 2015年1月10日
* @since JDK 1.7
* @see <a
* href="http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD.951-JS-SDK.E4.BD.BF.E7.94.A8.E6.9D.83.E9.99.90.E7.AD.BE.E5.90.8D.E7.AE.97.E6.B3.95">JS
* TICKET</a>
*/
public class WeixinJSTicketCreator implements TokenCreator {
private final String appid;
private final TokenHolder weixinTokenHolder;
private final HttpRequest request;
/**
* <font color="red">企业号的的access_token</font>
*
* @param weixinTokenHolder
*/
public WeixinJSTicketCreator(String appid, TokenHolder weixinTokenHolder) {
this.appid = appid;
this.weixinTokenHolder = weixinTokenHolder;
this.request = new HttpRequest();
}
@Override
public String getCacheKey() {
return String.format("qy_jsticket_%s", appid);
}
@Override
public Token createToken() throws WeixinException {
Response response = request.get(String.format(Consts.QY_JS_TICKET_URL,
weixinTokenHolder.getToken().getAccessToken()));
JSONObject result = response.getAsJson();
Token token = new Token(result.getString("ticket"));
token.setExpiresIn(result.getIntValue("expires_in"));
token.setTime(System.currentTimeMillis());
return token;
}
}
@@ -0,0 +1,58 @@
package com.foxinmy.weixin4j.qy.token;
import com.alibaba.fastjson.TypeReference;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.HttpRequest;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.model.WeixinAccount;
import com.foxinmy.weixin4j.token.TokenCreator;
import com.foxinmy.weixin4j.util.ConfigUtil;
/**
* 微信企业号TOKEN创建者
*
* @className WeixinTokenCreator
* @author jy
* @date 2015年1月10日
* @since JDK 1.7
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E4%B8%BB%E5%8A%A8%E8%B0%83%E7%94%A8">微信企业号获取token说明</a>
* @see com.foxinmy.weixin4j.model.Token
*/
public class WeixinTokenCreator implements TokenCreator {
private final HttpRequest request;
private final String corpid;
private final String corpsecret;
public WeixinTokenCreator() {
WeixinAccount weixinAccount = ConfigUtil.getWeixinAccount();
this.corpid = weixinAccount.getId();
this.corpsecret = weixinAccount.getSecret();
this.request = new HttpRequest();
}
public WeixinTokenCreator(String corpid, String corpsecret) {
this.corpid = corpid;
this.corpsecret = corpsecret;
this.request = new HttpRequest();
}
@Override
public String getCacheKey() {
return String.format("qy_token_%s", corpid);
}
@Override
public Token createToken() throws WeixinException {
String tokenUrl = String.format(Consts.QY_ASSESS_TOKEN_URL, corpid,
corpsecret);
Response response = request.get(tokenUrl);
Token token = response.getAsObject(new TypeReference<Token>() {
});
token.setTime(System.currentTimeMillis());
return token;
}
}
@@ -0,0 +1,34 @@
package com.foxinmy.weixin4j.qy.type;
/**
* 异步任务的状态
*
* @className BatchStatus
* @author jy
* @date 2015年3月31日
* @since JDK 1.7
* @see
*/
public enum BatchStatus {
/**
* 开始
*/
START(1),
/**
* 进行中
*/
PROCESS(2),
/**
* 完成
*/
DONE(3);
private int code;
BatchStatus(int code) {
this.code = code;
}
public int getCode() {
return code;
}
}
@@ -0,0 +1,39 @@
package com.foxinmy.weixin4j.qy.type;
/**
* 异步任务的类型
*
* @className BatchType
* @author jy
* @date 2015年3月31日
* @since JDK 1.7
* @see
*/
public enum BatchType {
/**
* 增量更新成员
*/
SYNC_USER(1),
/**
* 全量覆盖成员
*/
REPLACE_USER(2),
/**
* 邀请成员关注
*/
INVITE_USER(3),
/**
* 全量覆盖部门
*/
REPLACE_PARTY(4);
private int code;
BatchType(int code) {
this.code = code;
}
public int getCode() {
return code;
}
}
@@ -0,0 +1,25 @@
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;
}
@@ -0,0 +1,21 @@
package com.foxinmy.weixin4j.qy.type;
/**
* 邀请类型
*
* @className InviteType
* @author jy
* @date 2015年1月15日
* @since JDK 1.7
* @see
*/
public enum InviteType {
/**
* 微信邀请
*/
WEIXIN,
/**
* 邮件邀请
*/
EMAIL
}
@@ -0,0 +1,25 @@
package com.foxinmy.weixin4j.qy.type;
/**
* 上报策略
*
* @className ReportLocationType
* @author jy
* @date 2015年3月16日
* @since JDK 1.7
* @see
*/
public enum ReportLocationType {
/**
* 不上报
*/
NOT,
/**
* 进入回话上报
*/
DIALOG,
/**
* 持续上报
*/
PERSIST;
}
@@ -0,0 +1,38 @@
package com.foxinmy.weixin4j.qy.type;
/**
* 成员状态
*
* @className UserStatus
* @author jy
* @date 2014年11月19日
* @since JDK 1.7
* @see
*/
public enum UserStatus {
/**
* 0=全部
*/
BOTH(0),
/**
* 1=已关注
*/
FOLLOW(1),
/**
* 2=已冻结
*/
FROZEN(2),
/**
* 4=未关注
*/
UNFOLLOW(4);
private int val;
UserStatus(int val) {
this.val = val;
}
public int getVal() {
return val;
}
}
@@ -0,0 +1,10 @@
# \u6d4b\u8bd5\u4e4b\u7528 \u6b63\u5f0f\u73af\u5883\u4e0bcopy\u4e00\u4efd\u5230classpath
# \u4f01\u4e1a\u53f7\u4fe1\u606f
account={"id":"wxf10bce209c91d0e2","secret":"cW0OtP7-7YJ7jHKFZaJW2skJHE9bLHadxOswBdVdI2walRBSPfTSA6QqD_QXw8JZ",\
"token":"gp2eGT5mIpngr",\
"encodingAesKey":"BRYfV4zPFUJb3v3MySNBg1ERKE3vyyMRoScu76vFySv"}
# \u4f7f\u7528FileTokenHolder\u65f6token\u7684\u5b58\u653e\u8def\u5f84
token_path=/tmp/weixin/token
# \u5a92\u4f53\u6587\u4ef6\u4fdd\u5b58\u8def\u5f84
media_path=/tmp/weixin/media