package com.usoftchina.qywx.sdk;
import com.usoftchina.qywx.sdk.config.Agent;
import com.usoftchina.qywx.sdk.config.QywxProperties;
import com.usoftchina.qywx.sdk.dto.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.ModelMap;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
/**
* 通讯录管理
*
* @author yingp
*/
public class AddrBookSdk extends BaseSdk {
/**
* 通讯录管理私钥
*
使用应用secret只能进行“查询”、“邀请”等非写操作,而且只能操作应用可见范围内的通讯录
*/
public final static String ADDRESS_BOOK_AGENT_CODE = "AddressBook";
private final Logger logger = LoggerFactory.getLogger(AddrBookSdk.class);
public AddrBookSdk(QywxProperties properties) {
super(properties);
}
/**
* 是否启用
*
* @return
*/
public boolean enabled() {
Agent agent = getAgentMap().get(ADDRESS_BOOK_AGENT_CODE);
return null != agent && null != agent.getSecret();
}
/**
* sdk是否只有读权限
*
* @return
*/
public boolean isReadonly() {
return enabled() && getAgentMap().get(ADDRESS_BOOK_AGENT_CODE).isReadonly();
}
/**
* 创建成员
*
* @param req
*/
public void createUser(CreateUserReq req) {
tryAndIgnoreSystemError(() ->
restTemplate.postForEntity(baseUrl + "/cgi-bin/user/create?access_token={access_token}",
req.build(), BaseResp.class,
new ModelMap("access_token", getAccessToken(ADDRESS_BOOK_AGENT_CODE)))
);
}
/**
* 读取成员
*
* @param userId 成员UserID。对应管理端的帐号,企业内必须唯一。不区分大小写,长度为1~64个字节
*/
public GetUserResp getUser(String userId) {
ResponseEntity resp = restTemplate.getForEntity(baseUrl + "/cgi-bin/user/get?access_token={access_token}&userid={userid}",
GetUserResp.class,
new ModelMap("access_token", getAccessToken(ADDRESS_BOOK_AGENT_CODE)).addAttribute("userid", userId));
assertOK(resp);
return resp.getBody();
}
/**
* 更新成员
*
* @param req
*/
public void updateUser(UpdateUserReq req) {
tryAndIgnoreSystemError(() ->
restTemplate.postForEntity(baseUrl + "/cgi-bin/user/update?access_token={access_token}",
req.build(), BaseResp.class,
new ModelMap("access_token", getAccessToken(ADDRESS_BOOK_AGENT_CODE)))
);
}
/**
* 删除成员
*
* @param userId 成员UserID。对应管理端的帐号
*/
public void deleteUser(String userId) {
tryAndIgnoreSystemError(() ->
restTemplate.getForEntity(baseUrl + "/cgi-bin/user/delete?access_token={access_token}&userid={userid}",
BaseResp.class,
new ModelMap("access_token", getAccessToken(ADDRESS_BOOK_AGENT_CODE)).addAttribute("userid", userId))
);
}
/**
* 批量删除成员
*
* @param userIdList 成员UserID列表。对应管理端的帐号。最多支持200个。若存在无效UserID,直接返回错误
*/
public void deleteUser(List userIdList) {
tryAndIgnoreSystemError(() ->
restTemplate.postForEntity(baseUrl + "/cgi-bin/user/batchdelete?access_token={access_token}",
new ModelMap("useridlist", userIdList),
BaseResp.class,
new ModelMap("access_token", getAccessToken(ADDRESS_BOOK_AGENT_CODE)))
);
}
/**
* 获取部门成员
*
* @param departmentId 部门ID
* @param fetchChild 是否递归获取子部门下面的成员:1-递归获取,0-只获取本部门
* 企业微信升级,方法不可用
*/
@Deprecated
public List getSimpleUserList(Integer departmentId, boolean fetchChild) {
ResponseEntity resp = restTemplate.getForEntity(baseUrl + "/cgi-bin/user/simplelist?access_token={access_token}&department_id={department_id}&fetch_child={fetch_child}",
GetSimpleUserListResp.class,
new ModelMap("access_token", getAccessToken(ADDRESS_BOOK_AGENT_CODE))
.addAttribute("department_id", departmentId)
.addAttribute("fetch_child", fetchChild ? 1 : 0));
assertOK(resp);
return resp.getBody().getUserlist();
}
/**
* 获取部门成员详情
*
* @param departmentId 部门ID
* @param fetchChild 是否递归获取子部门下面的成员:1-递归获取,0-只获取本部门
* 企业微信升级,方法不可用
* @return
*/
@Deprecated
public List getUserList(Integer departmentId, boolean fetchChild) {
ResponseEntity resp = restTemplate.getForEntity(baseUrl + "/cgi-bin/user/list?access_token={access_token}&department_id={department_id}&fetch_child={fetch_child}",
GetUserListResp.class,
new ModelMap("access_token", getAccessToken(ADDRESS_BOOK_AGENT_CODE))
.addAttribute("department_id", departmentId)
.addAttribute("fetch_child", fetchChild ? 1 : 0));
assertOK(resp);
return resp.getBody().getUserlist();
}
/**
* 获取部门成员详情
* @param cursor 用于分页查询的游标,字符串类型,由上一次调用返回,首次调用不填
* limit 分页,预期请求的数据量,取值范围 1 ~ 10000 默认10000
* @return
*/
public List getUserIdList(List userList,String cursor) {
ResponseEntity resp = restTemplate.getForEntity(baseUrl + "/cgi-bin/user/list_id?access_token={access_token}&cursor={cursor}&limit={limit}",
GetSimpleUserIDListResp.class,
new ModelMap("access_token", getAccessToken(ADDRESS_BOOK_AGENT_CODE))
.addAttribute("cursor", cursor)
.addAttribute("limit", 10000));
assertOK(resp);
if(StringUtils.hasText(resp.getBody().getNext_cursor())){
System.out.println("Next_cursor:"+resp.getBody().getNext_cursor());
return getUserIdList(resp.getBody().getDept_user(),resp.getBody().getNext_cursor());
}else {
userList.addAll(resp.getBody().getDept_user());
return userList;
}
}
/**
* userid转openid
* 该接口使用场景为企业支付,在使用企业红包和向员工付款时,需要自行将企业微信的userid转成openid。
*
* @param userId
* @return
*/
public String getOpenId(String userId) {
ResponseEntity resp = restTemplate.postForEntity(baseUrl + "/cgi-bin/user/convert_to_openid?access_token={access_token}",
new ModelMap("userid", userId),
GetOpenIdResp.class,
new ModelMap("access_token", getAccessToken(ADDRESS_BOOK_AGENT_CODE)));
assertOK(resp);
return resp.getBody().getOpenid();
}
/**
* 二次验证
*
* 企业在开启二次验证时,必须在管理端填写企业二次验证页面的url。
* 当成员登录企业微信或关注微工作台(原企业号)加入企业时,会自动跳转到企业的验证页面。在跳转到企业的验证页面时,会带上如下参数:code=CODE。
* 企业收到code后,使用“通讯录同步助手”调用接口“根据code获取成员信息”获取成员的userid。然后在验证成员信息成功后,调用如下接口即可让成员成功加入企业
*
*
* @param userId
*/
public void authSuccess(String userId) {
ResponseEntity resp = restTemplate.getForEntity(baseUrl + "/cgi-bin/user/authsucc?access_token={access_token}&userid={userid}",
BaseResp.class,
new ModelMap("access_token", getAccessToken(ADDRESS_BOOK_AGENT_CODE))
.addAttribute("userid", userId));
assertOK(resp);
}
/**
* 邀请成员
* 企业可通过接口批量邀请成员使用企业微信,邀请后将通过短信或邮件下发通知
*
* @param req
*/
public InviteResp invite(InviteReq req) {
ResponseEntity resp = restTemplate.postForEntity(baseUrl + "/cgi-bin/batch/invite?access_token={access_token}",
req.build(), InviteResp.class,
new ModelMap("access_token", getAccessToken(ADDRESS_BOOK_AGENT_CODE)));
assertOK(resp);
return resp.getBody();
}
/**
* 获取加入企业二维码
*
* @param type 尺寸
* @return 二维码链接,有效期7天
*/
public String getJoinQrCode(QrCodeType type) {
ResponseEntity resp = restTemplate.getForEntity(baseUrl + "/cgi-bin/corp/get_join_qrcode?access_token={access_token}&size_type={size_type}",
GetJoinQrCodeResp.class,
new ModelMap("access_token", getAccessToken(ADDRESS_BOOK_AGENT_CODE))
.addAttribute("size_type", type.code));
assertOK(resp);
return resp.getBody().getJoin_qrcode();
}
/**
* qrcode尺寸类型
*/
public enum QrCodeType {
T_171_171(1),
T_399_399(2),
T_741_741(3),
T_2052_2052(4);
private final int code;
QrCodeType(int code) {
this.code = code;
}
public int getCode() {
return code;
}
}
/**
* 创建部门
*
* @param req
* @return 部门ID
*/
public Integer createDepartment(CreateDepartmentReq req) {
ResponseEntity resp = tryAndIgnoreSystemError(() ->
restTemplate.postForEntity(baseUrl + "/cgi-bin/department/create?access_token={access_token}",
req.build(), CreateDepartmentResp.class,
new ModelMap("access_token", getAccessToken(ADDRESS_BOOK_AGENT_CODE)))
);
return null == resp ? null : resp.getBody().getId();
}
/**
* 更新部门
*
* @param req
*/
public void updateDepartment(UpdateDepartmentReq req) {
tryAndIgnoreSystemError(() ->
restTemplate.postForEntity(baseUrl + "/cgi-bin/department/update?access_token={access_token}",
req.build(), BaseResp.class,
new ModelMap("access_token", getAccessToken(ADDRESS_BOOK_AGENT_CODE)))
);
}
/**
* 删除部门
*
* @param departmentId
*/
public void deleteDepartment(int departmentId) {
tryAndIgnoreSystemError(() ->
restTemplate.getForEntity(baseUrl + "/cgi-bin/department/delete?access_token={access_token}&id={id}",
BaseResp.class,
new ModelMap("access_token", getAccessToken(ADDRESS_BOOK_AGENT_CODE))
.addAttribute("id", departmentId))
);
}
/**
* 获取部门
* 企业微信升级,方法不可用
* @param departmentId
* @return
*/
@Deprecated
public GetDepartmentListResp.Department getDepartment(int departmentId) {
List departmentList = getDepartmentList(departmentId);
if (!CollectionUtils.isEmpty(departmentList)) {
for (GetDepartmentListResp.Department department : departmentList) {
if (department.getId().equals(departmentId)) {
return department;
}
}
}
return null;
}
/**
* 获取部门,包括下级
* 企业微信升级,方法不可用
* @param departmentId
* @return
*/
@Deprecated
public List getDepartmentList(int departmentId) {
ResponseEntity resp = restTemplate.getForEntity(baseUrl + "/cgi-bin/department/list?access_token={access_token}&id={id}",
GetDepartmentListResp.class,
new ModelMap("access_token", getAccessToken(ADDRESS_BOOK_AGENT_CODE))
.addAttribute("id", departmentId));
assertOK(resp);
if (!CollectionUtils.isEmpty(resp.getBody().getDepartment())) {
return resp.getBody().getDepartment();
}
return null;
}
/**
* 获取部门列表
* 企业微信升级,方法不可用
* @return
*/
@Deprecated
public List getDepartmentList() {
ResponseEntity resp = restTemplate.getForEntity(baseUrl + "/cgi-bin/department/list?access_token={access_token}",
GetDepartmentListResp.class,
new ModelMap("access_token", getAccessToken(ADDRESS_BOOK_AGENT_CODE)));
assertOK(resp);
return resp.getBody().getDepartment();
}
/**
* 获取部门列表
*
* @return
*/
public List getSimpleDepartmentList() {
ResponseEntity resp = restTemplate.getForEntity(baseUrl + "/cgi-bin/department/simplelist?access_token={access_token}&id={id}",
GetDepartmentSimpleListResp.class,
new ModelMap("access_token", getAccessToken(ADDRESS_BOOK_AGENT_CODE))
.addAttribute("id", 0));
assertOK(resp);
return resp.getBody().getDepartment_id();
}
/**
* 获取部门列表
*
* @return
*/
public List getSimpleDepartmentList(Integer departmentId) {
ResponseEntity resp = restTemplate.getForEntity(baseUrl + "/cgi-bin/department/simplelist?access_token={access_token}&id={id}",
GetDepartmentSimpleListResp.class,
new ModelMap("access_token", getAccessToken(ADDRESS_BOOK_AGENT_CODE))
.addAttribute("id", departmentId));
assertOK(resp);
return resp.getBody().getDepartment_id();
}
/**
* 获取访问用户身份
*
* @param agentCode 应用编号
* @param code 授权码
*/
public GetUserInfoResp getUserInfo(String agentCode, String code) {
ResponseEntity resp = restTemplate.getForEntity(baseUrl + "/cgi-bin/user/getuserinfo?access_token={access_token}&code={code}",
GetUserInfoResp.class,
new ModelMap("access_token", getAccessToken(agentCode))
.addAttribute("code", code));
assertOK(resp);
return resp.getBody();
}
/**
* 获取用户UserID
*
* @param mobile 手机号
* */
public GetUserInfoResp getUserInfoByMobile(String mobile) {
ResponseEntity resp = restTemplate.postForEntity(baseUrl + "/cgi-bin/user/getuserid?access_token={access_token}&debug=1",
new ModelMap("mobile", mobile),
GetUserInfoResp.class,
new ModelMap("access_token", getAccessToken(ADDRESS_BOOK_AGENT_CODE)));
return resp.getBody();
}
/**
* 获取用户openid
* access_token 代开发企业应用的access_token
* */
public GetUserOpenIDListResp convert_openUserId(List userList) {
logger.info("convert_openUserId:{}",String.join("," , userList));
ResponseEntity resp = restTemplate.postForEntity(
baseUrl + "/cgi-bin/batch/userid_to_openuserid?access_token={access_token}",
new ModelMap("userid_list", userList),
GetUserOpenIDListResp.class,
new ModelMap("access_token", getAccessToken(null)));
logger.info("convert_openUserId--:{}",resp.getBody());
assertOK(resp);
return resp.getBody();
}
/**
* 以下接口仅能获取企业内部openuserid
* */
/* public List convert_openUserId(List userList) {
List openUsers = new ArrayList<>();
for(String userId : userList) {
try {
GetUserOpenIDListResp.OpenUser openUser = new GetUserOpenIDListResp.OpenUser();
openUser.setUserid(userId);
openUser.setOpen_userid(getOpenId(userId));
openUsers.add(openUser);
} catch (Exception e) {
logger.error("转换用户ID失败: {}", userId, e);
// 失败时仍保留用户ID,但openid为null
GetUserOpenIDListResp.OpenUser openUser = new GetUserOpenIDListResp.OpenUser();
openUser.setUserid(userId);
openUsers.add(openUser);
}
}
return openUsers;
}*/
}