第一步:获取钉钉token

private string GetToken()
{
     var token = CacheFactory.Cache().GetCache<string>("DDToken");
     if (!token.IsEmpty()) return token;
     var url = "https://oapi.dingtalk.com/gettoken?corpid=" + CorpId + "&corpsecret=" + CorpSecret;
     var str = Get(url);
     var dictionary = str.ToObject<Dictionary<string, string>>();
     if (dictionary == null || dictionary.Count == 0 || dictionary["errcode"] != "0")
     {
          return string.Empty;
     }
     token = dictionary["access_token"];
     CacheFactory.Cache().WriteCache(token, "DDToken", DateTime.Now.AddMinutes(100));
     return token;
}

第二步:获取角色列表

public List<DDRoleEntity> GetAllRole(long offset, out bool has_more, out string msg)
{
     has_more = false;
     msg = null;
     IDingTalkClient client = new DefaultDingTalkClient("https://eco.taobao.com/router/rest", "json");
     CorpRoleListRequest req = new CorpRoleListRequest();
     req.Size = 100L;
     req.Offset = offset;
     CorpRoleListResponse rsp = client.Execute(req, Token);
     var result = rsp.Body.ToObject<DDRoleListRequestResult>();
     if (result == null) return null;
     if (result.error_response != null)
     {
         msg = result.error_response.msg;
         return null;
     }
     if (result.dingtalk_corp_role_list_response == null) return null;
     if (result.dingtalk_corp_role_list_response.result == null) return null;
     if (result.dingtalk_corp_role_list_response.result.has_more == "true")
     {
         has_more = true;
     }
     if (result.dingtalk_corp_role_list_response.result.list == null) return null;
     if (result.dingtalk_corp_role_list_response.result.list.role_groups == null) return null;
     var list = new List<DDRoleEntity>();
     foreach (var role_group in result.dingtalk_corp_role_list_response.result.list.role_groups)
     {
         if (role_group.roles == null) continue;
         if (role_group.roles.roles == null) continue;
         foreach (var role in role_group.roles.roles)
         {
             if (role == null) continue;
             list.Add(role);
         }
     }
     return list;
}

第三步:获取部门列表

public DDDeptList GetDeptList()
{
      var url = "https://oapi.dingtalk.com/department/list?access_token=" + Token + "&fetch_child=true";
      var str = Get(url);
      return str.ToObject<DDDeptList>();
}

循环部门列表,如果部门ID为1,则为根节点

第四步:获取部门详情

public DDDeptDetailEntity GetDeptDetail(long deptId)
{
       var url = "https://oapi.dingtalk.com/department/get?access_token=" + Token + "&id=" + deptId;
       var str = Get(url);
       return str.ToObject<DDDeptDetailEntity>();
}

第五步:获取部门下面的人员

public DDUserList GetUserList(long ddDeptId)
{
       var url = "https://oapi.dingtalk.com/user/getDeptMember?access_token=" + Token + "&deptId=" + ddDeptId;
       var str = Get(url);
       return str.ToObject<DDUserList>();
}

第六步:获取人员详情

public DDUserDetailEntity GetUserDetail(string userId)
{
     var url = "https://oapi.dingtalk.com/user/get?access_token=" + Token + "&userid=" + userId;
     var str = Get(url);
     return str.ToObject<DDUserDetailEntity>();
}

公共方法:

public string Get(string url)
        {
            HttpWebResponse httpResponse = null;
            HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.CreateDefault(new Uri(url));
            httpRequest.Method = "GET";
            httpRequest.ContentType = "application/json; charset=UTF-8";
            try
            {
                httpResponse = (HttpWebResponse)httpRequest.GetResponse();
            }
            catch (WebException ex)
            {
                httpResponse = (HttpWebResponse)ex.Response;
            }
            Stream st = httpResponse.GetResponseStream();
            StreamReader reader = new StreamReader(st, Encoding.GetEncoding("utf-8"));
            return reader.ReadToEnd();
        }

        public string Post(string url, string content)
        {
            string result = "";
            HttpWebResponse httpResponse = null;
            HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.CreateDefault(new Uri(url));
            httpRequest.Method = "POST";
            httpRequest.ContentType = "application/json";
            byte[] data = Encoding.UTF8.GetBytes(content);
            httpRequest.ContentLength = data.Length;
            using (Stream reqStream = httpRequest.GetRequestStream())
            {
                reqStream.Write(data, 0, data.Length);
                reqStream.Close();
            }
            try
            {
                httpResponse = (HttpWebResponse)httpRequest.GetResponse();
            }
            catch (WebException ex)
            {
                httpResponse = (HttpWebResponse)ex.Response;
            }
            Stream stream = httpResponse.GetResponseStream();
            using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
            {
                result = reader.ReadToEnd();
            }
            return result;
        }

公共类:

/// <summary>
    /// 钉钉返回公用字段
    /// </summary>
    public class DDRequestEntity
    {
        /// <summary>
        /// 返回码
        /// </summary>
        public int errcode { get; set; }

        /// <summary>
        /// 对返回码的文本描述内容
        /// </summary>
        public string errmsg { get; set; }
    }
    /// <summary>
    /// 成员详情
    /// </summary>
    public class DDUserDetailEntity : DDRequestEntity
    {
        /// <summary>
        /// 员工唯一标识ID(不可修改)
        /// </summary>
        public string userid { get; set; }

        /// <summary>
        /// 在本 服务窗运营服务商 范围内, 唯一标识关注者身份的id(不可修改)
        /// </summary>
        public string openid { get; set; }

        /// <summary>
        /// 成员名称
        /// </summary>
        public string name { get; set; }

        /// <summary>
        /// 分机号(仅限企业内部开发调用)
        /// </summary>
        public string tel { get; set; }

        /// <summary>
        /// 办公地点(ISV不可见)
        /// </summary>
        public string workPlace { get; set; }

        /// <summary>
        /// 备注(ISV不可见)
        /// </summary>
        public string remark { get; set; }

        /// <summary>
        /// 手机号码(ISV不可见)
        /// </summary>
        public string mobile { get; set; }

        /// <summary>
        /// 员工的电子邮箱(ISV不可见)
        /// </summary>
        public string email { get; set; }

        /// <summary>
        /// 员工的企业邮箱,如果员工已经开通了企业邮箱,接口会返回,否则不会返回(ISV不可见)
        /// </summary>
        public string orgEmail { get; set; }

        /// <summary>
        /// 是否已经激活, true表示已激活, false表示未激活
        /// </summary>
        public bool active { get; set; }

        /// <summary>
        /// 在对应的部门中的排序, Map结构的json字符串, key是部门的Id, value是人员在这个部门的排序值
        /// </summary>
        public object orderInDepts { get; set; }

        /// <summary>
        /// 是否为企业的管理员, true表示是, false表示不是
        /// </summary>
        public bool isAdmin { get; set; }

        /// <summary>
        /// 是否为企业的老板, true表示是, false表示不是(【设置负责人】:主管理员登陆钉钉手机客户端 -【通讯录】-【企业名后面的管理】-【企业通讯录】-【负责人设置】进行添加则可。)
        /// </summary>
        public bool isBoss { get; set; }

        /// <summary>
        /// 在当前isv全局范围内唯一标识一个用户的身份, 用户无法修改
        /// </summary>
        public string unionid { get; set; }

        /// <summary>
        /// 在对应的部门中是否为主管, Map结构的json字符串, key是部门的Id, value是人员在这个部门中是否为主管, true表示是, false表示不是
        /// </summary>
        public string isLeaderInDepts { get; set; }

        /// <summary>
        /// 是否号码隐藏, true表示隐藏, false表示不隐藏
        /// </summary>
        public bool isHide { get; set; }

        /// <summary>
        /// 成员所属部门id列表
        /// </summary>
        public long[] department { get; set; }

        /// <summary>
        /// 职位信息
        /// </summary>
        public string position { get; set; }

        /// <summary>
        /// 头像url
        /// </summary>
        public string avatar { get; set; }

        /// <summary>
        /// 入职时间
        /// </summary>
        public long hiredDate { get; set; }

        /// <summary>
        /// 员工工号
        /// </summary>
        public string jobnumber { get; set; }

        /// <summary>
        /// 扩展属性,可以设置多种属性(但手机上最多只能显示10个扩展属性,具体显示哪些属性,请到OA管理后台->设置->通讯录信息设置和OA管理后台->设置->手机端显示信息设置)
        /// </summary>
        public object extattr { get; set; }

        /// <summary>
        /// 角色信息(ISV不可见),json数组格式
        /// </summary>
        public List<Role> roles { get; set; }

        /// <summary>
        /// 手机号码区号
        /// </summary>
        public string stateCode { get; set; }

        /// <summary>
        /// 是否是高管
        /// </summary>
        public bool isSenior { get; set; }
    }
    /// <summary>
    /// 角色
    /// </summary>
    public class Role
    {
        /// <summary>
        /// 角色id(ISV不可见)
        /// </summary>
        public long id { get; set; }
        /// <summary>
        /// 角色名称(ISV不可见)
        /// </summary>
        public string name { get; set; }

        /// <summary>
        /// 角色分组名称(ISV不可见)
        /// </summary>
        public string groupName { get; set; }
    }
    /// <summary>
    /// 部门成员
    /// </summary>
    public class DDUserList : DDRequestEntity
    {
        /// <summary>
        /// 在分页查询时返回,代表是否还有下一页更多数据
        /// </summary>
        public bool hasMore { get; set; }
        /// <summary>
        /// 成员列表
        /// </summary>
        public List<Dictionary<string, string>> userlist { get; set; }
    }
    /// <summary>
    /// 角色列表请求返回结果
    /// </summary>
    public class DDRoleListRequestResult
    {
        /// <summary>
        /// 异常信息
        /// </summary>
        public RoleErrorResponse error_response { get; set; }
        /// <summary>
        /// 响应数据
        /// </summary>
        public DingtalkCorpRoleListResponse dingtalk_corp_role_list_response { get; set; }
    }
    /// <summary>
    /// 异常信息
    /// </summary>
    public class RoleErrorResponse
    {
        /// <summary>
        /// 异常代码描述
        /// </summary>
        public string sub_msg { get; set; }
        /// <summary>
        /// 代码
        /// </summary>
        public int code { get; set; }
        /// <summary>
        /// 异常代码
        /// </summary>
        public string sub_code { get; set; }
        /// <summary>
        /// 提示信息
        /// </summary>
        public string msg { get; set; }
    }
    public class DingtalkCorpRoleListResponse
    {
        /// <summary>
        /// 结果
        /// </summary>
        public RoleResult result { get; set; }
    }
    public class RoleResult
    {
        /// <summary>
        /// 是否还有
        /// </summary>
        public string has_more { get; set; }
        /// <summary>
        /// 列表
        /// </summary>
        public RoleList list { get; set; }
    }
    public class RoleList
    {
        public List<RoleGroups> role_groups { get; set; }
    }
    public class RoleGroups
    {
        /// <summary>
        /// 角色列表
        /// </summary>
        public RoleRoles roles { get; set; }
        /// <summary>
        /// 分组名称
        /// </summary>
        public string group_name { get; set; }
    }
    public class RoleRoles
    {
        public List<DDRoleEntity> roles { get; set; }
    }
    public class DDRoleEntity
    {
        public long id { get; set; }
        public string role_name { get; set; }
    }
    /// <summary>
    /// 钉钉部门详情
    /// </summary>
    public class DDDeptDetailEntity : DDRequestEntity
    {
        /// <summary>
        /// 部门id
        /// </summary>
        public long id { get; set; }

        /// <summary>
        /// 部门名称
        /// </summary>
        public string name { get; set; }

        /// <summary>
        /// 父部门id,根部门为1
        /// </summary>
        public long parentid { get; set; }

        /// <summary>
        /// 在父部门中的次序值
        /// </summary>
        public int order { get; set; }

        /// <summary>
        /// 是否同步创建一个关联此部门的企业群, true表示是, false表示不是
        /// </summary>
        public bool createDeptGroup { get; set; }

        /// <summary>
        /// 当群已经创建后,是否有新人加入部门会自动加入该群, true表示是, false表示不是
        /// </summary>
        public bool autoAddUser { get; set; }

        /// <summary>
        /// 是否隐藏部门, true表示隐藏, false表示显示
        /// </summary>
        public bool deptHiding { get; set; }

        /// <summary>
        /// 可以查看指定隐藏部门的其他部门列表,如果部门隐藏,则此值生效,取值为其他的部门id组成的的字符串,使用|符号进行分割
        /// </summary>
        public string deptPermits { get; set; }

        /// <summary>
        /// 可以查看指定隐藏部门的其他人员列表,如果部门隐藏,则此值生效,取值为其他的人员userid组成的的字符串,使用|符号进行分割
        /// </summary>
        public string userPermits { get; set; }

        /// <summary>
        /// 是否本部门的员工仅可见员工自己, 为true时,本部门员工默认只能看到员工自己
        /// </summary>
        public bool outerDept { get; set; }

        /// <summary>
        /// 本部门的员工仅可见员工自己为true时,可以配置额外可见部门,值为部门id组成的的字符串,使用|符号进行分割
        /// </summary>
        public string outerPermitDepts { get; set; }

        /// <summary>
        /// 本部门的员工仅可见员工自己为true时,可以配置额外可见人员,值为userid组成的的字符串,使用| 符号进行分割
        /// </summary>
        public string outerPermitUsers { get; set; }

        /// <summary>
        /// 企业群群主
        /// </summary>
        public string orgDeptOwner { get; set; }

        /// <summary>
        /// 部门的主管列表,取值为由主管的userid组成的字符串,不同的userid使用|符号进行分割
        /// </summary>
        public string deptManagerUseridList { get; set; }

        /// <summary>
        /// 部门标识字段,开发者可用该字段来唯一标识一个部门,并与钉钉外部通讯录里的部门做映射
        /// </summary>
        public string sourceIdentifier { get; set; }

        /// <summary>
        /// 部门群是否包含子部门
        /// </summary>
        public string groupContainSubDept { get; set; }
    }
    /// <summary>
    /// 所有上级父部门
    /// </summary>
    public class DDParentDepts : DDRequestEntity
    {
        /// <summary>
        /// 该部门的所有父部门id列表
        /// </summary>
        public long[] parentIds { get; set; }
    }
    /// <summary>
    /// 部门列表
    /// </summary>
    public class DDDeptList : DDRequestEntity
    {
        /// <summary>
        /// 部门列表数据
        /// </summary>
        public List<DDDeptDetailEntity> department { get; set; }
    }