Skip to content

Commit 1030115

Browse files
authored
🆕 #2612 【企业微信】增加获取企业活跃成员数和通讯录异步导出的接口
1 parent 5d0364f commit 1030115

File tree

10 files changed

+325
-0
lines changed

10 files changed

+325
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package me.chanjar.weixin.cp.api;
2+
3+
import me.chanjar.weixin.common.error.WxErrorException;
4+
import me.chanjar.weixin.cp.bean.export.WxCpExportRequest;
5+
import me.chanjar.weixin.cp.bean.export.WxCpExportResult;
6+
7+
/**
8+
* 异步导出接口
9+
*
10+
* @author <a href="https://github.com/zhongjun96">zhongjun</a>
11+
* @date 2022/4/21
12+
**/
13+
public interface WxCpExportService {
14+
15+
/**
16+
* <pre>
17+
*
18+
* 导出成员
19+
*
20+
* 请求方式:POST(HTTPS)
21+
* 请求地址:<a href="https://qyapi.weixin.qq.com/cgi-bin/export/simple_user?access_token=ACCESS_TOKEN">https://qyapi.weixin.qq.com/cgi-bin/export/simple_user?access_token=ACCESS_TOKEN</a>
22+
*
23+
* 文档地址:<a href="https://developer.work.weixin.qq.com/document/path/94849">https://developer.work.weixin.qq.com/document/path/94849</a>
24+
* </pre>
25+
*
26+
* @param params 导出参数
27+
* @return jobId 异步任务id
28+
* @throws WxErrorException .
29+
*/
30+
String simpleUser(WxCpExportRequest params) throws WxErrorException;
31+
32+
/**
33+
* <pre>
34+
*
35+
* 导出成员详情
36+
*
37+
* 请求方式:POST(HTTPS)
38+
* 请求地址:<a href="https://qyapi.weixin.qq.com/cgi-bin/export/user?access_token=ACCESS_TOKEN">https://qyapi.weixin.qq.com/cgi-bin/export/user?access_token=ACCESS_TOKEN</a>
39+
*
40+
* 文档地址:<a href="https://developer.work.weixin.qq.com/document/path/94851">https://developer.work.weixin.qq.com/document/path/94851</a>
41+
* </pre>
42+
*
43+
* @param params 导出参数
44+
* @return jobId 异步任务id
45+
* @throws WxErrorException .
46+
*/
47+
String user(WxCpExportRequest params) throws WxErrorException;
48+
49+
/**
50+
* <pre>
51+
*
52+
* 导出部门
53+
*
54+
* 请求方式:POST(HTTPS)
55+
* 请求地址:<a href="https://qyapi.weixin.qq.com/cgi-bin/export/department?access_token=ACCESS_TOKEN">https://qyapi.weixin.qq.com/cgi-bin/export/department?access_token=ACCESS_TOKEN</a>
56+
*
57+
* 文档地址:<a href="https://developer.work.weixin.qq.com/document/path/94852">https://developer.work.weixin.qq.com/document/path/94852</a>
58+
* </pre>
59+
*
60+
* @param params 导出参数
61+
* @return jobId 异步任务id
62+
* @throws WxErrorException .
63+
*/
64+
String department(WxCpExportRequest params) throws WxErrorException;
65+
66+
/**
67+
* <pre>
68+
*
69+
* 导出标签成员
70+
*
71+
* 请求方式:POST(HTTPS)
72+
* 请求地址:<a href="https://qyapi.weixin.qq.com/cgi-bin/export/taguser?access_token=ACCESS_TOKEN">https://qyapi.weixin.qq.com/cgi-bin/export/taguser?access_token=ACCESS_TOKEN</a>
73+
*
74+
* 文档地址:<a href="https://developer.work.weixin.qq.com/document/path/94853">https://developer.work.weixin.qq.com/document/path/94853</a>
75+
* </pre>
76+
*
77+
* @param params 导出参数
78+
* @return jobId 异步任务id
79+
* @throws WxErrorException .
80+
*/
81+
String tagUser(WxCpExportRequest params) throws WxErrorException;
82+
83+
/**
84+
* <pre>
85+
*
86+
* 获取导出结果
87+
*
88+
* 请求方式:GET(HTTPS)
89+
* 请求地址:<a href="https://qyapi.weixin.qq.com/cgi-bin/export/get_result?access_token=ACCESS_TOKEN&jobid=jobid_xxxxxxxxxxxxxxx">https://qyapi.weixin.qq.com/cgi-bin/export/get_result?access_token=ACCESS_TOKEN&jobid=jobid_xxxxxxxxxxxxxxx</a>
90+
*
91+
* 文档地址:<a href="https://developer.work.weixin.qq.com/document/path/94854">https://developer.work.weixin.qq.com/document/path/94854</a>
92+
* 返回的url文件下载解密可参考 <a href="https://blog.csdn.net/a201692/article/details/123530529">CSDN</a>
93+
* </pre>
94+
*
95+
* @param jobId 异步任务id
96+
* @return 导出结果
97+
* @throws WxErrorException .
98+
*/
99+
WxCpExportResult getResult(String jobId) throws WxErrorException;
100+
}

weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java

+14
Original file line numberDiff line numberDiff line change
@@ -511,4 +511,18 @@ public interface WxCpService extends WxService {
511511
* @param kfService the kf service
512512
*/
513513
void setKfService(WxCpKfService kfService);
514+
515+
/**
516+
* 获取异步导出服务
517+
*
518+
* @return 异步导出服务
519+
*/
520+
WxCpExportService getExportService();
521+
522+
/**
523+
* 设置异步导出服务
524+
*
525+
* @param exportService 异步导出服务
526+
*/
527+
void setExportService(WxCpExportService exportService);
514528
}

weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpUserService.java

+18
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import me.chanjar.weixin.cp.bean.WxCpUser;
66
import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactInfo;
77

8+
import java.util.Date;
89
import java.util.List;
910
import java.util.Map;
1011

@@ -199,4 +200,21 @@ public interface WxCpUserService {
199200
* @throws WxErrorException .
200201
*/
201202
String getJoinQrCode(int sizeType) throws WxErrorException;
203+
204+
/**
205+
* <pre>
206+
*
207+
* 获取企业活跃成员数。
208+
*
209+
* 请求方式:POST(HTTPS)
210+
* 请求地址:<a href="https://qyapi.weixin.qq.com/cgi-bin/user/get_active_stat?access_token=ACCESS_TOKEN">https://qyapi.weixin.qq.com/cgi-bin/user/get_active_stat?access_token=ACCESS_TOKEN</a>
211+
*
212+
* 文档地址:<a href="https://developer.work.weixin.qq.com/document/path/92714">https://developer.work.weixin.qq.com/document/path/92714</a>
213+
* </pre>
214+
*
215+
* @param date 具体某天的活跃人数,最长支持获取30天前数据
216+
* @return join_qrcode 活跃成员数
217+
* @throws WxErrorException .
218+
*/
219+
Integer getActiveStat(Date date) throws WxErrorException;
202220
}

weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/BaseWxCpServiceImpl.java

+13
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ public abstract class BaseWxCpServiceImpl<H, P> implements WxCpService, RequestH
6161
private WxCpAgentWorkBenchService workBenchService = new WxCpAgentWorkBenchServiceImpl(this);
6262
private WxCpKfService kfService = new WxCpKfServiceImpl(this);
6363

64+
private WxCpExportService exportService = new WxCpExportServiceImpl(this);
65+
6466
/**
6567
* 全局的是否正在刷新access token的锁.
6668
*/
@@ -588,4 +590,15 @@ public WxCpKfService getKfService() {
588590
public void setKfService(WxCpKfService kfService) {
589591
this.kfService = kfService;
590592
}
593+
594+
595+
@Override
596+
public WxCpExportService getExportService() {
597+
return exportService;
598+
}
599+
600+
@Override
601+
public void setExportService(WxCpExportService exportService) {
602+
this.exportService = exportService;
603+
}
591604
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package me.chanjar.weixin.cp.api.impl;
2+
3+
import com.google.gson.JsonObject;
4+
import lombok.RequiredArgsConstructor;
5+
import me.chanjar.weixin.common.error.WxErrorException;
6+
import me.chanjar.weixin.common.util.json.GsonParser;
7+
import me.chanjar.weixin.cp.api.WxCpExportService;
8+
import me.chanjar.weixin.cp.api.WxCpService;
9+
import me.chanjar.weixin.cp.bean.export.WxCpExportRequest;
10+
import me.chanjar.weixin.cp.bean.export.WxCpExportResult;
11+
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
12+
13+
import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Export.*;
14+
15+
/**
16+
* 异步导出接口
17+
*
18+
* @author <a href="https://github.com/zhongjun96">zhongjun</a>
19+
* @date 2022/4/21
20+
**/
21+
@RequiredArgsConstructor
22+
public class WxCpExportServiceImpl implements WxCpExportService {
23+
24+
private final WxCpService mainService;
25+
26+
@Override
27+
public String simpleUser(WxCpExportRequest params) throws WxErrorException {
28+
return export(SIMPLE_USER, params);
29+
}
30+
31+
@Override
32+
public String user(WxCpExportRequest params) throws WxErrorException {
33+
return export(USER, params);
34+
}
35+
36+
@Override
37+
public String department(WxCpExportRequest params) throws WxErrorException {
38+
return export(DEPARTMENT, params);
39+
}
40+
41+
@Override
42+
public String tagUser(WxCpExportRequest params) throws WxErrorException {
43+
return export(TAG_USER, params);
44+
}
45+
46+
@Override
47+
public WxCpExportResult getResult(String jobId) throws WxErrorException {
48+
String url = String.format(this.mainService.getWxCpConfigStorage().getApiUrl(GET_RESULT), jobId);
49+
String responseContent = this.mainService.get(url, null);
50+
return WxCpGsonBuilder.create().fromJson(responseContent, WxCpExportResult.class);
51+
}
52+
53+
private String export(String path, WxCpExportRequest params) throws WxErrorException {
54+
String url = this.mainService.getWxCpConfigStorage().getApiUrl(path);
55+
String responseContent = this.mainService.post(url, params.toJson());
56+
JsonObject tmpJson = GsonParser.parse(responseContent);
57+
return tmpJson.get("jobid").getAsString();
58+
}
59+
}

weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImpl.java

+15
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@
1414
import me.chanjar.weixin.cp.bean.WxCpUser;
1515
import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactInfo;
1616
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
17+
import org.apache.commons.lang3.time.FastDateFormat;
1718

19+
import java.text.Format;
20+
import java.util.Date;
1821
import java.util.List;
1922
import java.util.Map;
2023

@@ -29,6 +32,8 @@
2932
*/
3033
@RequiredArgsConstructor
3134
public class WxCpUserServiceImpl implements WxCpUserService {
35+
private final Format dateFormat = FastDateFormat.getInstance("yyyy-MM-dd");
36+
3237
private final WxCpService mainService;
3338

3439
@Override
@@ -208,4 +213,14 @@ public String getJoinQrCode(int sizeType) throws WxErrorException {
208213
JsonObject tmpJson = GsonParser.parse(responseContent);
209214
return tmpJson.get("join_qrcode").getAsString();
210215
}
216+
217+
@Override
218+
public Integer getActiveStat(Date date) throws WxErrorException {
219+
JsonObject jsonObject = new JsonObject();
220+
jsonObject.addProperty("date", this.dateFormat.format(date));
221+
String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_ACTIVE_STAT);
222+
String responseContent = this.mainService.post(url, jsonObject.toString());
223+
JsonObject tmpJson = GsonParser.parse(responseContent);
224+
return tmpJson.get("active_cnt").getAsInt();
225+
}
211226
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package me.chanjar.weixin.cp.bean.export;
2+
3+
import com.google.gson.annotations.SerializedName;
4+
import lombok.Data;
5+
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
6+
7+
import java.io.Serializable;
8+
9+
/**
10+
* 异步导出参数
11+
*
12+
* @author zhongjun
13+
* @date 2022/4/21
14+
**/
15+
@Data
16+
public class WxCpExportRequest implements Serializable {
17+
private static final long serialVersionUID = -8127528999898984359L;
18+
19+
/**
20+
* base64encode的加密密钥,长度固定为43,base64decode之后即得到AESKey。加密方式采用AES-256-CBC方式,数据采用PKCS#7填充至32字节的倍数;IV初始向量大小为16字节,取AESKey前16字节,详见:<a href="http://tools.ietf.org/html/rfc2315">http://tools.ietf.org/html/rfc2315</a>
21+
*/
22+
@SerializedName("encoding_aeskey")
23+
private String encodingAesKey;
24+
25+
/**
26+
* 每块数据的部门数,支持范围[104,106],默认值为10^6
27+
*/
28+
@SerializedName("block_size")
29+
private Integer blockSize;
30+
31+
/**
32+
* 需要导出的标签
33+
* 导出标签成员时使用
34+
*/
35+
@SerializedName("tagid")
36+
private Integer tagId;
37+
38+
public String toJson() {
39+
return WxCpGsonBuilder.create().toJson(this);
40+
}
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package me.chanjar.weixin.cp.bean.export;
2+
3+
import com.google.gson.annotations.SerializedName;
4+
import lombok.Data;
5+
import lombok.EqualsAndHashCode;
6+
import me.chanjar.weixin.cp.bean.WxCpBaseResp;
7+
8+
import java.util.List;
9+
10+
/**
11+
* 异步导出响应
12+
*
13+
* @author zhongjun
14+
* @date 2022/4/21
15+
**/
16+
@Data
17+
@EqualsAndHashCode(callSuper = true)
18+
public class WxCpExportResult extends WxCpBaseResp {
19+
private static final long serialVersionUID = -8673839248829238966L;
20+
21+
/**
22+
* 任务状态:0-未处理,1-处理中,2-完成,3-异常失败
23+
*/
24+
private Integer status;
25+
26+
@SerializedName("data_list")
27+
private List<ExportData> dataList;
28+
29+
30+
@Data
31+
public static class ExportData {
32+
33+
/**
34+
* 数据下载链接,支持指定Range头部分段下载。有效期2个小时
35+
*/
36+
private String url;
37+
38+
/**
39+
* 密文数据大小
40+
*/
41+
private Integer size;
42+
43+
/**
44+
* 密文数据md5
45+
*/
46+
private String md5;
47+
}
48+
}

weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java

+9
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ interface User {
215215
String GET_USER_ID = "/cgi-bin/user/getuserid";
216216
String GET_EXTERNAL_CONTACT = "/cgi-bin/crm/get_external_contact?external_userid=";
217217
String GET_JOIN_QR_CODE = "/cgi-bin/corp/get_join_qrcode?size_type=";
218+
String GET_ACTIVE_STAT = "/cgi-bin/user/get_active_stat";
218219
}
219220

220221
interface ExternalContact {
@@ -310,4 +311,12 @@ interface Kf {
310311
String CUSTOMER_BATCH_GET = "/cgi-bin/kf/customer/batchget";
311312

312313
}
314+
315+
interface Export {
316+
String SIMPLE_USER = "/cgi-bin/export/simple_user";
317+
String USER = "/cgi-bin/export/user";
318+
String DEPARTMENT = "/cgi-bin/export/department";
319+
String TAG_USER = "/cgi-bin/export/taguser";
320+
String GET_RESULT = "/cgi-bin/export/get_result?jobid=%s";
321+
}
313322
}

0 commit comments

Comments
 (0)