新增企业号工程并完成【部门管理】【成员管理】【标签管理】三个接口
This commit is contained in:
parent
f4aec9dc99
commit
5b213cd87f
12
README.md
12
README.md
@ -81,6 +81,18 @@ weixin4j
|
||||
* 2014-11-17
|
||||
|
||||
+ **weixin4j-mp**: 新增`冲正`和`被扫支付`接口
|
||||
|
||||
* 2014-11-19
|
||||
|
||||
+ **weixin4j-base**: 新增`WeixinQyAccount`企业号账号信息类
|
||||
|
||||
+ **weixin4j-qy**: 得到`weixin4j-qy`和`weixin4j-qy-server`工程
|
||||
|
||||
+ **weixin4j-qy**: 新增`部门管理`接口
|
||||
|
||||
+ **weixin4j-qy**: 新增`用户管理`接口
|
||||
|
||||
+ **weixin4j-qy**: 新增`标签管理`接口
|
||||
|
||||
接下来
|
||||
------
|
||||
|
||||
23
pom.xml
23
pom.xml
@ -131,6 +131,29 @@
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>${maven.assembly.plugin.version}</version>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>src/main/assembly.xml</descriptor>
|
||||
</descriptors>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/java</directory>
|
||||
|
||||
@ -25,4 +25,8 @@ weixin4j-base
|
||||
|
||||
* 2014-11-15
|
||||
|
||||
+ 新增`aes加密解密`函数
|
||||
+ 新增`aes加密解密`函数
|
||||
|
||||
* 2014-11-19
|
||||
|
||||
+ 新增`WeixinQyAccount`企业号账号信息类
|
||||
@ -11,7 +11,7 @@
|
||||
<desc>system error</desc>
|
||||
<text>系统繁忙</text>
|
||||
</error>
|
||||
<!-- 公众平台API错误 -->
|
||||
<!-- 公众平台&企业号API错误 -->
|
||||
<error>
|
||||
<code>40001</code>
|
||||
<desc>invalid credential</desc>
|
||||
@ -32,6 +32,14 @@
|
||||
<desc>invalid media type</desc>
|
||||
<text>不合法的媒体文件类型</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40005</code>
|
||||
<text>不合法的文件类型</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40006</code>
|
||||
<text>不合法的文件大小</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40007</code>
|
||||
<desc>invalid media_id</desc>
|
||||
@ -102,6 +110,14 @@
|
||||
<desc>invalid button url size</desc>
|
||||
<text>不合法的url长度</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40021</code>
|
||||
<text>不合法的菜单版本号</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40022</code>
|
||||
<text>不合法的子菜单级数</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40023</code>
|
||||
<desc>invalid sub button size</desc>
|
||||
@ -127,6 +143,10 @@
|
||||
<desc>invalid sub button url size</desc>
|
||||
<text>不合法的子菜单按钮url长度</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40028</code>
|
||||
<text>不合法的自定义菜单使用员工</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40029</code>
|
||||
<desc>invalid code</desc>
|
||||
@ -137,6 +157,22 @@
|
||||
<desc>invalid refresh_token</desc>
|
||||
<text>不合法的refresh_token</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40031</code>
|
||||
<text>不合法的UserID列表</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40032</code>
|
||||
<text>不合法的UserID列表长度</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40033</code>
|
||||
<text>不合法的请求字符,不能包含\uxxxx格式的字符</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40035</code>
|
||||
<text>不合法的参数</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40036</code>
|
||||
<desc>invalid template_id size</desc>
|
||||
@ -147,11 +183,27 @@
|
||||
<desc>invalid template_id</desc>
|
||||
<text>不合法的template_id</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40038</code>
|
||||
<text>不合法的请求格式</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40039</code>
|
||||
<desc>invalid url size</desc>
|
||||
<text>不合法的url长度</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40040</code>
|
||||
<text>不合法的插件token</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40041</code>
|
||||
<text>不合法的插件id</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40042</code>
|
||||
<text>不合法的插件会话</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40048</code>
|
||||
<desc>invalid url domain</desc>
|
||||
@ -167,10 +219,82 @@
|
||||
<desc>invalid button url domain</desc>
|
||||
<text>不合法的菜单按钮url域名</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40056</code>
|
||||
<text>不合法的agentid</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40057</code>
|
||||
<text>不合法的callbackurl</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40058</code>
|
||||
<text>不合法的红包参数</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40059</code>
|
||||
<text>不合法的上报地理位置标志位</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40060</code>
|
||||
<text>设置上报地理位置标志位时没有设置callbackurl</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40061</code>
|
||||
<text>设置应用头像失败</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40062</code>
|
||||
<text>不合法的应用模式</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40063</code>
|
||||
<text>红包参数为空</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40064</code>
|
||||
<text>管理组名字已存在</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40065</code>
|
||||
<text>不合法的管理组名字长度</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40066</code>
|
||||
<desc>invalid url</desc>
|
||||
<text>不合法的url</text>
|
||||
<desc>invalid url/department</desc>
|
||||
<text>不合法的url/不合法的部门列表</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40067</code>
|
||||
<text>标题长度不合法</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40068</code>
|
||||
<text>不合法的标签ID</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40069</code>
|
||||
<text>不合法的标签ID列表</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40070</code>
|
||||
<text>列表中所有标签(用户)ID都不合法</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40071</code>
|
||||
<text>不合法的标签名字,标签名字已经存在</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40072</code>
|
||||
<text>不合法的标签名字长度</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40073</code>
|
||||
<text>不合法的openid</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40074</code>
|
||||
<text>news消息不支持指定为高保密消息</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>41001</code>
|
||||
@ -222,6 +346,38 @@
|
||||
<desc>missing url</desc>
|
||||
<text>缺失url参数</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>41011</code>
|
||||
<text>缺少agentid</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>41012</code>
|
||||
<text>缺少应用头像mediaid</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>41013</code>
|
||||
<text>缺少应用名字</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>41014</code>
|
||||
<text>缺少应用描述</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>41015</code>
|
||||
<text>缺少Content</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>41016</code>
|
||||
<text>缺少标题</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>41017</code>
|
||||
<text>缺少标签ID</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>41018</code>
|
||||
<text>缺少标签名字</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>42001</code>
|
||||
<desc>access_token expired</desc>
|
||||
@ -237,6 +393,10 @@
|
||||
<desc>code expired</desc>
|
||||
<text>code超时</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>42004</code>
|
||||
<text>插件token超时</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>43001</code>
|
||||
<desc>require GET method</desc>
|
||||
@ -257,6 +417,34 @@
|
||||
<desc>require subscribe</desc>
|
||||
<text>需要订阅关系</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>43005</code>
|
||||
<text>需要好友关系</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>43006</code>
|
||||
<text>需要订阅</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>43007</code>
|
||||
<text>需要授权</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>43008</code>
|
||||
<text>需要支付授权</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>43009</code>
|
||||
<text>需要员工已关注</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>43010</code>
|
||||
<text>需要处于回调模式</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>43011</code>
|
||||
<text>需要企业授权</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>44001</code>
|
||||
<desc>empty media data</desc>
|
||||
@ -342,6 +530,10 @@
|
||||
<desc>template size out of limit</desc>
|
||||
<text>模板大小超过限制</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>45015</code>
|
||||
<text>回复时间超过限制</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>45016</code>
|
||||
<desc>can't modify sys group</desc>
|
||||
@ -357,11 +549,176 @@
|
||||
<desc>too many group now, no need to add new</desc>
|
||||
<text>组数量过多</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>45024</code>
|
||||
<text>账号数量超过上限</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>46001</code>
|
||||
<text>不存在媒体数据</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>46002</code>
|
||||
<text>不存在的菜单版本</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>46003</code>
|
||||
<text>不存在的菜单数据</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>46004</code>
|
||||
<text>不存在的员工</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>47001</code>
|
||||
<text>解析JSON/XML内容错误</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>48002</code>
|
||||
<text>Api禁用</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>50001</code>
|
||||
<desc>api unauthorized</desc>
|
||||
<desc>api/redirect_uri unauthorized</desc>
|
||||
<text>接口未授权</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>50002</code>
|
||||
<text>员工不在权限范围</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>50003</code>
|
||||
<text>应用已停用</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>50004</code>
|
||||
<text>员工状态不正确(未关注状态)</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>50005</code>
|
||||
<text>企业已禁用</text>
|
||||
</error>
|
||||
<!-- 企业号API错误 -->
|
||||
<error>
|
||||
<code>60001</code>
|
||||
<text>部门长度不符合限制</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60002</code>
|
||||
<text>部门层级深度超过限制</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60003</code>
|
||||
<text>部门不存在</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60004</code>
|
||||
<text>父亲部门不存在</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60005</code>
|
||||
<text>不允许删除有成员的部门</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60006</code>
|
||||
<text>不允许删除有子部门的部门</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60007</code>
|
||||
<text>不允许删除根部门</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60008</code>
|
||||
<text>部门名称已存在</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60009</code>
|
||||
<text>部门名称含有非法字符</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60010</code>
|
||||
<text>部门存在循环关系</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60011</code>
|
||||
<text>管理员权限不足(user/department/agent)无权限</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60012</code>
|
||||
<text>不允许删除默认应用</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60013</code>
|
||||
<text>不允许关闭应用</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60014</code>
|
||||
<text>不允许开启应用</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60015</code>
|
||||
<text>不允许修改默认应用可见范围</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60016</code>
|
||||
<text>不允许删除存在成员的标签</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60017</code>
|
||||
<text>不允许设置企业</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60102</code>
|
||||
<text>UserID已存在</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60103</code>
|
||||
<text>手机号码不合法</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60104</code>
|
||||
<text>手机号码已存在</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60105</code>
|
||||
<text>邮箱不合法</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60106</code>
|
||||
<text>邮箱已存在</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60107</code>
|
||||
<text>微信号不合法</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60108</code>
|
||||
<text>微信号已存在</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60109</code>
|
||||
<text>QQ号已存在</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60110</code>
|
||||
<text>部门个数超出限制</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60111</code>
|
||||
<text>UserID不存在</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60112</code>
|
||||
<text>成员姓名不合法</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60113</code>
|
||||
<text>身份认证信息(微信号/手机/邮箱)不能同时为空</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>60114</code>
|
||||
<text>性别不合法</text>
|
||||
</error>
|
||||
<!-- 语义理解API错误 -->
|
||||
<error>
|
||||
<code>7000000</code>
|
||||
|
||||
@ -11,4 +11,12 @@ public final class Consts {
|
||||
public static final String AES = "AES";
|
||||
public static final String PROTOCOL_FILE = "file";
|
||||
public static final String PROTOCOL_JAR = "jar";
|
||||
|
||||
public static final String MP_ASSESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
|
||||
public static final String QY_ASSESS_TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s";
|
||||
|
||||
public static final String UNIFIEDORDER = "https://api.mch.weixin.qq.com/pay/unifiedorder";
|
||||
public static final String MICROPAYURL = "https://api.mch.weixin.qq.com/pay/micropay";
|
||||
public static final String NATIVEURLV2 = "weixin://wxpay/bizpayurl?sign=%s&appid=%s&productid=%s×tamp=%s&noncestr=%s";
|
||||
public static final String NATIVEURLV3 = "weixin://wxpay/bizpayurl?sign=%s&appid=%s&mch_id=%s&product_id=%s&time_stamp=%s&nonce_str=%s";
|
||||
}
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
package com.foxinmy.weixin4j.model;
|
||||
|
||||
/**
|
||||
* 用户性别
|
||||
*
|
||||
* @className Gender
|
||||
* @author jy
|
||||
* @date 2014年11月5日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public enum Gender {
|
||||
male, female, unknown;
|
||||
}
|
||||
@ -2,48 +2,51 @@ package com.foxinmy.weixin4j.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* 微信账户信息
|
||||
* 微信账号信息
|
||||
*
|
||||
* @className WeixinAccount
|
||||
* @author jy
|
||||
* @date 2014年8月17日
|
||||
* @date 2014年11月18日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class WeixinAccount implements Serializable {
|
||||
private static final long serialVersionUID = 3689999353867189585L;
|
||||
public abstract class WeixinAccount implements Serializable {
|
||||
private static final long serialVersionUID = -6001008896414323534L;
|
||||
|
||||
// 唯一的身份标识
|
||||
private String id;
|
||||
// 调用接口的密钥
|
||||
private String secret;
|
||||
private String token;
|
||||
// 支付场景下为用户的openid 其余情况可能是公众号的原始ID
|
||||
private String openId;
|
||||
// 公众号身份的唯一标识
|
||||
private String appId;
|
||||
// 公众平台接口 API 的权限获取所需密钥 Key
|
||||
private String appSecret;
|
||||
// 公众号支付请求中用于加密的密钥 Key,可验证商户唯一身份,PaySignKey 对应于支付场景中的 appKey 值
|
||||
private String paySignKey;
|
||||
// 安全模式下的加密密钥
|
||||
private String encodingAesKey;
|
||||
// 财付通商户身份的标识
|
||||
private String partnerId;
|
||||
// 财付通商户权限密钥Key
|
||||
private String partnerKey;
|
||||
// 微信支付商户号V3.x版本
|
||||
private String mchId;
|
||||
// 微信支付分配的设备号
|
||||
private String deviceInfo;
|
||||
// 微信支付版本号(如果无则按照mchId来做判断)
|
||||
private int version;
|
||||
|
||||
// 是否已经认证
|
||||
private boolean isAlive;
|
||||
// 是否是服务号
|
||||
private boolean isService;
|
||||
// 是否是订阅号
|
||||
private boolean isSubscribe;
|
||||
public abstract String getTokenUrl();
|
||||
|
||||
public WeixinAccount() {
|
||||
}
|
||||
|
||||
public WeixinAccount(String id, String secret) {
|
||||
this.id = id;
|
||||
this.secret = secret;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getSecret() {
|
||||
return secret;
|
||||
}
|
||||
|
||||
public void setSecret(String secret) {
|
||||
this.secret = secret;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
@ -53,30 +56,6 @@ public class WeixinAccount implements Serializable {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public String getOpenId() {
|
||||
return openId;
|
||||
}
|
||||
|
||||
public void setOpenId(String openId) {
|
||||
this.openId = openId;
|
||||
}
|
||||
|
||||
public String getAppId() {
|
||||
return appId;
|
||||
}
|
||||
|
||||
public void setAppId(String appId) {
|
||||
this.appId = appId;
|
||||
}
|
||||
|
||||
public String getAppSecret() {
|
||||
return appSecret;
|
||||
}
|
||||
|
||||
public void setAppSecret(String appSecret) {
|
||||
this.appSecret = appSecret;
|
||||
}
|
||||
|
||||
public String getEncodingAesKey() {
|
||||
return encodingAesKey;
|
||||
}
|
||||
@ -85,130 +64,9 @@ public class WeixinAccount implements Serializable {
|
||||
this.encodingAesKey = encodingAesKey;
|
||||
}
|
||||
|
||||
public String getPaySignKey() {
|
||||
return paySignKey;
|
||||
}
|
||||
|
||||
public void setPaySignKey(String paySignKey) {
|
||||
this.paySignKey = paySignKey;
|
||||
}
|
||||
|
||||
public String getPartnerId() {
|
||||
return partnerId;
|
||||
}
|
||||
|
||||
public void setPartnerId(String partnerId) {
|
||||
this.partnerId = partnerId;
|
||||
}
|
||||
|
||||
public String getPartnerKey() {
|
||||
return partnerKey;
|
||||
}
|
||||
|
||||
public void setPartnerKey(String partnerKey) {
|
||||
this.partnerKey = partnerKey;
|
||||
}
|
||||
|
||||
public String getMchId() {
|
||||
return mchId;
|
||||
}
|
||||
|
||||
public void setMchId(String mchId) {
|
||||
this.mchId = mchId;
|
||||
}
|
||||
|
||||
public String getDeviceInfo() {
|
||||
return deviceInfo;
|
||||
}
|
||||
|
||||
public void setDeviceInfo(String deviceInfo) {
|
||||
this.deviceInfo = deviceInfo;
|
||||
}
|
||||
|
||||
public boolean getIsAlive() {
|
||||
return isAlive;
|
||||
}
|
||||
|
||||
public void setIsAlive(Boolean isAlive) {
|
||||
this.isAlive = isAlive;
|
||||
}
|
||||
|
||||
public boolean getIsService() {
|
||||
return isService;
|
||||
}
|
||||
|
||||
public void setIsService(Boolean isService) {
|
||||
this.isService = isService;
|
||||
}
|
||||
|
||||
public boolean getIsSubscribe() {
|
||||
return isSubscribe;
|
||||
}
|
||||
|
||||
public void setIsSubscribe(Boolean isSubscribe) {
|
||||
this.isSubscribe = isSubscribe;
|
||||
}
|
||||
|
||||
public int getVersion() {
|
||||
if (version == 0) {
|
||||
return StringUtils.isNotBlank(mchId) ? 3 : 2;
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(int version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public WeixinAccount() {
|
||||
|
||||
}
|
||||
|
||||
public WeixinAccount(String appId, String appSecret) {
|
||||
this.appId = appId;
|
||||
this.appSecret = appSecret;
|
||||
}
|
||||
|
||||
/**
|
||||
* V3版本字段
|
||||
*
|
||||
* @param appId
|
||||
* @param appSecret
|
||||
* @param paySignKey
|
||||
* @param mchId
|
||||
*/
|
||||
public WeixinAccount(String appId, String appSecret, String paySignKey,
|
||||
String mchId) {
|
||||
this(appId, appSecret);
|
||||
this.paySignKey = paySignKey;
|
||||
this.mchId = mchId;
|
||||
}
|
||||
|
||||
/**
|
||||
* V2版本字段
|
||||
*
|
||||
* @param appId
|
||||
* @param appSecret
|
||||
* @param paySignKey
|
||||
* @param partnerId
|
||||
* @param partnerKey
|
||||
*/
|
||||
public WeixinAccount(String appId, String appSecret, String paySignKey,
|
||||
String partnerId, String partnerKey) {
|
||||
this(appId, appSecret);
|
||||
this.paySignKey = paySignKey;
|
||||
this.partnerId = partnerId;
|
||||
this.partnerKey = partnerKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WeixinAccount [token=" + token + ", openId=" + openId
|
||||
+ ", appId=" + appId + ", appSecret=" + appSecret
|
||||
+ ", encodingAesKey=" + encodingAesKey + ", paySignKey="
|
||||
+ paySignKey + ", partnerId=" + partnerId + ", partnerKey="
|
||||
+ partnerKey + ", mchId=" + mchId + ", deviceInfo="
|
||||
+ deviceInfo + ", isAlive=" + isAlive + ", isService="
|
||||
+ isService + ", isSubscribe=" + isSubscribe + "]";
|
||||
return "WeixinAccount [id=" + id + ", secret=" + secret + ", token="
|
||||
+ token + ", encodingAesKey=" + encodingAesKey + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,178 @@
|
||||
package com.foxinmy.weixin4j.model;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* 微信公众平台信息
|
||||
*
|
||||
* @className WeixinMpAccount
|
||||
* @author jy
|
||||
* @date 2014年8月17日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class WeixinMpAccount extends WeixinAccount {
|
||||
private static final long serialVersionUID = 3689999353867189585L;
|
||||
|
||||
// 支付场景下为用户的openid 其余情况可能是公众号的原始ID
|
||||
private String openId;
|
||||
// 公众号支付请求中用于加密的密钥 Key,可验证商户唯一身份,PaySignKey 对应于支付场景中的 appKey 值
|
||||
private String paySignKey;
|
||||
// 财付通商户身份的标识
|
||||
private String partnerId;
|
||||
// 财付通商户权限密钥Key
|
||||
private String partnerKey;
|
||||
// 微信支付商户号V3.x版本
|
||||
private String mchId;
|
||||
// 微信支付分配的设备号
|
||||
private String deviceInfo;
|
||||
// 微信支付版本号(如果无则按照mchId来做判断)
|
||||
private int version;
|
||||
|
||||
// 是否已经认证
|
||||
private boolean isAlive;
|
||||
// 是否是服务号
|
||||
private boolean isService;
|
||||
// 是否是订阅号
|
||||
private boolean isSubscribe;
|
||||
|
||||
@Override
|
||||
public String getTokenUrl() {
|
||||
return String.format(Consts.MP_ASSESS_TOKEN_URL, getId(), getSecret());
|
||||
}
|
||||
|
||||
public String getOpenId() {
|
||||
return openId;
|
||||
}
|
||||
|
||||
public void setOpenId(String openId) {
|
||||
this.openId = openId;
|
||||
}
|
||||
|
||||
public String getPaySignKey() {
|
||||
return paySignKey;
|
||||
}
|
||||
|
||||
public void setPaySignKey(String paySignKey) {
|
||||
this.paySignKey = paySignKey;
|
||||
}
|
||||
|
||||
public String getPartnerId() {
|
||||
return partnerId;
|
||||
}
|
||||
|
||||
public void setPartnerId(String partnerId) {
|
||||
this.partnerId = partnerId;
|
||||
}
|
||||
|
||||
public String getPartnerKey() {
|
||||
return partnerKey;
|
||||
}
|
||||
|
||||
public void setPartnerKey(String partnerKey) {
|
||||
this.partnerKey = partnerKey;
|
||||
}
|
||||
|
||||
public String getMchId() {
|
||||
return mchId;
|
||||
}
|
||||
|
||||
public void setMchId(String mchId) {
|
||||
this.mchId = mchId;
|
||||
}
|
||||
|
||||
public String getDeviceInfo() {
|
||||
return deviceInfo;
|
||||
}
|
||||
|
||||
public void setDeviceInfo(String deviceInfo) {
|
||||
this.deviceInfo = deviceInfo;
|
||||
}
|
||||
|
||||
public boolean getIsAlive() {
|
||||
return isAlive;
|
||||
}
|
||||
|
||||
public void setIsAlive(Boolean isAlive) {
|
||||
this.isAlive = isAlive;
|
||||
}
|
||||
|
||||
public boolean getIsService() {
|
||||
return isService;
|
||||
}
|
||||
|
||||
public void setIsService(Boolean isService) {
|
||||
this.isService = isService;
|
||||
}
|
||||
|
||||
public boolean getIsSubscribe() {
|
||||
return isSubscribe;
|
||||
}
|
||||
|
||||
public void setIsSubscribe(Boolean isSubscribe) {
|
||||
this.isSubscribe = isSubscribe;
|
||||
}
|
||||
|
||||
public int getVersion() {
|
||||
if (version == 0) {
|
||||
return StringUtils.isNotBlank(mchId) ? 3 : 2;
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(int version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public WeixinMpAccount() {
|
||||
|
||||
}
|
||||
|
||||
public WeixinMpAccount(String appId, String appSecret) {
|
||||
super(appId, appSecret);
|
||||
}
|
||||
|
||||
/**
|
||||
* V3版本字段
|
||||
*
|
||||
* @param appId
|
||||
* @param appSecret
|
||||
* @param paySignKey
|
||||
* @param mchId
|
||||
*/
|
||||
public WeixinMpAccount(String appId, String appSecret, String paySignKey,
|
||||
String mchId) {
|
||||
this(appId, appSecret);
|
||||
this.paySignKey = paySignKey;
|
||||
this.mchId = mchId;
|
||||
}
|
||||
|
||||
/**
|
||||
* V2版本字段
|
||||
*
|
||||
* @param appId
|
||||
* @param appSecret
|
||||
* @param paySignKey
|
||||
* @param partnerId
|
||||
* @param partnerKey
|
||||
*/
|
||||
public WeixinMpAccount(String appId, String appSecret, String paySignKey,
|
||||
String partnerId, String partnerKey) {
|
||||
this(appId, appSecret);
|
||||
this.paySignKey = paySignKey;
|
||||
this.partnerId = partnerId;
|
||||
this.partnerKey = partnerKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WeixinMpAccount [openId=" + openId + ", paySignKey="
|
||||
+ paySignKey + ", partnerId=" + partnerId + ", partnerKey="
|
||||
+ partnerKey + ", mchId=" + mchId + ", deviceInfo="
|
||||
+ deviceInfo + ", version=" + version + ", isAlive=" + isAlive
|
||||
+ ", isService=" + isService + ", isSubscribe=" + isSubscribe
|
||||
+ ", getId()=" + getId() + ", getSecret()=" + getSecret()
|
||||
+ ", getToken()=" + getToken() + ", getEncodingAesKey()="
|
||||
+ getEncodingAesKey() + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.foxinmy.weixin4j.model;
|
||||
|
||||
/**
|
||||
* 微信企业号信息
|
||||
*
|
||||
* @className WeixinQyAccount
|
||||
* @author jy
|
||||
* @date 2014年11月18日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class WeixinQyAccount extends WeixinAccount {
|
||||
private static final long serialVersionUID = 3689999353867189585L;
|
||||
|
||||
public WeixinQyAccount() {
|
||||
}
|
||||
|
||||
public WeixinQyAccount(String corpid, String corpsecret) {
|
||||
super(corpid, corpsecret);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTokenUrl() {
|
||||
return String.format(Consts.QY_ASSESS_TOKEN_URL, getId(), getSecret());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WeixinQyAccount [getTokenUrl()=" + getTokenUrl() + ", getId()="
|
||||
+ getId() + ", getSecret()=" + getSecret() + ", getToken()="
|
||||
+ getToken() + ", getEncodingAesKey()=" + getEncodingAesKey()
|
||||
+ "]";
|
||||
}
|
||||
}
|
||||
@ -1,15 +1,8 @@
|
||||
package com.foxinmy.weixin4j.msg;
|
||||
|
||||
import java.io.Writer;
|
||||
|
||||
import com.foxinmy.weixin4j.model.BaseMsg;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.foxinmy.weixin4j.util.ClassUtil;
|
||||
import com.foxinmy.weixin4j.xml.XStream;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
||||
import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver;
|
||||
import com.thoughtworks.xstream.io.json.JsonWriter;
|
||||
|
||||
/**
|
||||
* 普通消息基类
|
||||
@ -26,32 +19,12 @@ import com.thoughtworks.xstream.io.json.JsonWriter;
|
||||
public class BaseMessage extends BaseMsg {
|
||||
|
||||
private static final long serialVersionUID = 7761192742840031607L;
|
||||
private final static XStream xmlStream = XStream.get();
|
||||
private final static XStream jsonStream = new XStream(
|
||||
new JsonHierarchicalStreamDriver() {
|
||||
public HierarchicalStreamWriter createWriter(Writer writer) {
|
||||
return new JsonWriter(writer, JsonWriter.DROP_ROOT_MODE);
|
||||
}
|
||||
});
|
||||
|
||||
@XStreamAlias("MsgType")
|
||||
private MessageType msgType; // 消息类型
|
||||
@XStreamAlias("MsgId")
|
||||
private long msgId; // 消息ID
|
||||
|
||||
static {
|
||||
Class<?>[] classes = ClassUtil.getClasses(
|
||||
TextMessage.class.getPackage()).toArray(new Class[0]);
|
||||
|
||||
xmlStream.processAnnotations(classes);
|
||||
xmlStream.omitField(BaseMessage.class, "msgId");
|
||||
|
||||
jsonStream.setMode(XStream.NO_REFERENCES);
|
||||
jsonStream.autodetectAnnotations(true);
|
||||
jsonStream.processAnnotations(classes);
|
||||
jsonStream.omitField(BaseMessage.class, "msgId");
|
||||
}
|
||||
|
||||
public BaseMessage(MessageType msgType) {
|
||||
this.msgType = msgType;
|
||||
}
|
||||
@ -79,25 +52,4 @@ public class BaseMessage extends BaseMsg {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息对象转换为微信服务器接受的xml格式消息
|
||||
*
|
||||
* @return xml字符串
|
||||
*/
|
||||
public String toXml() {
|
||||
Class<? extends BaseMessage> targetClass = getMsgType()
|
||||
.getMessageClass();
|
||||
xmlStream.alias("xml", targetClass);
|
||||
return xmlStream.toXML(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息对象转换为微信服务器接受的json格式字符串
|
||||
*
|
||||
* @return json字符串
|
||||
*/
|
||||
public String toJson() {
|
||||
return jsonStream.toXML(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,10 +2,11 @@ package com.foxinmy.weixin4j.token;
|
||||
|
||||
import com.foxinmy.weixin4j.http.HttpRequest;
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.type.AccountType;
|
||||
import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||
|
||||
/**
|
||||
* 获取weixin.properties中的appid&appsecret信息
|
||||
* 获取weixin.properties中的id&secret信息
|
||||
*
|
||||
* @className AbstractTokenHolder
|
||||
* @author jy
|
||||
@ -14,12 +15,18 @@ import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||
* @see
|
||||
*/
|
||||
public abstract class AbstractTokenHolder implements TokenHolder {
|
||||
protected final String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
|
||||
protected final HttpRequest request = new HttpRequest();
|
||||
private final WeixinAccount weixinAccount;
|
||||
|
||||
public AbstractTokenHolder() {
|
||||
this.weixinAccount = ConfigUtil.getWeixinAccount();
|
||||
protected final HttpRequest request = new HttpRequest();
|
||||
protected final WeixinAccount weixinAccount;
|
||||
|
||||
public AbstractTokenHolder(AccountType accountType) {
|
||||
if (accountType == AccountType.MP) {
|
||||
this.weixinAccount = ConfigUtil.getWeixinMpAccount();
|
||||
} else if (accountType == AccountType.QY) {
|
||||
this.weixinAccount = ConfigUtil.getWeixinQyAccount();
|
||||
} else {
|
||||
this.weixinAccount = null;
|
||||
}
|
||||
}
|
||||
|
||||
public AbstractTokenHolder(WeixinAccount weixinAccount) {
|
||||
|
||||
@ -13,6 +13,7 @@ import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.Response;
|
||||
import com.foxinmy.weixin4j.model.Token;
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.type.AccountType;
|
||||
import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||
import com.foxinmy.weixin4j.xml.XStream;
|
||||
|
||||
@ -24,23 +25,20 @@ import com.foxinmy.weixin4j.xml.XStream;
|
||||
* @date 2014年9月27日
|
||||
* @since JDK 1.7
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96access_token">获取token说明</a>
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96access_token">微信公众平台获取token说明</a>
|
||||
* @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 FileTokenHolder extends AbstractTokenHolder {
|
||||
|
||||
public FileTokenHolder() {
|
||||
super();
|
||||
public FileTokenHolder(AccountType accountType) {
|
||||
super(accountType);
|
||||
}
|
||||
|
||||
public FileTokenHolder(WeixinAccount weixinAccount) {
|
||||
super(weixinAccount);
|
||||
}
|
||||
|
||||
public FileTokenHolder(String appid, String appsecret) {
|
||||
this(new WeixinAccount(appid, appsecret));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取token
|
||||
* <p>
|
||||
@ -55,14 +53,13 @@ public class FileTokenHolder extends AbstractTokenHolder {
|
||||
*/
|
||||
@Override
|
||||
public Token getToken() throws WeixinException {
|
||||
String appid = getAccount().getAppId();
|
||||
String appsecret = getAccount().getAppSecret();
|
||||
if (StringUtils.isBlank(appid) || StringUtils.isBlank(appsecret)) {
|
||||
String id = weixinAccount.getId();
|
||||
if (StringUtils.isBlank(id) || StringUtils.isBlank(weixinAccount.getSecret())) {
|
||||
throw new IllegalArgumentException(
|
||||
"appid or appsecret not be null!");
|
||||
"id or secret not be null!");
|
||||
}
|
||||
File token_file = new File(String.format("%s/token_%s.xml",
|
||||
ConfigUtil.getValue("token_path"), appid));
|
||||
ConfigUtil.getValue("token_path"), id));
|
||||
Token token = null;
|
||||
Calendar ca = Calendar.getInstance();
|
||||
long now_time = ca.getTimeInMillis();
|
||||
@ -78,8 +75,7 @@ public class FileTokenHolder extends AbstractTokenHolder {
|
||||
} else {
|
||||
token_file.createNewFile();
|
||||
}
|
||||
String api_token_uri = String.format(tokenUrl, appid, appsecret);
|
||||
Response response = request.get(api_token_uri);
|
||||
Response response = request.get(weixinAccount.getTokenUrl());
|
||||
token = response.getAsObject(new TypeReference<Token>() {
|
||||
});
|
||||
token.setTime(now_time);
|
||||
|
||||
@ -11,6 +11,7 @@ import com.alibaba.fastjson.TypeReference;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.model.Token;
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.type.AccountType;
|
||||
|
||||
/**
|
||||
* 基于redis保存的Token获取类
|
||||
@ -20,7 +21,10 @@ import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
* @date 2014年9月27日
|
||||
* @since JDK 1.7
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96access_token">获取token说明</a>
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96access_token">微信公众平台获取token说明</a>
|
||||
* @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 RedisTokenHolder extends AbstractTokenHolder {
|
||||
@ -37,47 +41,39 @@ public class RedisTokenHolder extends AbstractTokenHolder {
|
||||
this.jedisPool = new JedisPool(poolConfig, host, port);
|
||||
}
|
||||
|
||||
public RedisTokenHolder() {
|
||||
this("localhost", 6379);
|
||||
}
|
||||
|
||||
public RedisTokenHolder(String host, int port) {
|
||||
super();
|
||||
public RedisTokenHolder(String host, int port, AccountType accountType) {
|
||||
super(accountType);
|
||||
createPool(host, port);
|
||||
}
|
||||
|
||||
public RedisTokenHolder(AccountType accountType) {
|
||||
this("localhost", 6379, accountType);
|
||||
}
|
||||
|
||||
public RedisTokenHolder(WeixinAccount weixinAccount) {
|
||||
this(weixinAccount, "localhost", 6379);
|
||||
this("localhost", 6379, weixinAccount);
|
||||
}
|
||||
|
||||
public RedisTokenHolder(String appId, String appSecret, String host,
|
||||
int port) {
|
||||
this(new WeixinAccount(appId, appSecret), host, port);
|
||||
}
|
||||
|
||||
public RedisTokenHolder(WeixinAccount weixinAccount, String host, int port) {
|
||||
public RedisTokenHolder(String host, int port, WeixinAccount weixinAccount) {
|
||||
super(weixinAccount);
|
||||
createPool(host, port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Token getToken() throws WeixinException {
|
||||
String appid = getAccount().getAppId();
|
||||
String appsecret = getAccount().getAppSecret();
|
||||
if (StringUtils.isBlank(appid) || StringUtils.isBlank(appsecret)) {
|
||||
throw new IllegalArgumentException(
|
||||
"appid or appsecret not be null!");
|
||||
String id = weixinAccount.getId();
|
||||
if (StringUtils.isBlank(id)
|
||||
|| StringUtils.isBlank(weixinAccount.getSecret())) {
|
||||
throw new IllegalArgumentException("id or secret not be null!");
|
||||
}
|
||||
Token token = null;
|
||||
Jedis jedis = null;
|
||||
try {
|
||||
jedis = jedisPool.getResource();
|
||||
String key = String.format("token:%s", appid);
|
||||
String key = String.format("token:%s", id);
|
||||
String accessToken = jedis.get(key);
|
||||
if (StringUtils.isBlank(accessToken)) {
|
||||
String api_token_uri = String
|
||||
.format(tokenUrl, appid, appsecret);
|
||||
token = request.get(api_token_uri).getAsObject(
|
||||
token = request.get(weixinAccount.getTokenUrl()).getAsObject(
|
||||
new TypeReference<Token>() {
|
||||
});
|
||||
jedis.setex(key, token.getExpiresIn() - 3,
|
||||
|
||||
@ -18,6 +18,5 @@ import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
*/
|
||||
public interface TokenHolder {
|
||||
public WeixinAccount getAccount();
|
||||
|
||||
public Token getToken() throws WeixinException;
|
||||
}
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
package com.foxinmy.weixin4j.type;
|
||||
|
||||
/**
|
||||
* 账号类型
|
||||
*
|
||||
* @className AccountType
|
||||
* @author jy
|
||||
* @date 2014年11月18日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public enum AccountType {
|
||||
MP, QY
|
||||
}
|
||||
@ -5,7 +5,8 @@ import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.model.WeixinMpAccount;
|
||||
import com.foxinmy.weixin4j.model.WeixinQyAccount;
|
||||
|
||||
/**
|
||||
* 商户配置工具类
|
||||
@ -33,8 +34,13 @@ public class ConfigUtil {
|
||||
return weixinBundle.getString(key);
|
||||
}
|
||||
|
||||
public static WeixinAccount getWeixinAccount() {
|
||||
public static WeixinMpAccount getWeixinMpAccount() {
|
||||
String text = getValue("account");
|
||||
return JSON.parseObject(text, WeixinAccount.class);
|
||||
return JSON.parseObject(text, WeixinMpAccount.class);
|
||||
}
|
||||
|
||||
public static WeixinQyAccount getWeixinQyAccount() {
|
||||
String text = getValue("account");
|
||||
return JSON.parseObject(text, WeixinQyAccount.class);
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,29 +19,6 @@
|
||||
</modules>
|
||||
<build>
|
||||
<finalName>weixin4j-mp</finalName>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>${maven.assembly.plugin.version}</version>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>src/main/assembly.xml</descriptor>
|
||||
</descriptors>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
||||
@ -46,7 +46,7 @@ weixin.properties说明
|
||||
|
||||
示例(properties中换行用右斜杆\\)
|
||||
|
||||
> account={"appId":"appId","appSecret":"appSecret",
|
||||
> account={"id":"appId","secret":"appSecret",
|
||||
> "token":"开放者的token 非必须","openId":"公众号的openid 非必须",
|
||||
> "encodingAesKey":"公众号设置了加密方式且为「安全模式」需要填入",
|
||||
> "mchId":"V3.x版本下的微信商户号",
|
||||
@ -69,7 +69,6 @@ weixin.properties说明
|
||||
3.针对`token`存储有两种方案,`File存储`/`Redis存储`,当然也可自己实现`TokenHolder`(继承`AbstractTokenHolder`并重写`getToken`方法),默认使用文件(xml)的方式保存token,如果环境中支持`redis`,建议使用`RedisTokenHolder`.
|
||||
|
||||
WeixinProxy weixinProxy = new WeixinProxy(new RedisTokenHolder());
|
||||
// weixinProxy = new WeixinProxy(new RedisTokenHolder(appid,appsecret));
|
||||
// weixinProxy = new WeixinProxy(new RedisTokenHolder(weixinAccount));
|
||||
|
||||
4.`mvn package`.
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
</parent>
|
||||
<artifactId>weixin4j-mp-api</artifactId>
|
||||
<name>weixin4j-mp-api</name>
|
||||
<url>https://github.com/foxinmy/weixin4j/tree/master/weixin4j-mp/weixin4j-api</url>
|
||||
<url>https://github.com/foxinmy/weixin4j/tree/master/weixin4j-mp/weixin4j-mp-api</url>
|
||||
<description>微信公众号API</description>
|
||||
<build>
|
||||
<finalName>weixin4j-mp-api</finalName>
|
||||
|
||||
@ -10,7 +10,7 @@ import com.alibaba.fastjson.JSONObject;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.JsonResult;
|
||||
import com.foxinmy.weixin4j.http.XmlResult;
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.model.WeixinMpAccount;
|
||||
import com.foxinmy.weixin4j.mp.api.CustomApi;
|
||||
import com.foxinmy.weixin4j.mp.api.GroupApi;
|
||||
import com.foxinmy.weixin4j.mp.api.HelperApi;
|
||||
@ -45,10 +45,11 @@ import com.foxinmy.weixin4j.mp.type.BillType;
|
||||
import com.foxinmy.weixin4j.mp.type.IdQuery;
|
||||
import com.foxinmy.weixin4j.token.FileTokenHolder;
|
||||
import com.foxinmy.weixin4j.token.TokenHolder;
|
||||
import com.foxinmy.weixin4j.type.AccountType;
|
||||
import com.foxinmy.weixin4j.type.MediaType;
|
||||
|
||||
/**
|
||||
* 微信服务实现
|
||||
* 微信公众平台接口实现
|
||||
*
|
||||
* @className WeixinProxy
|
||||
* @author jy.hu
|
||||
@ -74,18 +75,18 @@ public class WeixinProxy {
|
||||
* 默认采用文件存放Token信息
|
||||
*/
|
||||
public WeixinProxy() {
|
||||
this(new FileTokenHolder());
|
||||
this(new FileTokenHolder(AccountType.MP));
|
||||
}
|
||||
|
||||
/**
|
||||
* appid,appsecret<br/>
|
||||
* appid,appsecret<br>
|
||||
* <font color="red">将无法调用支付相关接口</font>
|
||||
*
|
||||
* @param appid
|
||||
* @param appsecret
|
||||
*/
|
||||
public WeixinProxy(String appid, String appsecret) {
|
||||
this(new FileTokenHolder(appid, appsecret));
|
||||
this(new WeixinMpAccount(appid, appsecret));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -93,7 +94,7 @@ public class WeixinProxy {
|
||||
*
|
||||
* @param weixinAccount
|
||||
*/
|
||||
public WeixinProxy(WeixinAccount weixinAccount) {
|
||||
public WeixinProxy(WeixinMpAccount weixinAccount) {
|
||||
this(new FileTokenHolder(weixinAccount));
|
||||
}
|
||||
|
||||
@ -793,7 +794,7 @@ public class WeixinProxy {
|
||||
* @throws WeixinException
|
||||
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
||||
*/
|
||||
public Order orderQueryV2(WeixinAccount weixinAccount, String outTradeNo)
|
||||
public Order orderQueryV2(WeixinMpAccount weixinAccount, String outTradeNo)
|
||||
throws WeixinException {
|
||||
return payApi.orderQueryV2(outTradeNo);
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ 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.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.model.WeixinMpAccount;
|
||||
import com.foxinmy.weixin4j.mp.model.SemQuery;
|
||||
import com.foxinmy.weixin4j.mp.model.SemResult;
|
||||
import com.foxinmy.weixin4j.token.TokenHolder;
|
||||
@ -65,10 +65,10 @@ public class HelperApi extends BaseApi {
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public SemResult semantic(SemQuery semQuery) throws WeixinException {
|
||||
WeixinAccount weixinAccount = tokenHolder.getAccount();
|
||||
WeixinMpAccount weixinAccount = (WeixinMpAccount) tokenHolder.getAccount();
|
||||
String semantic_uri = getRequestUri("semantic_uri");
|
||||
Token token = tokenHolder.getToken();
|
||||
semQuery.appid(weixinAccount.getAppId());
|
||||
semQuery.appid(weixinAccount.getId());
|
||||
Response response = request.post(
|
||||
String.format(semantic_uri, token.getAccessToken()),
|
||||
semQuery.toJson());
|
||||
|
||||
@ -41,7 +41,7 @@ import com.foxinmy.weixin4j.http.Response;
|
||||
import com.foxinmy.weixin4j.http.SSLHttpRequest;
|
||||
import com.foxinmy.weixin4j.http.XmlResult;
|
||||
import com.foxinmy.weixin4j.model.Token;
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.model.WeixinMpAccount;
|
||||
import com.foxinmy.weixin4j.mp.payment.ApiResult;
|
||||
import com.foxinmy.weixin4j.mp.payment.PayUtil;
|
||||
import com.foxinmy.weixin4j.mp.payment.Refund;
|
||||
@ -70,11 +70,11 @@ import com.foxinmy.weixin4j.util.RandomUtil;
|
||||
*/
|
||||
public class PayApi extends BaseApi {
|
||||
private final TokenHolder tokenHolder;
|
||||
private final WeixinAccount weixinAccount;
|
||||
private final WeixinMpAccount weixinAccount;
|
||||
|
||||
public PayApi(TokenHolder tokenHolder) {
|
||||
this.tokenHolder = tokenHolder;
|
||||
this.weixinAccount = tokenHolder.getAccount();
|
||||
this.weixinAccount = (WeixinMpAccount) tokenHolder.getAccount();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -101,7 +101,7 @@ public class PayApi extends BaseApi {
|
||||
Token token = tokenHolder.getToken();
|
||||
|
||||
Map<String, String> param = new HashMap<String, String>();
|
||||
param.put("appid", weixinAccount.getAppId());
|
||||
param.put("appid", weixinAccount.getId());
|
||||
param.put("appkey", weixinAccount.getPaySignKey());
|
||||
param.put("openid", openId);
|
||||
param.put("transid", transid);
|
||||
@ -142,14 +142,14 @@ public class PayApi extends BaseApi {
|
||||
|
||||
String timestamp = DateUtil.timestamp2string();
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("appid", weixinAccount.getAppId());
|
||||
obj.put("appid", weixinAccount.getId());
|
||||
obj.put("appkey", weixinAccount.getPaySignKey());
|
||||
obj.put("package", sb.toString());
|
||||
obj.put("timestamp", timestamp);
|
||||
String signature = PayUtil.paysignSha(obj, null);
|
||||
|
||||
obj.clear();
|
||||
obj.put("appid", weixinAccount.getAppId());
|
||||
obj.put("appid", weixinAccount.getId());
|
||||
obj.put("package", sb.toString());
|
||||
obj.put("timestamp", timestamp);
|
||||
obj.put("app_signature", signature);
|
||||
@ -494,7 +494,7 @@ public class PayApi extends BaseApi {
|
||||
String _billDate = DateUtil.fortmat2yyyyMMdd(billDate);
|
||||
String bill_path = ConfigUtil.getValue("bill_path");
|
||||
String fileName = String.format("%s_%s_%s.xls", _billDate, billType
|
||||
.name().toLowerCase(), weixinAccount.getAppId());
|
||||
.name().toLowerCase(), weixinAccount.getId());
|
||||
File file = new File(String.format("%s/%s", bill_path, fileName));
|
||||
if (file.exists()) {
|
||||
return file;
|
||||
@ -592,7 +592,7 @@ public class PayApi extends BaseApi {
|
||||
*/
|
||||
private Map<String, String> baseMapV3(IdQuery idQuery) {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("appid", weixinAccount.getAppId());
|
||||
map.put("appid", weixinAccount.getId());
|
||||
map.put("mch_id", weixinAccount.getMchId());
|
||||
map.put("nonce_str", RandomUtil.generateString(16));
|
||||
if (StringUtils.isNotBlank(weixinAccount.getDeviceInfo())) {
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.foxinmy.weixin4j.mp.api;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.JsonResult;
|
||||
import com.foxinmy.weixin4j.http.Response;
|
||||
@ -39,9 +40,9 @@ public class TmplApi extends BaseApi {
|
||||
throws WeixinException {
|
||||
Token token = tokenHolder.getToken();
|
||||
String template_send_uri = getRequestUri("template_send_uri");
|
||||
String para = JSON.toJSONString(tplMessage);
|
||||
Response response = request.post(
|
||||
String.format(template_send_uri, token.getAccessToken()),
|
||||
tplMessage.toJson());
|
||||
String.format(template_send_uri, token.getAccessToken()), para);
|
||||
|
||||
return response.getAsJsonResult();
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@ public class UserApi extends BaseApi {
|
||||
WeixinAccount weixinAccount = tokenHolder.getAccount();
|
||||
String user_token_uri = getRequestUri("sns_user_token_uri");
|
||||
Response response = request.get(String.format(user_token_uri,
|
||||
weixinAccount.getAppId(), weixinAccount.getAppSecret(), code));
|
||||
weixinAccount.getId(), weixinAccount.getSecret(), code));
|
||||
|
||||
return response.getAsObject(new TypeReference<OauthToken>() {
|
||||
});
|
||||
|
||||
@ -55,11 +55,10 @@ public class Group implements Serializable {
|
||||
/**
|
||||
* 返回创建分组所需的json格式字符串
|
||||
*
|
||||
* @return {"group": {"id": 107, "name": "test"}}
|
||||
* @return {"group": {"name": "test"}}
|
||||
*/
|
||||
public String toCreateJson() {
|
||||
return String.format("{\"group\":{\"id\":%s,\"name\":\"%s\"}}", id,
|
||||
name);
|
||||
return String.format("{\"group\":{\"name\":\"%s\"}}", name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -4,8 +4,8 @@ import java.io.Serializable;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.foxinmy.weixin4j.model.Gender;
|
||||
import com.foxinmy.weixin4j.mp.type.FaceSize;
|
||||
import com.foxinmy.weixin4j.mp.type.Gender;
|
||||
import com.foxinmy.weixin4j.mp.type.Lang;
|
||||
|
||||
/**
|
||||
|
||||
@ -4,6 +4,7 @@ import java.io.Serializable;
|
||||
import java.io.Writer;
|
||||
|
||||
import com.foxinmy.weixin4j.mp.type.ResponseType;
|
||||
import com.foxinmy.weixin4j.util.ClassUtil;
|
||||
import com.foxinmy.weixin4j.xml.XStream;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
||||
import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver;
|
||||
@ -22,6 +23,21 @@ public class BaseNotify implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 7190233634431087729L;
|
||||
|
||||
private final static XStream jsonStream = new XStream(
|
||||
new JsonHierarchicalStreamDriver() {
|
||||
public HierarchicalStreamWriter createWriter(Writer writer) {
|
||||
return new JsonWriter(writer, JsonWriter.DROP_ROOT_MODE);
|
||||
}
|
||||
});
|
||||
static {
|
||||
Class<?>[] classes = ClassUtil
|
||||
.getClasses(BaseNotify.class.getPackage())
|
||||
.toArray(new Class[0]);
|
||||
|
||||
jsonStream.setMode(XStream.NO_REFERENCES);
|
||||
jsonStream.autodetectAnnotations(true);
|
||||
jsonStream.processAnnotations(classes);
|
||||
}
|
||||
private String touser;
|
||||
private ResponseType msgtype;
|
||||
|
||||
@ -56,15 +72,7 @@ public class BaseNotify implements Serializable {
|
||||
* @return {"touser": "to","msgtype": "text","text": {"content": "123"}}
|
||||
*/
|
||||
public String toJson() {
|
||||
XStream xstream = new XStream(new JsonHierarchicalStreamDriver() {
|
||||
public HierarchicalStreamWriter createWriter(Writer writer) {
|
||||
return new JsonWriter(writer, JsonWriter.DROP_ROOT_MODE);
|
||||
}
|
||||
});
|
||||
xstream.setMode(XStream.NO_REFERENCES);
|
||||
xstream.autodetectAnnotations(true);
|
||||
xstream.processAnnotations(this.getClass());
|
||||
return xstream.toXML(this);
|
||||
return jsonStream.toXML(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -4,7 +4,7 @@ import java.util.Date;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.model.WeixinMpAccount;
|
||||
import com.foxinmy.weixin4j.util.RandomUtil;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
@ -33,10 +33,10 @@ public class MicroPayPackage extends PayPackage {
|
||||
|
||||
}
|
||||
|
||||
public MicroPayPackage(WeixinAccount weixinAccount, String body,
|
||||
public MicroPayPackage(WeixinMpAccount weixinAccount, String body,
|
||||
String attach, String out_trade_no, double total_fee,
|
||||
String spbill_create_ip, String auth_code) {
|
||||
this(weixinAccount.getAppId(), weixinAccount.getMchId(), weixinAccount
|
||||
this(weixinAccount.getId(), weixinAccount.getMchId(), weixinAccount
|
||||
.getDeviceInfo(), RandomUtil.generateString(16), body, attach,
|
||||
out_trade_no, total_fee, spbill_create_ip, null, null, null,
|
||||
auth_code);
|
||||
|
||||
@ -12,7 +12,7 @@ import com.alibaba.fastjson.JSONObject;
|
||||
import com.foxinmy.weixin4j.exception.PayException;
|
||||
import com.foxinmy.weixin4j.http.XmlResult;
|
||||
import com.foxinmy.weixin4j.model.Consts;
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.model.WeixinMpAccount;
|
||||
import com.foxinmy.weixin4j.mp.payment.v2.NativePayNotifyV2;
|
||||
import com.foxinmy.weixin4j.mp.payment.v2.NativePayResponseV2;
|
||||
import com.foxinmy.weixin4j.mp.payment.v2.PayFeedback;
|
||||
@ -46,7 +46,7 @@ public class PayAction {
|
||||
public JSONObject jsPay() {
|
||||
JSONObject obj = new JSONObject();
|
||||
PayPackage payPackage = null;
|
||||
WeixinAccount weixinAccount = ConfigUtil.getWeixinAccount();
|
||||
WeixinMpAccount weixinAccount = ConfigUtil.getWeixinMpAccount();
|
||||
// V3 支付
|
||||
payPackage = new PayPackageV3(weixinAccount, "用户openid", "商品描述",
|
||||
"系统内部订单号", 1d, "IP地址", TradeType.JSAPI);
|
||||
@ -111,7 +111,7 @@ public class PayAction {
|
||||
log.info("jspay_notify_orderinfo,{}", objMap);
|
||||
JsPayNotify payNotify = XStream.get(inputStream, JsPayNotify.class);
|
||||
log.info("jspay_notify_userinfo,{}", payNotify);
|
||||
WeixinAccount weixinAccount = ConfigUtil.getWeixinAccount();
|
||||
WeixinMpAccount weixinAccount = ConfigUtil.getWeixinMpAccount();
|
||||
// 验证财付通签名
|
||||
String sign = objMap.get("sign");
|
||||
objMap.remove("sign");
|
||||
@ -153,7 +153,7 @@ public class PayAction {
|
||||
log.info("jaapi_notify_order_info:", order);
|
||||
String sign = order.getSign();
|
||||
order.setSign(null);
|
||||
WeixinAccount weixinAccount = ConfigUtil.getWeixinAccount();
|
||||
WeixinMpAccount weixinAccount = ConfigUtil.getWeixinMpAccount();
|
||||
String valid_sign = PayUtil.paysignMd5(order,
|
||||
weixinAccount.getPaySignKey());
|
||||
log.info("微信签名----->sign={},vaild_sign={}", sign, valid_sign);
|
||||
@ -187,7 +187,7 @@ public class PayAction {
|
||||
NativePayNotifyV2 payNotify = XStream.get(inputStream,
|
||||
NativePayNotifyV2.class);
|
||||
log.info("native_pay_notify,{}", payNotify);
|
||||
WeixinAccount weixinAccount = ConfigUtil.getWeixinAccount();
|
||||
WeixinMpAccount weixinAccount = ConfigUtil.getWeixinMpAccount();
|
||||
String sign = payNotify.getPaySign();
|
||||
payNotify.setPaySign(null);
|
||||
payNotify.setSignType(null);
|
||||
@ -227,7 +227,7 @@ public class PayAction {
|
||||
NativePayNotifyV3.class);
|
||||
String sign = payNotify.getSign();
|
||||
payNotify.setSign(null);
|
||||
WeixinAccount weixinAccount = ConfigUtil.getWeixinAccount();
|
||||
WeixinMpAccount weixinAccount = ConfigUtil.getWeixinMpAccount();
|
||||
String valid_sign = PayUtil.paysignMd5(payNotify,
|
||||
weixinAccount.getPaySignKey());
|
||||
log.info("微信签名----->sign={},vaild_sign={}", sign, valid_sign);
|
||||
@ -272,7 +272,7 @@ public class PayAction {
|
||||
public String warning(InputStream inputStream) {
|
||||
PayWarn payWarn = XStream.get(inputStream, PayWarn.class);
|
||||
log.info("pay_warning,{}", payWarn);
|
||||
WeixinAccount weixinAccount = ConfigUtil.getWeixinAccount();
|
||||
WeixinMpAccount weixinAccount = ConfigUtil.getWeixinMpAccount();
|
||||
String sign = payWarn.getPaySign();
|
||||
payWarn.setPaySign(null);
|
||||
payWarn.setSignType(null);
|
||||
@ -293,7 +293,7 @@ public class PayAction {
|
||||
public String feedback(InputStream inputStream) {
|
||||
PayFeedback feedback = XStream.get(inputStream, PayFeedback.class);
|
||||
log.info("pay_feedback_info:{}", feedback);
|
||||
WeixinAccount weixinAccount = ConfigUtil.getWeixinAccount();
|
||||
WeixinMpAccount weixinAccount = ConfigUtil.getWeixinMpAccount();
|
||||
// 验证微信签名
|
||||
Map<String, String> obj = new HashMap<String, String>();
|
||||
obj.put("openid", feedback.getOpenId());
|
||||
|
||||
@ -13,7 +13,8 @@ import com.foxinmy.weixin4j.exception.PayException;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.HttpRequest;
|
||||
import com.foxinmy.weixin4j.http.Response;
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.model.Consts;
|
||||
import com.foxinmy.weixin4j.model.WeixinMpAccount;
|
||||
import com.foxinmy.weixin4j.mp.payment.v2.JsPayRequestV2;
|
||||
import com.foxinmy.weixin4j.mp.payment.v2.NativePayResponseV2;
|
||||
import com.foxinmy.weixin4j.mp.payment.v2.PayPackageV2;
|
||||
@ -37,11 +38,6 @@ import com.foxinmy.weixin4j.xml.XStream;
|
||||
* @see
|
||||
*/
|
||||
public class PayUtil {
|
||||
private static final String UNIFIEDORDER = "https://api.mch.weixin.qq.com/pay/unifiedorder";
|
||||
private static final String MICROPAYURL = "https://api.mch.weixin.qq.com/pay/micropay";
|
||||
private static final String NATIVEURLV2 = "weixin://wxpay/bizpayurl?sign=%s&appid=%s&productid=%s×tamp=%s&noncestr=%s";
|
||||
private static final String NATIVEURLV3 = "weixin://wxpay/bizpayurl?sign=%s&appid=%s&mch_id=%s&product_id=%s&time_stamp=%s&nonce_str=%s";
|
||||
|
||||
/**
|
||||
* 生成JSAPI字符串
|
||||
*
|
||||
@ -53,7 +49,7 @@ public class PayUtil {
|
||||
* @throws PayException
|
||||
*/
|
||||
public static String createPayJsRequestJson(PayPackage payPackage,
|
||||
WeixinAccount weixinAccount) throws PayException {
|
||||
WeixinMpAccount weixinAccount) throws PayException {
|
||||
if (payPackage instanceof PayPackageV2) {
|
||||
return createPayJsRequestJsonV2((PayPackageV2) payPackage,
|
||||
weixinAccount);
|
||||
@ -74,7 +70,7 @@ public class PayUtil {
|
||||
* @return
|
||||
*/
|
||||
public static String createPayJsRequestJsonV2(PayPackageV2 payPackage,
|
||||
WeixinAccount weixinAccount) {
|
||||
WeixinMpAccount weixinAccount) {
|
||||
if (StringUtils.isBlank(payPackage.getPartner())) {
|
||||
payPackage.setPartner(weixinAccount.getPartnerId());
|
||||
}
|
||||
@ -101,7 +97,7 @@ public class PayUtil {
|
||||
* @return
|
||||
*/
|
||||
public static String createPayJsRequestJsonV2(String body, String orderNo,
|
||||
double orderFee, String ip, WeixinAccount weixinAccount) {
|
||||
double orderFee, String ip, WeixinMpAccount weixinAccount) {
|
||||
PayPackageV2 payPackage = new PayPackageV2(body, orderNo, orderFee, ip);
|
||||
payPackage.setPartner(weixinAccount.getPartnerId());
|
||||
return createPayJsRequestJsonV2(payPackage, weixinAccount);
|
||||
@ -168,7 +164,7 @@ public class PayUtil {
|
||||
*/
|
||||
public static String createPayJsRequestJsonV3(String openId, String body,
|
||||
String orderNo, double orderFee, String ip, String notifyUrl,
|
||||
WeixinAccount weixinAccount) throws PayException {
|
||||
WeixinMpAccount weixinAccount) throws PayException {
|
||||
PayPackageV3 payPackage = new PayPackageV3(weixinAccount, openId, body,
|
||||
orderNo, orderFee, ip, TradeType.JSAPI);
|
||||
payPackage.setNotify_url(notifyUrl);
|
||||
@ -186,7 +182,7 @@ public class PayUtil {
|
||||
* @throws PayException
|
||||
*/
|
||||
public static String createPayJsRequestJsonV3(PayPackageV3 payPackage,
|
||||
WeixinAccount weixinAccount) throws PayException {
|
||||
WeixinMpAccount weixinAccount) throws PayException {
|
||||
String paySignKey = weixinAccount.getPaySignKey();
|
||||
payPackage.setSign(paysignMd5(payPackage, paySignKey));
|
||||
PrePay prePay = createPrePay(payPackage);
|
||||
@ -201,7 +197,7 @@ public class PayUtil {
|
||||
String payJsRequestXml = XStream.to(payPackage).replaceAll("__", "_");
|
||||
HttpRequest request = new HttpRequest();
|
||||
try {
|
||||
Response response = request.post(UNIFIEDORDER, payJsRequestXml);
|
||||
Response response = request.post(Consts.UNIFIEDORDER, payJsRequestXml);
|
||||
prePay = response.getAsObject(new TypeReference<PrePay>() {
|
||||
});
|
||||
} catch (WeixinException e) {
|
||||
@ -263,17 +259,17 @@ public class PayUtil {
|
||||
* 与订单ID等价
|
||||
* @return
|
||||
*/
|
||||
public String createNativePayRequestURLV2(WeixinAccount weixinAccount,
|
||||
public String createNativePayRequestURLV2(WeixinMpAccount weixinAccount,
|
||||
String productId) {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
String timestamp = DateUtil.timestamp2string();
|
||||
String noncestr = RandomUtil.generateString(16);
|
||||
map.put("appid", weixinAccount.getAppId());
|
||||
map.put("appid", weixinAccount.getId());
|
||||
map.put("timestamp", timestamp);
|
||||
map.put("noncestr", noncestr);
|
||||
map.put("productid", productId);
|
||||
String sign = paysignSha(map, weixinAccount.getPaySignKey());
|
||||
return String.format(NATIVEURLV2, sign, weixinAccount.getAppId(),
|
||||
return String.format(Consts.NATIVEURLV2, sign, weixinAccount.getId(),
|
||||
productId, timestamp, noncestr);
|
||||
}
|
||||
|
||||
@ -286,29 +282,29 @@ public class PayUtil {
|
||||
* 与订单ID等价
|
||||
* @return
|
||||
*/
|
||||
public String createNativePayRequestURLV3(WeixinAccount weixinAccount,
|
||||
public String createNativePayRequestURLV3(WeixinMpAccount weixinAccount,
|
||||
String productId) {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
String timestamp = DateUtil.timestamp2string();
|
||||
String noncestr = RandomUtil.generateString(16);
|
||||
map.put("appid", weixinAccount.getAppId());
|
||||
map.put("appid", weixinAccount.getId());
|
||||
map.put("mch_id", weixinAccount.getMchId());
|
||||
map.put("time_stamp", timestamp);
|
||||
map.put("nonce_str", noncestr);
|
||||
map.put("product_id", productId);
|
||||
String sign = paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
return String.format(NATIVEURLV3, sign, weixinAccount.getAppId(),
|
||||
return String.format(Consts.NATIVEURLV3, sign, weixinAccount.getId(),
|
||||
weixinAccount.getMchId(), productId, timestamp, noncestr);
|
||||
}
|
||||
|
||||
public static String createNativePayRequestV2(WeixinAccount weixinAccount,
|
||||
public static String createNativePayRequestV2(WeixinMpAccount weixinAccount,
|
||||
PayPackageV2 payPackage) {
|
||||
NativePayResponseV2 payRequest = new NativePayResponseV2(weixinAccount,
|
||||
payPackage);
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
String timestamp = DateUtil.timestamp2string();
|
||||
String noncestr = RandomUtil.generateString(16);
|
||||
map.put("appid", weixinAccount.getAppId());
|
||||
map.put("appid", weixinAccount.getId());
|
||||
map.put("timestamp", timestamp);
|
||||
map.put("noncestr", noncestr);
|
||||
map.put("package", payRequest.getPackageInfo());
|
||||
@ -336,12 +332,12 @@ public class PayUtil {
|
||||
* @param weixinAccount
|
||||
* 商户信息
|
||||
* @return 返回数据
|
||||
* @see {@link com.foxinmy.weixin4j.mp.payment.PayUtil#createMicroPay(MicroPayPackage, WeixinAccount)}
|
||||
* @see {@link com.foxinmy.weixin4j.mp.payment.PayUtil#createMicroPay(MicroPayPackage, WeixinMpAccount)}
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public static com.foxinmy.weixin4j.mp.payment.v3.Order createMicroPay(
|
||||
String authCode, String body, String attach, String orderNo,
|
||||
double orderFee, String ip, WeixinAccount weixinAccount)
|
||||
double orderFee, String ip, WeixinMpAccount weixinAccount)
|
||||
throws WeixinException {
|
||||
MicroPayPackage payPackage = new MicroPayPackage(weixinAccount, body,
|
||||
attach, orderNo, orderFee, ip, authCode);
|
||||
@ -359,13 +355,13 @@ public class PayUtil {
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public static com.foxinmy.weixin4j.mp.payment.v3.Order createMicroPay(
|
||||
MicroPayPackage payPackage, WeixinAccount weixinAccount)
|
||||
MicroPayPackage payPackage, WeixinMpAccount weixinAccount)
|
||||
throws WeixinException {
|
||||
String sign = paysignMd5(payPackage, weixinAccount.getPaySignKey());
|
||||
payPackage.setSign(sign);
|
||||
String para = XStream.to(payPackage).replaceAll("__", "_");
|
||||
HttpRequest request = new HttpRequest();
|
||||
Response response = request.post(MICROPAYURL, para);
|
||||
Response response = request.post(Consts.MICROPAYURL, para);
|
||||
return response
|
||||
.getAsObject(new TypeReference<com.foxinmy.weixin4j.mp.payment.v3.Order>() {
|
||||
});
|
||||
|
||||
@ -5,7 +5,7 @@ import java.beans.Transient;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.model.WeixinMpAccount;
|
||||
import com.foxinmy.weixin4j.mp.payment.PayRequest;
|
||||
import com.foxinmy.weixin4j.util.MapUtil;
|
||||
|
||||
@ -28,8 +28,8 @@ public class JsPayRequestV2 extends PayRequest {
|
||||
|
||||
private static final long serialVersionUID = -5972173459255255197L;
|
||||
|
||||
public JsPayRequestV2(WeixinAccount weixinAccount, PayPackageV2 payPackage) {
|
||||
this.setAppId(weixinAccount.getAppId());
|
||||
public JsPayRequestV2(WeixinMpAccount weixinAccount, PayPackageV2 payPackage) {
|
||||
this.setAppId(weixinAccount.getId());
|
||||
this.setPackageInfo(package2string(payPackage,
|
||||
weixinAccount.getPartnerKey()));
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package com.foxinmy.weixin4j.mp.payment.v2;
|
||||
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.model.WeixinMpAccount;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
@ -21,7 +21,7 @@ public class NativePayResponseV2 extends JsPayRequestV2 {
|
||||
@XStreamAlias("RetErrMsg")
|
||||
private String retMsg;
|
||||
|
||||
public NativePayResponseV2(WeixinAccount weixinAccount,
|
||||
public NativePayResponseV2(WeixinMpAccount weixinAccount,
|
||||
PayPackageV2 payPackage) {
|
||||
super(weixinAccount, payPackage);
|
||||
this.retCode = "0";
|
||||
|
||||
@ -4,7 +4,7 @@ import java.util.Date;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.model.WeixinMpAccount;
|
||||
import com.foxinmy.weixin4j.mp.payment.PayPackage;
|
||||
import com.foxinmy.weixin4j.mp.type.TradeType;
|
||||
import com.foxinmy.weixin4j.util.RandomUtil;
|
||||
@ -38,17 +38,17 @@ public class PayPackageV3 extends PayPackage {
|
||||
|
||||
}
|
||||
|
||||
public PayPackageV3(WeixinAccount weixinAccount, String openId,
|
||||
public PayPackageV3(WeixinMpAccount weixinAccount, String openId,
|
||||
String body, String out_trade_no, double total_fee,
|
||||
String spbill_create_ip, TradeType tradeType) {
|
||||
this(weixinAccount, openId, body, null, out_trade_no, total_fee,
|
||||
spbill_create_ip, null, tradeType);
|
||||
}
|
||||
|
||||
public PayPackageV3(WeixinAccount weixinAccount, String openId,
|
||||
public PayPackageV3(WeixinMpAccount weixinAccount, String openId,
|
||||
String body, String attach, String out_trade_no, double total_fee,
|
||||
String spbill_create_ip, String notify_url, TradeType tradeType) {
|
||||
this(weixinAccount.getAppId(), weixinAccount.getMchId(), weixinAccount
|
||||
this(weixinAccount.getId(), weixinAccount.getMchId(), weixinAccount
|
||||
.getDeviceInfo(), RandomUtil.generateString(16), body, attach,
|
||||
out_trade_no, total_fee, spbill_create_ip, null, null, null,
|
||||
notify_url, tradeType, openId, null);
|
||||
|
||||
@ -1,16 +1,11 @@
|
||||
package com.foxinmy.weixin4j.mp.response;
|
||||
|
||||
import java.io.Writer;
|
||||
|
||||
import com.foxinmy.weixin4j.model.BaseMsg;
|
||||
import com.foxinmy.weixin4j.mp.type.ResponseType;
|
||||
import com.foxinmy.weixin4j.msg.BaseMessage;
|
||||
import com.foxinmy.weixin4j.util.ClassUtil;
|
||||
import com.foxinmy.weixin4j.xml.XStream;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
||||
import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver;
|
||||
import com.thoughtworks.xstream.io.json.JsonWriter;
|
||||
|
||||
/**
|
||||
* 响应消息基类
|
||||
@ -28,26 +23,15 @@ public class BaseResponse extends BaseMsg {
|
||||
|
||||
private static final long serialVersionUID = 7761192742840031607L;
|
||||
protected final static XStream xmlStream = XStream.get();
|
||||
private final static XStream jsonStream = new XStream(
|
||||
new JsonHierarchicalStreamDriver() {
|
||||
public HierarchicalStreamWriter createWriter(Writer writer) {
|
||||
return new JsonWriter(writer, JsonWriter.DROP_ROOT_MODE);
|
||||
}
|
||||
});
|
||||
|
||||
@XStreamAlias("MsgType")
|
||||
private ResponseType msgType; // 消息类型
|
||||
|
||||
static {
|
||||
Class<?>[] classes = ClassUtil.getClasses(
|
||||
BaseResponse.class.getPackage()).toArray(new Class[0]);
|
||||
|
||||
xmlStream.autodetectAnnotations(true);
|
||||
xmlStream.processAnnotations(classes);
|
||||
|
||||
jsonStream.setMode(XStream.NO_REFERENCES);
|
||||
jsonStream.autodetectAnnotations(true);
|
||||
jsonStream.processAnnotations(classes);
|
||||
}
|
||||
@XStreamAlias("MsgType")
|
||||
private ResponseType msgType; // 消息类型
|
||||
|
||||
public BaseResponse(ResponseType msgType) {
|
||||
this.msgType = msgType;
|
||||
@ -59,7 +43,7 @@ public class BaseResponse extends BaseMsg {
|
||||
|
||||
public BaseResponse(ResponseType msgType, String toUserName,
|
||||
String fromUserName) {
|
||||
super(toUserName,fromUserName);
|
||||
super(toUserName, fromUserName);
|
||||
this.msgType = msgType;
|
||||
|
||||
}
|
||||
@ -78,17 +62,6 @@ public class BaseResponse extends BaseMsg {
|
||||
* @return xml字符串
|
||||
*/
|
||||
public String toXml() {
|
||||
Class<? extends BaseResponse> targetClass = msgType.getMessageClass();
|
||||
xmlStream.alias("xml", targetClass);
|
||||
return xmlStream.toXML(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息对象转换为微信服务器接受的json格式字符串
|
||||
*
|
||||
* @return json字符串
|
||||
*/
|
||||
public String toJson() {
|
||||
return jsonStream.toXML(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,13 +1,9 @@
|
||||
package com.foxinmy.weixin4j.mp.response;
|
||||
|
||||
import java.beans.Transient;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
|
||||
/**
|
||||
* 模板消息
|
||||
*
|
||||
@ -115,10 +111,4 @@ public class TemplateMessage implements Serializable {
|
||||
+ template_id + ", url=" + url + ", topcolor=" + topcolor
|
||||
+ ", data=" + data + "]";
|
||||
}
|
||||
|
||||
@Transient
|
||||
@JSONField(serialize = false)
|
||||
public String toJson() {
|
||||
return JSON.toJSONString(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
package com.foxinmy.weixin4j.mp.type;
|
||||
|
||||
/**
|
||||
* 用户性别
|
||||
* @className Gender
|
||||
* @author jy
|
||||
* @date 2014年11月5日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public enum Gender {
|
||||
male(1), female(2), unknown(0);
|
||||
|
||||
private int sex;
|
||||
|
||||
Gender(int sex) {
|
||||
this.sex = sex;
|
||||
}
|
||||
|
||||
public int getInt() {
|
||||
return sex;
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
# \u6d4b\u8bd5\u4e4b\u7528 \u6b63\u5f0f\u73af\u5883\u4e0bcopy\u4e00\u4efd\u5230classpath
|
||||
# \u516c\u4f17\u53f7\u4fe1\u606f
|
||||
account={"appId":"wx4ab8f8de58159a57","appSecret":"1d4eb0f4bf556aaed539f30ed05ca795",\
|
||||
account={"id":"wx4ab8f8de58159a57","secret":"1d4eb0f4bf556aaed539f30ed05ca795",\
|
||||
"token":"\u5f00\u653e\u8005\u7684token \u975e\u5fc5\u987b","openId":"\u516c\u4f17\u53f7\u7684openid \u975e\u5fc5\u987b",\
|
||||
"encodingAesKey":"\u516c\u4f17\u53f7\u8bbe\u7f6e\u4e86\u52a0\u5bc6\u65b9\u5f0f\u4e14\u4e3a\u300c\u5b89\u5168\u6a21\u5f0f\u300d\u65f6\u9700\u8981\u586b\u5165",\
|
||||
"mchId":"V3.x\u7248\u672c\u4e0b\u7684\u5fae\u4fe1\u5546\u6237\u53f7",\
|
||||
|
||||
@ -7,6 +7,7 @@ import org.junit.Test;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.token.FileTokenHolder;
|
||||
import com.foxinmy.weixin4j.token.TokenHolder;
|
||||
import com.foxinmy.weixin4j.type.AccountType;
|
||||
|
||||
/**
|
||||
* token测试
|
||||
@ -22,7 +23,7 @@ public class TokenTest {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
tokenHolder = new FileTokenHolder();
|
||||
tokenHolder = new FileTokenHolder(AccountType.MP);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
weixin4j-mp-server
|
||||
==================
|
||||
|
||||
微信netty服务
|
||||
微信公众平台netty服务
|
||||
------------
|
||||
|
||||
功能列表
|
||||
@ -26,7 +26,7 @@ weixin4j-mp-server
|
||||
|
||||
示例(properties中换行用右斜杆\\)
|
||||
|
||||
> account={"appId":"appId","appSecret":"appSecret",
|
||||
> account={"id":"appId","secret":"appSecret",
|
||||
> "token":"开放者的token 非必须","openId":"公众号的openid 非必须",
|
||||
> "encodingAesKey":"公众号设置了加密方式且为「安全模式」时需要填入",
|
||||
> "mchId":"V3.x版本下的微信商户号",
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
</parent>
|
||||
<artifactId>weixin4j-mp-server</artifactId>
|
||||
<name>weixin4j-mp-server</name>
|
||||
<url>https://github.com/foxinmy/weixin4j/tree/master/weixin4j-mp/weixin4j-server</url>
|
||||
<url>https://github.com/foxinmy/weixin4j/tree/master/weixin4j-mp/weixin4j-mp-server</url>
|
||||
<description>微信公众号服务</description>
|
||||
<build>
|
||||
<finalName>weixin-mp-server</finalName>
|
||||
|
||||
@ -13,7 +13,7 @@ import org.apache.http.Consts;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.model.WeixinMpAccount;
|
||||
import com.foxinmy.weixin4j.mp.model.HttpWeixinMessage;
|
||||
import com.foxinmy.weixin4j.mp.type.EncryptType;
|
||||
import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||
@ -37,7 +37,7 @@ public class WeixinMessageDecoder extends
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, FullHttpRequest req,
|
||||
List<Object> out) throws Exception {
|
||||
WeixinAccount account = ConfigUtil.getWeixinAccount();
|
||||
WeixinMpAccount mpAccount = ConfigUtil.getWeixinMpAccount();
|
||||
String xmlContent = req.content().toString(Consts.UTF_8);
|
||||
HttpWeixinMessage message = new HttpWeixinMessage();
|
||||
if (StringUtils.isNotBlank(xmlContent)) {
|
||||
@ -72,10 +72,10 @@ public class WeixinMessageDecoder extends
|
||||
|
||||
message.setXmlContent(xmlContent);
|
||||
if (message.getEncryptType() == EncryptType.AES) {
|
||||
message.setXmlContent(MessageUtil.aesDecrypt(account.getAppId(),
|
||||
account.getEncodingAesKey(), message.getEncryptContent()));
|
||||
message.setXmlContent(MessageUtil.aesDecrypt(mpAccount.getId(),
|
||||
mpAccount.getEncodingAesKey(), message.getEncryptContent()));
|
||||
}
|
||||
message.setToken(account.getToken());
|
||||
message.setToken(mpAccount.getToken());
|
||||
out.add(message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ import java.util.Map;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.model.WeixinMpAccount;
|
||||
import com.foxinmy.weixin4j.mp.response.BaseResponse;
|
||||
import com.foxinmy.weixin4j.mp.util.HttpUtil;
|
||||
import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||
@ -45,13 +45,13 @@ public class WeixinMessageEncoder extends MessageToMessageEncoder<BaseResponse>
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, BaseResponse response,
|
||||
List<Object> out) throws Exception {
|
||||
WeixinAccount account = ConfigUtil.getWeixinAccount();
|
||||
WeixinMpAccount mpAccount = ConfigUtil.getWeixinMpAccount();
|
||||
String xmlContent = response.toXml();
|
||||
String nonce = RandomUtil.generateString(32);
|
||||
String timestamp = DateUtil.timestamp2string();
|
||||
String encrtypt = MessageUtil.aesEncrypt(account.getAppId(),
|
||||
account.getEncodingAesKey(), xmlContent);
|
||||
String msgSignature = MessageUtil.signature(account.getToken(), nonce,
|
||||
String encrtypt = MessageUtil.aesEncrypt(mpAccount.getId(),
|
||||
mpAccount.getEncodingAesKey(), xmlContent);
|
||||
String msgSignature = MessageUtil.signature(mpAccount.getToken(), nonce,
|
||||
timestamp, encrtypt);
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("Encrypt", encrtypt);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# \u516c\u4f17\u53f7\u4fe1\u606f
|
||||
account={"appId":"wx4ab8f8de58159a57","appSecret":"1d4eb0f4bf556aaed539f30ed05ca795",\
|
||||
account={"id":"wx4ab8f8de58159a57","secret":"1d4eb0f4bf556aaed539f30ed05ca795",\
|
||||
"token":"\u5f00\u653e\u8005\u7684token \u975e\u5fc5\u987b","openId":"\u516c\u4f17\u53f7\u7684openid \u975e\u5fc5\u987b",\
|
||||
"encodingAesKey":"\u516c\u4f17\u53f7\u8bbe\u7f6e\u4e86\u52a0\u5bc6\u65b9\u5f0f\u4e14\u4e3a\u300c\u5b89\u5168\u6a21\u5f0f\u300d\u9700\u8981\u586b\u5165",\
|
||||
"mchId":"V3.x\u7248\u672c\u4e0b\u7684\u5fae\u4fe1\u5546\u6237\u53f7",\
|
||||
|
||||
@ -1,17 +1,27 @@
|
||||
weixin4j-qy
|
||||
===========
|
||||
|
||||
@(weixin4j)[企业号]
|
||||
|
||||
微信[企业号](http://qydev.weixin.qq.com/wiki/index.php)开发工具包
|
||||
[微信企业号](http://qydev.weixin.qq.com/wiki/index.php)开发工具包
|
||||
---------------------------------------------------------------
|
||||
|
||||
功能列表
|
||||
-------
|
||||
* **weixin4j-qy-api**
|
||||
|
||||
如何使用
|
||||
--------
|
||||
+ DepartApi `部门管理API`
|
||||
|
||||
+ UserApi `成员管理API`
|
||||
|
||||
+ TagApi `标签管理API`
|
||||
|
||||
更新LOG
|
||||
-------
|
||||
* 2014-11-19
|
||||
|
||||
+ 得到`weixin4j-qy-api`和`weixin4j-qy-server`工程
|
||||
|
||||
+ **weixin4j-qy-api**: 新增部门管理接口
|
||||
|
||||
+ **weixin4j-qy-api**: 新增用户管理接口
|
||||
|
||||
+ **weixin4j-qy-api**: 新增标签管理接口
|
||||
|
||||
@ -10,6 +10,18 @@
|
||||
</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>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.foxinmy.weixin4j</groupId>
|
||||
<artifactId>weixin4j-base</artifactId>
|
||||
<version>${weixin4j.base.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
28
weixin4j-qy/weixin4j-qy-api/.gitignore
vendored
Normal file
28
weixin4j-qy/weixin4j-qy-api/.gitignore
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
# 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
|
||||
|
||||
# maven ignore
|
||||
target/*
|
||||
|
||||
# other ignore
|
||||
*.log
|
||||
*.tmp
|
||||
Thumbs.db
|
||||
/target/
|
||||
.DS_Store
|
||||
56
weixin4j-qy/weixin4j-qy-api/README.md
Normal file
56
weixin4j-qy/weixin4j-qy-api/README.md
Normal file
@ -0,0 +1,56 @@
|
||||
weixin4j-qy-api
|
||||
===============
|
||||
|
||||
[微信企业号](http://qydev.weixin.qq.com/wiki/index.php)开发工具包
|
||||
---------------------------------------------------------------
|
||||
|
||||
功能列表
|
||||
-------
|
||||
|
||||
* DepartApi `部门管理API`
|
||||
|
||||
* UserApi `成员管理API`
|
||||
|
||||
* TagApi `标签管理API`
|
||||
|
||||
如何使用
|
||||
--------
|
||||
1.API工程可以单独打包到其他项目中使用,需新增或拷贝`weixin.properties`文件到项目的`classpath`中
|
||||
|
||||
weixin.properties说明
|
||||
|
||||
| 属性名 | 说明 |
|
||||
| :---------- | :-------------- |
|
||||
| account | 微信企业号信息 `json格式` |
|
||||
| token_path | 使用FileTokenHolder时token保存的物理路径 |
|
||||
|
||||
示例(properties中换行用右斜杆\\)
|
||||
|
||||
> account={"id":"corpid","secret":"corpsecret",
|
||||
> "token":"开放者的token 非必须",
|
||||
> "encodingAesKey":"AES加密密钥"}
|
||||
> token_path=/tmp/weixin/token <br/>
|
||||
|
||||
2.实例化一个`WeixinProxy`对象,调用API
|
||||
|
||||
WeixinProxy weixinProxy = new WeixinProxy();
|
||||
// weixinProxy = new WeixinProxy(corpid,corpsecret);
|
||||
// weixinProxy = new WeixinProxy(weixinAccount);
|
||||
weixinProxy.getUser(userid);
|
||||
|
||||
3.针对`token`存储有两种方案,`File存储`/`Redis存储`,当然也可自己实现`TokenHolder`(继承`AbstractTokenHolder`并重写`getToken`方法),默认使用文件(xml)的方式保存token,如果环境中支持`redis`,建议使用`RedisTokenHolder`.
|
||||
|
||||
WeixinProxy weixinProxy = new WeixinProxy(new RedisTokenHolder());
|
||||
// weixinProxy = new WeixinProxy(new RedisTokenHolder(weixinAccount));
|
||||
|
||||
4.`mvn package`.
|
||||
|
||||
更新LOG
|
||||
-------
|
||||
* 2014-11-19
|
||||
|
||||
+ 新增`部门管理`接口
|
||||
|
||||
+ 新增`用户管理`接口
|
||||
|
||||
+ 新增`标签管理`接口
|
||||
24
weixin4j-qy/weixin4j-qy-api/pom.xml
Normal file
24
weixin4j-qy/weixin4j-qy-api/pom.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<project
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.foxinmy.weixin4j</groupId>
|
||||
<artifactId>weixin4j-qy</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</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>
|
||||
<finalName>weixin4j-qy-api</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
31
weixin4j-qy/weixin4j-qy-api/src/main/assembly.xml
Normal file
31
weixin4j-qy/weixin4j-qy-api/src/main/assembly.xml
Normal file
@ -0,0 +1,31 @@
|
||||
<assembly
|
||||
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
|
||||
<id>full</id>
|
||||
<formats>
|
||||
<format>jar</format>
|
||||
</formats>
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<directory>target/classes</directory>
|
||||
<outputDirectory>/</outputDirectory>
|
||||
<includes>
|
||||
<include>/**</include>
|
||||
</includes>
|
||||
<excludes>
|
||||
<exclude>*.properties</exclude>
|
||||
<exclude>*.xml</exclude>
|
||||
</excludes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
<dependencySets>
|
||||
<dependencySet>
|
||||
<unpack>true</unpack>
|
||||
<includes>
|
||||
<include>com.foxinmy.weixin4j:weixin4j-base</include>
|
||||
</includes>
|
||||
</dependencySet>
|
||||
</dependencySets>
|
||||
</assembly>
|
||||
@ -0,0 +1,344 @@
|
||||
package com.foxinmy.weixin4j.qy;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.JsonResult;
|
||||
import com.foxinmy.weixin4j.model.WeixinQyAccount;
|
||||
import com.foxinmy.weixin4j.qy.api.DepartApi;
|
||||
import com.foxinmy.weixin4j.qy.api.TagApi;
|
||||
import com.foxinmy.weixin4j.qy.api.UserApi;
|
||||
import com.foxinmy.weixin4j.qy.model.Department;
|
||||
import com.foxinmy.weixin4j.qy.model.User;
|
||||
import com.foxinmy.weixin4j.qy.type.UserStatus;
|
||||
import com.foxinmy.weixin4j.token.FileTokenHolder;
|
||||
import com.foxinmy.weixin4j.token.TokenHolder;
|
||||
import com.foxinmy.weixin4j.type.AccountType;
|
||||
|
||||
/**
|
||||
* 微信企业号接口实现
|
||||
*
|
||||
* @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 DepartApi departApi;
|
||||
private final UserApi userApi;
|
||||
private final TagApi tagApi;
|
||||
|
||||
/**
|
||||
* 默认采用文件存放Token信息
|
||||
*/
|
||||
public WeixinProxy() {
|
||||
this(new FileTokenHolder(AccountType.QY));
|
||||
}
|
||||
|
||||
/**
|
||||
* appid,appsecret
|
||||
*
|
||||
* @param appid
|
||||
* @param appsecret
|
||||
*/
|
||||
public WeixinProxy(String corpid, String corpsecret) {
|
||||
this(new WeixinQyAccount(corpid, corpsecret));
|
||||
}
|
||||
|
||||
/**
|
||||
* WeixinAccount对象
|
||||
*
|
||||
* @param weixinAccount
|
||||
*/
|
||||
public WeixinProxy(WeixinQyAccount weixinAccount) {
|
||||
this(new FileTokenHolder(weixinAccount));
|
||||
}
|
||||
|
||||
/**
|
||||
* TokenHolder对象
|
||||
*
|
||||
* @param tokenHolder
|
||||
*/
|
||||
public WeixinProxy(TokenHolder tokenHolder) {
|
||||
this.departApi = new DepartApi(tokenHolder);
|
||||
this.userApi = new UserApi(tokenHolder);
|
||||
this.tagApi = new TagApi(tokenHolder);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建部门(根部门的parentid为1)
|
||||
*
|
||||
* @param depart
|
||||
* 部门对象
|
||||
* @see com.foxinmy.weixin4j.qy.model.Department
|
||||
* @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.DepartApi
|
||||
* @return 部门ID
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public int createDepart(Department depart) throws WeixinException {
|
||||
return departApi.createDepart(depart);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新部门(如果非必须的字段未指定 则不更新该字段之前的设置值)
|
||||
*
|
||||
* @param depart
|
||||
* 部门对象
|
||||
* @see com.foxinmy.weixin4j.qy.model.Department
|
||||
* @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.DepartApi
|
||||
* @return 处理结果
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public JsonResult updateDepart(Department depart) throws WeixinException {
|
||||
return departApi.updateDepart(depart);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询部门列表(以部门的order字段从小到大排列)
|
||||
*
|
||||
* @see com.foxinmy.weixin4j.qy.model.Department
|
||||
* @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.DepartApi
|
||||
* @return 部门列表
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public List<Department> listDepart() throws WeixinException {
|
||||
return departApi.listDepart();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除部门(不能删除根部门;不能删除含有子部门、成员的部门)
|
||||
*
|
||||
* @param departId
|
||||
* 部门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.DepartApi
|
||||
* @return 处理结果
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public JsonResult deleteDepart(int departId) throws WeixinException {
|
||||
return departApi.deleteDepart(departId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建成员
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取部门成员
|
||||
*
|
||||
* @param departId
|
||||
* 部门ID 必须
|
||||
* @param fetchChild
|
||||
* 是否递归获取子部门下面的成员 非必须
|
||||
* @param userStatus
|
||||
* 成员状态 status可叠加 非必须
|
||||
* @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 departId, boolean fetchChild,
|
||||
UserStatus userStatus) throws WeixinException {
|
||||
return userApi.listUser(departId, fetchChild, userStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取部门下所有状态成员(不进行递归)
|
||||
*
|
||||
* @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 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 tagId
|
||||
* 标签ID
|
||||
* @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#.E6.9B.B4.E6.96.B0.E6.A0.87.E7.AD.BE.E5.90.8D.E5.AD.97"
|
||||
* >更新标签说明</a>
|
||||
* @see com.foxinmy.weixin4j.qy.api.TagApi
|
||||
* @return 处理结果
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public JsonResult updateTag(int tagId, String tagName)
|
||||
throws WeixinException {
|
||||
return tagApi.updateTag(tagId, tagName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除标签(管理组必须是指定标签的创建者 并且标签的成员列表为空)
|
||||
*
|
||||
* @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.api.TagApi
|
||||
* @return 标签列表
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public JSONArray 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);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
package com.foxinmy.weixin4j.qy.api;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.foxinmy.weixin4j.http.HttpRequest;
|
||||
import com.foxinmy.weixin4j.xml.Map2ObjectConverter;
|
||||
import com.foxinmy.weixin4j.xml.XStream;
|
||||
import com.thoughtworks.xstream.core.ClassLoaderReference;
|
||||
import com.thoughtworks.xstream.mapper.DefaultMapper;
|
||||
|
||||
/**
|
||||
*
|
||||
* @className BaseApi
|
||||
* @author jy.hu
|
||||
* @date 2014年11月18日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://qydev.weixin.qq.com/wiki/index.php">api文档</a>
|
||||
*/
|
||||
public class BaseApi {
|
||||
protected final HttpRequest request = new HttpRequest();
|
||||
protected final static XStream mapXstream = XStream.get();
|
||||
private final static ResourceBundle weixinBundle;
|
||||
static {
|
||||
weixinBundle = ResourceBundle
|
||||
.getBundle("com/foxinmy/weixin4j/qy/api/weixin");
|
||||
mapXstream.alias("xml", Map.class);
|
||||
mapXstream.registerConverter(new Map2ObjectConverter(new DefaultMapper(
|
||||
new ClassLoaderReference(XStream.class.getClassLoader()))));
|
||||
}
|
||||
|
||||
protected String map2xml(Map<?, ?> map) {
|
||||
return mapXstream.toXML(map).replaceAll("__", "_");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Map<String, String> xml2map(String xml) {
|
||||
return mapXstream.fromXML(xml, Map.class);
|
||||
}
|
||||
|
||||
protected String getRequestUri(String key) {
|
||||
String url = weixinBundle.getString(key);
|
||||
Pattern p = Pattern.compile("(\\{[^\\}]*\\})");
|
||||
Matcher m = p.matcher(url);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
String sub = null;
|
||||
while (m.find()) {
|
||||
sub = m.group();
|
||||
m.appendReplacement(sb,
|
||||
getRequestUri(sub.substring(1, sub.length() - 1)));
|
||||
}
|
||||
m.appendTail(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,110 @@
|
||||
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.Department;
|
||||
import com.foxinmy.weixin4j.token.TokenHolder;
|
||||
|
||||
/**
|
||||
* 部门API
|
||||
*
|
||||
* @className DepartApi
|
||||
* @author jy
|
||||
* @date 2014年11月18日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.qy.model.Department
|
||||
* @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 DepartApi extends BaseApi {
|
||||
private final TokenHolder tokenHolder;
|
||||
|
||||
public DepartApi(TokenHolder tokenHolder) {
|
||||
this.tokenHolder = tokenHolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建部门(根部门的parentid为1)
|
||||
*
|
||||
* @param depart
|
||||
* 部门对象
|
||||
* @see com.foxinmy.weixin4j.qy.model.Department
|
||||
* @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 createDepart(Department 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.Department
|
||||
* @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 updateDepart(Department depart) throws WeixinException {
|
||||
String department_update_uri = getRequestUri("department_update_uri");
|
||||
JSONObject obj = (JSONObject) JSON.toJSON(depart);
|
||||
Token token = tokenHolder.getToken();
|
||||
Response response = request.post(
|
||||
String.format(department_update_uri, token.getAccessToken()),
|
||||
obj.toJSONString());
|
||||
return response.getAsJsonResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询部门列表(以部门的order字段从小到大排列)
|
||||
*
|
||||
* @see com.foxinmy.weixin4j.qy.model.Department
|
||||
* @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<Department> listDepart() 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"),
|
||||
Department.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除部门(不能删除根部门;不能删除含有子部门、成员的部门)
|
||||
*
|
||||
* @param departId
|
||||
* 部门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 deleteDepart(int departId) 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(), departId));
|
||||
return response.getAsJsonResult();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,179 @@
|
||||
package com.foxinmy.weixin4j.qy.api;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
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.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 BaseApi {
|
||||
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 tagId
|
||||
* 标签ID
|
||||
* @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#.E6.9B.B4.E6.96.B0.E6.A0.87.E7.AD.BE.E5.90.8D.E5.AD.97"
|
||||
* >更新标签说明</a>
|
||||
* @return 处理结果
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public JsonResult updateTag(int tagId, String tagName)
|
||||
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()), String.format(
|
||||
"{\"tagid\":%d,\"tagname\":\"%s\"}", tagId, tagName));
|
||||
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 标签列表
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public JSONArray 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 response.getAsJson().getJSONArray("taglist");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取标签成员(管理组须拥有“获取标签成员”的接口权限,标签须对管理组可见;返回列表仅包含管理组管辖范围的成员)
|
||||
*
|
||||
* @param tagId
|
||||
* 标签ID
|
||||
* @see com.foxinmy.weixin4j.qy.model.User
|
||||
* @see <a
|
||||
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%A0%87%E7%AD%BE#.E8.8E.B7.E5.8F.96.E6.A0.87.E7.AD.BE.E6.88.90.E5.91.98">获取标签成员说明</a>
|
||||
* @return 成员列表
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public List<User> getTagUsers(int tagId) throws WeixinException {
|
||||
String tag_get_user_uri = getRequestUri("tag_get_user_uri");
|
||||
Token token = tokenHolder.getToken();
|
||||
Response response = request.post(String.format(tag_get_user_uri,
|
||||
token.getAccessToken(), tagId));
|
||||
return JSON.parseArray(response.getAsJson().getString("userlist"),
|
||||
User.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增标签成员(标签对管理组可见且未加锁,成员属于管理组管辖范围)<br>
|
||||
* <font color="red">若部分userid非法,则在text中体现</font>
|
||||
*
|
||||
* @param tagId
|
||||
* 标签ID
|
||||
* @param userIds
|
||||
* 成员ID
|
||||
* @see <a
|
||||
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%A0%87%E7%AD%BE#.E5.A2.9E.E5.8A.A0.E6.A0.87.E7.AD.BE.E6.88.90.E5.91.98">新增标签成员说明</a>
|
||||
* @return 处理结果
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public JsonResult addTagUsers(int tagId, List<String> userIds)
|
||||
throws WeixinException {
|
||||
String tag_add_user_uri = getRequestUri("tag_add_user_uri");
|
||||
return excuteUsers(tag_add_user_uri, tagId, userIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除标签成员(标签对管理组可见且未加锁,成员属于管理组管辖范围)<br>
|
||||
* <font color="red">若部分userid非法,则在text中体现</font>
|
||||
*
|
||||
* @param tagId
|
||||
* 标签ID
|
||||
* @param userIds
|
||||
* 成员ID
|
||||
* @see <a
|
||||
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E6%A0%87%E7%AD%BE#.E5.88.A0.E9.99.A4.E6.A0.87.E7.AD.BE.E6.88.90.E5.91.98">删除标签成员说明</a>
|
||||
* @return 处理结果
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public JsonResult deleteTagUsers(int tagId, List<String> userIds)
|
||||
throws WeixinException {
|
||||
String tag_delete_user_uri = getRequestUri("tag_delete_user_uri");
|
||||
return excuteUsers(tag_delete_user_uri, tagId, userIds);
|
||||
}
|
||||
|
||||
private JsonResult excuteUsers(String uri, int tagId, List<String> userIds)
|
||||
throws WeixinException {
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("tagid", tagId);
|
||||
obj.put("userlist", userIds);
|
||||
Token token = tokenHolder.getToken();
|
||||
Response response = request.post(
|
||||
String.format(uri, token.getAccessToken()), obj.toJSONString());
|
||||
obj = response.getAsJson();
|
||||
JsonResult result = JSON.toJavaObject(obj, JsonResult.class);
|
||||
result.setText(obj.getString("invalidlist"));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,159 @@
|
||||
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.User;
|
||||
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 BaseApi {
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取部门成员
|
||||
*
|
||||
* @param departId
|
||||
* 部门ID 必须
|
||||
* @param fetchChild
|
||||
* 是否递归获取子部门下面的成员 非必须
|
||||
* @param userStatus
|
||||
* 成员状态 status可叠加 非必须
|
||||
* @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) throws WeixinException {
|
||||
String user_list_uri = getRequestUri("user_list_uri");
|
||||
Token token = tokenHolder.getToken();
|
||||
Response response = request.post(String.format(user_list_uri,
|
||||
token.getAccessToken(), departId, fetchChild ? 1 : 0,
|
||||
userStatus.getVal()));
|
||||
return JSON.parseArray(response.getAsJson().getString("userlist"),
|
||||
User.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取部门下所有状态成员(不进行递归)
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除成员
|
||||
*
|
||||
* @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();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
# ----------------------------------------------------------------------------
|
||||
# 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
|
||||
user_update_uri={api_base_url}/user/update?access_token=%s
|
||||
# \u83b7\u53d6\u6210\u5458
|
||||
user_get_uri={api_base_url}/user/get?access_token=%s&userid=%s
|
||||
# \u83b7\u53d6\u90e8\u95e8\u6210\u5458
|
||||
user_list_uri={api_base_url}/user/simplelist?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
|
||||
# \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
|
||||
@ -0,0 +1,74 @@
|
||||
package com.foxinmy.weixin4j.qy.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 部门对象
|
||||
*
|
||||
* @className Department
|
||||
* @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 Department implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -2567893218591084288L;
|
||||
private int id; // 部门ID
|
||||
private String name; // 部门名称。长度限制为1~64个字符
|
||||
private int parentid;// 父亲部门id。根部门id为1
|
||||
private int order;// 在父部门中的次序。从1开始,数字越大排序越靠后
|
||||
|
||||
public Department() {
|
||||
|
||||
}
|
||||
|
||||
public Department(String name) {
|
||||
this(name, 1, 1);
|
||||
}
|
||||
|
||||
public Department(String name, int parentid, int order) {
|
||||
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 "Department [id=" + id + ", name=" + name + ", parentid="
|
||||
+ parentid + ", order=" + order + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package com.foxinmy.weixin4j.qy.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class NameValue implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -348620146718819093L;
|
||||
private String name;
|
||||
private String value;
|
||||
|
||||
public NameValue() {
|
||||
|
||||
}
|
||||
|
||||
public NameValue(String name, String value) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NameValue [name=" + name + ", value=" + value + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,203 @@
|
||||
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;
|
||||
private String userid;// 是 员工UserID。对应管理端的帐号,企业内必须唯一。长度为1~64个字符
|
||||
private String name;// 是 成员名称。长度为1~64个字符
|
||||
private List<Integer> department;// 否 成员所属部门id列表。注意,每个部门的直属员工上限为1000个
|
||||
private String position;// 否 职位信息。长度为0~64个字符
|
||||
private String mobile;// 否 手机号码。企业内必须唯一,mobile/weixinid/email三者不能同时为空
|
||||
private int gender;// 否 性别。gender=0表示男,=1表示女。默认gender=0
|
||||
private String tel;// 否 办公电话。长度为0~64个字符
|
||||
private String email;// 否 邮箱。长度为0~64个字符。企业内必须唯一
|
||||
private String weixinid;// 否 微信号。企业内必须唯一
|
||||
private String avatar;// 头像url。注:如果要获取小图将url最后的"/0"改成"/64"即可
|
||||
private int status;// 关注状态: 1=已关注,2=已冻结,4=未关注
|
||||
private List<NameValue> extattr;// 否 扩展属性。扩展属性需要在WEB管理端创建后才生效,否则忽略未知属性的赋值
|
||||
|
||||
public User() {
|
||||
this.extattr = new ArrayList<NameValue>();
|
||||
}
|
||||
|
||||
public User(String userid, String name) {
|
||||
this(userid, name, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* mobile/weixinid/email三者不能同时为空
|
||||
*
|
||||
* @param userid
|
||||
* @param name
|
||||
* @param tel
|
||||
* @param email
|
||||
* @param weixinid
|
||||
*/
|
||||
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 getEnumGender() {
|
||||
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)
|
||||
public UserStatus getStatus() {
|
||||
for (UserStatus userStatus : UserStatus.values()) {
|
||||
if (userStatus.getVal() == status) {
|
||||
return userStatus;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setStatus(int status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
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=" + gender + ", tel=" + tel + ", email=" + email
|
||||
+ ", weixinid=" + weixinid + ", avatar=" + avatar + ", status="
|
||||
+ status + ", extattr=" + extattr + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package com.foxinmy.weixin4j.qy.type;
|
||||
|
||||
/**
|
||||
* 成员状态
|
||||
*
|
||||
* @className UserStatus
|
||||
* @author jy
|
||||
* @date 2014年11月19日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public enum UserStatus {
|
||||
BOTH(0), // 0=全部
|
||||
FOLLOW(1), // 1=已关注
|
||||
FROZEN(2), // 2=已冻结
|
||||
UNFOLLOW(4);// 4=未关注
|
||||
private int val;
|
||||
|
||||
UserStatus(int val) {
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
public int getVal() {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
# \u6d4b\u8bd5\u4e4b\u7528 \u6b63\u5f0f\u73af\u5883\u4e0bcopy\u4e00\u4efd\u5230classpath
|
||||
# \u4f01\u4e1a\u53f7\u4fe1\u606f
|
||||
account={"id":"wxd9d9fa581a07cefd","secret":"7tr6FXh2NORvqq1la9CVwxV0xZWGsRSgI6tfqd3-JFc9E2p7UukNNYeKoOTLe0Ru",\
|
||||
"token":"gp2eGT5mIpngr",\
|
||||
"encodingAesKey":"BRYfV4zPFUJb3v3MySNBg1ERKE3vyyMRoScu76vFySv"\
|
||||
}
|
||||
|
||||
# \u4f7f\u7528FileTokenHolder\u65f6token\u7684\u5b58\u653e\u8def\u5f84
|
||||
token_path=/tmp/weixin/token
|
||||
# \u4e8c\u7ef4\u7801\u4fdd\u5b58\u8def\u5f84
|
||||
qr_path=/tmp/weixin/qr
|
||||
# \u5a92\u4f53\u6587\u4ef6\u4fdd\u5b58\u8def\u5f84
|
||||
media_path=/tmp/weixin/media
|
||||
@ -0,0 +1,58 @@
|
||||
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.DepartApi;
|
||||
import com.foxinmy.weixin4j.qy.model.Department;
|
||||
|
||||
/**
|
||||
* 部门API测试
|
||||
*
|
||||
* @className DepartTest
|
||||
* @author jy
|
||||
* @date 2014年11月18日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class DepartTest extends TokenTest {
|
||||
public DepartApi departApi;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
this.departApi = new DepartApi(tokenHolder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void create() throws WeixinException {
|
||||
Department depart = new Department("苦逼组");
|
||||
int id = departApi.createDepart(depart);
|
||||
Assert.assertTrue(id > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void update() throws WeixinException {
|
||||
Department depart = new Department("苦逼组111");
|
||||
depart.setId(2);
|
||||
JsonResult result = departApi.updateDepart(depart);
|
||||
Assert.assertEquals("updated", result.getDesc());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void list() throws WeixinException {
|
||||
List<Department> list = departApi.listDepart();
|
||||
Assert.assertFalse(list.isEmpty());
|
||||
System.out.println(list);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void delete() throws WeixinException {
|
||||
JsonResult result = departApi.deleteDepart(2);
|
||||
Assert.assertEquals("deleted", result.getDesc());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
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.alibaba.fastjson.JSONArray;
|
||||
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.User;
|
||||
|
||||
/**
|
||||
* 部门API测试
|
||||
*
|
||||
* @className DepartTest
|
||||
* @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(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 {
|
||||
JSONArray 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());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
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.token.FileTokenHolder;
|
||||
import com.foxinmy.weixin4j.token.TokenHolder;
|
||||
import com.foxinmy.weixin4j.type.AccountType;
|
||||
|
||||
/**
|
||||
* 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(AccountType.QY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws WeixinException {
|
||||
Assert.assertNotNull(tokenHolder.getToken());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
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.UserApi;
|
||||
import com.foxinmy.weixin4j.qy.model.User;
|
||||
|
||||
/**
|
||||
* 部门API测试
|
||||
*
|
||||
* @className DepartTest
|
||||
* @author jy
|
||||
* @date 2014年11月18日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class UserTest extends TokenTest {
|
||||
public UserApi userApi;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
this.userApi = new UserApi(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 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);
|
||||
Assert.assertFalse(userList.isEmpty());
|
||||
System.out.println(userList);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void delete() throws WeixinException {
|
||||
JsonResult result = userApi.deleteUser("u001");
|
||||
Assert.assertEquals("deleted", result.getDesc());
|
||||
}
|
||||
}
|
||||
28
weixin4j-qy/weixin4j-qy-server/.gitignore
vendored
Normal file
28
weixin4j-qy/weixin4j-qy-server/.gitignore
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
# 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
|
||||
|
||||
# maven ignore
|
||||
target/*
|
||||
|
||||
# other ignore
|
||||
*.log
|
||||
*.tmp
|
||||
Thumbs.db
|
||||
/target/
|
||||
.DS_Store
|
||||
22
weixin4j-qy/weixin4j-qy-server/README.md
Normal file
22
weixin4j-qy/weixin4j-qy-server/README.md
Normal file
@ -0,0 +1,22 @@
|
||||
weixin4j-qy-server
|
||||
==================
|
||||
|
||||
微信企业号netty服务
|
||||
------------
|
||||
|
||||
功能列表
|
||||
-------
|
||||
|
||||
* `netty构建服务器`
|
||||
|
||||
* `消息分发`
|
||||
|
||||
如何使用
|
||||
--------
|
||||
|
||||
|
||||
更新LOG
|
||||
-------
|
||||
* 2014-11-19
|
||||
|
||||
+ 得到`weixin4j-qy-server`工程
|
||||
24
weixin4j-qy/weixin4j-qy-server/pom.xml
Normal file
24
weixin4j-qy/weixin4j-qy-server/pom.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<project
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.foxinmy.weixin4j</groupId>
|
||||
<artifactId>weixin4j-qy</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</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>微信企业号工具包</description>
|
||||
<build>
|
||||
<finalName>weixin-qy-server</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
36
weixin4j-qy/weixin4j-qy-server/src/main/assembly.xml
Normal file
36
weixin4j-qy/weixin4j-qy-server/src/main/assembly.xml
Normal file
@ -0,0 +1,36 @@
|
||||
<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>
|
||||
142
weixin4j-qy/weixin4j-qy-server/src/main/startup.sh
Normal file
142
weixin4j-qy/weixin4j-qy-server/src/main/startup.sh
Normal file
@ -0,0 +1,142 @@
|
||||
ulimit -n 110000
|
||||
#JDK home
|
||||
JAVA_HOME="/usr/local/java/"
|
||||
|
||||
#executing user
|
||||
RUNNING_USER=root
|
||||
|
||||
#Run home
|
||||
APP_HOME="/usr/local/weixin/weixin-mp-server"
|
||||
|
||||
#main class
|
||||
APP_MAINCLASS=com.foxinmy.weixin4j.mp.startup.WeixinServerBootstrap
|
||||
|
||||
#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
|
||||
Loading…
x
Reference in New Issue
Block a user