Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(企业微信):新增获取企业活跃成员数接口&通讯录异步导出接口 #2612

Merged
merged 3 commits into from
Apr 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package me.chanjar.weixin.cp.api;

import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.bean.export.WxCpExportRequest;
import me.chanjar.weixin.cp.bean.export.WxCpExportResult;

/**
* 异步导出接口
*
* @author <a href="https://github.com/zhongjun96">zhongjun</a>
* @date 2022/4/21
**/
public interface WxCpExportService {

/**
* <pre>
*
* 导出成员
*
* 请求方式:POST(HTTPS)
* 请求地址:<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>
*
* 文档地址:<a href="https://developer.work.weixin.qq.com/document/path/94849">https://developer.work.weixin.qq.com/document/path/94849</a>
* </pre>
*
* @param params 导出参数
* @return jobId 异步任务id
* @throws WxErrorException .
*/
String simpleUser(WxCpExportRequest params) throws WxErrorException;

/**
* <pre>
*
* 导出成员详情
*
* 请求方式:POST(HTTPS)
* 请求地址:<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>
*
* 文档地址:<a href="https://developer.work.weixin.qq.com/document/path/94851">https://developer.work.weixin.qq.com/document/path/94851</a>
* </pre>
*
* @param params 导出参数
* @return jobId 异步任务id
* @throws WxErrorException .
*/
String user(WxCpExportRequest params) throws WxErrorException;

/**
* <pre>
*
* 导出部门
*
* 请求方式:POST(HTTPS)
* 请求地址:<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>
*
* 文档地址:<a href="https://developer.work.weixin.qq.com/document/path/94852">https://developer.work.weixin.qq.com/document/path/94852</a>
* </pre>
*
* @param params 导出参数
* @return jobId 异步任务id
* @throws WxErrorException .
*/
String department(WxCpExportRequest params) throws WxErrorException;

/**
* <pre>
*
* 导出标签成员
*
* 请求方式:POST(HTTPS)
* 请求地址:<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>
*
* 文档地址:<a href="https://developer.work.weixin.qq.com/document/path/94853">https://developer.work.weixin.qq.com/document/path/94853</a>
* </pre>
*
* @param params 导出参数
* @return jobId 异步任务id
* @throws WxErrorException .
*/
String tagUser(WxCpExportRequest params) throws WxErrorException;

/**
* <pre>
*
* 获取导出结果
*
* 请求方式:GET(HTTPS)
* 请求地址:<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>
*
* 文档地址:<a href="https://developer.work.weixin.qq.com/document/path/94854">https://developer.work.weixin.qq.com/document/path/94854</a>
* 返回的url文件下载解密可参考 <a href="https://blog.csdn.net/a201692/article/details/123530529">CSDN</a>
* </pre>
*
* @param jobId 异步任务id
* @return 导出结果
* @throws WxErrorException .
*/
WxCpExportResult getResult(String jobId) throws WxErrorException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -511,4 +511,18 @@ public interface WxCpService extends WxService {
* @param kfService the kf service
*/
void setKfService(WxCpKfService kfService);

/**
* 获取异步导出服务
*
* @return 异步导出服务
*/
WxCpExportService getExportService();

/**
* 设置异步导出服务
*
* @param exportService 异步导出服务
*/
void setExportService(WxCpExportService exportService);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import me.chanjar.weixin.cp.bean.WxCpUser;
import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactInfo;

import java.util.Date;
import java.util.List;
import java.util.Map;

Expand Down Expand Up @@ -199,4 +200,21 @@ public interface WxCpUserService {
* @throws WxErrorException .
*/
String getJoinQrCode(int sizeType) throws WxErrorException;

/**
* <pre>
*
* 获取企业活跃成员数。
*
* 请求方式:POST(HTTPS)
* 请求地址:<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>
*
* 文档地址:<a href="https://developer.work.weixin.qq.com/document/path/92714">https://developer.work.weixin.qq.com/document/path/92714</a>
* </pre>
*
* @param date 具体某天的活跃人数,最长支持获取30天前数据
* @return join_qrcode 活跃成员数
* @throws WxErrorException .
*/
Integer getActiveStat(Date date) throws WxErrorException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ public abstract class BaseWxCpServiceImpl<H, P> implements WxCpService, RequestH
private WxCpAgentWorkBenchService workBenchService = new WxCpAgentWorkBenchServiceImpl(this);
private WxCpKfService kfService = new WxCpKfServiceImpl(this);

private WxCpExportService exportService = new WxCpExportServiceImpl(this);

/**
* 全局的是否正在刷新access token的锁.
*/
Expand Down Expand Up @@ -588,4 +590,15 @@ public WxCpKfService getKfService() {
public void setKfService(WxCpKfService kfService) {
this.kfService = kfService;
}


@Override
public WxCpExportService getExportService() {
return exportService;
}

@Override
public void setExportService(WxCpExportService exportService) {
this.exportService = exportService;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package me.chanjar.weixin.cp.api.impl;

import com.google.gson.JsonObject;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.json.GsonParser;
import me.chanjar.weixin.cp.api.WxCpExportService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.export.WxCpExportRequest;
import me.chanjar.weixin.cp.bean.export.WxCpExportResult;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;

import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Export.*;

/**
* 异步导出接口
*
* @author <a href="https://github.com/zhongjun96">zhongjun</a>
* @date 2022/4/21
**/
@RequiredArgsConstructor
public class WxCpExportServiceImpl implements WxCpExportService {

private final WxCpService mainService;

@Override
public String simpleUser(WxCpExportRequest params) throws WxErrorException {
return export(SIMPLE_USER, params);
}

@Override
public String user(WxCpExportRequest params) throws WxErrorException {
return export(USER, params);
}

@Override
public String department(WxCpExportRequest params) throws WxErrorException {
return export(DEPARTMENT, params);
}

@Override
public String tagUser(WxCpExportRequest params) throws WxErrorException {
return export(TAG_USER, params);
}

@Override
public WxCpExportResult getResult(String jobId) throws WxErrorException {
String url = String.format(this.mainService.getWxCpConfigStorage().getApiUrl(GET_RESULT), jobId);
String responseContent = this.mainService.get(url, null);
return WxCpGsonBuilder.create().fromJson(responseContent, WxCpExportResult.class);
}

private String export(String path, WxCpExportRequest params) throws WxErrorException {
String url = this.mainService.getWxCpConfigStorage().getApiUrl(path);
String responseContent = this.mainService.post(url, params.toJson());
JsonObject tmpJson = GsonParser.parse(responseContent);
return tmpJson.get("jobid").getAsString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
import me.chanjar.weixin.cp.bean.WxCpUser;
import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactInfo;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
import org.apache.commons.lang3.time.FastDateFormat;

import java.text.Format;
import java.util.Date;
import java.util.List;
import java.util.Map;

Expand All @@ -29,6 +32,8 @@
*/
@RequiredArgsConstructor
public class WxCpUserServiceImpl implements WxCpUserService {
private final Format dateFormat = FastDateFormat.getInstance("yyyy-MM-dd");

private final WxCpService mainService;

@Override
Expand Down Expand Up @@ -208,4 +213,14 @@ public String getJoinQrCode(int sizeType) throws WxErrorException {
JsonObject tmpJson = GsonParser.parse(responseContent);
return tmpJson.get("join_qrcode").getAsString();
}

@Override
public Integer getActiveStat(Date date) throws WxErrorException {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("date", this.dateFormat.format(date));
String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_ACTIVE_STAT);
String responseContent = this.mainService.post(url, jsonObject.toString());
JsonObject tmpJson = GsonParser.parse(responseContent);
return tmpJson.get("active_cnt").getAsInt();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package me.chanjar.weixin.cp.bean.export;

import com.google.gson.annotations.SerializedName;
import lombok.Data;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;

import java.io.Serializable;

/**
* 异步导出参数
*
* @author zhongjun
* @date 2022/4/21
**/
@Data
public class WxCpExportRequest implements Serializable {
private static final long serialVersionUID = -8127528999898984359L;

/**
* 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>
*/
@SerializedName("encoding_aeskey")
private String encodingAesKey;

/**
* 每块数据的部门数,支持范围[104,106],默认值为10^6
*/
@SerializedName("block_size")
private Integer blockSize;

/**
* 需要导出的标签
* 导出标签成员时使用
*/
@SerializedName("tagid")
private Integer tagId;

public String toJson() {
return WxCpGsonBuilder.create().toJson(this);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package me.chanjar.weixin.cp.bean.export;

import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import me.chanjar.weixin.cp.bean.WxCpBaseResp;

import java.util.List;

/**
* 异步导出响应
*
* @author zhongjun
* @date 2022/4/21
**/
@Data
@EqualsAndHashCode(callSuper = true)
public class WxCpExportResult extends WxCpBaseResp {
private static final long serialVersionUID = -8673839248829238966L;

/**
* 任务状态:0-未处理,1-处理中,2-完成,3-异常失败
*/
private Integer status;

@SerializedName("data_list")
private List<ExportData> dataList;


@Data
public static class ExportData {

/**
* 数据下载链接,支持指定Range头部分段下载。有效期2个小时
*/
private String url;

/**
* 密文数据大小
*/
private Integer size;

/**
* 密文数据md5
*/
private String md5;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ interface User {
String GET_USER_ID = "/cgi-bin/user/getuserid";
String GET_EXTERNAL_CONTACT = "/cgi-bin/crm/get_external_contact?external_userid=";
String GET_JOIN_QR_CODE = "/cgi-bin/corp/get_join_qrcode?size_type=";
String GET_ACTIVE_STAT = "/cgi-bin/user/get_active_stat";
}

interface ExternalContact {
Expand Down Expand Up @@ -310,4 +311,12 @@ interface Kf {
String CUSTOMER_BATCH_GET = "/cgi-bin/kf/customer/batchget";

}

interface Export {
String SIMPLE_USER = "/cgi-bin/export/simple_user";
String USER = "/cgi-bin/export/user";
String DEPARTMENT = "/cgi-bin/export/department";
String TAG_USER = "/cgi-bin/export/taguser";
String GET_RESULT = "/cgi-bin/export/get_result?jobid=%s";
}
}
Loading