Integrate with DingTalk to Synchronize Organizational Structure and Members
Overview
In enterprises, instant messaging tools like DingTalk are commonly used for daily office communication. Such tools typically provide functions like organizational structure management, user management, notifications, and to-do items. The following are the steps to integrate with DingTalk and synchronize organizational structure and members to Informat.
Implementation Steps
- Before synchronizing the DingTalk organizational structure, you need to complete the integration of "Third-Party Integration >> DingTalk".
- Enable address book permissions. In the application - Basic Information - Permission Management, you need to add the following permissions:
- Address book personal information reading permission
- Member information reading permission
- Address book department information reading permission
- Personal information such as email
- Enterprise employee phone number information
- Personal phone number information
Implementation Code
javascript
const defaultRole = "normal"; //Team role authorized to new users
const defaultPassword = "123456"; //Password set for new users, username is phone number
const syncMembers = true; //Whether to sync members
let rootDeptId = null;
export function syncDept() {
var deptList = getDeptList();
console.log("deptList---------------->", JSON.stringify(deptList));
rootDeptId = (
informat.dept.queryDeptList({
pageSize: 1,
filter: {
conditionList: [{ fieldId: "parentId", opt: "isnull" }],
},
})[0] || {}
).id;
console.log("rootDeptId", rootDeptId);
if (deptList != null) {
deptList.forEach((item) => {
var dept_id = `${item.dept_id}`;
var dept = informat.dept.getDept(dept_id);
console.log("dept_id", dept_id);
if (dept_id === "1") return;
if (dept == null) {
console.log("Add department", item);
informat.dept.addDept({
id: dept_id,
name: item.name,
remark: item.name,
parentId: item.parent_id === 1 ? rootDeptId : `${item.parent_id}`,
});
} else {
console.log("Edit department", item);
informat.dept.updateDept({
id: dept_id,
name: item.name,
parentId: item.parent_id === 1 ? rootDeptId : `${item.parent_id}`,
});
}
});
}
//Sync members
if (syncMembers) {
syncMemberList([{ dept_id: 1 }].concat(deptList));
}
}
function syncMemberList(deptList) {
if (Array.isArray(deptList)) {
deptList.forEach((dept) => {
const memberList = getMemberList(dept.dept_id);
memberList.forEach((member) => {
var memberList = informat.company.queryCompanyMemberList({
pageIndex: 1,
pageSize: 1,
filter: {
conditionList: [
{
fieldId: "dingtalkUserId",
opt: "eq",
value: member.userid,
},
],
},
});
var departmentList = getDeptIdListWithDingtalkDeptIdList(member.dept_id_list);
if (memberList.length == 0) {
//Add new
var accountId = addAccount(member);
var roleList = defaultRole == null ? [] : [defaultRole];
console.log("Add team member", member, departmentList);
informat.company.addCompanyMember(accountId, departmentList, roleList);
informat.company.updateCompanyMember({
id: accountId,
dingtalkUserId: member.userid,
});
} else {
//Edit
console.log("Edit team member", member, departmentList);
var member = memberList[0];
informat.company.updateCompanyMember({
id: member.id,
departmentList: departmentList,
});
}
});
});
} else {
console.log("syncMemberList, deptList is not array. deptList: ", deptList);
}
}
function getDeptIdListWithDingtalkDeptIdList(idList) {
const rootIndex = idList.indexOf(1);
if (rootIndex > -1) {
idList.splice(rootIndex, 1, rootDeptId);
}
return idList.map((id) => `${id}`);
}
function getMemberList(dept_id) {
var dingtalkAccessToken = informat.app.dingtalkAccessToken();
var url = `https://oapi.dingtalk.com/topapi/user/listid?access_token=${dingtalkAccessToken}`;
var rs = httpPost(
url,
JSON.stringify({
dept_id: dept_id,
})
);
const memberList = [];
if (rs.errcode === 0) {
rs.result.userid_list.forEach((id) => {
memberList.push(getMemeberInfo(id));
});
}
return memberList;
}
function getMemeberInfo(user_id) {
var dingtalkAccessToken = informat.app.dingtalkAccessToken();
var url = `https://oapi.dingtalk.com/topapi/v2/user/get?access_token=${dingtalkAccessToken}`;
var rs = httpPost(
url,
JSON.stringify({
language: "zh_CN",
userid: user_id,
})
);
return rs.result;
}
function getDeptList(dept_id, result = []) {
var dingtalkAccessToken = informat.app.dingtalkAccessToken();
var url = `https://oapi.dingtalk.com/topapi/v2/department/listsub?access_token=${dingtalkAccessToken}`;
//Passing the corresponding department id will identify all sub-department ids under that department
const data = {
language: "zh_CN",
};
if (dept_id) {
data.dept_id = dept_id;
}
var rs = httpPost(url, JSON.stringify(data));
if (rs.errcode) return result;
const deptList = rs.result;
deptList.forEach((item) => {
// var detail = getDeptInfo(id);
result.push(item);
getDeptList(item.dept_id, result);
});
return result;
}
function getDeptInfo(dept_id) {
var dingtalkAccessToken = informat.app.dingtalkAccessToken();
var url = `https://oapi.dingtalk.com/topapi/v2/department/get?access_token=${dingtalkAccessToken}`;
var rs = httpPost(
url,
JSON.stringify({
language: "zh_CN",
dept_id: dept_id,
})
);
return rs.result;
}
function addAccount(item) {
var mobile = item.mobile;
if (mobile == null) {
throw new Error("Employee phone number cannot be empty. Please enable phone number viewing permission.");
}
if (mobile.length == 14) {
mobile = mobile.substr(3);
}
var accountList = informat.system.queryAccountList({
pageIndex: 1,
pageSize: 1,
filter: {
conditionList: [
{
fieldId: "mobileNo",
opt: "eq",
value: mobile,
},
],
},
});
var accountId = null;
if (accountList.length == 0) {
//Account does not exist
console.log("Add account", item);
accountId = informat.system.addAccount({
oid: item.userid,
name: item.name,
avatar: "pic15.png",
userName: mobile,
mobileNo: mobile,
email: item.email,
password: defaultPassword,
});
} else {
var oldAccount = accountList[0];
accountId = oldAccount.id;
console.log("Edit account", item, oldAccount);
informat.system.updateAccount({
id: oldAccount.id,
name: item.name,
userName: mobile,
mobileNo: mobile,
});
}
return accountId;
}
function httpPost(url, body) {
console.log("url----------------->", url);
console.log("body----------------->", body);
var resp = informat.http.request({
headers: {
"Content-Type": "application/json;chartset=utf-8",
},
method: "POST",
timeout: 30000,
url: url,
body: body,
});
if (200 != resp.statusCode()) {
console.log("url", url);
console.log("resp statusCode", resp.statusCode());
console.log("resp body", resp.body());
throw new Error("Failed to initiate HTTP request. Please contact the developer.");
}
console.log("url------->", url);
console.log("resp----------->", resp.body());
return JSON.parse(resp.body());
}Common Errors
- Department API error codes
- Member API error codes

