Skip to content

钉钉

1.织信第三方集成钉钉

在织信工作台「团队 >> 团队设置」下,找到「第三方集成」,选择「钉钉」,点击「启用此功能」,填入企业微信CorpId、AgentId、AppKey 和 Secret后,点击「保存」。

设置项说明
CorpId钉钉企业ID,点击进入钉钉开发者后台中获取
AgentId应用凭证中的AgentId,根据上一步链接到应用开发-企业内部开发中具体应用的应用详情中获取
AppKey应用凭证中的AgentId,根据上一步链接到应用开发-企业内部开发中具体应用的应用详情中获取
Secret应用凭证中的Secret,根据上一步链接到应用开发-企业内部开发中具体应用的应用详情中获取

获取示例

配置dingding-thridLoginSetting.png

2.在钉钉工作台添加织信Next应用

  • 钉钉开发者后台中「应用开发 >> 钉钉应用 >> 应用详情 >> 网页应用」中修改应用首页地址PC端首页地址添加织信Next应用
  • 链接自动生成,获取入口:「织信工作台 >> 团队设置 >> 第三方集成」。 dingding-getLoginUrl.png
应用首页地址为:https://${域名}/mobile/ddlogin/${cluster}/${companyId}/${钉钉CorpId}
PC端首页地址:https://${域名}/auth/ddlogin/${cluster}/${companyId}/${钉钉CorpId}

注意

  • 如果不添加该步骤,将无法在钉钉工作通知中免登录进入织信系统中。
  • ${cluster}:默认为0

3.添加团队成员钉钉用户ID

  • 3.1 在钉钉管理后台「通讯录中 >> 成员管理」中点击「更多-编辑人员信息」获取【员工UserID】 获取钉钉用户ID
  • 3.2 在在织信工作台「团队 >> 团队设置 >> 成员 >> 编辑成员」中,填写钉钉用户ID 填写钉钉用户ID

4.钉钉扫码登录

  • 4.1 在织信工作台「团队 >> 团队设置 >> 登录页面」下,找到「启用团队登录页面」和「启用第三方扫码登录」,点击按钮启用。 团队登录
  • 4.2 将团队登录地址复制到钉钉应用管理中「应用详情 >> 分享设置 >> 回调域名」中。 回调域名
  • 4.3 在钉钉应用管理中「应用详情 >> 权限管理」上添加如下权限:
    • 通讯录个人信息读权限
    • 成员信息读权限 权限管理

5.对接钉钉同步组织架构和成员

5.1 概述

在企业内部通常会使用钉钉等即时通讯工具作为日常办公的沟通工具,这类工具通常提供了组织架构管理、用户管理、通知、待办等功能。 下面是对接飞书并同步组织架构和成员到织信的步骤。

5.2 实现步骤

  • 同步钉钉组织架构前,需要先完成「第三方集成 >> 钉钉」的集成。
  • 开通通讯录权限,在应用内-基础信息-权限管理,需要添加以下权限
    • 通讯录个人信息读权限
    • 成员信息读权限
    • 通讯录部门信息读权限
    • 邮箱等个人信息
    • 企业员工手机号信息
    • 个人手机号信息

5.3 实现代码

javascript
const defaultRole='normal';//授权给新用户的团队角色
const defaultPassword='123456';//新用户设置的密码,用户名为手机号
const syncMembers=true;//是否同步成员
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('新增部门',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('编辑部门',item);
        informat.dept.updateDept({
                'id': dept_id,
                  'name': item.name,
                    'parentId': item.parent_id === 1 ? rootDeptId : `${item.parent_id}`
              });
      }
    });
  }
    //同步成员
  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){//新增
                    var accountId=addAccount(member);
                    var roleList=defaultRole==null?[]:[defaultRole];
                    console.log('新增团队成员',member, departmentList);
                    informat.company.addCompanyMember(accountId, departmentList, roleList);
                    informat.company.updateCompanyMember({
                        id: accountId,
                        dingtalkUserId: member.userid,
                    });
                }else{//编辑
                    console.log('编辑团队成员',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}`;
    //传入对应部门的id会识别该部门下的所有子部门id
    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('员工手机号不能为空,请开放查看手机权限');
    }
    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){//账号不存在
        console.log('新增账号',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('编辑账号',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('发起http请求失败,请联系开发人员');
    }
    console.log("url------->",url)
    console.log("resp----------->",resp.body());
  return JSON.parse(resp.body());
}

5.4 常见错误