WeChatUtil.java
· 26 KiB · Java
Ham
public class WeChatUtil {
private final static Logger log = LoggerFactory.getLogger(WeChatUtil.class);
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private static final OkHttpClient OKHTTP_CLIENT = new OkHttpClient.Builder().build();
//缓存token-key
private static final String CACHE_KEY = "WECHAT_TOKEN_CACHE_KEY";
private static final String TOKEN_KEY = "ACCESS_TOKEN";
// private final Config config = ConfigKit.me().get("WeChatUtil.Config",Config.class);
/**
* 发送文本消息
*
* @param content 消息内容,最长不超过2048个字节,超过将截断
* @param userIds 指定接收消息的成员,成员ID列表 多个接收者用‘|’分隔,最多支持1000个 指定为"@all",则向该企业应用的全部成员发送
* @return 是否发送成功
*/
public static synchronized boolean sendMsg(Config config, String content, String... userIds) {
WorkAccessToken token = getOrFlushToken(config);
if (token == null) {
log.info("发送企业微信消息-获取 TOEKN 为空!");
return false;
}
//构建发送消息
JSONObject postParam = new JSONObject().fluentPut("touser", StringUtils.join(Arrays.asList(userIds), "|"))
.fluentPut("msgtype", "text")
.fluentPut("agentid", config.getAgentId())
.fluentPut("text", new JSONObject() {{
put("content", content);
}});
String msgUrl = String.format(config.getMessageSendUrl(), token.getAccessToken());
try (
Response response = OKHTTP_CLIENT.newCall(new Request.Builder()
.post(RequestBody.create(postParam.toJSONString(), MediaType.parse("application/json;charset=utf-8")))
.url(msgUrl)
.build()).execute()
) {
ResponseBody body = response.body();
if (Objects.isNull(body)) {
log.info("发送企业微信消息-返回结果为空!");
return false;
}
String resp = body.string();
log.info("messageSendUrl:{}", config.getMessageSendUrl());
log.info("msgUrl:{}", msgUrl);
log.info("postParam:{}", postParam.toJSONString());
log.info("res:{}", resp);
if (!StringUtils.isNotBlank(resp)) {
log.info("发送企业微信消息-返回结果为空!");
return false;
}
try {
WorkMsgResp workResp = OBJECT_MAPPER.readValue(resp, WorkMsgResp.class);
return workResp != null && workResp.isSuccess();
} catch (JsonProcessingException e) {
log.error("发送企业微信消息时异常!", e);
return false;
}
} catch (Exception e) {
log.error("发送企业微信消息时异常!", e);
return false;
}
}
/**
* 获取部门列表
*
* @param departmentId 部门id。获取指定部门及其下的子部门(以及子部门的子部门等等,递归)。 如果不填,默认获取全量组织架构
* @return 部门列表
*/
public static synchronized List<Department> listDepartments(Config config, Integer departmentId) {
WorkAccessToken token = getOrFlushToken(config);
if (token == null) {
log.info("获取企业微信部门列表-获取 TOEKN 为空!");
return null;
}
String url = String.format(config.getListDepartmentUrl(), token.getAccessToken(), departmentId);
try (
Response response = OKHTTP_CLIENT.newCall(new Request.Builder().url(url).build()).execute()
) {
ResponseBody body = response.body();
if (Objects.isNull(body)) {
log.info("获取企业微信部门列表-返回结果为空!");
return null;
}
String resp = body.string();
log.info("listDepartmentUrl:{}", url);
log.info("listDepartmentRes:{}", resp);
if (!StringUtils.isNotBlank(resp)) {
log.info("获取企业微信部门列表-返回结果为空!");
return null;
}
try {
JSONObject jsonObject = JSONObject.parseObject(resp);
if (jsonObject == null || !jsonObject.containsKey("department") || jsonObject.getInteger("errcode") != 0) {
log.info("获取企业微信部门列表-返回结果为空!");
return null;
}
return jsonObject.getJSONArray("department").toJavaList(Department.class);
} catch (Exception e) {
log.error("获取企业微信部门列表时异常!", e);
return null;
}
} catch (Exception e) {
log.error("获取企业微信部门列表时异常!", e);
return null;
}
}
/**
* 获取部门成员列表
*
* @param departmentId 部门编号
* @return 用户列表
*/
public static synchronized List<User> listUsersOfDepartment(Config config, Integer departmentId) {
WorkAccessToken token = getOrFlushToken(config);
if (token == null) {
log.info("获取企业微信部门成员列表-获取 TOEKN 为空!");
return null;
}
String url = String.format(config.getListUserOfDepartmentUrl(), token.getAccessToken(), departmentId);
try (
Response response = OKHTTP_CLIENT.newCall(new Request.Builder().url(url).build()).execute()
) {
ResponseBody body = response.body();
if (Objects.isNull(body)) {
log.info("获取企业微信部门成员列表-返回结果为空!");
return null;
}
String resp = body.string();
log.info("listUserOfDepartmentUrl:{}", url);
log.info("listUserOfDepartmentRes:{}", resp);
if (!StringUtils.isNotBlank(resp)) {
log.info("获取企业微信部门成员列表-返回结果为空!");
return null;
}
try {
JSONObject jsonObject = JSONObject.parseObject(resp);
if (jsonObject == null || !jsonObject.containsKey("userlist") || jsonObject.getInteger("errcode") != 0) {
log.info("获取企业微信部门成员列表-返回结果为空!");
return null;
}
return jsonObject.getJSONArray("userlist").toJavaList(User.class);
} catch (Exception e) {
log.error("获取企业微信部门成员列表时异常!", e);
return null;
}
} catch (Exception e) {
log.error("获取企业微信部门成员列表时异常!", e);
return null;
}
}
/**
* 获取或刷新token <br>
* 1. 从缓存中获取token <br>
* 2. 如果 token 存在且未过期, 直接返回token <br>
* 3. 如果 token 不存在或已过期, 请求企业微信获取新的token <br>
* 3. 将获取到的token存入缓存 <br>
* 4. 返回token
* @return token
*/
private static WorkAccessToken getOrFlushToken(Config config) {
MapApi tokenCacheMap = FerryCache.proManager().map(CACHE_KEY);
WorkAccessToken token = (WorkAccessToken) tokenCacheMap.hashGet(TOKEN_KEY);
if (token != null && token.isUnExpired()) return token;
synchronized (WeChatUtil.class) {
try {
token = (WorkAccessToken) tokenCacheMap.hashGet(TOKEN_KEY);
if (token != null && token.isUnExpired()) return token;
token = requestToken(config);
if (token != null) {
tokenCacheMap.hashSet(TOKEN_KEY, token);
}
} catch (Exception e) {
log.error("获取或刷新token时异常!", e);
}
}
return token;
}
/**
* 请求企业微信获取token
* @return access token
*/
private static WorkAccessToken requestToken(Config config) {
String url = String.format(config.getAccessTokenUrl(), config.getCorpId(), config.getSecret());
String resp;
try (
Response response = OKHTTP_CLIENT.newCall(new Request.Builder().url(url).build()).execute()
) {
ResponseBody body = response.body();
if (Objects.isNull(body)) {
log.error("请求企业微信[url:" + url + "]获取ACCESS_TOKEN异常!");
return null;
}
resp = body.string();
log.info("accessTokenUrl:{}", url);
log.info("accessTokenRes:{}", resp);
} catch (Exception e) {
log.error("请求企业微信[url:{}]获取ACCESS_TOKEN异常!", url, e);
return null;
}
if (!StringUtils.isNotBlank(resp)) {
log.info("请求企业微信获取ACCESS_TOKEN为空!");
return null;
}
try {
WorkAccessToken token = OBJECT_MAPPER.readValue(resp, WorkAccessToken.class);
if (token == null || !token.isSuccess()) {
log.info("请求企业微信获取ACCESS_TOKEN失败!-TOKEN:{}", resp);
return null;
}
return token;
} catch (JsonProcessingException e) {
log.error("请求企业微信[url:{}]获取ACCESS_TOKEN异常!", url, e);
return null;
}
}
/**
* 企业微信token
*/
private static class WorkAccessToken implements Serializable {
private static final long serialVersionUID = -1704884833558543917L;
/**
* 数据示例
* {
* "errcode": 0,
* "errmsg": "ok",
* "access_token": "hyVmxRCyYUAH0...",
* "expires_in": 7200
* }
*/
//成功状态码
private static final Integer SUCCESS_CODE = 0;
private static final Integer PERIOD = 60;//token 过期缓冲时间-s
/**
* 状态码
* 出错返回码,为0表示成功,非0表示调用失败
*
* @see "https://elinkuat.spic.com.cn/api/doc#10649"
*/
@JsonProperty("errcode")
private Integer errCode;
//消息 返回码提示语
@JsonProperty("errmsg")
private String errMsg;
//token 获取到的凭证,最长为512字节
@JsonProperty("access_token")
private String accessToken;
//过期时间 凭证的有效时间(秒)
@JsonProperty("expires_in")
private Long expiresIn;
//创建时间 秒
private Long createTime = TimeUnit.SECONDS.toSeconds(System.currentTimeMillis());
//是否成功
public boolean isSuccess() {
return this.errCode != null && this.errCode.equals(SUCCESS_CODE);
}
//是否过期-> true 未过期 false 过期
public boolean isUnExpired() {
return TimeUnit.SECONDS.toSeconds(System.currentTimeMillis()) + PERIOD
<= (expiresIn + createTime);
}
/**********************************get & set******************************/
public Integer getErrCode() {
return errCode;
}
public void setErrCode(Integer errCode) {
this.errCode = errCode;
}
public String getErrMsg() {
return errMsg;
}
public void setErrMsg(String errMsg) {
this.errMsg = errMsg;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public Long getExpiresIn() {
return expiresIn;
}
public void setExpiresIn(Long expiresIn) {
this.expiresIn = expiresIn;
}
public Long getCreateTime() {
return createTime;
}
public void setCreateTime(Long createTime) {
this.createTime = createTime;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
WorkAccessToken that = (WorkAccessToken) o;
return Objects.equals(errCode, that.errCode) && Objects.equals(errMsg, that.errMsg) && Objects.equals(accessToken, that.accessToken) && Objects.equals(expiresIn, that.expiresIn) && Objects.equals(createTime, that.createTime);
}
@Override
public int hashCode() {
return Objects.hash(errCode, errMsg, accessToken, expiresIn, createTime);
}
@Override
public String toString() {
return "WorkAccessToken{" +
"errCode=" + errCode +
", errMsg='" + errMsg + '\'' +
", accessToken='" + accessToken + '\'' +
", expiresIn=" + expiresIn +
", createTime=" + createTime +
'}';
}
}
/**
* 企业微信消息返回
*/
private static class WorkMsgResp implements Serializable {
/**
* {
* "errcode" : 0,
* "errmsg" : "ok",
* "invaliduser" : "UserID1", // 不区分大小写,返回的列表都统一转为小写
* "invalidparty" : "PartyID1",
* "msgid" : "xxxxxxxxxx"
* }
*/
//成功状态码
private static final Integer SUCCESS_CODE = 0;
/**
* 状态码
* 出错返回码,为0表示成功,非0表示调用失败
*
* @see "https://elinkuat.spic.com.cn/api/doc#10649"
*/
@JsonProperty("errcode")
private Integer errCode;
//消息 返回码提示语
@JsonProperty("errmsg")
private String errMsg;
@JsonProperty("invaliduser")
private String invalidUser;
@JsonProperty("invalidparty")
private String invalidParty;
@JsonProperty("msgid")
private String msgId;
//是否成功
public boolean isSuccess() {
return this.errCode != null && this.errCode.equals(SUCCESS_CODE);
}
/**********************************get & set******************************/
public String getErrMsg() {
return errMsg;
}
public void setErrMsg(String errMsg) {
this.errMsg = errMsg;
}
public String getInvalidUser() {
return invalidUser;
}
public void setInvalidUser(String invalidUser) {
this.invalidUser = invalidUser;
}
public String getInvalidParty() {
return invalidParty;
}
public void setInvalidParty(String invalidParty) {
this.invalidParty = invalidParty;
}
public String getMsgId() {
return msgId;
}
public void setMsgId(String msgId) {
this.msgId = msgId;
}
@Override
public String toString() {
return "WorkResp{" +
"errCode=" + errCode +
", errMsg='" + errMsg + '\'' +
", invalidUser='" + invalidUser + '\'' +
", invalidParty='" + invalidParty + '\'' +
", msgId='" + msgId + '\'' +
'}';
}
}
/**
* 企业微信部门
*/
public static class Department implements Serializable {
// {
// "id": 2,
// "name": "广州研发中心",
// "name_en": "RDGZ",
// "department_leader":["zhangsan","lisi"],
// "parentid": 1,
// "order": 10
// }
/**
* 部门编号
*/
@JsonProperty("id")
private Integer id;
/**
* 部门名称
*/
@JsonProperty("name")
private String name;
/**
* 部门名称(英文)
*/
@JsonProperty("name_en")
private String nameEn;
/**
* 部门名称(英文)
*/
@JsonProperty("department_leader")
private List<String> departmentLeader;
/**
* 父元素编号
*/
@JsonProperty("parentid")
private Integer parentId;
/**
* 排序编号
*/
@JsonProperty("order")
private Integer order;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNameEn() {
return nameEn;
}
public void setNameEn(String nameEn) {
this.nameEn = nameEn;
}
public List<String> getDepartmentLeader() {
return departmentLeader;
}
public void setDepartmentLeader(List<String> departmentLeader) {
this.departmentLeader = departmentLeader;
}
public Integer getParentId() {
return parentId;
}
public void setParentId(Integer parentId) {
this.parentId = parentId;
}
public Integer getOrder() {
return order;
}
public void setOrder(Integer order) {
this.order = order;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Department that = (Department) o;
return Objects.equals(id, that.id) && Objects.equals(name, that.name) && Objects.equals(nameEn, that.nameEn) && Objects.equals(departmentLeader, that.departmentLeader) && Objects.equals(parentId, that.parentId) && Objects.equals(order, that.order);
}
@Override
public int hashCode() {
return Objects.hash(id, name, nameEn, departmentLeader, parentId, order);
}
@Override
public String toString() {
return "Department{" +
"id=" + id +
", name='" + name + '\'' +
", nameEn='" + nameEn + '\'' +
", departmentLeader=" + departmentLeader +
", parentId=" + parentId +
", order=" + order +
'}';
}
}
/**
* 企业微信用户
*/
public static class User implements Serializable {
// {
// "userid": "zhangsan",
// "name": "张三",
// "department": [1, 2],
// "open_userid": "xxxxxx"
// }
/**
* 成员UserID。对应管理端的帐号
*/
@JsonProperty("userid")
private String userId;
/**
* 成员名称
*/
@JsonProperty("name")
private String name;
/**
* 成员所属部门id列表
*/
@JsonProperty("department")
private List<Integer> department;
/**
* 全局唯一。对于同一个服务商,不同应用获取到企业内同一个成员的open_userid是相同的,最多64个字节。仅第三方应用可获取
*/
@JsonProperty("open_userid")
private String openUserId;
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 String getOpenUserId() {
return openUserId;
}
public void setOpenUserId(String openUserId) {
this.openUserId = openUserId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(userId, user.userId) && Objects.equals(name, user.name) && Objects.equals(department, user.department) && Objects.equals(openUserId, user.openUserId);
}
@Override
public int hashCode() {
return Objects.hash(userId, name, department, openUserId);
}
@Override
public String toString() {
return "User{" +
"userId='" + userId + '\'' +
", name='" + name + '\'' +
", department=" + department +
", openUserId='" + openUserId + '\'' +
'}';
}
}
/**
* 企业微信配置
*/
public static class Config extends BaseConfigBean implements Serializable {
private String secret;
private String corpId;
private String agentId;
// https://10.252.1.8/cgi-bin/gettoken?corpid=%s&corpsecret=%s
private String accessTokenUrl; //获取access_token
// https://10.252.1.8/cgi-bin/message/send?access_token=%s
private String messageSendUrl;//给企业微信成员发送消息
// https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=%s&id=%s
private String listDepartmentUrl; // 列举部门列表
// https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?access_token=ACCESS_TOKEN&department_id=DEPARTMENT_ID
private String listUserOfDepartmentUrl; // 获取部门成员
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
public String getCorpId() {
return corpId;
}
public void setCorpId(String corpId) {
this.corpId = corpId;
}
public String getAccessTokenUrl() {
return accessTokenUrl;
}
public void setAccessTokenUrl(String accessTokenUrl) {
this.accessTokenUrl = accessTokenUrl;
}
public String getMessageSendUrl() {
return messageSendUrl;
}
public void setMessageSendUrl(String messageSendUrl) {
this.messageSendUrl = messageSendUrl;
}
public String getListDepartmentUrl() {
return listDepartmentUrl;
}
public void setListDepartmentUrl(String listDepartmentUrl) {
this.listDepartmentUrl = listDepartmentUrl;
}
public String getListUserOfDepartmentUrl() {
return listUserOfDepartmentUrl;
}
public void setListUserOfDepartmentUrl(String listUserOfDepartmentUrl) {
this.listUserOfDepartmentUrl = listUserOfDepartmentUrl;
}
public String getAgentId() {
return agentId;
}
public void setAgentId(String agentId) {
this.agentId = agentId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Config config = (Config) o;
return Objects.equals(secret, config.secret) && Objects.equals(corpId, config.corpId) && Objects.equals(agentId, config.agentId) && Objects.equals(accessTokenUrl, config.accessTokenUrl) && Objects.equals(messageSendUrl, config.messageSendUrl) && Objects.equals(listDepartmentUrl, config.listDepartmentUrl) && Objects.equals(listUserOfDepartmentUrl, config.listUserOfDepartmentUrl);
}
@Override
public int hashCode() {
return Objects.hash(secret, corpId, agentId, accessTokenUrl, messageSendUrl, listDepartmentUrl, listUserOfDepartmentUrl);
}
@Override
public String toString() {
return "Config{" +
"secret='" + secret + '\'' +
", corpId='" + corpId + '\'' +
", agentId='" + agentId + '\'' +
", accessTokenUrl='" + accessTokenUrl + '\'' +
", messageSendUrl='" + messageSendUrl + '\'' +
", listDepartmentUrl='" + listDepartmentUrl + '\'' +
", listUserOfDepartmentUrl='" + listUserOfDepartmentUrl + '\'' +
'}';
}
}
// public static void main(String[] args) {
// WeChatUtil weChatUtil = new WeChatUtil();
// Config config = new Config();
// config.secret = "6eqa8hRx9DEUR6ecbnkGtuLk8cjrw4TgGM1Oh6ygBh4";
// config.corpId = "ww7660541f094cb144";
// config.accessTokenUrl = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s";
// config.messageSendUrl = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=%s";
// config.listDepartmentUrl = "https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=%s&id=%s";
// weChatUtil.config = config;
// List<Department> departments = weChatUtil.listDepartments(null);
// System.out.println(departments);
// List<User> users = weChatUtil.listUsersOfDepartment(1);
// System.out.println(users);
// }
}
| 1 | public class WeChatUtil { |
| 2 | private final static Logger log = LoggerFactory.getLogger(WeChatUtil.class); |
| 3 | |
| 4 | private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); |
| 5 | private static final OkHttpClient OKHTTP_CLIENT = new OkHttpClient.Builder().build(); |
| 6 | |
| 7 | //缓存token-key |
| 8 | private static final String CACHE_KEY = "WECHAT_TOKEN_CACHE_KEY"; |
| 9 | private static final String TOKEN_KEY = "ACCESS_TOKEN"; |
| 10 | |
| 11 | // private final Config config = ConfigKit.me().get("WeChatUtil.Config",Config.class); |
| 12 | |
| 13 | /** |
| 14 | * 发送文本消息 |
| 15 | * |
| 16 | * @param content 消息内容,最长不超过2048个字节,超过将截断 |
| 17 | * @param userIds 指定接收消息的成员,成员ID列表 多个接收者用‘|’分隔,最多支持1000个 指定为"@all",则向该企业应用的全部成员发送 |
| 18 | * @return 是否发送成功 |
| 19 | */ |
| 20 | public static synchronized boolean sendMsg(Config config, String content, String... userIds) { |
| 21 | WorkAccessToken token = getOrFlushToken(config); |
| 22 | if (token == null) { |
| 23 | log.info("发送企业微信消息-获取 TOEKN 为空!"); |
| 24 | return false; |
| 25 | } |
| 26 | //构建发送消息 |
| 27 | JSONObject postParam = new JSONObject().fluentPut("touser", StringUtils.join(Arrays.asList(userIds), "|")) |
| 28 | .fluentPut("msgtype", "text") |
| 29 | .fluentPut("agentid", config.getAgentId()) |
| 30 | .fluentPut("text", new JSONObject() {{ |
| 31 | put("content", content); |
| 32 | }}); |
| 33 | |
| 34 | String msgUrl = String.format(config.getMessageSendUrl(), token.getAccessToken()); |
| 35 | try ( |
| 36 | Response response = OKHTTP_CLIENT.newCall(new Request.Builder() |
| 37 | .post(RequestBody.create(postParam.toJSONString(), MediaType.parse("application/json;charset=utf-8"))) |
| 38 | .url(msgUrl) |
| 39 | .build()).execute() |
| 40 | ) { |
| 41 | ResponseBody body = response.body(); |
| 42 | if (Objects.isNull(body)) { |
| 43 | log.info("发送企业微信消息-返回结果为空!"); |
| 44 | return false; |
| 45 | } |
| 46 | String resp = body.string(); |
| 47 | log.info("messageSendUrl:{}", config.getMessageSendUrl()); |
| 48 | log.info("msgUrl:{}", msgUrl); |
| 49 | log.info("postParam:{}", postParam.toJSONString()); |
| 50 | log.info("res:{}", resp); |
| 51 | if (!StringUtils.isNotBlank(resp)) { |
| 52 | log.info("发送企业微信消息-返回结果为空!"); |
| 53 | return false; |
| 54 | } |
| 55 | try { |
| 56 | WorkMsgResp workResp = OBJECT_MAPPER.readValue(resp, WorkMsgResp.class); |
| 57 | return workResp != null && workResp.isSuccess(); |
| 58 | } catch (JsonProcessingException e) { |
| 59 | log.error("发送企业微信消息时异常!", e); |
| 60 | return false; |
| 61 | } |
| 62 | } catch (Exception e) { |
| 63 | log.error("发送企业微信消息时异常!", e); |
| 64 | return false; |
| 65 | } |
| 66 | |
| 67 | } |
| 68 | |
| 69 | /** |
| 70 | * 获取部门列表 |
| 71 | * |
| 72 | * @param departmentId 部门id。获取指定部门及其下的子部门(以及子部门的子部门等等,递归)。 如果不填,默认获取全量组织架构 |
| 73 | * @return 部门列表 |
| 74 | */ |
| 75 | public static synchronized List<Department> listDepartments(Config config, Integer departmentId) { |
| 76 | WorkAccessToken token = getOrFlushToken(config); |
| 77 | if (token == null) { |
| 78 | log.info("获取企业微信部门列表-获取 TOEKN 为空!"); |
| 79 | return null; |
| 80 | } |
| 81 | String url = String.format(config.getListDepartmentUrl(), token.getAccessToken(), departmentId); |
| 82 | try ( |
| 83 | Response response = OKHTTP_CLIENT.newCall(new Request.Builder().url(url).build()).execute() |
| 84 | ) { |
| 85 | ResponseBody body = response.body(); |
| 86 | if (Objects.isNull(body)) { |
| 87 | log.info("获取企业微信部门列表-返回结果为空!"); |
| 88 | return null; |
| 89 | } |
| 90 | String resp = body.string(); |
| 91 | log.info("listDepartmentUrl:{}", url); |
| 92 | log.info("listDepartmentRes:{}", resp); |
| 93 | if (!StringUtils.isNotBlank(resp)) { |
| 94 | log.info("获取企业微信部门列表-返回结果为空!"); |
| 95 | return null; |
| 96 | } |
| 97 | try { |
| 98 | JSONObject jsonObject = JSONObject.parseObject(resp); |
| 99 | if (jsonObject == null || !jsonObject.containsKey("department") || jsonObject.getInteger("errcode") != 0) { |
| 100 | log.info("获取企业微信部门列表-返回结果为空!"); |
| 101 | return null; |
| 102 | } |
| 103 | return jsonObject.getJSONArray("department").toJavaList(Department.class); |
| 104 | } catch (Exception e) { |
| 105 | log.error("获取企业微信部门列表时异常!", e); |
| 106 | return null; |
| 107 | } |
| 108 | } catch (Exception e) { |
| 109 | log.error("获取企业微信部门列表时异常!", e); |
| 110 | return null; |
| 111 | } |
| 112 | } |
| 113 | |
| 114 | /** |
| 115 | * 获取部门成员列表 |
| 116 | * |
| 117 | * @param departmentId 部门编号 |
| 118 | * @return 用户列表 |
| 119 | */ |
| 120 | public static synchronized List<User> listUsersOfDepartment(Config config, Integer departmentId) { |
| 121 | WorkAccessToken token = getOrFlushToken(config); |
| 122 | if (token == null) { |
| 123 | log.info("获取企业微信部门成员列表-获取 TOEKN 为空!"); |
| 124 | return null; |
| 125 | } |
| 126 | String url = String.format(config.getListUserOfDepartmentUrl(), token.getAccessToken(), departmentId); |
| 127 | try ( |
| 128 | Response response = OKHTTP_CLIENT.newCall(new Request.Builder().url(url).build()).execute() |
| 129 | ) { |
| 130 | ResponseBody body = response.body(); |
| 131 | if (Objects.isNull(body)) { |
| 132 | log.info("获取企业微信部门成员列表-返回结果为空!"); |
| 133 | return null; |
| 134 | } |
| 135 | String resp = body.string(); |
| 136 | log.info("listUserOfDepartmentUrl:{}", url); |
| 137 | log.info("listUserOfDepartmentRes:{}", resp); |
| 138 | if (!StringUtils.isNotBlank(resp)) { |
| 139 | log.info("获取企业微信部门成员列表-返回结果为空!"); |
| 140 | return null; |
| 141 | } |
| 142 | try { |
| 143 | JSONObject jsonObject = JSONObject.parseObject(resp); |
| 144 | if (jsonObject == null || !jsonObject.containsKey("userlist") || jsonObject.getInteger("errcode") != 0) { |
| 145 | log.info("获取企业微信部门成员列表-返回结果为空!"); |
| 146 | return null; |
| 147 | } |
| 148 | return jsonObject.getJSONArray("userlist").toJavaList(User.class); |
| 149 | } catch (Exception e) { |
| 150 | log.error("获取企业微信部门成员列表时异常!", e); |
| 151 | return null; |
| 152 | } |
| 153 | } catch (Exception e) { |
| 154 | log.error("获取企业微信部门成员列表时异常!", e); |
| 155 | return null; |
| 156 | } |
| 157 | } |
| 158 | |
| 159 | |
| 160 | /** |
| 161 | * 获取或刷新token <br> |
| 162 | * 1. 从缓存中获取token <br> |
| 163 | * 2. 如果 token 存在且未过期, 直接返回token <br> |
| 164 | * 3. 如果 token 不存在或已过期, 请求企业微信获取新的token <br> |
| 165 | * 3. 将获取到的token存入缓存 <br> |
| 166 | * 4. 返回token |
| 167 | * @return token |
| 168 | */ |
| 169 | private static WorkAccessToken getOrFlushToken(Config config) { |
| 170 | MapApi tokenCacheMap = FerryCache.proManager().map(CACHE_KEY); |
| 171 | WorkAccessToken token = (WorkAccessToken) tokenCacheMap.hashGet(TOKEN_KEY); |
| 172 | if (token != null && token.isUnExpired()) return token; |
| 173 | synchronized (WeChatUtil.class) { |
| 174 | try { |
| 175 | token = (WorkAccessToken) tokenCacheMap.hashGet(TOKEN_KEY); |
| 176 | if (token != null && token.isUnExpired()) return token; |
| 177 | token = requestToken(config); |
| 178 | if (token != null) { |
| 179 | tokenCacheMap.hashSet(TOKEN_KEY, token); |
| 180 | } |
| 181 | } catch (Exception e) { |
| 182 | log.error("获取或刷新token时异常!", e); |
| 183 | } |
| 184 | } |
| 185 | return token; |
| 186 | } |
| 187 | |
| 188 | /** |
| 189 | * 请求企业微信获取token |
| 190 | * @return access token |
| 191 | */ |
| 192 | private static WorkAccessToken requestToken(Config config) { |
| 193 | String url = String.format(config.getAccessTokenUrl(), config.getCorpId(), config.getSecret()); |
| 194 | String resp; |
| 195 | try ( |
| 196 | Response response = OKHTTP_CLIENT.newCall(new Request.Builder().url(url).build()).execute() |
| 197 | ) { |
| 198 | ResponseBody body = response.body(); |
| 199 | if (Objects.isNull(body)) { |
| 200 | log.error("请求企业微信[url:" + url + "]获取ACCESS_TOKEN异常!"); |
| 201 | return null; |
| 202 | } |
| 203 | resp = body.string(); |
| 204 | log.info("accessTokenUrl:{}", url); |
| 205 | log.info("accessTokenRes:{}", resp); |
| 206 | } catch (Exception e) { |
| 207 | log.error("请求企业微信[url:{}]获取ACCESS_TOKEN异常!", url, e); |
| 208 | return null; |
| 209 | } |
| 210 | if (!StringUtils.isNotBlank(resp)) { |
| 211 | log.info("请求企业微信获取ACCESS_TOKEN为空!"); |
| 212 | return null; |
| 213 | } |
| 214 | |
| 215 | try { |
| 216 | WorkAccessToken token = OBJECT_MAPPER.readValue(resp, WorkAccessToken.class); |
| 217 | if (token == null || !token.isSuccess()) { |
| 218 | log.info("请求企业微信获取ACCESS_TOKEN失败!-TOKEN:{}", resp); |
| 219 | return null; |
| 220 | } |
| 221 | return token; |
| 222 | } catch (JsonProcessingException e) { |
| 223 | log.error("请求企业微信[url:{}]获取ACCESS_TOKEN异常!", url, e); |
| 224 | return null; |
| 225 | } |
| 226 | } |
| 227 | |
| 228 | |
| 229 | /** |
| 230 | * 企业微信token |
| 231 | */ |
| 232 | private static class WorkAccessToken implements Serializable { |
| 233 | private static final long serialVersionUID = -1704884833558543917L; |
| 234 | /** |
| 235 | * 数据示例 |
| 236 | * { |
| 237 | * "errcode": 0, |
| 238 | * "errmsg": "ok", |
| 239 | * "access_token": "hyVmxRCyYUAH0...", |
| 240 | * "expires_in": 7200 |
| 241 | * } |
| 242 | */ |
| 243 | //成功状态码 |
| 244 | private static final Integer SUCCESS_CODE = 0; |
| 245 | private static final Integer PERIOD = 60;//token 过期缓冲时间-s |
| 246 | |
| 247 | /** |
| 248 | * 状态码 |
| 249 | * 出错返回码,为0表示成功,非0表示调用失败 |
| 250 | * |
| 251 | * @see "https://elinkuat.spic.com.cn/api/doc#10649" |
| 252 | */ |
| 253 | @JsonProperty("errcode") |
| 254 | private Integer errCode; |
| 255 | //消息 返回码提示语 |
| 256 | @JsonProperty("errmsg") |
| 257 | private String errMsg; |
| 258 | //token 获取到的凭证,最长为512字节 |
| 259 | @JsonProperty("access_token") |
| 260 | private String accessToken; |
| 261 | //过期时间 凭证的有效时间(秒) |
| 262 | @JsonProperty("expires_in") |
| 263 | private Long expiresIn; |
| 264 | //创建时间 秒 |
| 265 | private Long createTime = TimeUnit.SECONDS.toSeconds(System.currentTimeMillis()); |
| 266 | |
| 267 | //是否成功 |
| 268 | public boolean isSuccess() { |
| 269 | return this.errCode != null && this.errCode.equals(SUCCESS_CODE); |
| 270 | } |
| 271 | |
| 272 | //是否过期-> true 未过期 false 过期 |
| 273 | public boolean isUnExpired() { |
| 274 | return TimeUnit.SECONDS.toSeconds(System.currentTimeMillis()) + PERIOD |
| 275 | <= (expiresIn + createTime); |
| 276 | } |
| 277 | |
| 278 | /**********************************get & set******************************/ |
| 279 | |
| 280 | public Integer getErrCode() { |
| 281 | return errCode; |
| 282 | } |
| 283 | |
| 284 | public void setErrCode(Integer errCode) { |
| 285 | this.errCode = errCode; |
| 286 | } |
| 287 | |
| 288 | public String getErrMsg() { |
| 289 | return errMsg; |
| 290 | } |
| 291 | |
| 292 | public void setErrMsg(String errMsg) { |
| 293 | this.errMsg = errMsg; |
| 294 | } |
| 295 | |
| 296 | public String getAccessToken() { |
| 297 | return accessToken; |
| 298 | } |
| 299 | |
| 300 | public void setAccessToken(String accessToken) { |
| 301 | this.accessToken = accessToken; |
| 302 | } |
| 303 | |
| 304 | public Long getExpiresIn() { |
| 305 | return expiresIn; |
| 306 | } |
| 307 | |
| 308 | public void setExpiresIn(Long expiresIn) { |
| 309 | this.expiresIn = expiresIn; |
| 310 | } |
| 311 | |
| 312 | public Long getCreateTime() { |
| 313 | return createTime; |
| 314 | } |
| 315 | |
| 316 | public void setCreateTime(Long createTime) { |
| 317 | this.createTime = createTime; |
| 318 | } |
| 319 | |
| 320 | @Override |
| 321 | public boolean equals(Object o) { |
| 322 | if (this == o) return true; |
| 323 | if (o == null || getClass() != o.getClass()) return false; |
| 324 | WorkAccessToken that = (WorkAccessToken) o; |
| 325 | return Objects.equals(errCode, that.errCode) && Objects.equals(errMsg, that.errMsg) && Objects.equals(accessToken, that.accessToken) && Objects.equals(expiresIn, that.expiresIn) && Objects.equals(createTime, that.createTime); |
| 326 | } |
| 327 | |
| 328 | @Override |
| 329 | public int hashCode() { |
| 330 | return Objects.hash(errCode, errMsg, accessToken, expiresIn, createTime); |
| 331 | } |
| 332 | |
| 333 | @Override |
| 334 | public String toString() { |
| 335 | return "WorkAccessToken{" + |
| 336 | "errCode=" + errCode + |
| 337 | ", errMsg='" + errMsg + '\'' + |
| 338 | ", accessToken='" + accessToken + '\'' + |
| 339 | ", expiresIn=" + expiresIn + |
| 340 | ", createTime=" + createTime + |
| 341 | '}'; |
| 342 | } |
| 343 | } |
| 344 | |
| 345 | /** |
| 346 | * 企业微信消息返回 |
| 347 | */ |
| 348 | private static class WorkMsgResp implements Serializable { |
| 349 | /** |
| 350 | * { |
| 351 | * "errcode" : 0, |
| 352 | * "errmsg" : "ok", |
| 353 | * "invaliduser" : "UserID1", // 不区分大小写,返回的列表都统一转为小写 |
| 354 | * "invalidparty" : "PartyID1", |
| 355 | * "msgid" : "xxxxxxxxxx" |
| 356 | * } |
| 357 | */ |
| 358 | |
| 359 | //成功状态码 |
| 360 | private static final Integer SUCCESS_CODE = 0; |
| 361 | |
| 362 | /** |
| 363 | * 状态码 |
| 364 | * 出错返回码,为0表示成功,非0表示调用失败 |
| 365 | * |
| 366 | * @see "https://elinkuat.spic.com.cn/api/doc#10649" |
| 367 | */ |
| 368 | @JsonProperty("errcode") |
| 369 | private Integer errCode; |
| 370 | //消息 返回码提示语 |
| 371 | @JsonProperty("errmsg") |
| 372 | private String errMsg; |
| 373 | |
| 374 | @JsonProperty("invaliduser") |
| 375 | private String invalidUser; |
| 376 | |
| 377 | @JsonProperty("invalidparty") |
| 378 | private String invalidParty; |
| 379 | |
| 380 | @JsonProperty("msgid") |
| 381 | private String msgId; |
| 382 | |
| 383 | //是否成功 |
| 384 | public boolean isSuccess() { |
| 385 | return this.errCode != null && this.errCode.equals(SUCCESS_CODE); |
| 386 | } |
| 387 | |
| 388 | /**********************************get & set******************************/ |
| 389 | public String getErrMsg() { |
| 390 | return errMsg; |
| 391 | } |
| 392 | |
| 393 | public void setErrMsg(String errMsg) { |
| 394 | this.errMsg = errMsg; |
| 395 | } |
| 396 | |
| 397 | public String getInvalidUser() { |
| 398 | return invalidUser; |
| 399 | } |
| 400 | |
| 401 | public void setInvalidUser(String invalidUser) { |
| 402 | this.invalidUser = invalidUser; |
| 403 | } |
| 404 | |
| 405 | public String getInvalidParty() { |
| 406 | return invalidParty; |
| 407 | } |
| 408 | |
| 409 | public void setInvalidParty(String invalidParty) { |
| 410 | this.invalidParty = invalidParty; |
| 411 | } |
| 412 | |
| 413 | public String getMsgId() { |
| 414 | return msgId; |
| 415 | } |
| 416 | |
| 417 | public void setMsgId(String msgId) { |
| 418 | this.msgId = msgId; |
| 419 | } |
| 420 | |
| 421 | @Override |
| 422 | public String toString() { |
| 423 | return "WorkResp{" + |
| 424 | "errCode=" + errCode + |
| 425 | ", errMsg='" + errMsg + '\'' + |
| 426 | ", invalidUser='" + invalidUser + '\'' + |
| 427 | ", invalidParty='" + invalidParty + '\'' + |
| 428 | ", msgId='" + msgId + '\'' + |
| 429 | '}'; |
| 430 | } |
| 431 | } |
| 432 | |
| 433 | /** |
| 434 | * 企业微信部门 |
| 435 | */ |
| 436 | public static class Department implements Serializable { |
| 437 | // { |
| 438 | // "id": 2, |
| 439 | // "name": "广州研发中心", |
| 440 | // "name_en": "RDGZ", |
| 441 | // "department_leader":["zhangsan","lisi"], |
| 442 | // "parentid": 1, |
| 443 | // "order": 10 |
| 444 | // } |
| 445 | |
| 446 | /** |
| 447 | * 部门编号 |
| 448 | */ |
| 449 | @JsonProperty("id") |
| 450 | private Integer id; |
| 451 | /** |
| 452 | * 部门名称 |
| 453 | */ |
| 454 | @JsonProperty("name") |
| 455 | private String name; |
| 456 | /** |
| 457 | * 部门名称(英文) |
| 458 | */ |
| 459 | @JsonProperty("name_en") |
| 460 | private String nameEn; |
| 461 | /** |
| 462 | * 部门名称(英文) |
| 463 | */ |
| 464 | @JsonProperty("department_leader") |
| 465 | private List<String> departmentLeader; |
| 466 | /** |
| 467 | * 父元素编号 |
| 468 | */ |
| 469 | @JsonProperty("parentid") |
| 470 | private Integer parentId; |
| 471 | /** |
| 472 | * 排序编号 |
| 473 | */ |
| 474 | @JsonProperty("order") |
| 475 | private Integer order; |
| 476 | |
| 477 | public Integer getId() { |
| 478 | return id; |
| 479 | } |
| 480 | |
| 481 | public void setId(Integer id) { |
| 482 | this.id = id; |
| 483 | } |
| 484 | |
| 485 | public String getName() { |
| 486 | return name; |
| 487 | } |
| 488 | |
| 489 | public void setName(String name) { |
| 490 | this.name = name; |
| 491 | } |
| 492 | |
| 493 | public String getNameEn() { |
| 494 | return nameEn; |
| 495 | } |
| 496 | |
| 497 | public void setNameEn(String nameEn) { |
| 498 | this.nameEn = nameEn; |
| 499 | } |
| 500 | |
| 501 | public List<String> getDepartmentLeader() { |
| 502 | return departmentLeader; |
| 503 | } |
| 504 | |
| 505 | public void setDepartmentLeader(List<String> departmentLeader) { |
| 506 | this.departmentLeader = departmentLeader; |
| 507 | } |
| 508 | |
| 509 | public Integer getParentId() { |
| 510 | return parentId; |
| 511 | } |
| 512 | |
| 513 | public void setParentId(Integer parentId) { |
| 514 | this.parentId = parentId; |
| 515 | } |
| 516 | |
| 517 | public Integer getOrder() { |
| 518 | return order; |
| 519 | } |
| 520 | |
| 521 | public void setOrder(Integer order) { |
| 522 | this.order = order; |
| 523 | } |
| 524 | |
| 525 | @Override |
| 526 | public boolean equals(Object o) { |
| 527 | if (this == o) return true; |
| 528 | if (o == null || getClass() != o.getClass()) return false; |
| 529 | Department that = (Department) o; |
| 530 | return Objects.equals(id, that.id) && Objects.equals(name, that.name) && Objects.equals(nameEn, that.nameEn) && Objects.equals(departmentLeader, that.departmentLeader) && Objects.equals(parentId, that.parentId) && Objects.equals(order, that.order); |
| 531 | } |
| 532 | |
| 533 | @Override |
| 534 | public int hashCode() { |
| 535 | return Objects.hash(id, name, nameEn, departmentLeader, parentId, order); |
| 536 | } |
| 537 | |
| 538 | @Override |
| 539 | public String toString() { |
| 540 | return "Department{" + |
| 541 | "id=" + id + |
| 542 | ", name='" + name + '\'' + |
| 543 | ", nameEn='" + nameEn + '\'' + |
| 544 | ", departmentLeader=" + departmentLeader + |
| 545 | ", parentId=" + parentId + |
| 546 | ", order=" + order + |
| 547 | '}'; |
| 548 | } |
| 549 | } |
| 550 | |
| 551 | /** |
| 552 | * 企业微信用户 |
| 553 | */ |
| 554 | public static class User implements Serializable { |
| 555 | // { |
| 556 | // "userid": "zhangsan", |
| 557 | // "name": "张三", |
| 558 | // "department": [1, 2], |
| 559 | // "open_userid": "xxxxxx" |
| 560 | // } |
| 561 | |
| 562 | /** |
| 563 | * 成员UserID。对应管理端的帐号 |
| 564 | */ |
| 565 | @JsonProperty("userid") |
| 566 | private String userId; |
| 567 | /** |
| 568 | * 成员名称 |
| 569 | */ |
| 570 | @JsonProperty("name") |
| 571 | private String name; |
| 572 | /** |
| 573 | * 成员所属部门id列表 |
| 574 | */ |
| 575 | @JsonProperty("department") |
| 576 | private List<Integer> department; |
| 577 | /** |
| 578 | * 全局唯一。对于同一个服务商,不同应用获取到企业内同一个成员的open_userid是相同的,最多64个字节。仅第三方应用可获取 |
| 579 | */ |
| 580 | @JsonProperty("open_userid") |
| 581 | private String openUserId; |
| 582 | |
| 583 | public String getUserId() { |
| 584 | return userId; |
| 585 | } |
| 586 | |
| 587 | public void setUserId(String userId) { |
| 588 | this.userId = userId; |
| 589 | } |
| 590 | |
| 591 | public String getName() { |
| 592 | return name; |
| 593 | } |
| 594 | |
| 595 | public void setName(String name) { |
| 596 | this.name = name; |
| 597 | } |
| 598 | |
| 599 | public List<Integer> getDepartment() { |
| 600 | return department; |
| 601 | } |
| 602 | |
| 603 | public void setDepartment(List<Integer> department) { |
| 604 | this.department = department; |
| 605 | } |
| 606 | |
| 607 | public String getOpenUserId() { |
| 608 | return openUserId; |
| 609 | } |
| 610 | |
| 611 | public void setOpenUserId(String openUserId) { |
| 612 | this.openUserId = openUserId; |
| 613 | } |
| 614 | |
| 615 | @Override |
| 616 | public boolean equals(Object o) { |
| 617 | if (this == o) return true; |
| 618 | if (o == null || getClass() != o.getClass()) return false; |
| 619 | User user = (User) o; |
| 620 | return Objects.equals(userId, user.userId) && Objects.equals(name, user.name) && Objects.equals(department, user.department) && Objects.equals(openUserId, user.openUserId); |
| 621 | } |
| 622 | |
| 623 | @Override |
| 624 | public int hashCode() { |
| 625 | return Objects.hash(userId, name, department, openUserId); |
| 626 | } |
| 627 | |
| 628 | @Override |
| 629 | public String toString() { |
| 630 | return "User{" + |
| 631 | "userId='" + userId + '\'' + |
| 632 | ", name='" + name + '\'' + |
| 633 | ", department=" + department + |
| 634 | ", openUserId='" + openUserId + '\'' + |
| 635 | '}'; |
| 636 | } |
| 637 | } |
| 638 | |
| 639 | /** |
| 640 | * 企业微信配置 |
| 641 | */ |
| 642 | public static class Config extends BaseConfigBean implements Serializable { |
| 643 | private String secret; |
| 644 | private String corpId; |
| 645 | private String agentId; |
| 646 | // https://10.252.1.8/cgi-bin/gettoken?corpid=%s&corpsecret=%s |
| 647 | private String accessTokenUrl; //获取access_token |
| 648 | // https://10.252.1.8/cgi-bin/message/send?access_token=%s |
| 649 | private String messageSendUrl;//给企业微信成员发送消息 |
| 650 | // https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=%s&id=%s |
| 651 | private String listDepartmentUrl; // 列举部门列表 |
| 652 | // https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?access_token=ACCESS_TOKEN&department_id=DEPARTMENT_ID |
| 653 | private String listUserOfDepartmentUrl; // 获取部门成员 |
| 654 | |
| 655 | public String getSecret() { |
| 656 | return secret; |
| 657 | } |
| 658 | |
| 659 | public void setSecret(String secret) { |
| 660 | this.secret = secret; |
| 661 | } |
| 662 | |
| 663 | public String getCorpId() { |
| 664 | return corpId; |
| 665 | } |
| 666 | |
| 667 | public void setCorpId(String corpId) { |
| 668 | this.corpId = corpId; |
| 669 | } |
| 670 | |
| 671 | public String getAccessTokenUrl() { |
| 672 | return accessTokenUrl; |
| 673 | } |
| 674 | |
| 675 | public void setAccessTokenUrl(String accessTokenUrl) { |
| 676 | this.accessTokenUrl = accessTokenUrl; |
| 677 | } |
| 678 | |
| 679 | public String getMessageSendUrl() { |
| 680 | return messageSendUrl; |
| 681 | } |
| 682 | |
| 683 | public void setMessageSendUrl(String messageSendUrl) { |
| 684 | this.messageSendUrl = messageSendUrl; |
| 685 | } |
| 686 | |
| 687 | public String getListDepartmentUrl() { |
| 688 | return listDepartmentUrl; |
| 689 | } |
| 690 | |
| 691 | public void setListDepartmentUrl(String listDepartmentUrl) { |
| 692 | this.listDepartmentUrl = listDepartmentUrl; |
| 693 | } |
| 694 | |
| 695 | public String getListUserOfDepartmentUrl() { |
| 696 | return listUserOfDepartmentUrl; |
| 697 | } |
| 698 | |
| 699 | public void setListUserOfDepartmentUrl(String listUserOfDepartmentUrl) { |
| 700 | this.listUserOfDepartmentUrl = listUserOfDepartmentUrl; |
| 701 | } |
| 702 | |
| 703 | public String getAgentId() { |
| 704 | return agentId; |
| 705 | } |
| 706 | |
| 707 | public void setAgentId(String agentId) { |
| 708 | this.agentId = agentId; |
| 709 | } |
| 710 | |
| 711 | @Override |
| 712 | public boolean equals(Object o) { |
| 713 | if (this == o) return true; |
| 714 | if (o == null || getClass() != o.getClass()) return false; |
| 715 | Config config = (Config) o; |
| 716 | return Objects.equals(secret, config.secret) && Objects.equals(corpId, config.corpId) && Objects.equals(agentId, config.agentId) && Objects.equals(accessTokenUrl, config.accessTokenUrl) && Objects.equals(messageSendUrl, config.messageSendUrl) && Objects.equals(listDepartmentUrl, config.listDepartmentUrl) && Objects.equals(listUserOfDepartmentUrl, config.listUserOfDepartmentUrl); |
| 717 | } |
| 718 | |
| 719 | @Override |
| 720 | public int hashCode() { |
| 721 | return Objects.hash(secret, corpId, agentId, accessTokenUrl, messageSendUrl, listDepartmentUrl, listUserOfDepartmentUrl); |
| 722 | } |
| 723 | |
| 724 | @Override |
| 725 | public String toString() { |
| 726 | return "Config{" + |
| 727 | "secret='" + secret + '\'' + |
| 728 | ", corpId='" + corpId + '\'' + |
| 729 | ", agentId='" + agentId + '\'' + |
| 730 | ", accessTokenUrl='" + accessTokenUrl + '\'' + |
| 731 | ", messageSendUrl='" + messageSendUrl + '\'' + |
| 732 | ", listDepartmentUrl='" + listDepartmentUrl + '\'' + |
| 733 | ", listUserOfDepartmentUrl='" + listUserOfDepartmentUrl + '\'' + |
| 734 | '}'; |
| 735 | } |
| 736 | } |
| 737 | |
| 738 | // public static void main(String[] args) { |
| 739 | // WeChatUtil weChatUtil = new WeChatUtil(); |
| 740 | // Config config = new Config(); |
| 741 | // config.secret = "6eqa8hRx9DEUR6ecbnkGtuLk8cjrw4TgGM1Oh6ygBh4"; |
| 742 | // config.corpId = "ww7660541f094cb144"; |
| 743 | // config.accessTokenUrl = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s"; |
| 744 | // config.messageSendUrl = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=%s"; |
| 745 | // config.listDepartmentUrl = "https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=%s&id=%s"; |
| 746 | |
| 747 | // weChatUtil.config = config; |
| 748 | // List<Department> departments = weChatUtil.listDepartments(null); |
| 749 | // System.out.println(departments); |
| 750 | // List<User> users = weChatUtil.listUsersOfDepartment(1); |
| 751 | // System.out.println(users); |
| 752 | // } |
| 753 | } |
| 754 |