c# mvc 钉钉接口开发--用户免登录,获取通讯录
2019-06-14 本文已影响0人
孤傲小狼
我一直认为先有效果图,才能让读者知道自己需不需要,好的习惯从我做起!
1、效果图
获取到用户的个人信息 获取通讯录下部门及成员
2、目录结构图
目录结构图
3、Scripts文件夹下
需要引入jquery-1.10.2.min.js
4、controllers文件夹下
DingdingService类
using ddproject.Helper;
using ddproject.Models;
using ddproject.Models.Result;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ddproject.Controllers
{
public class DingdingService
{
/// <summary>
/// 这三个值都是在自己创建的小程序中的参数 三个重要的东西
/// 你们自己替换 自己企业的
/// </summary>
public static string AppId = "123456789";
public static string AppSecret = "123456789";
public static string agentId = "123456789";
//private DataBriefServer dataBrief;
//public DingdingService()
//{
// dataBrief = new DataBriefServer();
//}
/// <summary>
/// 获取钉钉的Token
/// </summary>
/// <param name="code"></param>
/// <returns></returns>
public static string GetToken()
{
string DD_Token = CookieHelper.Instance.GetCookie("DD_Token");
if (string.IsNullOrEmpty(DD_Token))
{
string url = string.Format("https://oapi.dingtalk.com/gettoken?corpid={0}&corpsecret={1}", AppId, AppSecret);
string json = HttpHelper.GetHtml(url);
Access_Token access_token = JsonHelper.DeserializeObject<Access_Token>(json);
DD_Token = access_token.access_token;
CookieHelper.Instance.SaveCookie("DD_Token", DD_Token, 10);
}
return DD_Token;
}
/// <summary>
/// 通过用户编号 获取 用户信息
/// </summary>
/// <param name="uid"></param>
/// <returns></returns>
public Dingding_User GetUeser(string uid)
{
string url = string.Format("https://oapi.dingtalk.com/user/get?access_token={0}&userid={1}", GetToken(), uid);
string json = HttpHelper.GetHtml(url);
return JsonHelper.DeserializeObject<Dingding_User>(json);
}
/// <summary>
/// 通过用户编号 获取 用户信息
/// </summary>
/// <param name="uid"></param>
/// <returns></returns>
public Access_UserInfo GetUserInfo(string code)
{
string url = string.Format("https://oapi.dingtalk.com/user/getuserinfo?access_token={0}&code={1}", GetToken(), code);
string json = HttpHelper.GetHtml(url);
return JsonHelper.DeserializeObject<Access_UserInfo>(json);
}
/// <summary>
/// 获取 ticker
/// </summary>
/// <returns></returns>
private Access_Ticket GetTicket()
{
string url = string.Format("https://oapi.dingtalk.com/get_jsapi_ticket?access_token={0}", GetToken());
string json = HttpHelper.GetHtml(url);
return JsonHelper.DeserializeObject<Access_Ticket>(json);
}
/// <summary>
/// 签名算法 对string1进行sha1签名,得到signature
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
private Access_Sdk GetSdk(string url)
{
string noncestr = GuidHelper.GuidTo16String();
string timestamp = DateTime.Now.Ticks.ToString();
Access_Ticket access_Ticket = GetTicket();
string string1 = "jsapi_ticket=" + access_Ticket.ticket + "&noncestr=" + noncestr + "×tamp=" + timestamp + "&url=" + url + "";
string signature = MD5Helper.SHA1(string1);
Access_Sdk sdk = new Access_Sdk();
sdk.noncestr = noncestr;
sdk.timestamp = timestamp;
sdk.signature = signature;
return sdk;
}
/// <summary>
/// 获取部门详细信息
/// </summary>
/// <param name="accessToken"></param>
/// <param name="departmentId"></param>
/// <returns></returns>
public string getDepartmentInfo(string accessToken, string departmentId)
{
string result = null;
string url = "https://oapi.dingtalk.com/department/get?access_token=" + accessToken + "&id=" + departmentId;
result = HttpHelper.GetHtml(url);
return result;
}
/// <summary>
/// 获取部门列表
/// </summary>
/// <returns></returns>
public dept_list getDeptlist()
{
string url = string.Format("https://oapi.dingtalk.com/department/list?access_token={0}", GetToken());
string json = HttpHelper.GetHtml(url);
System.Diagnostics.Debug.WriteLine(json);
return JsonHelper.DeserializeObject<dept_list>(json);
}
/// <summary>
/// 获取部门成员
/// </summary>
/// <param name="department_id">部门id</param>
/// <returns></returns>
public static dept_userlist GetSimplelistUserInfo(string department_id)
{
string AccessToken = GetToken();
string url = "https://oapi.dingtalk.com/user/list?access_token=" + AccessToken + "&department_id=" + department_id;
string json = HttpHelper.GetHtml(url);
System.Diagnostics.Debug.WriteLine(json);
return JsonHelper.DeserializeObject<dept_userlist>(json);
}
/// <summary>
/// 合并 config 需要的参数
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public ResultInfo<object> GetDingdingConfig(string url)
{
Access_Sdk sdk = GetSdk(url);
Dictionary<string, string> dic = new Dictionary<string, string>();
dic.Add("agentId", agentId);
dic.Add("corpId", AppId);
dic.Add("timeStamp", sdk.timestamp);
dic.Add("nonceStr", sdk.noncestr);
dic.Add("signature", sdk.signature);
ResultInfo<object> result = new ResultInfo<object>();
result.Code = ResultCode.Success;
result.Data = dic;
result.Message = "ok";
return result;
}
}
}
HomeController类
using ddproject.Helper;
using ddproject.Models;
using ddproject.Models.Result;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace ddproject.Controllers
{
public class HomeController : Controller
{
protected Dictionary<string, string> dic = new Dictionary<string, string>();
private DingdingService dingdingService;
protected string code;
public ActionResult Index()
{
dingdingService = new DingdingService();
var data = dingdingService.GetDingdingConfig(RequsertHelper.GetUrl());
if (data.Code == ResultCode.Success)
{
dic = (Dictionary<String, String>)data.Data;
}
return View();
}
/// <summary>
/// 免登获取用户详细信息
/// </summary>
/// <param name="id"></param>
public void getUserInfo(string id)
{
dingdingService = new DingdingService();
code = id;
string uid = dingdingService.GetUserInfo(code).userid;
ResultInfo<object> result = new ResultInfo<object>();
result.Data = dingdingService.GetUeser(uid);
result.Code = ResultCode.Success;
result.Message = "免登录,获取个人信息成功!";
Response.Write(JsonHelper.GetJson(result));
}
public ActionResult MailList()
{
dingdingService = new DingdingService();
//获取dd内部门信息及部门成员
List<dept_Info> depts = ViewBag.dept = dingdingService.getDeptlist().department;
foreach (dept_Info dept in depts)
{
dept.UserList = DingdingService.GetSimplelistUserInfo(dept.id).userlist;
}
//System.Diagnostics.Debug.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(depts));
return View();
}
public ActionResult About()
{
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
}
}
3、Helper文件夹下
CookHelper类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ddproject.Helper
{
public class CookieHelper
{
private static CookieHelper _Instance = new CookieHelper();
public static CookieHelper Instance
{
get { return _Instance; }
}
/// <summary>
/// 保存一个Cookie
/// </summary>
/// <param name="CookieName">Cookie名称</param>
/// <param name="CookieValue">Cookie值</param>
/// <param name="CookieTime">Cookie过期时间(分钟),0为关闭页面失效</param>
public void SaveCookie(string CookieName, string CookieValue, double CookieTime)
{
HttpCookie myCookie = new HttpCookie(CookieName);
DateTime now = DateTime.Now;
myCookie.Value = CookieValue;
myCookie.Domain = string.Empty;
if (CookieTime != 0)
{
myCookie.Expires = now.AddSeconds(CookieTime);
}
if (HttpContext.Current.Response.Cookies[CookieName] != null)
HttpContext.Current.Response.Cookies.Remove(CookieName);
HttpContext.Current.Response.Cookies.Add(myCookie);
}
/// <summary>
/// 取得CookieValue
/// </summary>
/// <param name="CookieName">Cookie名称</param>
/// <returns>Cookie的值</returns>
public string GetCookie(string CookieName)
{
HttpCookie myCookie = new HttpCookie(CookieName);
myCookie = HttpContext.Current.Request.Cookies[CookieName];
if (myCookie != null)
{
myCookie.Domain = string.Empty;
return myCookie.Value;
}
else
return null;
}
/// <summary>
/// 清除CookieValue
/// </summary>
/// <param name="CookieName">Cookie名称</param>
public void ClearCookie(string CookieName)
{
HttpCookie myCookie = new HttpCookie(CookieName);
DateTime now = DateTime.Now;
myCookie.Domain = string.Empty;
myCookie.Expires = now.AddYears(-2);
HttpContext.Current.Response.Cookies.Add(myCookie);
}
}
}
GuidHelper类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ddproject.Helper
{
public class GuidHelper
{
/// <summary>
/// 根据GUID获取16位的唯一字符串
/// </summary>
/// <param name=\"guid\"></param>
/// <returns></returns>
public static string GuidTo16String()
{
long i = 1;
foreach (byte b in Guid.NewGuid().ToByteArray())
i *= ((int)b + 1);
return string.Format("{0:x}", i - DateTime.Now.Ticks);
}
}
}
HttpHelper类
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
namespace ddproject.Helper
{
public class HttpHelper
{
//以GET方式抓取远程页面内容
public static string GetHtml(string tUrl)
{
string strResult;
try
{
HttpWebRequest hwr = (HttpWebRequest)HttpWebRequest.Create(tUrl);
hwr.Timeout = 19600;
HttpWebResponse hwrs = (HttpWebResponse)hwr.GetResponse();
Stream myStream = hwrs.GetResponseStream();
StreamReader sr = new StreamReader(myStream, Encoding.UTF8);
//StringBuilder sb = new StringBuilder();
strResult = sr.ReadToEnd();
//while (-1 != sr.Peek())
//{
// sb.Append(sr.ReadLine() + "\r\n");
//}
//strResult = sb.ToString();
hwrs.Close();
}
catch (Exception ee)
{
strResult = ee.Message;
}
return strResult;
}
}
}
JsonHelper类
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ddproject.Helper
{
public class JsonHelper
{
public static string GetJson(object obj)
{
return JsonConvert.SerializeObject(obj);
}
public static T DeserializeObject<T>(string json)
{
return JsonConvert.DeserializeObject<T>(json);
}
public static dynamic ConvertDynamic(object obj)
{
return JsonConvert.DeserializeObject<dynamic>(GetJson(obj));
}
}
}
MD5Helper类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ddproject.Helper
{
public class MD5Helper
{
/// <summary>
/// 16位小写
/// </summary>
/// <returns></returns>
public static string Lower16(string s)
{
s = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(s, "md5").ToString();
return s.ToLower().Substring(8, 16);
}
/// <summary>
/// 32位小写
/// </summary>
/// <returns></returns>
public static string Lower32(string s)
{
s = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(s, "md5").ToString();
return s.ToLower();
}
/// <summary>
/// 32位小写
/// </summary>
/// <returns></returns>
public static string SHA1(string s)
{
s = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(s, "SHA1").ToString();
return s.ToLower();
}
}
}
RequserHelper类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ddproject.Helper
{
public class RequsertHelper
{
/// <summary>
/// 获得当前完整Url地址
/// </summary>
/// <returns>当前完整Url地址</returns>
public static string GetUrl()
{
return HttpContext.Current.Request.Url.ToString();
}
}
}
4、Models文件夹下
Result文件夹下两个类ResultCode,ResultInfo
ResultCode类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ddproject.Helper
{
public class RequsertHelper
{
/// <summary>
/// 获得当前完整Url地址
/// </summary>
/// <returns>当前完整Url地址</returns>
public static string GetUrl()
{
return HttpContext.Current.Request.Url.ToString();
}
}
}
ResultInfo类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ddproject.Models.Result
{
public class ResultInfo<T>
{
/// <summary>
/// 错误代码
/// </summary>
public ResultCode Code
{
get;
set;
}
/// <summary>
/// 信息提示
/// </summary>
public string Message
{
get;
set;
}
/// <summary>
/// 数据集结果
/// </summary>
public T Data
{
get;
set;
}
}
}
Access_Sdk类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ddproject.Models
{
public class Access_Sdk
{
public string signature { get; set; }
public string noncestr { get; set; }
public string timestamp { get; set; }
}
}
Access_Sign类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ddproject.Models
{
public class Access_Sign
{
public String agentId { get; set; }
public String corpId { get; set; }
public String timeStamp { get; set; }
public String nonceStr { get; set; }
public String signature { get; set; }
public String url { get; set; }
public String rawstring { get; set; }
public string jsticket
{
get; set;
}
}
}
Access_Ticket类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ddproject.Models
{
public class Access_Ticket
{
public string errcode;
public string errmsg;
public string ticket;
public string expires_in;
}
}
Access_Token类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ddproject.Models
{
public class Access_Token
{
public string errcode;
public string errmsg;
public string expires_in;
public string access_token;
}
}
Access_UserInfo类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ddproject.Models
{
public class Access_UserInfo
{
public string errcode { get; set; }
public string errmsg { get; set; }
public string userid { get; set; }
/// <summary>
/// 手机设备号,由钉钉在安装时随机产生
/// </summary>
public string deviceId { get; set; }
/// <summary>
/// 是否是管理员
/// </summary>
public string is_sys { get; set; }
/// <summary>
/// 级别,0:非管理员 1:超级管理员(主管理员) 2:普通管理员(子管理员) 100:老板
/// </summary>
public string sys_level { get; set; }
}
}
dept_Info类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ddproject.Models
{
public class dept_Info
{
public string id { get; set; }
public string name { get; set; }
/// <summary>
/// 父部门id,根部门为1
/// </summary>
public string parentid { get; set; }
/// <summary>
/// 是否同步创建一个关联此部门的企业群 ,true表示是,false表示不是
/// </summary>
public string createDeptGroup { get; set; }
/// <summary>
/// 当群创建后,是否有新人加入部门会自动加入该群,true表示是,false表示不是
/// </summary>
public string autoAddUser { get; set; }
/// <summary>
/// 部门用户列表,.net4.0版本以下不支持此写法
/// </summary>
private List<Dingding_User> userList = new List<Dingding_User>();
public List<Dingding_User> UserList
{
get { return userList; }
set { userList = value; }
}
}
}
dept_list类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ddproject.Models
{
public class dept_list
{
public string errcode { get; set; }
public string errmsg { get; set; }
public List<dept_Info> department { get; set; }
}
}
dept_userlist类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ddproject.Models
{
public class dept_userlist
{
public string errcode { get; set; }
public string errmsg { get; set; }
public List<Dingding_User> userlist { get; set; }
}
}
Dingding_User类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ddproject.Models
{
public class Dingding_User
{
public string errcode;
public string errmsg;
public string userid;
/// <summary>
/// 成员名称
/// </summary>
public string name;
/// <summary>
/// 分机号(仅限企业内部开发调用)
/// </summary>
public string tel;
/// <summary>
/// 办公地点(ISV不可见)
/// </summary>
public string workPlace;
/// <summary>
/// 备注(ISV不可见)
/// </summary>
public string remark;
/// <summary>
/// 手机号码(ISV不可见)
/// </summary>
public string mobile;
/// <summary>
/// 员工的电子邮箱(ISV不可见)
/// </summary>
public string email;
/// <summary>
/// 员工的企业邮箱,如果员工已经开通了企业邮箱,接口会返回,否则不会返回(ISV不可见)
/// </summary>
public string orgEmail;
/// <summary>
/// 是否已经激活, true表示已激活, false表示未激活
/// </summary>
public bool active;
/// <summary>
/// 在对应的部门中的排序, Map结构的json字符串, key是部门的Id, value是人员在这个部门的排序值
/// </summary>
public string orderInDepts;
/// <summary>
/// 是否为企业的管理员, true表示是, false表示不是
/// </summary>
public bool isAdmin;
/// <summary>
/// 是否为企业的老板, true表示是, false表示不是(【设置负责人】:主管理员登陆钉钉手机客户端 -【通讯录】-【企业名后面的管理】-【企业通讯录】-【负责人设置】进行添加则可。)
/// </summary>
public bool isBoss;
/// <summary>
/// 钉钉Id,在钉钉全局范围内标识用户的身份(不可修改
/// </summary>
public string dingId;
public string unionid;
/// <summary>
/// 在对应的部门中是否为主管, Map结构的json字符串, key是部门的Id, value是人员在这个部门中是否为主管, true表示是, false表示不是
/// </summary>
public string isLeaderInDepts;
/// <summary>
/// 是否号码隐藏, true表示隐藏, false表示不隐藏
/// </summary>
public bool isHide;
/// <summary>
/// 成员所属部门id列表
/// </summary>
public string[] department;
/// <summary>
/// 职位信息
/// </summary>
public string position;
/// <summary>
/// 头像url
/// </summary>
public string avatar;
/// <summary>
/// 入职时间
/// </summary>
public string hiredDate;
/// <summary>
/// 员工工号
/// </summary>
public string jobnumber;
/// <summary>
/// 扩展属性,可以设置多种属性(但手机上最多只能显示10个扩展属性,具体显示哪些属性,请到OA管理后台->设置->通讯录信息设置和OA管理后台->设置->手机端显示信息设置)
/// </summary>
public string extattr;
///// <summary>
///// 角色信息(ISV不可见),json数组格式
///// </summary>
//public Roles roles;
/// <summary>
/// 手机号码区号
/// </summary>
public string stateCode;
/// <summary>
/// 是否是高管
/// </summary>
public string isSenior;
}
public class Roles
{
/// <summary>
/// 角色id(ISV不可见)
/// </summary>
public string id;
/// <summary>
///角色名称(ISV不可见)
/// </summary>
public string name;
/// <summary>
/// 角色分组名称(ISV不可见)
/// </summary>
public string groupName;
/// <summary>
///
/// </summary>
public string type;
}
}
5、Views文件夹下
Index.cshtml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ddproject.Models
{
public class Dingding_User
{
public string errcode;
public string errmsg;
public string userid;
/// <summary>
/// 成员名称
/// </summary>
public string name;
/// <summary>
/// 分机号(仅限企业内部开发调用)
/// </summary>
public string tel;
/// <summary>
/// 办公地点(ISV不可见)
/// </summary>
public string workPlace;
/// <summary>
/// 备注(ISV不可见)
/// </summary>
public string remark;
/// <summary>
/// 手机号码(ISV不可见)
/// </summary>
public string mobile;
/// <summary>
/// 员工的电子邮箱(ISV不可见)
/// </summary>
public string email;
/// <summary>
/// 员工的企业邮箱,如果员工已经开通了企业邮箱,接口会返回,否则不会返回(ISV不可见)
/// </summary>
public string orgEmail;
/// <summary>
/// 是否已经激活, true表示已激活, false表示未激活
/// </summary>
public bool active;
/// <summary>
/// 在对应的部门中的排序, Map结构的json字符串, key是部门的Id, value是人员在这个部门的排序值
/// </summary>
public string orderInDepts;
/// <summary>
/// 是否为企业的管理员, true表示是, false表示不是
/// </summary>
public bool isAdmin;
/// <summary>
/// 是否为企业的老板, true表示是, false表示不是(【设置负责人】:主管理员登陆钉钉手机客户端 -【通讯录】-【企业名后面的管理】-【企业通讯录】-【负责人设置】进行添加则可。)
/// </summary>
public bool isBoss;
/// <summary>
/// 钉钉Id,在钉钉全局范围内标识用户的身份(不可修改
/// </summary>
public string dingId;
public string unionid;
/// <summary>
/// 在对应的部门中是否为主管, Map结构的json字符串, key是部门的Id, value是人员在这个部门中是否为主管, true表示是, false表示不是
/// </summary>
public string isLeaderInDepts;
/// <summary>
/// 是否号码隐藏, true表示隐藏, false表示不隐藏
/// </summary>
public bool isHide;
/// <summary>
/// 成员所属部门id列表
/// </summary>
public string[] department;
/// <summary>
/// 职位信息
/// </summary>
public string position;
/// <summary>
/// 头像url
/// </summary>
public string avatar;
/// <summary>
/// 入职时间
/// </summary>
public string hiredDate;
/// <summary>
/// 员工工号
/// </summary>
public string jobnumber;
/// <summary>
/// 扩展属性,可以设置多种属性(但手机上最多只能显示10个扩展属性,具体显示哪些属性,请到OA管理后台->设置->通讯录信息设置和OA管理后台->设置->手机端显示信息设置)
/// </summary>
public string extattr;
///// <summary>
///// 角色信息(ISV不可见),json数组格式
///// </summary>
//public Roles roles;
/// <summary>
/// 手机号码区号
/// </summary>
public string stateCode;
/// <summary>
/// 是否是高管
/// </summary>
public string isSenior;
}
public class Roles
{
/// <summary>
/// 角色id(ISV不可见)
/// </summary>
public string id;
/// <summary>
///角色名称(ISV不可见)
/// </summary>
public string name;
/// <summary>
/// 角色分组名称(ISV不可见)
/// </summary>
public string groupName;
/// <summary>
///
/// </summary>
public string type;
}
}
MailList.cshtml
@{
ViewBag.Title = "MailList";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>通讯录</h2>
<style>
.deptname {
background-color:#eb8025;
font-size:22px;
}
</style>
<div>
@{
foreach (var v in ViewBag.dept)
{
<span>部门编号: @v.id</span><br />
<span class="deptname">名称: @v.name </span><br /><br />
foreach (var u in @v.UserList)
{
<span>员工名:@u.name</span>
<span>手机号:@u.mobile</span>
<br />
}
<br /><br /><br /><br />
}
}
</div>