+ * 正常情况下返回{"type":"TYPE","media_id":"MEDIA_ID","created_at":123456789},
+ * 否则抛出异常.
+ *
+ *
+ * @param bytes
+ * 媒体数据包
+ * @param mediaType
+ * 媒体类型
+ * @return 上传到微信服务器返回的媒体标识
+ * @see com.foxinmy.weixin4j.qy.api.MediaApi
+ * @see parties)
+ throws WeixinException {
+ return mediaApi.batchUploadParties(parties);
+ }
+
/**
* 创建成员
*
@@ -451,7 +661,7 @@ public class WeixinProxy {
public JsonResult setAgent(AgentSetter agentSet) throws WeixinException {
return agentApi.setAgent(agentSet);
}
-
+
/**
* 批量邀请成员关注
*
@@ -473,7 +683,7 @@ public class WeixinProxy {
String tips) throws WeixinException {
return batchApi.inviteuser(parameter, callback, tips);
}
-
+
/**
* 批量更新成员,本接口以userid为主键,增量更新企业号通讯录成员。
*
@@ -497,7 +707,7 @@ public class WeixinProxy {
throws WeixinException {
return batchApi.syncuser(mediaId, callback);
}
-
+
/**
* 批量覆盖成员,本接口以userid为主键,全量覆盖企业号通讯录成员,任务完成后企业号通讯录成员与提交的文件完全保持一致。
*
@@ -522,6 +732,25 @@ public class WeixinProxy {
throws WeixinException {
return batchApi.replaceuser(mediaId, callback);
}
+
+ /**
+ * 批量上传成员
+ *
+ * @param users
+ * 成员列表
+ * @see com.foxinmy.weixin4j.qy.api.MediaApi
+ * @see com.foxinmy.weixin4j.qy.api.BatchApi
+ * @see {@link com.foxinmy.weixin4j.qy.WeixinProxy#syncuser(String,Callback)}
+ * @see {@link com.foxinmy.weixin4j.qy.WeixinProxy#replaceuser(String,Callback)}
+ * @see 批量任务
+ * @return 上传后的mediaId
+ * @throws WeixinException
+ */
+ public String batchUploadUsers(List users) throws WeixinException {
+ return mediaApi.batchUploadUsers(users);
+ }
+
/**
* 批量覆盖部门,本接口以partyid为键,全量覆盖企业号通讯录组织架构,任务完成后企业号通讯录组织架构与提交的文件完全保持一致。
*
@@ -545,7 +774,7 @@ public class WeixinProxy {
throws WeixinException {
return batchApi.replaceparty(mediaId, callback);
}
-
+
/**
* 获取异步任务执行的结果
*
diff --git a/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/api/BatchApi.java b/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/api/BatchApi.java
index 9dbd7cf2..ee2468f3 100644
--- a/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/api/BatchApi.java
+++ b/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/api/BatchApi.java
@@ -63,6 +63,7 @@ public class BatchApi extends QyApi {
/**
* 批量更新成员,本接口以userid为主键,增量更新企业号通讯录成员。
+ *
*
* 1.模板中的部门需填写部门ID,多个部门用分号分隔,部门ID必须为数字
* 2.文件中存在、通讯录中也存在的成员,更新成员在文件中指定的字段值 3.文件中存在、通讯录中不存在的成员,执行添加操作
@@ -70,10 +71,11 @@ public class BatchApi extends QyApi {
*
*
* @param mediaId
- * 带user信息的cvs文件上传后的media_id TODO
+ * 带user信息的cvs文件上传后的media_id
* @param callback
* 接收任务执行结果的回调地址等信息
* @return 异步任务id,最大长度为64字符
+ * @see {@link com.foxinmy.weixin4j.qy.api.UserApi#batchUploadUsers(List)}
* @see com.foxinmy.weixin4j.qy.model.Callback
* @see 批量更新成员
@@ -111,6 +113,7 @@ public class BatchApi extends QyApi {
* @param callback
* 接收任务执行结果的回调地址等信息
* @return 异步任务id,最大长度为64字符
+ * @see {@link com.foxinmy.weixin4j.qy.api.UserApi#batchUploadUsers(List)}
* @see com.foxinmy.weixin4j.qy.model.Callback
* @see 批量覆盖成员
diff --git a/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/api/MediaApi.java b/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/api/MediaApi.java
index 859daff3..21e992bf 100644
--- a/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/api/MediaApi.java
+++ b/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/api/MediaApi.java
@@ -5,14 +5,26 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
+import java.io.StringWriter;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.entity.mime.content.ByteArrayBody;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.serializer.PropertyFilter;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.PartParameter;
import com.foxinmy.weixin4j.http.Response;
+import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.model.Token;
+import com.foxinmy.weixin4j.qy.model.Callback;
+import com.foxinmy.weixin4j.qy.model.Party;
+import com.foxinmy.weixin4j.qy.model.User;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.type.MediaType;
import com.foxinmy.weixin4j.util.ConfigUtil;
@@ -137,8 +149,8 @@ public class MediaApi extends QyApi {
os = new FileOutputStream(file);
os.write(datas);
} else {
- throw new WeixinException(String.format(
- "create file fail:%s", file.getAbsolutePath()));
+ throw new WeixinException(String.format("create file fail:%s",
+ file.getAbsolutePath()));
}
} catch (IOException e) {
throw new WeixinException(e.getMessage());
@@ -171,4 +183,70 @@ public class MediaApi extends QyApi {
token.getAccessToken(), mediaId));
return response.getBody();
}
+
+ /**
+ * 批量上传成员
+ *
+ * @param users
+ * 成员列表
+ * @see {@link com.foxinmy.weixin4j.qy.api.BatchApi#syncuser(String,Callback)}
+ * @see {@link com.foxinmy.weixin4j.qy.api.BatchApi#replaceuser(String,Callback)}
+ * @see 批量任务
+ * @return 上传后的mediaId
+ * @throws WeixinException
+ */
+ public String batchUploadUsers(List users) throws WeixinException {
+ return batchUpload("batch_syncuser.cvs", users);
+ }
+
+ /**
+ * 批量上传部门
+ *
+ * @param parties
+ * 部门列表
+ * @see {@link com.foxinmy.weixin4j.qy.api.BatchApi#replaceparty(String,Callback)}
+ * @see 批量任务
+ * @return 上传后的mediaId
+ * @throws WeixinException
+ */
+ public String batchUploadParties(List parties)
+ throws WeixinException {
+ return batchUpload("batch_replaceparty.cvs", parties);
+ }
+
+ private String batchUpload(String batchName, List models)
+ throws WeixinException {
+ JSONObject csvObj = JSON.parseObject(getConfigValue(batchName));
+ JSONArray columns = csvObj.getJSONArray("column");
+ StringWriter writer = new StringWriter();
+ writer.write(csvObj.getString("header"));
+ final Map column = new LinkedHashMap();
+ for (Object col : columns) {
+ column.put(col.toString(), "");
+ }
+ writer.write("\r\n");
+ for (T model : models) {
+ JSON.toJSONString(model, new PropertyFilter() {
+ @Override
+ public boolean apply(Object object, String name, Object value) {
+ if (column.containsKey(name)) {
+ column.put(name, value);
+ }
+ return true;
+ }
+ });
+ writer.write(StringUtils.join(column.values(), ","));
+ writer.write("\r\n");
+ }
+ String mediaId = uploadMedia(batchName,
+ writer.toString().getBytes(Consts.UTF_8), MediaType.file.name());
+ try {
+ writer.close();
+ } catch (IOException e) {
+ ;
+ }
+ return mediaId;
+ }
}
diff --git a/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/api/MenuApi.java b/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/api/MenuApi.java
index dc01c64b..9ad02e42 100644
--- a/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/api/MenuApi.java
+++ b/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/api/MenuApi.java
@@ -32,6 +32,9 @@ public class MenuApi extends QyApi {
* 自定义菜单(管理员须拥有应用的管理权限 并且应用必须设置在回调模式)
*
* @param btnList
+ * 菜单列表
+ * @param agentid
+ * 应用ID
* @throws WeixinException
* @see 创建自定义菜单
@@ -53,6 +56,8 @@ public class MenuApi extends QyApi {
/**
* 查询菜单(管理员须拥有应用的管理权限 并且应用必须设置在回调模式。)
*
+ * @param agentid
+ * 应用ID
* @return 菜单集合
* @throws WeixinException
* @see 删除菜单
diff --git a/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/api/UserApi.java b/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/api/UserApi.java
index 3196b772..ecf818e0 100644
--- a/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/api/UserApi.java
+++ b/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/api/UserApi.java
@@ -251,7 +251,7 @@ public class UserApi extends QyApi {
* 成员ID
* @param tips
* 推送到微信上的提示语(只有认证号可以使用)。当使用微信推送时,该字段默认为“请关注XXX企业号”,邮件邀请时,该字段无效。
- * @return 调用结果
+ * @return 邀请类型
* @see 邀请成员关注说明
* @throws WeixinException
diff --git a/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/api/weixin.properties b/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/api/weixin.properties
index b36c4b3c..391ae66b 100644
--- a/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/api/weixin.properties
+++ b/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/api/weixin.properties
@@ -69,9 +69,11 @@ agent_set_uri={api_base_url}/agent/set?access_token=%s
batch_inviteuser_uri={api_base_url}/batch/inviteuser?access_token=%s
# \u6279\u91cf\u66f4\u65b0\u6210\u5458
batch_syncuser_uri={api_base_url}/batch/syncuser?access_token=%s
+batch_syncuser.cvs={"header":"\u59d3\u540d,\u8d26\u53f7,\u5fae\u4fe1\u53f7,\u624b\u673a\u53f7,\u90ae\u7bb1,\u6240\u5728\u90e8\u95e8,\u804c\u4f4d","column":["name","userid","weixinid","mobile","email","department","position"]}
# \u6279\u91cf\u8986\u76d6\u6210\u5458
batch_replaceuser_uri={api_base_url}/batch/replaceuser?access_token=%s
# \u6279\u91cf\u8986\u76d6\u90e8\u95e8
batch_replaceparty_uri={api_base_url}/batch/replaceparty?access_token=%s
+batch_replaceparty.cvs={"header":"\u90e8\u95e8\u540d\u79f0,\u90e8\u95e8ID,\u7236\u90e8\u95e8ID,\u6392\u5e8f","column":["name","id","parentid","order"]}
# \u83b7\u53d6\u5f02\u6b65\u4efb\u52a1\u6267\u884c\u7ed3\u679c
batch_getresult_uri={api_base_url}/batch/getresult?access_token=%s&jobid=%s
\ No newline at end of file
diff --git a/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/model/BatchResult.java b/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/model/BatchResult.java
index 559e89b2..a16afc02 100644
--- a/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/model/BatchResult.java
+++ b/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/model/BatchResult.java
@@ -51,7 +51,7 @@ public class BatchResult extends JsonResult {
}
public BatchType getType() {
- return BatchType.valueOf(type);
+ return BatchType.valueOf(type.toUpperCase());
}
public void setType(String type) {
@@ -92,7 +92,7 @@ public class BatchResult extends JsonResult {
@Override
public String toString() {
- return "BatchResult [status=" + status + ", type=" + type + ", total="
+ return "BatchResult [status=" + getStatus() + ", type=" + getType() + ", total="
+ total + ", percentage=" + percentage + ", remaintime="
+ remaintime + ", result=" + result + "]";
}
diff --git a/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/model/Party.java b/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/model/Party.java
index ed0498e5..a83622a7 100644
--- a/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/model/Party.java
+++ b/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/model/Party.java
@@ -37,10 +37,11 @@ public class Party implements Serializable {
}
public Party(String name) {
- this(name, 1, 1);
+ this(0, name, 1, 1);
}
- public Party(String name, int parentid, int order) {
+ public Party(int id, String name, int parentid, int order) {
+ this.id = id;
this.name = name;
this.parentid = parentid;
this.order = order;
@@ -80,7 +81,7 @@ public class Party implements Serializable {
@Override
public String toString() {
- return "Party [id=" + id + ", name=" + name + ", parentid="
- + parentid + ", order=" + order + "]";
+ return "Party [id=" + id + ", name=" + name + ", parentid=" + parentid
+ + ", order=" + order + "]";
}
}
diff --git a/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/model/User.java b/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/model/User.java
index 6d2c5f95..cb9928c1 100644
--- a/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/model/User.java
+++ b/weixin4j-qy/weixin4j-qy-api/src/main/java/com/foxinmy/weixin4j/qy/model/User.java
@@ -66,6 +66,10 @@ public class User implements Serializable {
* 关注状态: 1=已关注,2=已冻结,4=未关注
*/
private int status;
+ /**
+ * 启用/禁用成员。1表示启用成员,0表示禁用成员
+ */
+ private int enable;
/**
* 非必须 扩展属性。扩展属性需要在WEB管理端创建后才生效,否则忽略未知属性的赋值
*/
@@ -152,7 +156,7 @@ public class User implements Serializable {
}
@JSONField(serialize = false)
- public Gender getEnumGender() {
+ public Gender getFormatGender() {
if (gender == 0) {
return Gender.male;
} else if (gender == 1) {
@@ -199,8 +203,8 @@ public class User implements Serializable {
this.avatar = avatar;
}
- @JSONField(serialize = false)
- public UserStatus getStatus() {
+ @JSONField(serialize = false, deserialize = false)
+ public UserStatus getFormatStatus() {
for (UserStatus userStatus : UserStatus.values()) {
if (userStatus.getVal() == status) {
return userStatus;
@@ -213,6 +217,19 @@ public class User implements Serializable {
this.status = status;
}
+ public int getEnable() {
+ return enable;
+ }
+
+ @JSONField(serialize = false, deserialize = false)
+ public boolean getFormatEnable() {
+ return enable == 1;
+ }
+
+ public void setEnable(int enable) {
+ this.enable = enable;
+ }
+
public List getExtattr() {
return extattr;
}
@@ -237,8 +254,9 @@ public class User implements Serializable {
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 + "]";
+ + ", gender=" + getFormatGender() + ", tel=" + tel + ", email="
+ + email + ", weixinid=" + weixinid + ", avatar=" + avatar
+ + ", status=" + getFormatStatus() + ", enable="
+ + getFormatEnable() + ", extattr=" + extattr + "]";
}
}
diff --git a/weixin4j-qy/weixin4j-qy-api/src/test/java/com/foxinmy/weixin4j/qy/test/BatchTest.java b/weixin4j-qy/weixin4j-qy-api/src/test/java/com/foxinmy/weixin4j/qy/test/BatchTest.java
index e5dd07da..3c22448e 100644
--- a/weixin4j-qy/weixin4j-qy-api/src/test/java/com/foxinmy/weixin4j/qy/test/BatchTest.java
+++ b/weixin4j-qy/weixin4j-qy-api/src/test/java/com/foxinmy/weixin4j/qy/test/BatchTest.java
@@ -1,12 +1,16 @@
package com.foxinmy.weixin4j.qy.test;
+import java.util.Arrays;
+
import org.junit.Before;
import org.junit.Test;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.qy.api.BatchApi;
+import com.foxinmy.weixin4j.qy.api.MediaApi;
import com.foxinmy.weixin4j.qy.model.BatchResult;
import com.foxinmy.weixin4j.qy.model.Callback;
+import com.foxinmy.weixin4j.qy.model.Party;
/**
* 异步任务测试
@@ -19,21 +23,39 @@ import com.foxinmy.weixin4j.qy.model.Callback;
*/
public class BatchTest extends TokenTest {
public BatchApi batchApi;
+ public MediaApi mediaApi;
@Before
public void init() {
this.batchApi = new BatchApi(tokenHolder);
+ this.mediaApi = new MediaApi(tokenHolder);
+ }
+
+ @Test
+ public void syncuser() throws WeixinException {
+ String jobId = batchApi
+ .syncuser(
+ "1QFmZ8LE9dFxPPx8EH5Kfm3cqGXB0OuXY432ZpsfwMFTJjEDt7QI4GZB1UhYGOSYr",
+ new Callback("http://182.254.188.133:8090",
+ "gp2eGT5mIpngr",
+ "BRYfV4zPFUJb3v3MySNBg1ERKE3vyyMRoScu76vFySv"));
+ System.err.println(jobId);
}
@Test
public void replaceparty() throws WeixinException {
- String jobId = batchApi.replaceparty("mediaId", new Callback("url", "token", "aesKey"));
+ String mediaId = mediaApi.batchUploadParties(Arrays.asList(new Party(5,
+ "部门1", 1, 1), new Party(6, "部门2", 1, 1)));
+ String jobId = batchApi.replaceparty(mediaId, new Callback(
+ "http://182.254.188.133:8090", "gp2eGT5mIpngr",
+ "BRYfV4zPFUJb3v3MySNBg1ERKE3vyyMRoScu76vFySv"));
System.err.println(jobId);
}
-
+
@Test
public void getresult() throws WeixinException {
- BatchResult result = batchApi.getresult("jobId");
+ BatchResult result = batchApi
+ .getresult("PVucPBfEapLnvQZ1ru2Vdw3Dbl-jXs3AEQdS24cqmI0");
System.err.println(result);
}
}
diff --git a/weixin4j-qy/weixin4j-qy-api/src/test/java/com/foxinmy/weixin4j/qy/test/UserTest.java b/weixin4j-qy/weixin4j-qy-api/src/test/java/com/foxinmy/weixin4j/qy/test/UserTest.java
index 3d6ac3ed..ceab6cab 100644
--- a/weixin4j-qy/weixin4j-qy-api/src/test/java/com/foxinmy/weixin4j/qy/test/UserTest.java
+++ b/weixin4j-qy/weixin4j-qy-api/src/test/java/com/foxinmy/weixin4j/qy/test/UserTest.java
@@ -1,5 +1,6 @@
package com.foxinmy.weixin4j.qy.test;
+import java.util.Arrays;
import java.util.List;
import org.junit.Assert;
@@ -8,14 +9,15 @@ import org.junit.Test;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.JsonResult;
+import com.foxinmy.weixin4j.qy.api.MediaApi;
import com.foxinmy.weixin4j.qy.api.UserApi;
import com.foxinmy.weixin4j.qy.model.User;
import com.foxinmy.weixin4j.qy.type.UserStatus;
/**
- * 部门API测试
+ * 用户API测试
*
- * @className DepartTest
+ * @className UserTest
* @author jy
* @date 2014年11月18日
* @since JDK 1.7
@@ -23,10 +25,12 @@ import com.foxinmy.weixin4j.qy.type.UserStatus;
*/
public class UserTest extends TokenTest {
public UserApi userApi;
+ public MediaApi mediaApi;
@Before
public void init() {
this.userApi = new UserApi(tokenHolder);
+ this.mediaApi = new MediaApi(tokenHolder);
}
@Test
@@ -39,6 +43,15 @@ public class UserTest extends TokenTest {
Assert.assertEquals("created", result.getDesc());
}
+ @Test
+ public void batchUpload() throws WeixinException {
+ User user = new User("u001", "jack");
+ user.setMobile("13500000000");
+ user.setDepartment(1);
+ String mediaId = mediaApi.batchUploadUsers(Arrays.asList(user));
+ System.err.println(mediaId);
+ }
+
@Test
public void update() throws WeixinException {
User user = new User("u001", "ted");
@@ -71,9 +84,9 @@ public class UserTest extends TokenTest {
JsonResult result = userApi.deleteUser("u001");
Assert.assertEquals("deleted", result.getDesc());
}
-
+
@Test
- public void invite()throws WeixinException{
+ public void invite() throws WeixinException {
userApi.inviteUser("11", null);
}
}
diff --git a/weixin4j-qy/weixin4j-qy-server/src/main/resources/logback.xml b/weixin4j-qy/weixin4j-qy-server/src/main/resources/logback.xml
index 38b9858c..69223c03 100644
--- a/weixin4j-qy/weixin4j-qy-server/src/main/resources/logback.xml
+++ b/weixin4j-qy/weixin4j-qy-server/src/main/resources/logback.xml
@@ -26,7 +26,7 @@
- /tmp/weixin/log/weixin.qy.%d{yyyy-MM-dd}.log
+ /tmp/weixin/log/qy/weixin.qy.%d{yyyy-MM-dd}.log
30