电脑桌面
添加蚂蚁七词文库到电脑桌面
安装后可以在桌面快捷访问

钉钉通讯录同步二开案例

来源:金蝶云社区作者:金蝶2024-09-2322

钉钉通讯录同步二开案例

一、背景

目前钉钉支持手机号或者邮箱同步钉钉通讯录,有些客户需要使用工号同步,或者客户使用了企业专属账号,苍穹当前版本产品接口不支持同步(v6.0.6版本以上支持),则需要现场二开解决。

二、方案

新增一个调度任务,在调度中调用钉钉的接口进行通讯录同步。

具体步骤

1. 获取token

根据配置好的应用信息获取token,方法如下:

请求方式:GET

请求地址:https://oapi.dingtalk.com/gettoken ?appkey=xxx&appsecret=xxx

请求参数:

appkey

String

dingeqqpkv3xxxx

应用的唯一标识key。

appsecret

String

GT-lsu-taDAsTsxxxx

应用的密钥。AppKey和AppSecret可在钉钉开发者后台 的应用详情页面获取。


2. 获取授权部门

在钉钉管理后台【权限管理】中需要配置授权部门,如果调用接口获取非授权部门的人员信息则会提示无权限,所以需要主动获取授权部门。

请求方式:GET

请求地址:https://oapi.dingtalk.com/auth/scopes ? access_token =xxxxx

请求参数:

access_token

String

6ed1bxxx

调用该接口的应用凭证。


3. 获取授权部门及其子部门

请求方式:GET

请求地址:

https://oapi.dingtalk.com/department/list? access_token =xxx& fetch_child =true&id=xxx

请求参数:

access_token

String

6ed1bxxx

调用服务端API的应用凭证。

lang

String

zh_CN

通讯录语言,默认zh_CN。

fetch_child

Boolean

true

是否递归部门的全部子部门。

id

String

1

父部门ID。

如果不传,默认部门为根部门,根部门ID为1。


4. 获取部门下的人员信息

请求方式:POST

请求地址:https://oapi.dingtalk.com/topapi/v2/user/list ? access_token =xxxx

请求参数:

access_token

String

be3Fxxxx

调用该接口的应用凭证。

Body参数:

dept_id

Number

10

部门ID,可调用获取部门列表 获取,如果是根部门,该参数传1。

cursor

Number

0

分页查询的游标,最开始传0,后续传返回参数中的next_cursor值。

size

Number

10

分页大小。

order_field

String

modify_desc

部门成员的排序规则,默认不传是按自定义排序(custom):

entry_asc:代表按照进入部门的时间升序

entry_desc:代表按照进入部门的时间降序

modify_asc:代表按照部门信息修改时间升序

modify_desc:代表按照部门信息修改时间降序

custom:代表用户定义(未定义时按照拼音)排序

contain_access_limit

Boolean

false

是否返回访问受限的员工:

true:返回

false:不返回

language

String

zh_CN

通讯录语言,取值。


5. 根据相关字段(如手机号或者邮箱)与苍穹(星瀚)人员信息进行匹配

6. 将钉钉人员信息保存在映射表中

参考代码:

package hnzb.sys.base.plugin.task;


import com.alibaba.fastjson.JSON;

import com.alibaba.fastjson.JSONArray;

import com.alibaba.fastjson.JSONObject;

import kd.bos.context.RequestContext;

import kd.bos.dataentity.utils.ObjectUtils;

import kd.bos.dd.service.DingDingServiceHelper;

import kd.bos.exception.KDException;

import kd.bos.lang.Lang;

import kd.bos.logging.Log;

import kd.bos.logging.LogFactory;

import kd.bos.org.utils.Consts;

import kd.bos.schedule.executor.AbstractTask;

import kd.bos.sec.user.task.SynUserTypeEnum;

import kd.bos.sec.user.utils.UserOperationUtils;

import kd.bos.util.HttpClientUtils;

import kd.bos.util.StringUtils;

import kd.sdk.plugin.Plugin;


import java.io.IOException;

import java.util.*;



/**

* @BelongsProject: hnzb-cosmic

* @BelongsPackage: hnzb.sys.base.plugin.task

* @Author:

* @CreateTime: 2023-12-21  17:37

* @Description: TODO 查询系统中指定日期修改的组织单元、人员、岗位,然后同步到主数据系统

* @Version: 1.0

* @PageNumber:

*/

public class SynDingUserToUserMappingTask extends AbstractTask {

   private static Log logger = LogFactory.getLog(SynDingUserToUserMappingTask.class);


   @Override

   public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {

       synDing();

   }


   /**

    * 钉钉openid同步

    */

   public static void synDing() {

       String accessToken = DingDingServiceHelper.getAccess_token();

       logger.info("authScope" + accessToken);

       if (kd.bos.util.StringUtils.isEmpty(accessToken)) {

           return;

       }

       Map<String, List<String>> authScope = getAuthScope(accessToken);

       logger.info("authScope" + authScope);


       //如果设置了权限范围 则只查询有权的组织及人员

       if (isAuthScope(authScope)) {

           List<String> authedUser = authScope.get("authed_user");

           logger.info("authedUser" + authedUser);

           int userSize = 0;

           int deptSize = 0;

           //授权人员

           if (null != authedUser && !authedUser.isEmpty()) {

               List<Map<String, String>> userList = getAuthScopeUsers(authedUser, accessToken);

               logger.info("userList" + userList);

               UserOperationUtils.saveIMMapping(userList, "mobile", Consts.PHONE, SynUserTypeEnum.DINGDING.getValue());

               userSize = authedUser.size();

           }

           List<String> authedDept = authScope.get("authed_dept");

           logger.info("authed_dept" + authedDept);


           int deptCount = 0;

           //授权部门

           if (null != authedDept && !authedDept.isEmpty()) {

               //获取子部门

               List<String> allDept = getChildrenList(accessToken,authedDept);

               authedDept.addAll(allDept);

               deptSize = authedDept.size();

               deptCount = saveUserMappingByDept(accessToken, authedDept, imTypeFieldName, sysFieldName);

               logger.info("deptCount" + deptCount);


           }

           return;

       }

       List<String> deptList = DingDingServiceHelper.getDeptList(accessToken);

       if (deptList == null || deptList.isEmpty()) {

           return;

       }

       saveUserMappingByDept(accessToken, deptList);


   }


    private static List<String> getChildrenList(String accessToken, List<String> authedDept) {

       List<String> allDept = new ArrayList<>(authedDept.size());

       for (String deptId : authedDept) {

           List<String> deptList = getDeptList(accessToken,deptId);

           allDept.addAll(deptList);

       }

       return allDept;

   }


   private static int saveUserMappingByDept(String accessToken, List<String> deptList) {

       int completedCount = 1;

       for (String deptId : deptList) {

           long offset = 0;

           long size = 100;

           while (true) {

               List<Map<String, String>> userList = getDeptUserList(accessToken,

                       Long.parseLong(deptId), offset, size, null);

               logger.error("saveUserMappingByDept**userList" + userList);


               if (userList == null || userList.isEmpty()) {

                   break;

               }

               boolean mobile = UserOperationUtils.saveIMMapping(userList, "mobile", Consts.PHONE, SynUserTypeEnum.DINGDING.getValue());

               logger.error("saveUserMappingByDept**mobile" + mobile);


               if (userList.size() < 100) {

                   break;

               }

               offset += 100;

           }

           completedCount++;

       }

       return completedCount;

   }


   private static boolean isAuthScope(Map<String, List<String>> authScope) {

       //授权范围为空

       if (authScope.isEmpty()) {

           logger.error("authScope is empty");

           return false;

       }

       //授权范围为全部员工

       List<String> authedDept = authScope.get("authed_dept");

       if (null != authedDept && !authedDept.isEmpty()) {

           String dept = authedDept.get(0);

           if ("1".equals(dept)) {

               logger.info("authed_dept : 1");

               return false;

           }

       }

       return true;

   }



   /**

    * 获取钉钉应用的授权范围

    *

    * @param token

    * @return

    */

   public static Map<String, List<String>> getAuthScope(String token) {


       String ddHost = "https://oapi.dingtalk.com";

       StringBuilder url = new StringBuilder(ddHost).append("/auth/scopes?access_token=");

       url.append(token);

       try {

           String data = HttpClientUtils.get(url.toString());

           HashMap<String, Object> map = JSON.parseObject(data, HashMap.class);

           //权限范围

           Map<String, Object> authOrgScopes = (Map<String, Object>) map.get("auth_org_scopes");

           //授权人员

           JSONArray authed_user = (JSONArray) authOrgScopes.get("authed_user");

           //授权部门

           JSONArray authed_dept = (JSONArray) authOrgScopes.get("authed_dept");

           HashMap<String, List<String>> dataMap = new HashMap<>(2);

           if (authed_user != null) {

               List<String> userList = authed_user.toJavaList(String.class);

               dataMap.put("authed_user", userList);

           }

           if (authed_dept != null) {

               List<String> deptList = authed_dept.toJavaList(String.class);

               dataMap.put("authed_dept", deptList);

           }

           return dataMap;


       } catch (Exception e) {

           logger.error(e);

       }

       return Collections.emptyMap();

   }


   /**

    * 根据授权范围获取人员信息

    *

    * @param authedUser  授权范围:授权人员

    * @param accessToken

    * @return

    */

   public static List<Map<String, String>> getAuthScopeUsers(List<String> authedUser, String accessToken) {

       List<Map<String, String>> userList = new ArrayList<>(16);

       //1.获取授权人员信息

       String ddHost = "https://oapi.dingtalk.com";

       StringBuilder url = new StringBuilder(ddHost).append("/topapi/v2/user/get?access_token=");

       url.append(accessToken);

       HashMap<String, Object> params = new HashMap<>(2);

       params.put("language", Lang.get().name());

       try {

           for (String userId : authedUser) {

           

钉钉通讯录同步二开案例

一、背景目前钉钉支持手机号或者邮箱同步钉钉通讯录,有些客户需要使用工号同步,或者客户使用了企业专属账号,苍穹当前版本产品接口不支持...
点击下载文档文档为doc格式

声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。如若本站内容侵犯了原著者的合法权益,可联系本站删除。

确认删除?
回到顶部
客服QQ
  • 客服QQ点击这里给我发消息
QQ群
  • 答案:my7c点击这里加入QQ群
支持邮箱
微信
  • 微信