大重构:weixin4j精简为weixin4j-base、weixin4j-mp、weixin4j-qy、weixin4j-server四个子工程。
This commit is contained in:
+20
-102
@@ -6,35 +6,28 @@ weixin4j-qy
|
||||
|
||||
功能列表
|
||||
-------
|
||||
* **weixin4j-qy-api**
|
||||
|
||||
+ PartyApi `部门管理API`
|
||||
* PartyApi `部门管理API`
|
||||
|
||||
+ UserApi `成员管理API`
|
||||
* UserApi `成员管理API`
|
||||
|
||||
+ TagApi `标签管理API`
|
||||
* TagApi `标签管理API`
|
||||
|
||||
+ MediaApi `多媒体管理API`
|
||||
* MediaApi `多媒体管理API`
|
||||
|
||||
+ MenuApi `菜单管理API`
|
||||
* MenuApi `菜单管理API`
|
||||
|
||||
+ NotifyApi `消息发送API`
|
||||
* NotifyApi `消息发送API`
|
||||
|
||||
+ AgentApi `应用设置API`
|
||||
* AgentApi `应用设置API`
|
||||
|
||||
+ BatchApi `批量任务API`
|
||||
* BatchApi `批量操作API`
|
||||
|
||||
* **weixin4j-qy-server**
|
||||
如何使用
|
||||
--------
|
||||
1.API工程可以单独打包到其他项目中使用,需新增或拷贝`weixin.properties`文件到项目的`classpath`中
|
||||
|
||||
+ `netty服务器` & `消息分发`
|
||||
|
||||
+ 回调连接`AES`加密、解密
|
||||
|
||||
项目说明
|
||||
-------
|
||||
1.`weixin4j-qy`包含「微信企业号」的API封装以及一个半成品的netty服务实现.
|
||||
|
||||
2.API的成功调用依赖于正确的appid等数据,创建(或者copy项目里面的)一个名为**weixin.properties**的资源文件放在自己工程中的classpath下.
|
||||
weixin.properties说明
|
||||
|
||||
| 属性名 | 说明 |
|
||||
| :---------- | :-------------- |
|
||||
@@ -51,94 +44,19 @@ weixin4j-qy
|
||||
token_path=/tmp/weixin/token
|
||||
media_path=/tmp/weixin/media
|
||||
|
||||
3.在项目根目录执行`mvn package`命令后得到jar包,将`weixin4j-qy-full`包或者`weixin4j-base`跟`weixin4j-qy-api`两个包引入到自己的工程内.
|
||||
2.实例化一个`WeixinProxy`对象,调用API
|
||||
|
||||
WeixinProxy weixinProxy = new WeixinProxy();
|
||||
// weixinProxy = new WeixinProxy(corpid,corpsecret);
|
||||
// weixinProxy = new WeixinProxy(weixinAccount);
|
||||
weixinProxy.getUser(userid);
|
||||
|
||||
4.如需使用netty服务,则可以在相应的action中实现自己的业务处理,打包后放到`正确的目录`下解压`weixin-qy-server-bin.zip`执行`sh startup.sh start`便可启动服务.
|
||||
3.针对`token`存储有两种方案,`File存储`/`Redis存储`,当然也可自己实现`TokenHolder`,默认使用文件(xml)的方式保存token,如果环境中支持`redis`,建议使用`RedisTokenHolder`.
|
||||
|
||||
@ActionAnnotation(msgType = MessageType.text)
|
||||
public class TextAction extends AbstractAction<TextMessage> {
|
||||
|
||||
@Override
|
||||
public ResponseMessage execute(TextMessage inMessage) {
|
||||
return new ResponseMessage(new Text("Hello World!"), inMessage);
|
||||
}
|
||||
}
|
||||
WeixinProxy weixinProxy = new WeixinProxy(new RedisTokenHolder());
|
||||
// weixinProxy = new WeixinProxy(new RedisTokenHolder(weixinAccount));
|
||||
|
||||
4.`mvn package`.
|
||||
|
||||
更新LOG
|
||||
-------
|
||||
* 2014-11-19
|
||||
|
||||
+ 得到`weixin4j-qy-api`和`weixin4j-qy-server`工程
|
||||
|
||||
+ **weixin4j-qy-api**: 新增部门管理接口
|
||||
|
||||
+ **weixin4j-qy-api**: 新增用户管理接口
|
||||
|
||||
+ **weixin4j-qy-api**: 新增标签管理接口
|
||||
|
||||
* 2014-11-23
|
||||
|
||||
+ **weixin4j-qy-api**: 新增`多媒体管理`接口
|
||||
|
||||
+ **weixin4j-qy-api**: 新增`发送消息`接口
|
||||
|
||||
+ **weixin4j-qy-api**: 新增`菜单管理`接口
|
||||
|
||||
* 2014-11-24
|
||||
|
||||
+ **weixin4j-qy-server**: 新增netty服务与消息分发
|
||||
|
||||
* 2014-12-28
|
||||
|
||||
+ **weixin4j-qy-api**: 增加用户进入应用的callback事件
|
||||
|
||||
+ **weixin4j-qy-api**: 增加批量获取用户详情的接口
|
||||
|
||||
+ **weixin4j-qy-api**: 新增获取微信服务器IP接口
|
||||
|
||||
+ **weixin4j-qy-server**: 调整回调模式下的首次验证的签名方式
|
||||
|
||||
* 2015-01-04
|
||||
|
||||
+ **weixin4j-qy-api**: 新增批量删除员工接口
|
||||
|
||||
* 2015-01-15
|
||||
|
||||
+ **weixin4j-qy-api**: 新增邀请成员关注接口
|
||||
|
||||
* 2015-03-08
|
||||
|
||||
+ **weixin4j-qy-api**: 新增根据code获取成员信息接口
|
||||
|
||||
* 2015-03-17
|
||||
|
||||
+ **weixin4j-qy-api**: 新增企业应用设置接口
|
||||
|
||||
+ **weixin4j-qy-server**: 新增deploy.xml远程部署ant脚本
|
||||
|
||||
* 2015-03-29
|
||||
|
||||
+ **weixin4j-qy-api**: 单行注释调整为多行文档注释
|
||||
|
||||
* 2015-04-01
|
||||
|
||||
+ **weixin4j-qy-api**: 新增[BatchApi](./weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/api/BatchApi.java)批量异步执行任务接口
|
||||
|
||||
+ **weixin4j-qy-api**: <font color="red">DepartApi命名为[PartyApi](./weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/api/PartyApi.java)</font>
|
||||
|
||||
* 2015-04-04
|
||||
|
||||
+ **weixin4j-qy-api**: [MediaApi](./weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/api/MediaApi.java)新增批量上传成员和部门接口
|
||||
|
||||
* 2015-04-09
|
||||
|
||||
+ **weixin4j-qy-api**: [AgentApi](./weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/api/AgentApi.java)新增获取应用列表概况接口
|
||||
|
||||
* 2015-04-13
|
||||
|
||||
+ **weixin4j-qy-api**: 新增WeixinTokenCreator与WeixinJSTicketCreator类
|
||||
[更新LOG](./CHANGE.md)
|
||||
----------------------
|
||||
+28
-6
@@ -8,11 +8,33 @@
|
||||
</parent>
|
||||
<artifactId>weixin4j-qy</artifactId>
|
||||
<name>weixin4j-qy</name>
|
||||
<packaging>pom</packaging>
|
||||
<url>https://github.com/foxinmy/weixin4j/tree/master/weixin4j-qy</url>
|
||||
<description>微信企业号工具包</description>
|
||||
<modules>
|
||||
<module>weixin4j-qy-api</module>
|
||||
<module>weixin4j-qy-server</module>
|
||||
</modules>
|
||||
<description>微信企业号API</description>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<configuration>
|
||||
<finalName>weixin4j-qy-${project.version}</finalName>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.foxinmy</groupId>
|
||||
<artifactId>weixin4j-base</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jaxen</groupId>
|
||||
<artifactId>jaxen</artifactId>
|
||||
<version>${jaxen.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.foxinmy.weixin4j.qy.event;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.foxinmy.weixin4j.message.event.EventMessage;
|
||||
import com.foxinmy.weixin4j.qy.type.EventType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 异步任务事件完成通知
|
||||
*
|
||||
* @className BatchjobresultMessage
|
||||
* @author jy
|
||||
* @date 2015年3月31日
|
||||
* @since JDK 1.7
|
||||
* @see <a
|
||||
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E4%BA%8B%E4%BB%B6#.E5.BC.82.E6.AD.A5.E4.BB.BB.E5.8A.A1.E5.AE.8C.E6.88.90.E4.BA.8B.E4.BB.B6.E6.8E.A8.E9.80.81">异步任务事件完成通知</a>
|
||||
*/
|
||||
public class BatchjobresultMessage extends EventMessage {
|
||||
|
||||
private static final long serialVersionUID = 8014540441322209657L;
|
||||
|
||||
public BatchjobresultMessage() {
|
||||
super(EventType.batch_job_result.name());
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务信息
|
||||
*/
|
||||
@XStreamAlias("BatchJob")
|
||||
private BatchJob batchJob;
|
||||
|
||||
public BatchJob getBatchJob() {
|
||||
return batchJob;
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务信息
|
||||
*
|
||||
* @className BatchJob
|
||||
* @author jy
|
||||
* @date 2015年4月1日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public static class BatchJob implements Serializable {
|
||||
private static final long serialVersionUID = -7520032656787156391L;
|
||||
/**
|
||||
* 异步任务id,最大长度为64字符
|
||||
*/
|
||||
@XStreamAlias("JobId")
|
||||
private String jobId;
|
||||
/**
|
||||
* 操作类型,字符串,目前分别有: 1. sync_user(增量更新成员) 2. replace_user(全量覆盖成员) 3.
|
||||
* invite_user(邀请成员关注) 4. replace_party(全量覆盖部门)
|
||||
*
|
||||
* @see com.foxinmy.weixin4j.qy.type.BatchType
|
||||
*/
|
||||
@XStreamAlias("JobType")
|
||||
private String jobType;
|
||||
/**
|
||||
* 返回码
|
||||
*/
|
||||
@XStreamAlias("ErrCode")
|
||||
private String ErrCode;
|
||||
/**
|
||||
* 对返回码的文本描述内容
|
||||
*/
|
||||
@XStreamAlias("ErrMsg")
|
||||
private String errMsg;
|
||||
|
||||
public String getJobId() {
|
||||
return jobId;
|
||||
}
|
||||
|
||||
public String getJobType() {
|
||||
return jobType;
|
||||
}
|
||||
|
||||
public String getErrCode() {
|
||||
return ErrCode;
|
||||
}
|
||||
|
||||
public String getErrMsg() {
|
||||
return errMsg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[jobId=" + jobId + ", jobType=" + jobType + ", ErrCode="
|
||||
+ ErrCode + ", errMsg=" + errMsg + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BatchjobresultMessage [batchJob=" + batchJob + ", "
|
||||
+ super.toString() + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.foxinmy.weixin4j.qy.event;
|
||||
|
||||
import com.foxinmy.weixin4j.message.event.EventMessage;
|
||||
import com.foxinmy.weixin4j.qy.type.EventType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 用户进入应用的事件推送(企业号)本事件只有在应用的回调模式中打开上报开关时上报
|
||||
*
|
||||
* @className EnterAgentEventMessage
|
||||
* @author jy
|
||||
* @date 2014年12月28日
|
||||
* @since JDK 1.7
|
||||
* @see <a href=
|
||||
* "http://qydev.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E4%BA%8B%E4%BB%B6#.E7.94.A8.E6.88.B7.E8.BF.9B.E5.85.A5.E5.BA.94.E7.94.A8.E7.9A.84.E4.BA.8B.E4.BB.B6.E6.8E.A8.E9.80.81"
|
||||
* >用户进入应用的事件推送</a>
|
||||
*/
|
||||
public class EnterAgentEventMessage extends EventMessage {
|
||||
|
||||
private static final long serialVersionUID = 7675732524832500820L;
|
||||
|
||||
public EnterAgentEventMessage() {
|
||||
super(EventType.enter_agent.name());
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件KEY值,与自定义菜单接口中KEY值对应
|
||||
*/
|
||||
@XStreamAlias("EventKey")
|
||||
private String eventKey;
|
||||
|
||||
public String getEventKey() {
|
||||
return eventKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EnterAgentEventMessage [eventKey=" + eventKey + ", "
|
||||
+ super.toString() + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.foxinmy.weixin4j.qy.model;
|
||||
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
|
||||
/**
|
||||
* 微信企业号信息
|
||||
*
|
||||
* @className WeixinQyAccount
|
||||
* @author jy
|
||||
* @date 2014年11月18日
|
||||
* @since JDK 1.7
|
||||
* @see <a href=
|
||||
* "https://qy.weixin.qq.com/cgi-bin/home?lang=zh_CN&token=685923034#setting"
|
||||
* >企业号设置</a>
|
||||
*/
|
||||
public class WeixinQyAccount extends WeixinAccount {
|
||||
private static final long serialVersionUID = 3689999353867189585L;
|
||||
|
||||
public WeixinQyAccount() {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param corpid
|
||||
* 企业ID
|
||||
* @param corpsecret
|
||||
* 管理组的凭证密钥
|
||||
*/
|
||||
public WeixinQyAccount(String corpid, String corpsecret) {
|
||||
super(corpid, corpsecret);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WeixinQyAccount [" + super.toString() + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
||||
*~
|
||||
|
||||
# eclipse ignore
|
||||
*.settings/*
|
||||
/.project
|
||||
/.classpath
|
||||
/.tomcatplugin
|
||||
|
||||
# idea ignore
|
||||
/.idea
|
||||
*.iml
|
||||
|
||||
# maven ignore
|
||||
target/*
|
||||
|
||||
# other ignore
|
||||
*.log
|
||||
*.tmp
|
||||
Thumbs.db
|
||||
/target/
|
||||
.DS_Store
|
||||
@@ -1,113 +0,0 @@
|
||||
weixin4j-qy-api
|
||||
===============
|
||||
|
||||
[微信企业号](http://qydev.weixin.qq.com/wiki/index.php)开发工具包
|
||||
---------------------------------------------------------------
|
||||
|
||||
功能列表
|
||||
-------
|
||||
|
||||
* PartyApi `部门管理API`
|
||||
|
||||
* UserApi `成员管理API`
|
||||
|
||||
* TagApi `标签管理API`
|
||||
|
||||
* MediaApi `多媒体管理API`
|
||||
|
||||
* MenuApi `菜单管理API`
|
||||
|
||||
* NotifyApi `消息发送API`
|
||||
|
||||
* AgentApi `应用设置API`
|
||||
|
||||
* BatchApi `批量操作API`
|
||||
|
||||
如何使用
|
||||
--------
|
||||
1.API工程可以单独打包到其他项目中使用,需新增或拷贝`weixin.properties`文件到项目的`classpath`中
|
||||
|
||||
weixin.properties说明
|
||||
|
||||
| 属性名 | 说明 |
|
||||
| :---------- | :-------------- |
|
||||
| account | 微信企业号信息 `json格式` |
|
||||
| token_path | 使用FileTokenHolder时token保存的物理路径 |
|
||||
| media_path | 调用媒体接口时保存媒体文件的物理路径 |
|
||||
|
||||
示例(properties中换行用右斜杆\\)
|
||||
|
||||
account={"id":"corpid","secret":"corpsecret",\
|
||||
"token":"企业号中应用在回调模式下的token",\
|
||||
"encodingAesKey":"企业号中应用在回调模式下AES加密密钥"}
|
||||
|
||||
token_path=/tmp/weixin/token
|
||||
media_path=/tmp/weixin/media
|
||||
|
||||
2.实例化一个`WeixinProxy`对象,调用API
|
||||
|
||||
WeixinProxy weixinProxy = new WeixinProxy();
|
||||
// weixinProxy = new WeixinProxy(corpid,corpsecret);
|
||||
// weixinProxy = new WeixinProxy(weixinAccount);
|
||||
weixinProxy.getUser(userid);
|
||||
|
||||
3.针对`token`存储有两种方案,`File存储`/`Redis存储`,当然也可自己实现`TokenHolder`,默认使用文件(xml)的方式保存token,如果环境中支持`redis`,建议使用`RedisTokenHolder`.
|
||||
|
||||
WeixinProxy weixinProxy = new WeixinProxy(new RedisTokenHolder());
|
||||
// weixinProxy = new WeixinProxy(new RedisTokenHolder(weixinAccount));
|
||||
|
||||
4.`mvn package`.
|
||||
|
||||
更新LOG
|
||||
-------
|
||||
* 2014-11-19
|
||||
|
||||
+ 新增`部门管理`接口
|
||||
|
||||
+ 新增`用户管理`接口
|
||||
|
||||
+ 新增`标签管理`接口
|
||||
|
||||
* 2014-12-28
|
||||
|
||||
+ 增加`批量获取用户详情`的接口
|
||||
|
||||
+ 新增`获取微信服务器IP`接口
|
||||
|
||||
* 2015-01-04
|
||||
|
||||
+ 新增批量删除员工接口
|
||||
|
||||
* 2015-01-15
|
||||
|
||||
+ 新增邀请成员关注接口
|
||||
|
||||
* 2015-03-08
|
||||
|
||||
+ 新增根据code获取成员信息接口
|
||||
|
||||
* 2015-03-17
|
||||
|
||||
+ 新增企业应用设置接口
|
||||
|
||||
* 2015-03-29
|
||||
|
||||
+ 单行注释调整为多行文档注释
|
||||
|
||||
* 2015-04-01
|
||||
|
||||
+ 新增[BatchApi](./src/main/java/com/foxinmy/weixin4j/qy/api/BatchApi.java)批量异步执行任务接口
|
||||
|
||||
+ <font color="red">DepartApi命名为[PartyApi](./src/main/java/com/foxinmy/weixin4j/qy/api/PartyApi.java)</font>
|
||||
|
||||
* 2015-04-04
|
||||
|
||||
+ [MediaApi](./src/main/java/com/foxinmy/weixin4j/qy/api/MediaApi.java)新增批量上传成员和部门接口
|
||||
|
||||
* 2015-04-09
|
||||
|
||||
+ [AgentApi](./src/main/java/com/foxinmy/weixin4j/qy/api/AgentApi.java)新增获取应用列表概况接口
|
||||
|
||||
* 2015-04-13
|
||||
|
||||
+ 新增WeixinTokenCreator与WeixinJSTicketCreator类
|
||||
@@ -1,40 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.foxinmy</groupId>
|
||||
<artifactId>weixin4j-qy</artifactId>
|
||||
<version>1.3</version>
|
||||
</parent>
|
||||
<artifactId>weixin4j-qy-api</artifactId>
|
||||
<name>weixin4j-qy-api</name>
|
||||
<url>https://github.com/foxinmy/weixin4j/tree/master/weixin4j-qy/weixin4j-qy-api</url>
|
||||
<description>微信企业号API</description>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<configuration>
|
||||
<finalName>weixin4j-qy-${project.version}</finalName>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.foxinmy</groupId>
|
||||
<artifactId>weixin4j-base</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jaxen</groupId>
|
||||
<artifactId>jaxen</artifactId>
|
||||
<version>${jaxen.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -1,31 +0,0 @@
|
||||
<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>
|
||||
@@ -1,807 +0,0 @@
|
||||
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.msg.model.Text
|
||||
* @see com.foxinmy.weixin4j.msg.model.Image
|
||||
* @see com.foxinmy.weixin4j.msg.model.Voice
|
||||
* @see com.foxinmy.weixin4j.msg.model.Video
|
||||
* @see com.foxinmy.weixin4j.msg.model.File
|
||||
* @see com.foxinmy.weixin4j.msg.model.News
|
||||
* @see com.foxinmy.weixin4j.msg.model.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);
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
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>() {
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,252 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
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.msg.model.Base;
|
||||
import com.foxinmy.weixin4j.msg.model.Notifyable;
|
||||
import com.foxinmy.weixin4j.qy.message.NotifyMessage;
|
||||
import com.foxinmy.weixin4j.token.TokenHolder;
|
||||
|
||||
/**
|
||||
* 发送消息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.msg.model.Text
|
||||
* @see com.foxinmy.weixin4j.msg.model.Image
|
||||
* @see com.foxinmy.weixin4j.msg.model.Voice
|
||||
* @see com.foxinmy.weixin4j.msg.model.Video
|
||||
* @see com.foxinmy.weixin4j.msg.model.File
|
||||
* @see com.foxinmy.weixin4j.msg.model.News
|
||||
* @see com.foxinmy.weixin4j.msg.model.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.msg.model.Text
|
||||
* @see com.foxinmy.weixin4j.msg.model.Image
|
||||
* @see com.foxinmy.weixin4j.msg.model.Voice
|
||||
* @see com.foxinmy.weixin4j.msg.model.Video
|
||||
* @see com.foxinmy.weixin4j.msg.model.File
|
||||
* @see com.foxinmy.weixin4j.msg.model.News
|
||||
* @see com.foxinmy.weixin4j.msg.model.MpNews
|
||||
* @see com.foxinmy.weixin4j.qy.message.NotifyMessage
|
||||
*/
|
||||
public JSONObject sendNotify(NotifyMessage notify) throws WeixinException {
|
||||
Base box = notify.getBox();
|
||||
if (!(box instanceof Notifyable)) {
|
||||
throw new WeixinException(String.format(
|
||||
"%s not implement Notifyable", box.getClass()));
|
||||
}
|
||||
String msgtype = box.getMediaType().name();
|
||||
JSONObject obj = (JSONObject) JSON.toJSON(notify);
|
||||
obj.put("msgtype", msgtype);
|
||||
obj.put(msgtype, box);
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,280 +0,0 @@
|
||||
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);
|
||||
Object attrs = obj.getJSONObject("extattr").remove("attrs");
|
||||
if (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;
|
||||
}
|
||||
}
|
||||
}
|
||||
-81
@@ -1,81 +0,0 @@
|
||||
# ----------------------------------------------------------------------------
|
||||
# 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
|
||||
-156
@@ -1,156 +0,0 @@
|
||||
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.msg.model.Base;
|
||||
|
||||
/**
|
||||
* 发送消息对象
|
||||
*
|
||||
* @className NotifyMessage
|
||||
* @author jy
|
||||
* @date 2014年11月22日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.msg.model.Text
|
||||
* @see com.foxinmy.weixin4j.msg.model.Image
|
||||
* @see com.foxinmy.weixin4j.msg.model.Voice
|
||||
* @see com.foxinmy.weixin4j.msg.model.Video
|
||||
* @see com.foxinmy.weixin4j.msg.model.File
|
||||
* @see com.foxinmy.weixin4j.msg.model.News
|
||||
* @see com.foxinmy.weixin4j.msg.model.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 Base box;
|
||||
|
||||
public NotifyMessage(Base box, int agentid) {
|
||||
this(null, null, null, box, agentid, false);
|
||||
this.touser = "@all";
|
||||
}
|
||||
|
||||
public NotifyMessage(List<String> tousers, List<String> topartys,
|
||||
List<String> totags, Base box, 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.box = box;
|
||||
}
|
||||
|
||||
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 Base getBox() {
|
||||
return box;
|
||||
}
|
||||
|
||||
public void setBox(Base box) {
|
||||
this.box = box;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NotifyMessage [touser=" + touser + ", toparty=" + toparty
|
||||
+ ", totag=" + totag + ", agentid=" + agentid + ", safe="
|
||||
+ safe + ", box=" + box + "]";
|
||||
}
|
||||
}
|
||||
-109
@@ -1,109 +0,0 @@
|
||||
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() + "]";
|
||||
}
|
||||
}
|
||||
-67
@@ -1,67 +0,0 @@
|
||||
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 + "]";
|
||||
}
|
||||
}
|
||||
-135
@@ -1,135 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
-99
@@ -1,99 +0,0 @@
|
||||
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 + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
-64
@@ -1,64 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
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 + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
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 + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
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 + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,262 +0,0 @@
|
||||
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 + "]";
|
||||
}
|
||||
}
|
||||
-55
@@ -1,55 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
-58
@@ -1,58 +0,0 @@
|
||||
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.WeixinQyAccount;
|
||||
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() {
|
||||
WeixinQyAccount weixinAccount = ConfigUtil.getWeixinQyAccount();
|
||||
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;
|
||||
}
|
||||
}
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.type;
|
||||
|
||||
/**
|
||||
* 邀请类型
|
||||
*
|
||||
* @className InviteType
|
||||
* @author jy
|
||||
* @date 2015年1月15日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public enum InviteType {
|
||||
/**
|
||||
* 微信邀请
|
||||
*/
|
||||
WEIXIN,
|
||||
/**
|
||||
* 邮件邀请
|
||||
*/
|
||||
EMAIL
|
||||
}
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
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;
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
# \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
|
||||
-64
@@ -1,64 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
|
||||
public class AesMsgTest extends MessagePush {
|
||||
StringBuilder xmlSb = new StringBuilder();
|
||||
|
||||
@Test
|
||||
public void testValidate() throws WeixinException, IOException {
|
||||
String para = "?msg_signature=33f680b72cfd87a6f8f4d751575bcc31266853a9×tamp=1416488666&nonce=1358224345&echostr=WZu9tT6KDuyhgOZ1aT%2FIoPNaUkA%2FsfVR%2F%2BDua5q84Kvhs6Fc1%2F6f2510%2BUuMByessdQWsoeak0lSIpaYOIlHrw%3D%3D";
|
||||
xmlSb.delete(0, xmlSb.length());
|
||||
String response = get(para);
|
||||
Assert.assertEquals("2143641595566077626", response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testType1() throws WeixinException, IOException {
|
||||
String para = "?signature=6dd806a20a314723e78bc58742a1b98a7adfd151×tamp=1415979366&nonce=1865915590";
|
||||
xmlSb.delete(0, xmlSb.length());
|
||||
xmlSb.append("<xml>");
|
||||
xmlSb.append("<ToUserName><![CDATA[gh_248c6f91d64f]]></ToUserName>");
|
||||
xmlSb.append("<FromUserName><![CDATA[oyFLst1bqtuTcxK-ojF8hOGtLQao]]></FromUserName>");
|
||||
xmlSb.append("<CreateTime>1415979365</CreateTime>");
|
||||
xmlSb.append("<MsgType><![CDATA[event]]></MsgType>");
|
||||
xmlSb.append("<Event><![CDATA[CLICK]]></Event>");
|
||||
xmlSb.append("<EventKey><![CDATA[CHECKIN]]></EventKey>");
|
||||
xmlSb.append("</xml>");
|
||||
String response = push(para, xmlSb.toString());
|
||||
Assert.assertNotNull(response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testType2() throws WeixinException, IOException {
|
||||
String para = "?signature=ad05f836772d1cbba1ff2edb7be4b9c9fb3a43d5×tamp=1415980001&nonce=1803216865&encrypt_type=raw&msg_signature=c0d38e9ca00548f7142627ec2908a4fe8481025e";
|
||||
xmlSb.delete(0, xmlSb.length());
|
||||
xmlSb.append("<xml>");
|
||||
xmlSb.append("<ToUserName><![CDATA[gh_248c6f91d64f]]></ToUserName>");
|
||||
xmlSb.append("<FromUserName><![CDATA[oyFLst1bqtuTcxK-ojF8hOGtLQao]]></FromUserName>");
|
||||
xmlSb.append("<CreateTime>1415980001</CreateTime>");
|
||||
xmlSb.append("<MsgType><![CDATA[event]]></MsgType>");
|
||||
xmlSb.append("<Event><![CDATA[CLICK]]></Event>");
|
||||
xmlSb.append("<EventKey><![CDATA[CHECKIN]]></EventKey>");
|
||||
xmlSb.append("</xml>");
|
||||
String response = push(para, xmlSb.toString());
|
||||
Assert.assertNotNull(response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testType3() throws WeixinException, IOException {
|
||||
String para = "?signature=ad05f836772d1cbba1ff2edb7be4b9c9fb3a43d5×tamp=1415980001&nonce=1803216865&encrypt_type=aes&msg_signature=c0d38e9ca00548f7142627ec2908a4fe8481025e";
|
||||
xmlSb.delete(0, xmlSb.length());
|
||||
xmlSb.append("<xml>");
|
||||
xmlSb.append("<ToUserName><![CDATA[gh_248c6f91d64f]]></ToUserName>");
|
||||
xmlSb.append("<Encrypt><![CDATA[R6VQIWDR14XgSRLm25zc7V/WJYqK15gsUiMh0u/5GTMZME6jGtHkyfVN079ZPL065b+ZDq3TnoFKKtjtZlzcodY6Fm8+EujvtbTdVMMFSwdo8AwqVViAn09+DDfqPaNvbHUSiYsL3qlxArs1MH6APRUHFo7MU/piY1x2stJc8+kv28xtF+K8Aou0RuPO7PeQ18Zu/GkLnYNiI1E7UG31UYfOgVKcRjeE0PXa18iF5LBS8G/ce/l+/pH/DJWUBw5uXaqSOlo21tctlgLXu3bYUUkIu8tT49QwhHvRZILtO9icoyCNuTA7iTcHIdlAe1bD1S0ncmopIQCGmoU2/AXC2CCi6trONf3EPNKKKfDeQYHadnVZOg6kTX2cnYmHZLviYeLzjCKFSqSNkimoSKQ/Dcutpsq1D82NCwiExUZW4oo=]]></Encrypt>");
|
||||
xmlSb.append("</xml>");
|
||||
String response = push(para, xmlSb.toString());
|
||||
Assert.assertNotNull(response);
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.JsonResult;
|
||||
import com.foxinmy.weixin4j.qy.api.AgentApi;
|
||||
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.type.ReportLocationType;
|
||||
|
||||
/**
|
||||
* 应用API测试
|
||||
*
|
||||
* @className AgentTest
|
||||
* @author jy
|
||||
* @date 2015年03月17日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class AgentTest extends TokenTest {
|
||||
public AgentApi agentApi;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
this.agentApi = new AgentApi(tokenHolder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void get() throws WeixinException {
|
||||
AgentInfo agent = agentApi.getAgent(0);
|
||||
Assert.assertTrue(agent != null);
|
||||
System.err.println(agent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void set() throws WeixinException {
|
||||
AgentSetter agentSet = new AgentSetter(1);
|
||||
agentSet.setDescription("test");
|
||||
agentSet.setRedirectDomain("test.com");
|
||||
agentSet.setReportLocationType(ReportLocationType.DIALOG);
|
||||
JsonResult result = agentApi.setAgent(agentSet);
|
||||
Assert.assertTrue(result.getCode() == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void list() throws WeixinException {
|
||||
List<AgentOverview> list = agentApi.listAgentOverview();
|
||||
System.err.println(list);
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.test;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.qy.api.BatchApi;
|
||||
import com.foxinmy.weixin4j.qy.api.MediaApi;
|
||||
import com.foxinmy.weixin4j.qy.model.BatchResult;
|
||||
import com.foxinmy.weixin4j.qy.model.Callback;
|
||||
import com.foxinmy.weixin4j.qy.model.Party;
|
||||
|
||||
/**
|
||||
* 异步任务测试
|
||||
*
|
||||
* @className BatchTest
|
||||
* @author jy
|
||||
* @date 2015年3月31日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class BatchTest extends TokenTest {
|
||||
public BatchApi batchApi;
|
||||
public MediaApi mediaApi;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
this.batchApi = new BatchApi(tokenHolder);
|
||||
this.mediaApi = new MediaApi(tokenHolder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void syncuser() throws WeixinException {
|
||||
String jobId = batchApi
|
||||
.syncuser(
|
||||
"1QFmZ8LE9dFxPPx8EH5Kfm3cqGXB0OuXY432ZpsfwMFTJjEDt7QI4GZB1UhYGOSYr",
|
||||
new Callback("http://182.254.188.133:8090",
|
||||
"gp2eGT5mIpngr",
|
||||
"BRYfV4zPFUJb3v3MySNBg1ERKE3vyyMRoScu76vFySv"));
|
||||
System.err.println(jobId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void replaceparty() throws WeixinException {
|
||||
String mediaId = mediaApi.batchUploadParties(Arrays.asList(new Party(5,
|
||||
"部门1", 1, 1), new Party(6, "部门2", 1, 1)));
|
||||
String jobId = batchApi.replaceparty(mediaId, new Callback(
|
||||
"http://182.254.188.133:8090", "gp2eGT5mIpngr",
|
||||
"BRYfV4zPFUJb3v3MySNBg1ERKE3vyyMRoScu76vFySv"));
|
||||
System.err.println(jobId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getresult() throws WeixinException {
|
||||
BatchResult result = batchApi
|
||||
.getresult("PVucPBfEapLnvQZ1ru2Vdw3Dbl-jXs3AEQdS24cqmI0");
|
||||
System.err.println(result);
|
||||
}
|
||||
}
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.qy.api.HelperApi;
|
||||
|
||||
/**
|
||||
* 辅助API测试
|
||||
*
|
||||
* @className HelperTest
|
||||
* @author jy
|
||||
* @date 2014年12月28日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class HelperTest extends TokenTest {
|
||||
public HelperApi helperApi;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
this.helperApi = new HelperApi(tokenHolder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void backip() throws WeixinException {
|
||||
List<String> ips = helperApi.getcallbackip();
|
||||
Assert.assertTrue(ips != null && !ips.isEmpty());
|
||||
System.out.println(ips);
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.qy.api.MediaApi;
|
||||
import com.foxinmy.weixin4j.type.MediaType;
|
||||
|
||||
/**
|
||||
* 媒体上传下载测试
|
||||
*
|
||||
* @className MediaTest
|
||||
* @author jy.hu
|
||||
* @date 2014年4月10日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class MediaTest extends TokenTest {
|
||||
|
||||
private MediaApi mediaApi;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
mediaApi = new MediaApi(tokenHolder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upload() throws IOException, WeixinException {
|
||||
File file = new File("/tmp/test.docx");
|
||||
String mediaId = mediaApi.uploadMedia(file, MediaType.file);
|
||||
// 1-1gpykXsR8bhNvO13-ZvskptCBxQF1UE535jFdCF63N2inGRAqEb-psF6eppjIIl
|
||||
// 1CF6sBgWWFGY9s4JCEet5ASszsTuyHpeN1f2LWXADveqBlKoxSgb3cO401NEM7dNY
|
||||
Assert.assertNotNull(mediaId);
|
||||
System.out.println(mediaId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void download() throws WeixinException, IOException {
|
||||
File file = mediaApi
|
||||
.downloadMedia(
|
||||
"1CF6sBgWWFGY9s4JCEet5ASszsTuyHpeN1f2LWXADveqBlKoxSgb3cO401NEM7dNY",
|
||||
"docx");
|
||||
Assert.assertTrue(file.exists());
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.JsonResult;
|
||||
import com.foxinmy.weixin4j.model.Button;
|
||||
import com.foxinmy.weixin4j.qy.api.MenuApi;
|
||||
import com.foxinmy.weixin4j.type.ButtonType;
|
||||
|
||||
/**
|
||||
* 自定义菜单测试
|
||||
*
|
||||
* @className MenuTest
|
||||
* @author jy.hu
|
||||
* @date 2014年4月10日
|
||||
* @since JDK 1.7
|
||||
*/
|
||||
public class MenuTest extends TokenTest {
|
||||
|
||||
private MenuApi menuApi;
|
||||
private List<Button> btnList;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
menuApi = new MenuApi(tokenHolder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void create() throws WeixinException {
|
||||
btnList = new ArrayList<Button>();
|
||||
|
||||
Button b = new Button("click", "name", ButtonType.click);
|
||||
btnList.add(b);
|
||||
|
||||
b = new Button("qq", "http://www.qq.com", ButtonType.view);
|
||||
btnList.add(b);
|
||||
b = new Button("photo", "photo", ButtonType.pic_photo_or_album);
|
||||
btnList.add(b);
|
||||
JsonResult result = menuApi.createMenu(btnList, 1);
|
||||
Assert.assertEquals(0, result.getCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void get() throws WeixinException {
|
||||
btnList = menuApi.getMenu(1);
|
||||
for (Button btn : btnList) {
|
||||
System.out.println(btn);
|
||||
}
|
||||
Assert.assertEquals(2, btnList.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void delete() throws WeixinException {
|
||||
JsonResult result = menuApi.deleteMenu(1);
|
||||
Assert.assertEquals(0, result.getCode());
|
||||
}
|
||||
}
|
||||
-68
@@ -1,68 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.StatusLine;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
|
||||
public class MessagePush {
|
||||
|
||||
private final String server = "http://localhost:8090";
|
||||
private final HttpClient httpClient;
|
||||
private final HttpPost httpPost;
|
||||
private final HttpGet httpGet;
|
||||
|
||||
public MessagePush() {
|
||||
httpClient = new DefaultHttpClient();
|
||||
httpPost = new HttpPost();
|
||||
httpPost.setURI(URI.create(server));
|
||||
|
||||
httpGet = new HttpGet();
|
||||
httpGet.setURI(URI.create(server));
|
||||
}
|
||||
|
||||
public String get(String para) throws WeixinException, IOException {
|
||||
httpGet.setURI(URI.create(server + para));
|
||||
HttpResponse httpResponse = httpClient.execute(httpGet);
|
||||
return entity(httpResponse);
|
||||
}
|
||||
|
||||
public String push(String xml) throws WeixinException, IOException {
|
||||
return push("", xml);
|
||||
}
|
||||
|
||||
public String push(String para, String xml) throws WeixinException,
|
||||
IOException {
|
||||
httpPost.setURI(URI.create(server + para));
|
||||
httpPost.setEntity(new StringEntity(xml, StandardCharsets.UTF_8));
|
||||
HttpResponse httpResponse = httpClient.execute(httpPost);
|
||||
return entity(httpResponse);
|
||||
}
|
||||
|
||||
private String entity(HttpResponse httpResponse) throws WeixinException,
|
||||
IOException {
|
||||
StatusLine statusLine = httpResponse.getStatusLine();
|
||||
|
||||
int status = statusLine.getStatusCode();
|
||||
if (status != HttpStatus.SC_OK) {
|
||||
throw new WeixinException(Integer.toString(status), "request fail");
|
||||
}
|
||||
if (status == HttpStatus.SC_MOVED_PERMANENTLY
|
||||
|| status == HttpStatus.SC_MOVED_TEMPORARILY) {
|
||||
throw new WeixinException(Integer.toString(status), "uri moved");
|
||||
}
|
||||
return EntityUtils.toString(httpResponse.getEntity(),
|
||||
StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
-93
@@ -1,93 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.test;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.msg.model.File;
|
||||
import com.foxinmy.weixin4j.msg.model.Image;
|
||||
import com.foxinmy.weixin4j.msg.model.MpNews;
|
||||
import com.foxinmy.weixin4j.msg.model.News;
|
||||
import com.foxinmy.weixin4j.msg.model.Text;
|
||||
import com.foxinmy.weixin4j.msg.model.Video;
|
||||
import com.foxinmy.weixin4j.msg.model.Voice;
|
||||
import com.foxinmy.weixin4j.qy.api.NotifyApi;
|
||||
import com.foxinmy.weixin4j.qy.message.NotifyMessage;
|
||||
|
||||
/**
|
||||
* 客服消息测试
|
||||
*
|
||||
* @className MessageNotifyTest
|
||||
* @author jy.hu
|
||||
* @date 2014年4月10日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class NotifyMsgTest extends TokenTest {
|
||||
|
||||
private NotifyApi notifyApi;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
notifyApi = new NotifyApi(tokenHolder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void text() throws WeixinException {
|
||||
NotifyMessage notify = new NotifyMessage(new Text("content"), 0);
|
||||
System.out.println(notifyApi.sendNotify(notify));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void image() throws WeixinException {
|
||||
NotifyMessage notify = new NotifyMessage(new Image("123"), 0);
|
||||
System.out.println(notifyApi.sendNotify(notify));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void voice() throws WeixinException {
|
||||
NotifyMessage notify = new NotifyMessage(new Voice("123"), 0);
|
||||
System.out.println(notifyApi.sendNotify(notify));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void video() throws WeixinException {
|
||||
NotifyMessage notify = new NotifyMessage(new Video("123"), 0);
|
||||
System.out.println(notifyApi.sendNotify(notify));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void file() throws WeixinException {
|
||||
File file = new File("file");
|
||||
NotifyMessage notify = new NotifyMessage(file, 0);
|
||||
System.out.println(notifyApi.sendNotify(notify));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void news() throws WeixinException {
|
||||
News news = new News();
|
||||
NotifyMessage notify = new NotifyMessage(news, 0);
|
||||
news.pushArticle("title1", "desc1", "picUrl1", "url1");
|
||||
news.pushArticle("title2", "desc2", "picUrl2", "url2");
|
||||
System.out.println(notifyApi.sendNotify(notify));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mpnews() throws WeixinException {
|
||||
MpNews news = new MpNews();
|
||||
NotifyMessage notify = new NotifyMessage(news, 0);
|
||||
news.pushArticle("thumbMediaId1", "title1", "content1");
|
||||
news.pushArticle("thumbMediaId2", "title1", "content2");
|
||||
System.out.println(notifyApi.sendNotify(notify));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void send1() throws WeixinException {
|
||||
Text text = new Text("this is a text");
|
||||
JSONObject result = notifyApi.sendNotify(new NotifyMessage(text, 1));
|
||||
Assert.assertEquals(0, result.getIntValue("errcode"));
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.JsonResult;
|
||||
import com.foxinmy.weixin4j.qy.api.PartyApi;
|
||||
import com.foxinmy.weixin4j.qy.model.Party;
|
||||
|
||||
/**
|
||||
* 部门API测试
|
||||
*
|
||||
* @className PartyTest
|
||||
* @author jy
|
||||
* @date 2014年11月18日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class PartyTest extends TokenTest {
|
||||
public PartyApi partyApi;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
this.partyApi = new PartyApi(tokenHolder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void create() throws WeixinException {
|
||||
Party Party = new Party("苦逼组");
|
||||
int id = partyApi.createParty(Party);
|
||||
Assert.assertTrue(id > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void update() throws WeixinException {
|
||||
Party Party = new Party("苦逼组111");
|
||||
Party.setId(2);
|
||||
JsonResult result = partyApi.updateParty(Party);
|
||||
Assert.assertEquals("updated", result.getDesc());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void list() throws WeixinException {
|
||||
List<Party> list = partyApi.listParty(1);
|
||||
Assert.assertFalse(list.isEmpty());
|
||||
System.out.println(list);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void delete() throws WeixinException {
|
||||
JsonResult result = partyApi.deleteParty(2);
|
||||
Assert.assertEquals("deleted", result.getDesc());
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.JsonResult;
|
||||
import com.foxinmy.weixin4j.qy.api.TagApi;
|
||||
import com.foxinmy.weixin4j.qy.model.Tag;
|
||||
import com.foxinmy.weixin4j.qy.model.User;
|
||||
|
||||
/**
|
||||
* 标签API测试
|
||||
*
|
||||
* @className TagTest
|
||||
* @author jy
|
||||
* @date 2014年11月18日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class TagTest extends TokenTest {
|
||||
public TagApi tagApi;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
this.tagApi = new TagApi(tokenHolder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void create() throws WeixinException {
|
||||
int tagId = tagApi.createTag("coder");
|
||||
Assert.assertTrue(tagId > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void update() throws WeixinException {
|
||||
JsonResult result = tagApi.updateTag(new Tag(1, "coder456"));
|
||||
Assert.assertEquals("updated", result.getDesc());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUsers() throws WeixinException {
|
||||
List<User> listUser = tagApi.getTagUsers(1);
|
||||
Assert.assertFalse(listUser.isEmpty());
|
||||
System.out.println(listUser);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addUsers() throws WeixinException {
|
||||
JsonResult result = tagApi.addTagUsers(1, Arrays.asList("jinyu"));
|
||||
Assert.assertEquals("ok", result.getDesc());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteUsers() throws WeixinException {
|
||||
JsonResult result = tagApi.deleteTagUsers(1, Arrays.asList("jinyu"));
|
||||
Assert.assertEquals("ok", result.getDesc());
|
||||
System.out.println(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void list() throws WeixinException {
|
||||
List<Tag> tags = tagApi.listTag();
|
||||
Assert.assertFalse(tags.isEmpty());
|
||||
System.out.println(tags);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void delete() throws WeixinException {
|
||||
JsonResult result = tagApi.deleteTag(3);
|
||||
Assert.assertEquals("deleted", result.getDesc());
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.test;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.qy.token.WeixinTokenCreator;
|
||||
import com.foxinmy.weixin4j.token.FileTokenHolder;
|
||||
import com.foxinmy.weixin4j.token.TokenHolder;
|
||||
|
||||
/**
|
||||
* token测试
|
||||
*
|
||||
* @className TokenTest
|
||||
* @author jy.hu
|
||||
* @date 2014年4月10日
|
||||
* @since JDK 1.7
|
||||
*/
|
||||
public class TokenTest {
|
||||
|
||||
protected TokenHolder tokenHolder;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
tokenHolder = new FileTokenHolder(
|
||||
new WeixinTokenCreator());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws WeixinException {
|
||||
Assert.assertNotNull(tokenHolder.getToken());
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.JsonResult;
|
||||
import com.foxinmy.weixin4j.qy.api.MediaApi;
|
||||
import com.foxinmy.weixin4j.qy.api.UserApi;
|
||||
import com.foxinmy.weixin4j.qy.model.User;
|
||||
import com.foxinmy.weixin4j.qy.type.UserStatus;
|
||||
|
||||
/**
|
||||
* 用户API测试
|
||||
*
|
||||
* @className UserTest
|
||||
* @author jy
|
||||
* @date 2014年11月18日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class UserTest extends TokenTest {
|
||||
public UserApi userApi;
|
||||
public MediaApi mediaApi;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
this.userApi = new UserApi(tokenHolder);
|
||||
this.mediaApi = new MediaApi(tokenHolder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void create() throws WeixinException {
|
||||
User user = new User("u001", "jack");
|
||||
user.setMobile("13500000000");
|
||||
user.setDepartment(1);
|
||||
user.pushExattr("爱好", "code");
|
||||
JsonResult result = userApi.createUser(user);
|
||||
Assert.assertEquals("created", result.getDesc());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void batchUpload() throws WeixinException {
|
||||
User user = new User("u001", "jack");
|
||||
user.setMobile("13500000000");
|
||||
user.setDepartment(1);
|
||||
String mediaId = mediaApi.batchUploadUsers(Arrays.asList(user));
|
||||
System.err.println(mediaId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void update() throws WeixinException {
|
||||
User user = new User("u001", "ted");
|
||||
user.setMobile("13500000000");
|
||||
user.setDepartment(1);
|
||||
user.pushExattr("爱好", "code");
|
||||
JsonResult result = userApi.updateUser(user);
|
||||
Assert.assertEquals("updated", result.getDesc());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void get() throws WeixinException {
|
||||
User user = userApi.getUser("u001");
|
||||
Assert.assertTrue(user != null);
|
||||
System.out.println(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void list() throws WeixinException {
|
||||
List<User> userList = userApi.listUser(1, true, UserStatus.BOTH, true);
|
||||
Assert.assertFalse(userList.isEmpty());
|
||||
System.out.println(userList);
|
||||
userList = userApi.listUser(1);
|
||||
Assert.assertFalse(userList.isEmpty());
|
||||
System.out.println(userList);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void delete() throws WeixinException {
|
||||
JsonResult result = userApi.deleteUser("u001");
|
||||
Assert.assertEquals("deleted", result.getDesc());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invite() throws WeixinException {
|
||||
userApi.inviteUser("11", null);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
||||
*~
|
||||
|
||||
# eclipse ignore
|
||||
*.settings/*
|
||||
/.project
|
||||
/.classpath
|
||||
/.tomcatplugin
|
||||
|
||||
# idea ignore
|
||||
/.idea
|
||||
*.iml
|
||||
|
||||
# maven ignore
|
||||
target/*
|
||||
|
||||
# other ignore
|
||||
*.log
|
||||
*.tmp
|
||||
Thumbs.db
|
||||
/target/
|
||||
.DS_Store
|
||||
@@ -1,78 +0,0 @@
|
||||
weixin4j-qy-server
|
||||
==================
|
||||
|
||||
微信企业号netty服务
|
||||
------------
|
||||
|
||||
功能列表
|
||||
-------
|
||||
|
||||
* `netty构建服务器`
|
||||
|
||||
* `消息分发`
|
||||
|
||||
如何使用
|
||||
--------
|
||||
1.正确填写`weixin.properties`中的属性值
|
||||
|
||||
| 属性名 | 说明 |
|
||||
| :---------- | :-------------- |
|
||||
| account | 微信企业号信息 `json格式` |
|
||||
| token_path | 使用FileTokenHolder时token保存的物理路径 |
|
||||
| media_path | 调用媒体接口时保存媒体文件的物理路径 |
|
||||
|
||||
示例(properties中换行用右斜杆\\)
|
||||
|
||||
account={"id":"corpid","secret":"corpsecret",\
|
||||
"token":"企业号中应用在回调模式下的token",\
|
||||
"encodingAesKey":"企业号中应用在回调模式下AES加密密钥"}
|
||||
|
||||
token_path=/tmp/weixin/token
|
||||
media_path=/tmp/weixin/media
|
||||
|
||||
2.在对应的action中实现自己的具体业务 如 TextAction 则表示收到文本消息
|
||||
|
||||
@Override
|
||||
public ResponseMessage execute(TextMessage inMessage) {
|
||||
return new ResponseMessage(new Text("Hello World!"), inMessage);
|
||||
}
|
||||
|
||||
3.`mvn package`,得到一个zip的压缩包,解压(也可使用deploy.xml部署到远程服务器)到`启动目录`
|
||||
|
||||
4.启动netty服务(`com.foxinmy.weixin4j.mp.startup.WeixinQyServerBootstrap`)
|
||||
|
||||
sh startup.sh start
|
||||
|
||||
> 1.服务的启动脚本[startup.sh](./src/main/startup.sh)需要被注意到,有`JAVA_HOME`和`APP_HOME`两个参数.
|
||||
|
||||
> 2.其中`JAVA_HOME`参数值指的是java运行环境(jre|jdk)的安装根目录,如果与脚本中的值不一致,可以改更为实际的路径或者使用`ln -s /usr/local/java target`软链接命令创建期望的链接.
|
||||
|
||||
> 3.其中`APP_HOME`参数值指的是本服务的启动目录,此目录需要被正确事先创建好,同时[`deploy.xml`](./deploy.xml)远程部署命令也依赖于此.
|
||||
|
||||
> 4.Ant远程部署[`deploy.xml`](./deploy.xml)的正确执行需要[`jsch`](http://www.jcraft.com/jsch/)包的支持,下载jar包将其引入执行Ant命令时的`classpath`中.
|
||||
|
||||
> 5.一般来说*Action事件处理类中应该有自己的实际业务类(`service`)需要被注入,可以使用org.springframework.context.ApplicationContext#getBeansWithAnnotation(ActionAnnotation.class)函数获取Action集合后再来实现[`AbstractActionMapping`](https://github.com/foxinmy/weixin4j/blob/master/weixin4j-base/src/main/java/com/foxinmy/weixin4j/action/mapping/AbstractActionMapping.java).
|
||||
|
||||
更新LOG
|
||||
-------
|
||||
* 2014-11-19
|
||||
|
||||
+ 得到`weixin4j-qy-server`工程
|
||||
|
||||
* 2014-11-24
|
||||
|
||||
+ 新增netty服务与消息分发
|
||||
|
||||
* 2014-12-28
|
||||
|
||||
+ 增加用户进入应用的callback事件
|
||||
|
||||
+ 调整回调模式下的首次验证的签名方式
|
||||
|
||||
* 2015-03-25
|
||||
|
||||
+ 新增deploy.xml远程部署ant脚本
|
||||
|
||||
* 2015-04-01
|
||||
|
||||
+ 新增批量任务执行完成事件
|
||||
@@ -1,54 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="qy-server" default="deploy" basedir=".">
|
||||
<property name="app.home" value="." />
|
||||
<property name="target.home" value="${app.home}/target" />
|
||||
<property name="zip.name" value="weixin-qy-server-bin.zip" />
|
||||
<property name="host" value="服务器IP" />
|
||||
<property name="pwd" value="服务器口令" />
|
||||
<property name="main.dir" value="服务部署的主目录,如/usr/local/weixin" />
|
||||
<property name="sub.dir" value="服务部署的子目录,如weixin-qy-server" />
|
||||
|
||||
<target name="removeZip">
|
||||
<echo>
|
||||
${host}:删除[${zip.name}]...
|
||||
</echo>
|
||||
<sshexec host="${host}" username="root" password="${pwd}" trust="true" command="cd ${main.dir};pwd;rm -rf ${main.dir}/${zip.name};" />
|
||||
</target>
|
||||
|
||||
<target name="uploadZip" depends="removeZip">
|
||||
<echo>
|
||||
${host}:上传[${zip.name}]...
|
||||
</echo>
|
||||
<scp file="${target.home}/${zip.name}" todir="root:${pwd}@${host}:${main.dir}" trust="true" />
|
||||
</target>
|
||||
|
||||
<target name="shutdownService" depends="uploadZip">
|
||||
<echo>
|
||||
${host}:停止[${sub.dir}]...
|
||||
</echo>
|
||||
<sshexec host="${host}" username="root" password="${pwd}" trust="true" command="cd ${main.dir}/${sub.dir};pwd;sh startup.sh stop;rm -rf ${main.dir}/${sub.dir};" />
|
||||
</target>
|
||||
|
||||
<target name="unzipProject" depends="shutdownService">
|
||||
<echo>
|
||||
${host}:解压${zip.name}...
|
||||
</echo>
|
||||
<sshexec host="${host}" username="root" password="${pwd}" trust="true" command="cd ${main.dir};pwd;unzip ${zip.name};" />
|
||||
</target>
|
||||
|
||||
<target name="startupService" depends="unzipProject">
|
||||
<echo>
|
||||
${host}:启动服务...
|
||||
</echo>
|
||||
<sshexec host="${host}" username="root" password="${pwd}" trust="true" command="cd ${main.dir}/${sub.dir};pwd;sh startup.sh start;" />
|
||||
</target>
|
||||
|
||||
<target name="build" depends="startupService">
|
||||
<echo>
|
||||
target.home = ${target.home}
|
||||
file.zip = ${target.home}/${zip.name}
|
||||
</echo>
|
||||
</target>
|
||||
<target name="deploy" depends="build">
|
||||
</target>
|
||||
</project>
|
||||
@@ -1,81 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.foxinmy</groupId>
|
||||
<artifactId>weixin4j-qy</artifactId>
|
||||
<version>1.3</version>
|
||||
</parent>
|
||||
<artifactId>weixin4j-qy-server</artifactId>
|
||||
<name>weixin4j-qy-server</name>
|
||||
<url>https://github.com/foxinmy/weixin4j/tree/master/weixin4j-qy/weixin4j-qy-server</url>
|
||||
<description>微信企业号netty服务</description>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<configuration>
|
||||
<finalName>weixin-qy-server</finalName>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.foxinmy</groupId>
|
||||
<artifactId>weixin4j-qy-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-core</artifactId>
|
||||
<version>${logback.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>${logback.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>logback-core</artifactId>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<version>${jcl.over.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>log4j-over-slf4j</artifactId>
|
||||
<version>${log4j.over.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -1,36 +0,0 @@
|
||||
<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>bin</id>
|
||||
<formats>
|
||||
<format>zip</format>
|
||||
</formats>
|
||||
<includeBaseDirectory>true</includeBaseDirectory>
|
||||
<dependencySets>
|
||||
<dependencySet>
|
||||
<useProjectArtifact>true</useProjectArtifact>
|
||||
<outputDirectory>/lib</outputDirectory>
|
||||
</dependencySet>
|
||||
</dependencySets>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<directory>com/foxinmy/weixin4j/qy</directory>
|
||||
<includes>
|
||||
<include>**/*.md</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>src/main</directory>
|
||||
<outputDirectory>/</outputDirectory>
|
||||
<includes>
|
||||
<include>*.sh</include>
|
||||
<include>*.bat</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>src/main/resources</directory>
|
||||
<outputDirectory>/conf</outputDirectory>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
</assembly>
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.action;
|
||||
|
||||
import com.foxinmy.weixin4j.action.DebugAction;
|
||||
import com.foxinmy.weixin4j.action.mapping.ActionAnnotation;
|
||||
import com.foxinmy.weixin4j.msg.ImageMessage;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
|
||||
/**
|
||||
* 图片消息处理
|
||||
*
|
||||
* @className ImageAction
|
||||
* @author jy
|
||||
* @date 2014年10月9日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.msg.ImageMessage
|
||||
*/
|
||||
@ActionAnnotation(msgType = MessageType.image)
|
||||
public class ImageAction extends DebugAction<ImageMessage> {
|
||||
|
||||
}
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.action;
|
||||
|
||||
import com.foxinmy.weixin4j.action.DebugAction;
|
||||
import com.foxinmy.weixin4j.action.mapping.ActionAnnotation;
|
||||
import com.foxinmy.weixin4j.msg.LinkMessage;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
|
||||
/**
|
||||
* 链接消息处理
|
||||
*
|
||||
* @className LinkAction
|
||||
* @author jy
|
||||
* @date 2014年10月9日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.msg.LinkMessage
|
||||
*/
|
||||
@ActionAnnotation(msgType = MessageType.link)
|
||||
public class LinkAction extends DebugAction<LinkMessage> {
|
||||
|
||||
}
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.action;
|
||||
|
||||
import com.foxinmy.weixin4j.action.DebugAction;
|
||||
import com.foxinmy.weixin4j.action.mapping.ActionAnnotation;
|
||||
import com.foxinmy.weixin4j.msg.LocationMessage;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
|
||||
/**
|
||||
* 地理位置处理
|
||||
*
|
||||
* @className LocationAction
|
||||
* @author jy
|
||||
* @date 2014年10月9日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.msg.LocationMessage
|
||||
*/
|
||||
@ActionAnnotation(msgType = MessageType.location)
|
||||
public class LocationAction extends DebugAction<LocationMessage> {
|
||||
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
普通消息对应的Action
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.action;
|
||||
|
||||
import com.foxinmy.weixin4j.action.AbstractAction;
|
||||
import com.foxinmy.weixin4j.action.mapping.ActionAnnotation;
|
||||
import com.foxinmy.weixin4j.msg.TextMessage;
|
||||
import com.foxinmy.weixin4j.msg.model.Text;
|
||||
import com.foxinmy.weixin4j.response.ResponseMessage;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
|
||||
/**
|
||||
* 文字消息处理
|
||||
*
|
||||
* @className TextAction
|
||||
* @author jy
|
||||
* @date 2014年10月9日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.msg.TextMessage
|
||||
*/
|
||||
@ActionAnnotation(msgType = MessageType.text)
|
||||
public class TextAction extends AbstractAction<TextMessage> {
|
||||
|
||||
@Override
|
||||
public ResponseMessage execute(TextMessage inMessage) {
|
||||
return new ResponseMessage(new Text("Hello World!"), inMessage);
|
||||
}
|
||||
}
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.action;
|
||||
|
||||
import com.foxinmy.weixin4j.action.DebugAction;
|
||||
import com.foxinmy.weixin4j.action.mapping.ActionAnnotation;
|
||||
import com.foxinmy.weixin4j.msg.VideoMessage;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
|
||||
/**
|
||||
* 视频消息处理
|
||||
*
|
||||
* @className VideoAction
|
||||
* @author jy
|
||||
* @date 2014年10月9日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.msg.VideoMessage
|
||||
*/
|
||||
@ActionAnnotation(msgType = MessageType.video)
|
||||
public class VideoAction extends DebugAction<VideoMessage> {
|
||||
|
||||
}
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.action;
|
||||
|
||||
import com.foxinmy.weixin4j.action.DebugAction;
|
||||
import com.foxinmy.weixin4j.action.mapping.ActionAnnotation;
|
||||
import com.foxinmy.weixin4j.msg.VoiceMessage;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
|
||||
/**
|
||||
* 语音消息处理
|
||||
*
|
||||
* @className VoiceAction
|
||||
* @author jy
|
||||
* @date 2014年10月9日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.msg.VoiceMessage
|
||||
*/
|
||||
@ActionAnnotation(msgType = MessageType.voice)
|
||||
public class VoiceAction extends DebugAction<VoiceMessage> {
|
||||
|
||||
}
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.action.event;
|
||||
|
||||
import com.foxinmy.weixin4j.action.DebugAction;
|
||||
import com.foxinmy.weixin4j.action.mapping.ActionAnnotation;
|
||||
import com.foxinmy.weixin4j.msg.event.BatchjobresultMessage;
|
||||
import com.foxinmy.weixin4j.type.EventType;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
|
||||
/**
|
||||
* 异步任务完成事件
|
||||
*
|
||||
* @className BatchJobAction
|
||||
* @author jy
|
||||
* @date 2015年3月31日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.msg.event.BatchjobresultMessage
|
||||
*/
|
||||
@ActionAnnotation(msgType = MessageType.event, eventType = { EventType.batch_job_result })
|
||||
public class BatchJobAction extends DebugAction<BatchjobresultMessage> {
|
||||
|
||||
}
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.action.event;
|
||||
|
||||
import com.foxinmy.weixin4j.action.DebugAction;
|
||||
import com.foxinmy.weixin4j.action.mapping.ActionAnnotation;
|
||||
import com.foxinmy.weixin4j.msg.event.EnterAgentEventMessage;
|
||||
import com.foxinmy.weixin4j.type.EventType;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
|
||||
/**
|
||||
* 用户进入应用的事件推送
|
||||
*
|
||||
* @className EnterAgentAction
|
||||
* @author jy
|
||||
* @date 2014年12月28日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.msg.event.EnterAgentEventMessage
|
||||
* @see<a href=
|
||||
* "http://qydev.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E4%BA%8B%E4%BB%B6#.E7.94.A8.E6.88.B7.E8.BF.9B.E5.85.A5.E5.BA.94.E7.94.A8.E7.9A.84.E4.BA.8B.E4.BB.B6.E6.8E.A8.E9.80.81"
|
||||
* >用户进入应用的事件推送</a>
|
||||
*/
|
||||
@ActionAnnotation(msgType = MessageType.event, eventType = { EventType.enter_agent })
|
||||
public class EnterAgentAction extends DebugAction<EnterAgentEventMessage> {
|
||||
|
||||
}
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.action.event;
|
||||
|
||||
import com.foxinmy.weixin4j.action.DebugAction;
|
||||
import com.foxinmy.weixin4j.action.mapping.ActionAnnotation;
|
||||
import com.foxinmy.weixin4j.msg.event.LocationEventMessage;
|
||||
import com.foxinmy.weixin4j.type.EventType;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
|
||||
/**
|
||||
* 上报地理位置后触发
|
||||
*
|
||||
* @className LocationAction
|
||||
* @author jy
|
||||
* @date 2014年10月9日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.msg.event.LocationEventMessage
|
||||
*/
|
||||
@ActionAnnotation(msgType = MessageType.event, eventType = { EventType.location })
|
||||
public class LocationAction extends DebugAction<LocationEventMessage> {
|
||||
|
||||
}
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.action.event;
|
||||
|
||||
import com.foxinmy.weixin4j.action.DebugAction;
|
||||
import com.foxinmy.weixin4j.action.mapping.ActionAnnotation;
|
||||
import com.foxinmy.weixin4j.msg.event.MassEventMessage;
|
||||
import com.foxinmy.weixin4j.type.EventType;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
|
||||
/**
|
||||
* 群发消息发送动作完成后触发
|
||||
*
|
||||
* @className MassSendAction
|
||||
* @author jy
|
||||
* @date 2014年10月9日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.msg.event.MassEventMessage
|
||||
*/
|
||||
@ActionAnnotation(msgType = MessageType.event, eventType = { EventType.masssendjobfinish })
|
||||
public class MassSendAction extends DebugAction<MassEventMessage> {
|
||||
|
||||
}
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.action.event;
|
||||
|
||||
import com.foxinmy.weixin4j.action.DebugAction;
|
||||
import com.foxinmy.weixin4j.action.mapping.ActionAnnotation;
|
||||
import com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage;
|
||||
import com.foxinmy.weixin4j.type.EventType;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
|
||||
/**
|
||||
* click类型菜单点击时触发
|
||||
*
|
||||
* @className MenuClickAction
|
||||
* @author jy
|
||||
* @date 2014年10月9日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage
|
||||
*/
|
||||
@ActionAnnotation(msgType = MessageType.event, eventType = { EventType.click })
|
||||
public class MenuClickAction extends DebugAction<MenuEventMessage> {
|
||||
|
||||
}
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.action.event;
|
||||
|
||||
import com.foxinmy.weixin4j.action.DebugAction;
|
||||
import com.foxinmy.weixin4j.action.mapping.ActionAnnotation;
|
||||
import com.foxinmy.weixin4j.msg.event.menu.MenuLocationEventMessage;
|
||||
import com.foxinmy.weixin4j.type.EventType;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
|
||||
/**
|
||||
* 点击菜单发送地理位置时触发
|
||||
*
|
||||
* @className MenuLocationAction
|
||||
* @author jy
|
||||
* @date 2014年10月9日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.msg.event.menu.MenuLocationEventMessage
|
||||
*/
|
||||
@ActionAnnotation(msgType = MessageType.event, eventType = { EventType.location_select })
|
||||
public class MenuLocationAction extends DebugAction<MenuLocationEventMessage> {
|
||||
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.action.event;
|
||||
|
||||
import com.foxinmy.weixin4j.action.DebugAction;
|
||||
import com.foxinmy.weixin4j.action.mapping.ActionAnnotation;
|
||||
import com.foxinmy.weixin4j.msg.event.menu.MenuPhotoEventMessage;
|
||||
import com.foxinmy.weixin4j.type.EventType;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
|
||||
/**
|
||||
* 点击菜单发送图片时触发
|
||||
*
|
||||
* @className MenuPhotoAction
|
||||
* @author jy
|
||||
* @date 2014年10月9日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.msg.event.menu.MenuPhotoEventMessage
|
||||
*/
|
||||
@ActionAnnotation(msgType = MessageType.event, eventType = {
|
||||
EventType.pic_photo_or_album, EventType.pic_sysphoto,
|
||||
EventType.pic_weixin })
|
||||
public class MenuPhotoAction extends DebugAction<MenuPhotoEventMessage> {
|
||||
|
||||
}
|
||||
-22
@@ -1,22 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.action.event;
|
||||
|
||||
import com.foxinmy.weixin4j.action.DebugAction;
|
||||
import com.foxinmy.weixin4j.action.mapping.ActionAnnotation;
|
||||
import com.foxinmy.weixin4j.msg.event.menu.MenuScanEventMessage;
|
||||
import com.foxinmy.weixin4j.type.EventType;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
|
||||
/**
|
||||
* 点击菜单扫描时触发
|
||||
*
|
||||
* @className MenuScanAction
|
||||
* @author jy
|
||||
* @date 2014年10月9日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.msg.event.menu.MenuScanEventMessage
|
||||
*/
|
||||
@ActionAnnotation(msgType = MessageType.event, eventType = { EventType.scancode_push,
|
||||
EventType.scancode_waitmsg })
|
||||
public class MenuScanAction extends DebugAction<MenuScanEventMessage> {
|
||||
|
||||
}
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.action.event;
|
||||
|
||||
import com.foxinmy.weixin4j.action.DebugAction;
|
||||
import com.foxinmy.weixin4j.action.mapping.ActionAnnotation;
|
||||
import com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage;
|
||||
import com.foxinmy.weixin4j.type.EventType;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
|
||||
/**
|
||||
* view类型菜单点击时触发
|
||||
*
|
||||
* @className MenuViewAction
|
||||
* @author jy
|
||||
* @date 2014年10月9日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage
|
||||
*/
|
||||
@ActionAnnotation(msgType = MessageType.event, eventType = { EventType.view })
|
||||
public class MenuViewAction extends DebugAction<MenuEventMessage> {
|
||||
|
||||
}
|
||||
-1
@@ -1 +0,0 @@
|
||||
事件消息对应的Action
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.action.event;
|
||||
|
||||
import com.foxinmy.weixin4j.action.DebugAction;
|
||||
import com.foxinmy.weixin4j.action.mapping.ActionAnnotation;
|
||||
import com.foxinmy.weixin4j.msg.event.ScanEventMessage;
|
||||
import com.foxinmy.weixin4j.type.EventType;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
|
||||
/**
|
||||
* 扫描事件时触发
|
||||
*
|
||||
* @className ScanAction
|
||||
* @author jy
|
||||
* @date 2014年10月9日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.msg.event.ScanEventMessage
|
||||
*/
|
||||
@ActionAnnotation(msgType = MessageType.event, eventType = { EventType.scan })
|
||||
public class ScanAction extends DebugAction<ScanEventMessage> {
|
||||
|
||||
}
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.action.event;
|
||||
|
||||
import com.foxinmy.weixin4j.action.DebugAction;
|
||||
import com.foxinmy.weixin4j.action.mapping.ActionAnnotation;
|
||||
import com.foxinmy.weixin4j.msg.event.ScribeEventMessage;
|
||||
import com.foxinmy.weixin4j.type.EventType;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
|
||||
/**
|
||||
* 关注时触发
|
||||
*
|
||||
* @className SubscribeAction
|
||||
* @author jy
|
||||
* @date 2014年10月9日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.msg.event.ScribeEventMessage
|
||||
*/
|
||||
@ActionAnnotation(msgType = MessageType.event, eventType = { EventType.subscribe })
|
||||
public class SubscribeAction extends DebugAction<ScribeEventMessage> {
|
||||
|
||||
}
|
||||
-22
@@ -1,22 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.action.event;
|
||||
|
||||
import com.foxinmy.weixin4j.action.DebugAction;
|
||||
import com.foxinmy.weixin4j.action.mapping.ActionAnnotation;
|
||||
import com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage;
|
||||
import com.foxinmy.weixin4j.type.EventType;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
|
||||
/**
|
||||
* 模板消息发送动作完成时触发
|
||||
*
|
||||
* @className TemplateSendAction
|
||||
* @author jy
|
||||
* @date 2014年10月10日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage
|
||||
*/
|
||||
@ActionAnnotation(msgType = MessageType.event, eventType = { EventType.templatesendjobfinish })
|
||||
public class TemplateSendAction extends
|
||||
DebugAction<TemplatesendjobfinishMessage> {
|
||||
|
||||
}
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.action.event;
|
||||
|
||||
import com.foxinmy.weixin4j.action.DebugAction;
|
||||
import com.foxinmy.weixin4j.action.mapping.ActionAnnotation;
|
||||
import com.foxinmy.weixin4j.msg.event.ScribeEventMessage;
|
||||
import com.foxinmy.weixin4j.type.EventType;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
|
||||
/**
|
||||
* 取消关注时触发
|
||||
*
|
||||
* @className UnsubscribeAction
|
||||
* @author jy
|
||||
* @date 2014年10月10日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.msg.event.ScribeEventMessage
|
||||
*/
|
||||
@ActionAnnotation(msgType = MessageType.event, eventType = { EventType.unsubscribe })
|
||||
public class UnsubscribeAction extends DebugAction<ScribeEventMessage> {
|
||||
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
WeixinMessageDecoder:对微信消息进行解码
|
||||
|
||||
WeixinMessageEncoder:对微信消息进行编码
|
||||
|
||||
WeixinServerHandler:微信请求处理类
|
||||
-83
@@ -1,83 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.server;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||
import io.netty.handler.codec.http.FullHttpRequest;
|
||||
import io.netty.handler.codec.http.HttpMethod;
|
||||
import io.netty.handler.codec.http.QueryStringDecoder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.Consts;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.foxinmy.weixin4j.model.WeixinQyAccount;
|
||||
import com.foxinmy.weixin4j.response.HttpWeixinMessage;
|
||||
import com.foxinmy.weixin4j.type.EncryptType;
|
||||
import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||
import com.foxinmy.weixin4j.util.MessageUtil;
|
||||
import com.foxinmy.weixin4j.xml.XmlStream;
|
||||
|
||||
/**
|
||||
* 微信消息解码类
|
||||
*
|
||||
* @className WeixinMessageDecoder
|
||||
* @author jy
|
||||
* @date 2014年11月13日
|
||||
* @since JDK 1.7
|
||||
* @see <a
|
||||
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%9B%9E%E8%B0%83%E6%A8%A1%E5%BC%8F">回调模式</a>
|
||||
*/
|
||||
public class WeixinMessageDecoder extends
|
||||
MessageToMessageDecoder<FullHttpRequest> {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, FullHttpRequest req,
|
||||
List<Object> out) throws Exception {
|
||||
WeixinQyAccount qyAccount = ConfigUtil.getWeixinQyAccount();
|
||||
String content = req.content().toString(Consts.UTF_8);
|
||||
HttpWeixinMessage message = new HttpWeixinMessage();
|
||||
message.setOriginalContent(content);
|
||||
if (StringUtils.isNotBlank(content)) {
|
||||
message = XmlStream.get(content, HttpWeixinMessage.class);
|
||||
message.setOriginalContent(MessageUtil.aesDecrypt(
|
||||
qyAccount.getId(), qyAccount.getEncodingAesKey(),
|
||||
message.getEncryptContent()));
|
||||
}
|
||||
message.setMethod(req.getMethod().name());
|
||||
QueryStringDecoder queryDecoder = new QueryStringDecoder(req.getUri(),
|
||||
true);
|
||||
log.info("\n=================receive request=================");
|
||||
log.info("{}", req.getMethod());
|
||||
log.info("{}", req.getUri());
|
||||
log.info("{}", content);
|
||||
Map<String, List<String>> parameters = queryDecoder.parameters();
|
||||
String msgSignature = parameters.containsKey("msg_signature") ? parameters
|
||||
.get("msg_signature").get(0) : "";
|
||||
message.setSignature(msgSignature);
|
||||
String echoStr = parameters.containsKey("echostr") ? parameters.get(
|
||||
"echostr").get(0) : "";
|
||||
message.setEchoStr(echoStr);
|
||||
String timeStamp = parameters.containsKey("timestamp") ? parameters
|
||||
.get("timestamp").get(0) : "";
|
||||
message.setTimeStamp(timeStamp);
|
||||
String nonce = parameters.containsKey("nonce") ? parameters
|
||||
.get("nonce").get(0) : "";
|
||||
message.setNonce(nonce);
|
||||
|
||||
message.setToken(qyAccount.getToken());
|
||||
message.setEncryptType(EncryptType.AES);
|
||||
|
||||
// 解密 echostr 20141228 added
|
||||
if (message.getMethod().equals(HttpMethod.GET.name())
|
||||
&& StringUtils.isNotBlank(echoStr)) {
|
||||
message.setOriginalContent(MessageUtil.aesDecrypt(
|
||||
qyAccount.getId(), qyAccount.getEncodingAesKey(), echoStr));
|
||||
}
|
||||
out.add(message);
|
||||
}
|
||||
}
|
||||
-69
@@ -1,69 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.server;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToMessageEncoder;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.foxinmy.weixin4j.model.WeixinQyAccount;
|
||||
import com.foxinmy.weixin4j.qy.util.HttpUtil;
|
||||
import com.foxinmy.weixin4j.response.ResponseMessage;
|
||||
import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||
import com.foxinmy.weixin4j.util.DateUtil;
|
||||
import com.foxinmy.weixin4j.util.MessageUtil;
|
||||
import com.foxinmy.weixin4j.util.RandomUtil;
|
||||
import com.foxinmy.weixin4j.xml.Map2ObjectConverter;
|
||||
import com.foxinmy.weixin4j.xml.XmlStream;
|
||||
import com.thoughtworks.xstream.core.ClassLoaderReference;
|
||||
import com.thoughtworks.xstream.mapper.DefaultMapper;
|
||||
|
||||
/**
|
||||
* 微信消息编码类
|
||||
*
|
||||
* @className WeixinMessageEncoder
|
||||
* @author jy
|
||||
* @date 2014年11月13日
|
||||
* @since JDK 1.7
|
||||
* @see <a
|
||||
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%8A%A0%E8%A7%A3%E5%AF%86%E6%96%B9%E6%A1%88%E7%9A%84%E8%AF%A6%E7%BB%86%E8%AF%B4%E6%98%8E">加密接入指引</a>
|
||||
*/
|
||||
public class WeixinMessageEncoder extends
|
||||
MessageToMessageEncoder<ResponseMessage> {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
private final static XmlStream mapXstream = XmlStream.get();
|
||||
static {
|
||||
mapXstream.alias("xml", Map.class);
|
||||
mapXstream.registerConverter(new Map2ObjectConverter(new DefaultMapper(
|
||||
new ClassLoaderReference(XmlStream.class.getClassLoader()))));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, ResponseMessage response,
|
||||
List<Object> out) throws Exception {
|
||||
WeixinQyAccount qyAccount = ConfigUtil.getWeixinQyAccount();
|
||||
String xmlContent = response.toXml();
|
||||
String nonce = RandomUtil.generateString(32);
|
||||
String timestamp = DateUtil.timestamp2string();
|
||||
String encrtypt = MessageUtil.aesEncrypt(qyAccount.getId(),
|
||||
qyAccount.getEncodingAesKey(), xmlContent);
|
||||
String msgSignature = MessageUtil.signature(qyAccount.getToken(),
|
||||
nonce, timestamp, encrtypt);
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("Encrypt", encrtypt);
|
||||
map.put("MsgSignature", msgSignature);
|
||||
map.put("TimeStamp", timestamp);
|
||||
map.put("Nonce", nonce);
|
||||
|
||||
String content = mapXstream.toXML(map);
|
||||
out.add(HttpUtil.createWeixinMessageResponse(
|
||||
content, null));
|
||||
|
||||
log.info("\n=================aes encrtypt out=================");
|
||||
log.info("{}", content);
|
||||
}
|
||||
}
|
||||
-99
@@ -1,99 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.server;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.handler.codec.http.DefaultFullHttpResponse;
|
||||
import io.netty.handler.codec.http.HttpMethod;
|
||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
import io.netty.handler.codec.http.HttpVersion;
|
||||
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.foxinmy.weixin4j.action.WeixinAction;
|
||||
import com.foxinmy.weixin4j.action.mapping.ActionMapping;
|
||||
import com.foxinmy.weixin4j.qy.util.HttpUtil;
|
||||
import com.foxinmy.weixin4j.response.HttpWeixinMessage;
|
||||
import com.foxinmy.weixin4j.response.ResponseMessage;
|
||||
import com.foxinmy.weixin4j.util.MessageUtil;
|
||||
|
||||
/**
|
||||
* 微信被动消息处理类
|
||||
*
|
||||
* @className WeixinServerHandler
|
||||
* @author jy
|
||||
* @date 2014年11月16日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class WeixinServerHandler extends
|
||||
SimpleChannelInboundHandler<HttpWeixinMessage> {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private final ActionMapping actionMapping;
|
||||
|
||||
public WeixinServerHandler(ActionMapping actionMapping) {
|
||||
this.actionMapping = actionMapping;
|
||||
}
|
||||
|
||||
public void channelReadComplete(ChannelHandlerContext ctx) {
|
||||
ctx.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
||||
cause.printStackTrace();
|
||||
ctx.close();
|
||||
log.error("catch the exception:{}", cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx,
|
||||
HttpWeixinMessage httpMessage) throws Exception {
|
||||
log.info("\n=================message in=================\n{}",
|
||||
httpMessage);
|
||||
boolean isGet = httpMessage.getMethod().equals(HttpMethod.GET.name());
|
||||
boolean validate = false;
|
||||
if (isGet) {
|
||||
validate = MessageUtil.signature(httpMessage.getToken(),
|
||||
httpMessage.getTimeStamp(), httpMessage.getNonce(),
|
||||
httpMessage.getEchoStr())
|
||||
.equals(httpMessage.getSignature());
|
||||
if (validate) {
|
||||
ctx.write(HttpUtil.createWeixinMessageResponse(
|
||||
httpMessage.getOriginalContent(),
|
||||
ContentType.TEXT_PLAIN));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
validate = MessageUtil.signature(httpMessage.getToken(),
|
||||
httpMessage.getTimeStamp(), httpMessage.getNonce(),
|
||||
httpMessage.getEncryptContent()).equals(
|
||||
httpMessage.getSignature());
|
||||
}
|
||||
if (!validate) {
|
||||
ctx.write(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
|
||||
HttpResponseStatus.FORBIDDEN));
|
||||
return;
|
||||
}
|
||||
|
||||
String xmlContent = httpMessage.getOriginalContent();
|
||||
WeixinAction action = actionMapping.getAction(xmlContent);
|
||||
if (action == null) {
|
||||
ctx.write(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
|
||||
HttpResponseStatus.NOT_FOUND));
|
||||
return;
|
||||
}
|
||||
ResponseMessage response = action.execute(xmlContent);
|
||||
log.info("\n=================message out=================\n{}",
|
||||
response);
|
||||
if (response == null) {
|
||||
ctx.write(HttpUtil.createWeixinMessageResponse("",
|
||||
ContentType.TEXT_PLAIN));
|
||||
return;
|
||||
}
|
||||
ctx.write(response);
|
||||
}
|
||||
}
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.server;
|
||||
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.handler.codec.http.HttpObjectAggregator;
|
||||
import io.netty.handler.codec.http.HttpServerCodec;
|
||||
|
||||
import com.foxinmy.weixin4j.action.mapping.ActionMapping;
|
||||
import com.foxinmy.weixin4j.action.mapping.AnnotationActionMapping;
|
||||
import com.foxinmy.weixin4j.qy.action.ImageAction;
|
||||
|
||||
public class WeixinServerInitializer extends ChannelInitializer<SocketChannel> {
|
||||
private final ActionMapping actionMapping;
|
||||
|
||||
public WeixinServerInitializer() {
|
||||
this.actionMapping = new AnnotationActionMapping(
|
||||
ImageAction.class.getPackage());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initChannel(SocketChannel channel) throws Exception {
|
||||
ChannelPipeline pipeline = channel.pipeline();
|
||||
pipeline.addLast(new HttpServerCodec());
|
||||
pipeline.addLast(new HttpObjectAggregator(65536));
|
||||
pipeline.addLast(new WeixinMessageDecoder());
|
||||
pipeline.addLast(new WeixinMessageEncoder());
|
||||
pipeline.addLast(new WeixinServerHandler(actionMapping));
|
||||
}
|
||||
}
|
||||
-54
@@ -1,54 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.startup;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import io.netty.handler.logging.LoggingHandler;
|
||||
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import com.foxinmy.weixin4j.qy.server.WeixinServerInitializer;
|
||||
|
||||
/**
|
||||
* 微信服务netty启动程序
|
||||
*
|
||||
* @className WeixinServerBootstrap
|
||||
* @author jy
|
||||
* @date 2014年10月12日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public final class WeixinQyServerBootstrap {
|
||||
|
||||
private final static int port;
|
||||
private final static int workerThreads;
|
||||
static {
|
||||
ResourceBundle netty = ResourceBundle.getBundle("netty");
|
||||
port = Integer.parseInt(netty.getString("port"));
|
||||
workerThreads = Integer.parseInt(netty.getString("workerThreads"));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
|
||||
EventLoopGroup workerGroup = new NioEventLoopGroup(workerThreads);
|
||||
try {
|
||||
ServerBootstrap b = new ServerBootstrap();
|
||||
b.option(ChannelOption.SO_BACKLOG, 1024);
|
||||
b.group(bossGroup, workerGroup)
|
||||
.channel(NioServerSocketChannel.class)
|
||||
.handler(new LoggingHandler())
|
||||
.childHandler(new WeixinServerInitializer());
|
||||
Channel ch = b.bind(port).sync().channel();
|
||||
System.err.println("weixin server startup OK:" + port);
|
||||
ch.closeFuture().sync();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
bossGroup.shutdownGracefully();
|
||||
workerGroup.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
}
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
package com.foxinmy.weixin4j.qy.util;
|
||||
|
||||
import static io.netty.handler.codec.http.HttpHeaders.Names.CONNECTION;
|
||||
import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_LENGTH;
|
||||
import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE;
|
||||
import static io.netty.handler.codec.http.HttpHeaders.Names.DATE;
|
||||
import static io.netty.handler.codec.http.HttpHeaders.Names.SERVER;
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.OK;
|
||||
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.handler.codec.http.DefaultFullHttpResponse;
|
||||
import io.netty.handler.codec.http.FullHttpResponse;
|
||||
import io.netty.handler.codec.http.HttpHeaders.Values;
|
||||
import io.netty.handler.codec.http.HttpResponse;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.http.Consts;
|
||||
import org.apache.http.entity.ContentType;
|
||||
|
||||
/**
|
||||
* HTTP工具类
|
||||
*
|
||||
* @className HttpUtil
|
||||
* @author jy
|
||||
* @date 2014年11月15日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class HttpUtil {
|
||||
|
||||
public static HttpResponse createWeixinMessageResponse(String content,
|
||||
ContentType contentType) {
|
||||
if (contentType == null) {
|
||||
contentType = ContentType.APPLICATION_XML;
|
||||
}
|
||||
FullHttpResponse httpResponse = new DefaultFullHttpResponse(HTTP_1_1,
|
||||
OK, Unpooled.copiedBuffer(content, Consts.UTF_8));
|
||||
httpResponse.headers().set(
|
||||
CONTENT_TYPE,
|
||||
String.format("%s;encoding=%s", contentType.getMimeType(),
|
||||
Consts.UTF_8.displayName()));
|
||||
|
||||
httpResponse.headers().set(CONTENT_LENGTH, content.getBytes(Consts.UTF_8).length);
|
||||
httpResponse.headers().set(CONNECTION, Values.KEEP_ALIVE);
|
||||
httpResponse.headers().set(DATE, new Date());
|
||||
httpResponse.headers().set(SERVER, "netty4");
|
||||
return httpResponse;
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!-- For assistance related to logback-translator or configuration -->
|
||||
<!-- files in general, please contact the logback user mailing list -->
|
||||
<!-- at http://www.qos.ch/mailman/listinfo/logback-user -->
|
||||
<!-- -->
|
||||
<!-- For professional support please see -->
|
||||
<!-- http://www.qos.ch/shop/products/professionalSupport -->
|
||||
<!-- -->
|
||||
<configuration>
|
||||
|
||||
<!-- 控制台输出日志 -->
|
||||
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<charset>UTF-8</charset>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 文件输出指定项目日志 -->
|
||||
<appender name="file"
|
||||
class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<!--See http://logback.qos.ch/manual/appenders.html#RollingFileAppender -->
|
||||
<!--and http://logback.qos.ch/manual/appenders.html#TimeBasedRollingPolicy -->
|
||||
<!--for further documentation -->
|
||||
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>/tmp/weixin/log/qy/weixin.qy.%d{yyyy-MM-dd}.log
|
||||
</fileNamePattern>
|
||||
<maxHistory>30</maxHistory>
|
||||
</rollingPolicy>
|
||||
|
||||
<encoder>
|
||||
<charset>UTF-8</charset>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 异步输出指定项目日志 -->
|
||||
<appender name="async" class="ch.qos.logback.classic.AsyncAppender">
|
||||
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
|
||||
<discardingThreshold>0</discardingThreshold>
|
||||
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
|
||||
<queueSize>512</queueSize>
|
||||
<!-- 添加附加的appender,最多只能添加一个 -->
|
||||
<appender-ref ref="file" />
|
||||
</appender>
|
||||
|
||||
<logger name="org.apache" level="INFO">
|
||||
<appender-ref ref="stdout" />
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework" level="INFO">
|
||||
<appender-ref ref="stdout" />
|
||||
</logger>
|
||||
|
||||
<logger name="com.foxinmy.weixin4j" level="INFO">
|
||||
<appender-ref ref="async" />
|
||||
</logger>
|
||||
|
||||
</configuration>
|
||||
@@ -1,4 +0,0 @@
|
||||
# netty\u76d1\u542c\u7aef\u53e3 \u7531\u4e8e\u5fae\u4fe1\u56de\u8c03url\u76ee\u524d\u53ea\u652f\u630180\u7aef\u53e3 \u53ef\u4ee5\u8003\u8651\u7528nginx\u8f6c\u53d1\u7684\u65b9\u5f0f\u6765\u89e3\u51b380\u7aef\u53e3\u88ab\u5360\u6709\u7684\u95ee\u9898
|
||||
port=8090
|
||||
# \u5de5\u4f5c\u8fdb\u7a0b\u6570
|
||||
workerThreads=20
|
||||
@@ -1,9 +0,0 @@
|
||||
# \u4f01\u4e1a\u53f7\u4fe1\u606f
|
||||
account={"id":"corpid","secret":"corpsecret",\
|
||||
"token":"\u4f01\u4e1a\u53f7\u4e2d\u5e94\u7528\u5728\u56de\u8c03\u6a21\u5f0f\u4e0b\u7684token",\
|
||||
"encodingAesKey":"\u4f01\u4e1a\u53f7\u4e2d\u5e94\u7528\u5728\u56de\u8c03\u6a21\u5f0f\u4e0bAES\u52a0\u5bc6\u5bc6\u94a5"}
|
||||
|
||||
# \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
|
||||
@@ -1,142 +0,0 @@
|
||||
ulimit -n 110000
|
||||
#JDK home
|
||||
JAVA_HOME="/usr/local/java/"
|
||||
|
||||
#executing user
|
||||
RUNNING_USER=root
|
||||
|
||||
#Run home
|
||||
APP_HOME="/usr/local/weixin/weixin-qy-server"
|
||||
|
||||
#main class
|
||||
APP_MAINCLASS=com.foxinmy.weixin4j.qy.startup.WeixinQyServerBootstrap
|
||||
|
||||
#classpath
|
||||
CLASSPATH=$APP_HOME/classes
|
||||
for i in "$APP_HOME"/lib/*.jar; do
|
||||
CLASSPATH="$CLASSPATH":"$i"
|
||||
done
|
||||
|
||||
CLASSPATH="$CLASSPATH":"$APP_HOME"/conf
|
||||
|
||||
#jvm options
|
||||
JAVA_OPTS="-Xms256m -Xmx512m -Djava.awt.headless=true -XX:MaxPermSize=128m -server -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=85 -XX:+DisableExplicitGC -Xnoclassgc -Xverify:none"
|
||||
|
||||
#psid
|
||||
psid=0
|
||||
|
||||
checkpid() {
|
||||
javaps=`$JAVA_HOME/bin/jps -l | grep $APP_MAINCLASS`
|
||||
|
||||
if [ -n "$javaps" ]; then
|
||||
psid=`echo $javaps | awk '{print $1}'`
|
||||
else
|
||||
psid=0
|
||||
fi
|
||||
}
|
||||
|
||||
###################################
|
||||
#startup
|
||||
###################################
|
||||
start() {
|
||||
checkpid
|
||||
|
||||
if [ $psid -ne 0 ]; then
|
||||
echo "====================================================="
|
||||
echo "warn: $APP_MAINCLASS already started! (pid=$psid)"
|
||||
echo "====================================================="
|
||||
else
|
||||
echo -n "Starting $APP_MAINCLASS ..."
|
||||
# JAVA_CMD="nohup $JAVA_HOME/bin/java $JAVA_OPTS -classpath $CLASSPATH $APP_MAINCLASS >/dev/null 2>&1 &"
|
||||
JAVA_CMD="$JAVA_HOME/bin/java $JAVA_OPTS -classpath $CLASSPATH $APP_MAINCLASS &"
|
||||
su - $RUNNING_USER -c "$JAVA_CMD"
|
||||
checkpid
|
||||
if [ $psid -ne 0 ]; then
|
||||
echo "(pid=$psid) [OK]"
|
||||
else
|
||||
echo "[Failed]"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
###################################
|
||||
#stop
|
||||
###################################
|
||||
stop() {
|
||||
checkpid
|
||||
|
||||
if [ $psid -ne 0 ]; then
|
||||
echo -n "Stopping $APP_MAINCLASS ...(pid=$psid) "
|
||||
su - $RUNNING_USER -c "kill -9 $psid"
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "[OK]"
|
||||
else
|
||||
echo "[Failed]"
|
||||
fi
|
||||
|
||||
checkpid
|
||||
if [ $psid -ne 0 ]; then
|
||||
stop
|
||||
fi
|
||||
else
|
||||
echo "====================================================="
|
||||
echo "warn: $APP_MAINCLASS is not running"
|
||||
echo "====================================================="
|
||||
fi
|
||||
}
|
||||
|
||||
###################################
|
||||
#status
|
||||
###################################
|
||||
status() {
|
||||
checkpid
|
||||
|
||||
if [ $psid -ne 0 ]; then
|
||||
echo "$APP_MAINCLASS is running! (pid=$psid)"
|
||||
else
|
||||
echo "$APP_MAINCLASS is not running"
|
||||
fi
|
||||
}
|
||||
|
||||
###################################
|
||||
#info
|
||||
###################################
|
||||
info() {
|
||||
echo "System Information:"
|
||||
echo "****************************"
|
||||
echo `head -n 1 /etc/issue`
|
||||
echo `uname -a`
|
||||
echo
|
||||
echo "JAVA_HOME=$JAVA_HOME"
|
||||
echo `$JAVA_HOME/bin/java -version`
|
||||
echo
|
||||
echo "APP_HOME=$APP_HOME"
|
||||
echo "APP_MAINCLASS=$APP_MAINCLASS"
|
||||
echo "****************************"
|
||||
}
|
||||
|
||||
###################################
|
||||
#access only 1 argument:{start|stop|restart|status|info}
|
||||
###################################
|
||||
case "$1" in
|
||||
'start')
|
||||
start
|
||||
;;
|
||||
'stop')
|
||||
stop
|
||||
;;
|
||||
'restart')
|
||||
stop
|
||||
start
|
||||
;;
|
||||
'status')
|
||||
status
|
||||
;;
|
||||
'info')
|
||||
info
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart|status|info}"
|
||||
exit 1
|
||||
esac
|
||||
exit 0
|
||||
Reference in New Issue
Block a user