Integrate with Feishu to Synchronize Organizational Structure and Members
Overview
Enterprises typically use instant messaging tools like Feishu as communication tools for daily office work. These tools usually provide functions such as organizational structure management, user management, notifications, and todos. Below are the steps to integrate with Feishu and synchronize organizational structure and members to Informat.
Implementation Steps
- Before synchronizing Feishu organizational structure, you need to complete the integration in "Third-Party Integration >> Feishu".
- Enable address book permissions, including at least the following six permissions: Get basic department information, Get address book department organizational structure information, Get user basic information, Get user userID, Get user phone number, and Read address book as an application.
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
export function syncDepartments() {
syncDepartmentList("0", 10, null);
console.log("syncDepartments finished");
}
function syncDepartmentList(parentId, pageSize, pageToken) {
var url = `https://open.feishu.cn/open-apis/contact/v3/departments/${parentId}/children?department_id_type=department_id&fetch_child=false&page_size=${pageSize}&user_id_type=user_id`;
if (pageToken) {
url = url + "&page_token=" + pageToken;
}
const resp = httpGet(url);
const result = JSON.parse(resp.body());
console.log("body", resp.body());
if (result.data.items) {
result.data.items.forEach((item) => {
var dept = informat.dept.getDept(item.department_id);
if (dept == null) {
console.log("Add department", item);
console.log("parentId", parentId);
informat.dept.addDept({
id: item.department_id,
name: item.name,
remark: item.name,
parentId: item.parent_department_id === "0" ? null : parentId,
});
} else {
console.log("Edit department", item);
informat.dept.updateDept({
id: item.department_id,
name: item.name,
});
}
syncDepartmentList(item.department_id, pageSize, null);
});
}
var hasMore = result.data.has_more;
if (hasMore) {
syncDepartmentList(parentId, pageSize, result.data.page_token);
}
// Sync members
if (syncMembers) {
syncMemberList(parentId, pageSize, null);
}
}
//
function syncMemberList(departmentId, pageSize, pageToken) {
var url = `https://open.feishu.cn/open-apis/contact/v3/users/find_by_department?department_id_type=department_id&department_id=${departmentId}&page_size=${pageSize}&user_id_type=user_id`;
if (pageToken) {
url = url + "&page_token=" + pageToken;
}
const resp = httpGet(url);
const result = JSON.parse(resp.body());
console.log("body", resp.body());
if (result.data.items) {
result.data.items.forEach((item) => {
var memberList = informat.company.queryCompanyMemberList({
pageIndex: 1,
pageSize: 1,
filter: {
conditionList: [
{
fieldId: "feishuUserId",
opt: "eq",
value: item.user_id,
},
],
},
});
var departmentList = item.department_ids;
if (memberList.length == 0) {
// Add new member
var accountId = addAccount(item);
var roleList = defaultRole == null ? [] : [defaultRole];
console.log("Add team member", item, departmentId);
informat.company.addCompanyMember(accountId, departmentList, roleList);
informat.company.updateCompanyMember({
id: accountId,
feishuUserId: item.user_id,
});
} else {
// Edit member
var member = memberList[0];
console.log("Edit team member", member.id);
informat.company.updateCompanyMember({
id: member.id,
departmentList: departmentList,
});
}
});
}
var hasMore = result.data.has_more;
if (hasMore) {
syncMemberList(departmentId, pageSize, result.data.page_token);
}
}
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.user_id,
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);
informat.system.updateAccount({
id: oldAccount.id,
name: item.name,
userName: mobile,
mobileNo: mobile,
});
}
return accountId;
}
function httpGet(url) {
var feishuAccessToken = informat.app.feishuAccessToken();
var resp = informat.http.request({
headers: {
Authorization: "Bearer " + feishuAccessToken,
},
method: "GET",
timeout: 30000,
url: url,
});
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 developers");
}
return resp;
}Common Errors
- Error codes for department API
- Error codes for member API

