开源一夏 |企业内部应用接入钉钉获取部门及人员信息
- 2022 年 8 月 22 日 北京
本文字数:12682 字
阅读完需:约 42 分钟
开发者后台配置
1.登录开发者后台并配置
首先需要登录开发者后台,配置企业内部应用,如图
可以点击【返回旧版】,个人比较习惯了旧版的操作风格,旧版风格如下
2.创建应用
选中【H5 微应用】,点击【创建应用】
应用创建完成之后可以看到如图
记录下对应的 AgentId、AppKey、AppSecret,上面步骤都操作完成之后需要开启对应权限,由于我们需要获取部门及人员信息,因此需要开启对应权限,点击【权限管理】选择需要的权限点击【申请权限】即可,如图
java 开发阶段
1.所需钉钉接口文档
完成了【开发者后台】配置后,就可以进入开发阶段了,首先确定需要两个接口,文档为获取部门列表和获取部门用户详情,仔细阅读完文档后进入后面操作。
2.springboot 项目配置类
添加配置类 DingDingProperties.java 读取配置信息,代码中给出的对应 key 信息为默认信息,后面可通过配置文件设置
package com.dongao.project.config.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @ClassName:DingDingProperties
* @author:dongao
* @date 2022/1/27 10:23
*/
@Component
@ConfigurationProperties(prefix = "dingtalk.msg")
public class DingDingProperties {
public String agentId = "1111111";
public String appKey = "dingbmxxxggddfdf";
public String appSecret = "KIy8DasdfghbbdhghdvgfdfC5gztU-m1nFYQfiUUil-6pnHJN-wU_Xv";
public String getAgentId() {
return agentId;
}
public void setAgentId(String agentId) {
this.agentId = agentId;
}
public String getAppKey() {
return appKey;
}
public void setAppKey(String appKey) {
this.appKey = appKey;
}
public String getAppSecret() {
return appSecret;
}
public void setAppSecret(String appSecret) {
this.appSecret = appSecret;
}
}
代码中的配置参数可以通过 application.properties 文件进行更改
dingtalk.msg.agentId=12345345
dingtalk.msg.appKey=fggsfhnhhjsdfdsf
dingtalk.msg.appSecret=234dfgfhbvbhsdfdsgsf-fgdfhghbbdhjj-6pnHJN-wU_Xv
3.pom.xml
pom.xml 文件引入钉钉 jar 包依赖
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>alibaba-dingtalk-service-sdk</artifactId>
<version>2.0.0</version>
</dependency>
4.编写接口及实现类
编写钉钉接口 IDingDingService.java,这里面也包括了发送钉钉消息相关的内容,此文可以忽略,只关注获取钉钉部门及部门下人员信息即可
package com.dongao.project.common.dingding;
import com.dingtalk.api.response.*;
import com.taobao.api.ApiException;
import org.springframework.web.multipart.MultipartFile;
/**
* Created by nao'nao on 2020/3/31.
* @author dingding
* 工作通知消息的发送限制
*(1)企业开发者每分钟最多可调用接口1500次,ISV开发者每分钟最多可调用接口1000次
*(2)企业发送消息单次最多只能给5000人发送,ISV发送消息单次最多能给1000人发送
*(3)给同一员工发送内容相同的消息,一天只能发一次
*(4)企业发送每个员工每天最多可发送500条,ISV方式最多可发送50条
*(5)企业/ISV发送消息时每分钟最多只能有5000人可以接收到消息
*/
public interface IDingDingService {
/**
* 调用钉钉上传文件
* (1) 图片(image):1MB,支持JPG格式
* (2)语音(voice):2MB,播放长度不超过60s,AMR格式
* (3)普通文件(file):10MB
* @param type 文件类型 image file (voice暂不支持)
* @param file 文件
* @return 返回上传成功对象 OapiMediaUploadResponse
*/
OapiMediaUploadResponse uploadMedia(String type, MultipartFile file);
/**
* 根据unionId获取userId
* @param unionId 当前钉钉用户在当前企业下的唯一识别码
* @return
*/
OapiUserGetUseridByUnionidResponse getUserIdByUnionId(String unionId);
/**
* 根据unionId获取userId
* @param unionId 当前钉钉用户在当前企业下的唯一识别码
* @return
*/
OapiUserGetbyunionidResponse getUserIdByUnionIdV2(String unionId);
/**
* 根据手机号获取userid
* @param phone
* @return
*/
OapiV2UserGetbymobileResponse getUserIdByPhone(String phone);
/**
* 发送消息调用
* @param msgInfo 发送消息的内容对象
* @return AjaxResult
*/
int sendMessage(MsgInfo msgInfo);
/**
* 获取部门列表
* @param accessToken
* @param deptId
* @return
*/
OapiV2DepartmentListsubResponse getDeptList(String accessToken, Long deptId) throws Exception;
/**
* 获取部门下用户信息列表
* @param accessToken
* @param deptId
* @param cursor
* @param size
* @return
* @throws Exception
*/
OapiV2UserListResponse getUserListByDeptId(String accessToken, Long deptId, Long cursor, Long size) throws Exception;
/**
* 获取企业凭证 access_token
* @return
* @throws ApiException
*/
String getAccessToken() throws ApiException;
/**
* 获取部门详情
* @param accessToken
* @param deptId
* @return
* @throws Exception
*/
OapiV2DepartmentGetResponse getDeptDetail(String accessToken, Long deptId) throws Exception;
}
实现类 DingDingServiceImpl.java
package com.dongao.project.common.dingding;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.*;
import com.dingtalk.api.response.*;
import com.dongao.project.common.constants.Constants;
import com.dongao.project.config.properties.DingDingProperties;
import com.dongao.project.keymsghistory.domain.KeyMsgHistory;
import com.dongao.project.keymsghistory.service.IKeyMsgHistoryService;
import com.dongao.project.sysuser.service.ISysUserService;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.text.Convert;
import com.taobao.api.ApiException;
import com.taobao.api.FileItem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.util.Objects;
/**
* Created by nao'nao on 2020/3/31.
* @author dingding
*/
@Service
public class DingDingServiceImpl implements IDingDingService {
@Autowired
private DingDingProperties dingDingProperties;
@Autowired
private ISysUserService sysUserService;
@Autowired
private IKeyMsgHistoryService msgHistoryService;
/**
* 调用钉钉发送工作通知消息
* @param useridList 员工在当前开发者企业账号范围内的userid
* @param msgTemplet 消息模板
* @return 异步发送消息返回发送任务对象 OapiMessageCorpconversationAsyncsendV2Response
*/
private OapiMessageCorpconversationAsyncsendV2Response sendWorkMsg(String useridList, MsgTemplet msgTemplet) {
try {
//给钉钉用户发送工作通知消息
OapiMessageCorpconversationAsyncsendV2Response rsp = send(useridList, msgTemplet);
return rsp;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 给钉钉用户发送工作通知消息
* @param useridList 接收者的用户userid列表,最大用户列表长度:100 zhangsan,lisi
* @param msgTemplet 消息内容
* @return OapiMessageCorpconversationAsyncsendV2Response
*/
private OapiMessageCorpconversationAsyncsendV2Response send(String useridList, MsgTemplet msgTemplet) {
//获取企业认证
try {
String accessToken = getAccessToken();
//给钉钉用户发送工作通知消息
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2");
OapiMessageCorpconversationAsyncsendV2Request req = new OapiMessageCorpconversationAsyncsendV2Request();
req.setAgentId(Long.parseLong(dingDingProperties.getAgentId()));
req.setUseridList(useridList);
//部门id串 ,分隔
///req2.setDeptIdList("1");
//是否发送给企业全部用户
///req2.setToAllUser(false);
OapiMessageCorpconversationAsyncsendV2Request.Msg obj1 = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
if (Constants.MsgType.TEXT.getValue().equals(msgTemplet.getTempletType())) {
//发送文本消息
obj1.setMsgtype(Constants.MsgType.TEXT.getValue());
OapiMessageCorpconversationAsyncsendV2Request.Text obj2 = new OapiMessageCorpconversationAsyncsendV2Request.Text();
obj2.setContent(msgTemplet.getContent());
obj1.setText(obj2);
}else if (Constants.MsgType.IMAGE.getValue().equals(msgTemplet.getTempletType())) {
//发送图片信息 content即为图片media_id
obj1.setMsgtype(Constants.MsgType.IMAGE.getValue());
OapiMessageCorpconversationAsyncsendV2Request.Image obj2 = new OapiMessageCorpconversationAsyncsendV2Request.Image();
obj2.setMediaId(msgTemplet.getContent());
obj1.setImage(obj2);
}else if (Constants.MsgType.FILE.getValue().equals(msgTemplet.getTempletType())) {
//发送文件信息 content即为图片media_id
obj1.setMsgtype(Constants.MsgType.FILE.getValue());
OapiMessageCorpconversationAsyncsendV2Request.File obj2 = new OapiMessageCorpconversationAsyncsendV2Request.File();
obj2.setMediaId(msgTemplet.getContent());
obj1.setFile(obj2);
}else if (Constants.MsgType.LINK.getValue().equals(msgTemplet.getTempletType())) {
obj1.setMsgtype(Constants.MsgType.LINK.getValue());
OapiMessageCorpconversationAsyncsendV2Request.Link obj2 = new OapiMessageCorpconversationAsyncsendV2Request.Link();
obj2.setPicUrl(msgTemplet.getPicUrl());
obj2.setMessageUrl(msgTemplet.getMessageUrl());
obj2.setText(msgTemplet.getContent());
obj2.setTitle(msgTemplet.getTitle());
obj1.setLink(obj2);
}else if (Constants.MsgType.MARKDOWN.getValue().equals(msgTemplet.getTempletType())) {
obj1.setMsgtype(Constants.MsgType.MARKDOWN.getValue());
OapiMessageCorpconversationAsyncsendV2Request.Markdown obj2 = new OapiMessageCorpconversationAsyncsendV2Request.Markdown();
obj2.setText(msgTemplet.getContent());
obj2.setTitle(msgTemplet.getTitle());
obj1.setMarkdown(obj2);
}
req.setMsg(obj1);
OapiMessageCorpconversationAsyncsendV2Response rsp = client.execute(req, accessToken);
return rsp;
} catch (ApiException e) {
e.printStackTrace();
}
return null;
}
/**
* 获取企业凭证 access_token
*/
@Override
public String getAccessToken() throws ApiException {
//获取企业凭证 access_token 正常情况下access_token有效期为7200秒,有效期内重复获取返回相同结果,并自动续期。
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
OapiGettokenRequest req = new OapiGettokenRequest();
req.setAppkey(dingDingProperties.getAppKey());
req.setAppsecret(dingDingProperties.getAppSecret());
req.setHttpMethod("GET");
OapiGettokenResponse rsp = client.execute(req);
return rsp.getAccessToken();
}
/**
* 调用钉钉上传文件
* (1) 图片(image):1MB,支持JPG格式
* (2)语音(voice):2MB,播放长度不超过60s,AMR格式
* (3)普通文件(file):10MB
* @param type 文件类型 image file (voice暂不支持)
* @param file 文件
* @return
*/
@Override
public OapiMediaUploadResponse uploadMedia(String type, MultipartFile file) {
try {
//获取企业凭证 access_token
String accessToken = getAccessToken();
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/media/upload");
OapiMediaUploadRequest req = new OapiMediaUploadRequest();
req.setType(type);
req.setMedia(new FileItem(file.getOriginalFilename(),file.getInputStream()));
OapiMediaUploadResponse rsp = client.execute(req, accessToken);
return rsp;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 根据unionId获取userId
* @param unionId 当前钉钉用户在当前企业下的唯一识别码
* @return
*/
@Override
public OapiUserGetUseridByUnionidResponse getUserIdByUnionId(String unionId) {
try {
String accessToken = getAccessToken();
//根据unionId获取userId
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/getUseridByUnionid");
OapiUserGetUseridByUnionidRequest req = new OapiUserGetUseridByUnionidRequest();
req.setUnionid(unionId);
req.setHttpMethod("GET");
OapiUserGetUseridByUnionidResponse rsp = client.execute(req, accessToken);
return rsp;
} catch (ApiException e) {
e.printStackTrace();
}
return null;
}
/**
* 根据unionId获取userId 2.0版本
* @param unionId 当前钉钉用户在当前企业下的唯一识别码
* @return
*/
@Override
public OapiUserGetbyunionidResponse getUserIdByUnionIdV2(String unionId) {
try {
String accessToken = getAccessToken();
//根据unionId获取userId
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/user/getbyunionid");
OapiUserGetbyunionidRequest req = new OapiUserGetbyunionidRequest();
req.setUnionid(unionId);
OapiUserGetbyunionidResponse rsp = client.execute(req, accessToken);
return rsp;
} catch (ApiException e) {
e.printStackTrace();
}
return null;
}
/**
* 根据手机号获取userid
* @param phone
* @return
*/
@Override
public OapiV2UserGetbymobileResponse getUserIdByPhone(String phone){
try {
String accessToken = getAccessToken();
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/getbymobile");
OapiV2UserGetbymobileRequest req = new OapiV2UserGetbymobileRequest();
req.setMobile(phone);
OapiV2UserGetbymobileResponse rsp = client.execute(req, accessToken);
return rsp;
} catch (ApiException e) {
e.printStackTrace();
}
return null;
}
/**
* 发送消息调用
* @param msgInfo 发送消息的内容对象
* @return AjaxResult
*/
@Override
public int sendMessage(MsgInfo msgInfo) {
String userIdsStr = msgInfo.getUserIds();
if (msgInfo != null && StringUtils.isNotEmpty(userIdsStr)) {
//获取用户userId对应的钉钉平台用户userid
String[] userIds = Convert.toStrArray(userIdsStr);
String useridList = sysUserService.selectDingdingUseridList(userIds);
if (StringUtils.isNotEmpty(useridList)) {
//获取消息模板
MsgTemplet msgTemplet = msgInfo.getMsgTemplet();
if (msgTemplet != null) {
OapiMessageCorpconversationAsyncsendV2Response rsp = sendWorkMsg(useridList, msgTemplet);
//插入消息发送记录表
KeyMsgHistory msgHistory = new KeyMsgHistory();
for (String userId:userIds) {
msgHistory.setUserId(Long.parseLong(userId));
if (Objects.nonNull(rsp)){
msgHistory.setErrCode(rsp.getErrcode());
msgHistory.setErrMsg(rsp.getErrmsg());
msgHistory.setTaskId(rsp.getTaskId());
}
msgHistory.setContent(msgTemplet.getContent());
msgHistory.setType(msgTemplet.getTempletType());
msgHistoryService.insertKeyMsgHistory(msgHistory);
}
if (Objects.nonNull(rsp) && rsp.isSuccess()) {
//success
return 1;
}
}
}
}
return 0;
}
/**
* 获取部门列表
* @throws Exception
*/
@Override
public OapiV2DepartmentListsubResponse getDeptList(String accessToken, Long deptId) throws Exception {
try {
if (StringUtils.isEmpty(accessToken)) {
accessToken = getAccessToken();
}
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/department/listsub");
OapiV2DepartmentListsubRequest req = new OapiV2DepartmentListsubRequest();
if (deptId != null) {
req.setDeptId(deptId);
}
OapiV2DepartmentListsubResponse rsp = client.execute(req, accessToken);
return rsp;
} catch (ApiException e) {
e.printStackTrace();
return null;
}
}
/**
* 获取部门下用户信息列表
* @throws Exception
*/
@Override
public OapiV2UserListResponse getUserListByDeptId(String accessToken, Long deptId, Long cursor, Long size) throws Exception {
try {
if (StringUtils.isEmpty(accessToken)) {
accessToken = getAccessToken();
}
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/list");
OapiV2UserListRequest req = new OapiV2UserListRequest();
req.setDeptId(deptId);
req.setCursor(cursor);
req.setSize(size);
OapiV2UserListResponse rsp = client.execute(req, accessToken);
return rsp;
} catch (ApiException e) {
e.printStackTrace();
return null;
}
}
/**
* 获取部门详情
* @param accessToken
* @param deptId
* @return
* @throws Exception
*/
@Override
public OapiV2DepartmentGetResponse getDeptDetail(String accessToken, Long deptId) throws Exception {
try {
if (StringUtils.isEmpty(accessToken)) {
accessToken = getAccessToken();
}
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/department/get");
OapiV2DepartmentGetRequest req = new OapiV2DepartmentGetRequest();
req.setDeptId(deptId);
OapiV2DepartmentGetResponse rsp = client.execute(req, accessToken);
return rsp;
} catch (ApiException e) {
e.printStackTrace();
return null;
}
}
}
5.获取钉钉部门及人员并保存
获取钉钉部门及部门下人员 java 类主要方法如下
/**
* 保存钉钉部门人员信息
* @param param
* @return
*/
@Override
public AjaxResult saveDingDingDeptListV3(String param) {
//逐级获取部门信息列表并保存
AjaxResult ajaxResult = new AjaxResult();
ajaxResult.setMsg("成功!");
try {
String accessToken = dingDingService.getAccessToken();
if (StringUtils.isNotEmpty(param)) {
//获取多个部门的部门信息
String[] split = param.split(",");
for (String s : split) {
//获取叶子部门列表 and 获取部门下人员信息
saveDeptListV3(ajaxResult, accessToken, Long.parseLong(s));
}
}else {
//获取根部门列表 and 获取部门下人员信息
saveDeptListV3(ajaxResult, accessToken, null);
}
}catch (Exception e) {
e.printStackTrace();
}
return ajaxResult;
}
private void saveDeptListV3(AjaxResult ajaxResult, String accessToken, Long reqDeptId) throws Exception {
//保存当前部门下的人员信息
saveUserListV3(ajaxResult, accessToken, reqDeptId);
//获取部门列表
OapiV2DepartmentListsubResponse deptrsp = dingDingService.getDeptList(accessToken, reqDeptId);
if (deptrsp.isSuccess()) {
List<OapiV2DepartmentListsubResponse.DeptBaseResponse> result = deptrsp.getResult();
if (CollectionUtils.isNotEmpty(result)) {
SysDept sysDept = new SysDept();
for (OapiV2DepartmentListsubResponse.DeptBaseResponse dept : result) {
Long deptId = dept.getDeptId();
if (deptId > 0) {
//判定当前部门是否已存在,存在则不再新增
SysDept sysdept = sysDeptMapper.selectSysDeptByDeptId(deptId);
if (sysdept == null) {
sysDept.setDeptId(deptId);
sysDept.setDeptName(dept.getName());
sysDept.setParentId(dept.getParentId());
sysDept.setCreateBy("定时任务拉取");
sysDept.setCreateTime(new Date());
//保存部门信息
sysDeptMapper.insertSysDept(sysDept);
}
}
//继续获取当前部门下的子级部门
saveDeptListV3(ajaxResult, accessToken, deptId);
}
}else {
ajaxResult.setMsg("当前部门已是叶子部门");
}
}else {
ajaxResult.setMsg("获取部门列表API调用失败");
}
}
private void saveUserListV3(AjaxResult ajaxResult, String accessToken, Long reqDeptId) throws Exception {
//获取当前部门下的人员信息并保存
Boolean hasMore = false;
OapiV2UserListResponse userrsp = dingDingService.getUserListByDeptId(accessToken, reqDeptId, 0L, 10L);
if (userrsp.isSuccess()) {
OapiV2UserListResponse.PageResult result = userrsp.getResult();
List<OapiV2UserListResponse.ListUserResponse> list = result.getList();
if (CollectionUtils.isNotEmpty(list)) {
saveDingDingUserV3(list);
//继续
hasMore = result.getHasMore();
while (hasMore) {
userrsp = dingDingService.getUserListByDeptId(accessToken, reqDeptId, result.getNextCursor(), 10L);
if (userrsp.isSuccess()) {
result = userrsp.getResult();
list = result.getList();
saveDingDingUserV3(list);
hasMore = result.getHasMore();
}
}
}else {
ajaxResult.setMsg("当前部门下无人员信息");
}
}else {
ajaxResult.setMsg("获取部门人员列表API调用失败");
}
}
private void saveDingDingUserV3(List<OapiV2UserListResponse.ListUserResponse> list) {
SysUser sysUser = new SysUser();
for (OapiV2UserListResponse.ListUserResponse user : list) {
//判断是否已经插入过
String userid = user.getUserid();
int count = sysUserMapper.countSysUserByDingDingUserId(userid);
if (count == 0) {
sysUser.setDingdingUserid(user.getUserid());
sysUser.setAvatar(user.getAvatar());
sysUser.setUnionId(user.getUnionid());
String userName = user.getName();
sysUser.setUserName(userName);
//中文转拼音作为loginName
String loginName = PinYinUtils.getPingYin(userName);
sysUser.setLoginName(loginName);
List<Long> deptIdList = user.getDeptIdList();
if (CollectionUtils.isNotEmpty(deptIdList)) {
for (Long deptid : deptIdList) {
sysUser.setDeptId(deptid);
sysUser.setCreateBy("定时任务拉取");
sysUser.setCreateTime(new Date());
sysUserMapper.insertSysUser(sysUser);
}
}
}
}
}
6.补充
在获取钉钉部门及人员信息时用到了汉字转拼音 jar,代码需要补充如下
pom.xml 引入 jar 包
<dependency>
<groupId>com.belerweb</groupId>
<artifactId>pinyin4j</artifactId>
<version>2.5.0</version>
</dependency>
添加工具类 PinYinUtils.java
package com.dongao.project.utils;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
/**
* @ClassName:PinYinUtils
* @author:dongao
* @date 2022/2/10 14:05
*/
public class PinYinUtils {
/**
* 中文转拼音
* @param inputStr
* @return
*/
public static String getPingYin(String inputStr) {
if (inputStr == null || "".equals(inputStr)) {
return "";
}
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
//UPPERCASE 大写 LOWERCASE 小写
format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
//WITH_TONE_NUMBER 音标用数字 WITHOUT_TONE 无音标 WITH_TONE_MARK 直接用音标
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
//WITH_U_AND_COLON 用u表示ü WITH_V 用v表示ü WITH_U_UNICODE 用ü表示ü
format.setVCharType(HanyuPinyinVCharType.WITH_V);
StringBuilder pYStr = new StringBuilder();
char[] input = inputStr.trim().toCharArray();
try {
for (int i = 0; i < input.length; i++) {
if (Character.toString(input[i]).matches("[\\u4E00-\\u9FA5]+")) {
pYStr.append(PinyinHelper.toHanyuPinyinStringArray(input[i], format)[0]);
} else if (!(input[i] == ' ')) {
//过滤空格
pYStr.append(input[i]);
}
}
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
}
return pYStr.toString();
}
}
总结:通过以上步骤即可以获取钉钉下部门及人员信息,sql 表语句此处没有列出是大家可以自行根据上面 set 字段进行创建表即可
版权声明: 本文为 InfoQ 作者【六月的雨在infoQ】的原创文章。
原文链接:【http://xie.infoq.cn/article/c8cbd4b12f9ea642f2bf5e74a】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
六月的雨在infoQ
让技术不再枯燥,让每一位技术人爱上技术 2022.07.22 加入
还未添加个人简介
评论