首選要先理解釘釘的幾個應用,因為應用不同,對應的接口也不一樣,能夠調用的權限也不一樣,所以首先不要盲目的開發,看文檔。
也就是這四個。總體來說,如果你只是想在釘釘上開個門,用來進到自己的H5應用,就直接選微應用,然后如果你是要上架到應用市場去就選第三方企業應用。如果選擇小程序就比較麻煩,針對ISV接口會不同,第三方企業應用的前端接口更加豐富。咱們主要講微應用。微應用的前端API也有發Ding功能
開發:
首先你要下載釘釘sdk下載地址:https://ding-doc.dingtalk.com/doc#/faquestions/vzbp02
你可以自己用釘釘賬號創建一個企業,創建部門、員工、用作測試。然后創建一個企業內部微應用。
獲取Token方法:
/// <summary> /// 獲取token /// </summary> /// <returns></returns> public static string GetAccessToken() { var client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken"); OapiGettokenRequest tokenRequest = new OapiGettokenRequest(); tokenRequest.Corpid = Global.AppKey; tokenRequest.Corpsecret = Global.AppSecret; tokenRequest.SetHttpMethod("get"); Api.Response.OapiGettokenResponse retString = client.Execute(tokenRequest); ////根據CorpId和CorpSecret發送get請求獲得access_token //string url = string.Format("https://oapi.dingtalk.com/gettoken?corpid={0}&corpsecret={1}", Global.CorpId, Global.CorpSecret); ////返回內容 //string retString = HttpMethod.HttpGet(url); //TokenEntity.TokenData obj = retString.ToObject<TokenEntity.TokenData>(); if (retString.Errmsg == "ok") { string accessToken = retString.AccessToken; Access_Token = accessToken; //DingTalk.Log.Info($"釘釘 獲取TOKNE:{accessToken}"); return accessToken; } else { string message = "釘釘 獲取TOKEN失敗\r\n{" + retString.Errmsg + "}\r\nCORPID:{" + Global.AppKey + "}\r\nCORPSECRET:{" + Global.AppSecret + "}"; return message; } }
Global方法:
public class Global { private static string _AppKey = string.Empty; /// <summary> /// CorpId /// </summary> public static string AppKey { get { if (_AppKey.IsNullOrEmpty()) { try { _AppKey = ConfigurationManager.AppSettings["AppKey"]; } catch { } } return _AppKey; } } public static string _AppId = string.Empty; /// <summary> /// CorpSecret /// </summary> public static string AppId { get { if (_AppId.IsNullOrEmpty()) { try { _AppSecret = ConfigurationManager.AppSettings["AppId"]; } catch { } } return _AppSecret; } } public static string _AppSecret = string.Empty; /// <summary> /// CorpSecret /// </summary> public static string AppSecret { get { if (_AppSecret.IsNullOrEmpty()) { try { _AppSecret = ConfigurationManager.AppSettings["AppSecret"]; } catch { } } return _AppSecret; } } private static long _AgentId = 0; /// <summary> /// 微應用agentId /// </summary> public static long AgentId { get { if (_AgentId.Equals(0)) { try { _AgentId = Convert.ToInt64(System.Configuration.ConfigurationManager.AppSettings["AgentId"]); } catch { } } return _AgentId; } } private static string _suiteKey = string.Empty; public static string suiteKey { get { if (_suiteKey.IsNullOrEmpty()) { try { _suiteKey = ConfigurationManager.AppSettings["suiteKey"]; } catch { } } return _suiteKey; } } private static string _suiteSecret = string.Empty; public static string suiteSecret { get { if (_suiteSecret.IsNullOrEmpty()) { try { _suiteSecret = ConfigurationManager.AppSettings["suiteSecret"]; } catch { } } return _suiteSecret; } } private static long _suiteId = 0; public static long suiteId { get { if (_suiteId.Equals(0)) { try { _suiteId = Convert.ToInt64(System.Configuration.ConfigurationManager.AppSettings["suiteId"]); } catch { } } return _suiteId; } } /// <summary> /// <!--加密Token--> /// </summary> private static string _Token = string.Empty; public static string Token { get { if (_Token.IsNullOrEmpty()) { try { _Token = ConfigurationManager.AppSettings["Token"]; } catch { } } return _Token; } } /// <summary> /// <!--數據加密秘鑰--> /// </summary> private static string _SecretKey = string.Empty; public static string SecretKey { get { if (_SecretKey.IsNullOrEmpty()) { try { _SecretKey = ConfigurationManager.AppSettings["SecretKey"]; } catch { } } return _SecretKey; } } /// <summary> /// 企業ID /// </summary> private static string _CorpId = string.Empty; public static string CorpId { get { if (_CorpId.IsNullOrEmpty()) { try { _CorpId = ConfigurationManager.AppSettings["CorpId"]; } catch { } } return _CorpId; } } }
企業內部應用主要用到:AppKey和AppSecret以及AgentId
獲取部門用戶列表,注意,先根據Token權限獲取部門ID,然后獲取該部門下面的用戶列表,另外獲取部門那個接口是獲取一級部門,如果有二級部門就查不出來,需要遞歸去查詢,然后根據部門ID集合去查詢用戶列表,另外建議自己寫個實體類加上注釋,用來反序列化存儲釘釘返回的數據
public class UserUtil { public ArrayList al = new ArrayList(); public ArrayList al2 = new ArrayList(); /// <summary> /// 根據部門ID獲取該部門下面的用戶列表 /// </summary> /// <returns></returns> public List<userlist> GetUserInfoListByDepartment() { try { //獲取access_token string access_token = TokenUtil.GetAccessToken(); if (string.IsNullOrEmpty(access_token)) return null; DepartmentResult departmentResult = DepartmentUtil.GetDepartmentInfo(); if (departmentResult.errcode != 0 || departmentResult.department.Count <= 0) return null; List<userlist> userList = new List<userlist>(); foreach (var item in departmentResult.department) { //根據部門ID獲取部門人員詳情 string url = "https://oapi.dingtalk.com/user/list?access_token=" + access_token + "&department_id=" + item.id; var client = new DefaultDingTalkClient(url); OapiUserGetDeptMemberRequest req = new OapiUserGetDeptMemberRequest(); req.SetHttpMethod("get"); var retString = client.Execute(req); //Log.Info($"獲取釘釘用戶列表結果:{retString.Body}"); var userResult = JsonConvert.DeserializeObject<UserResult>(retString.Body); if (userResult.errcode == 0 && userResult.userlist != null && userResult.userlist.Count > 0) { userList.AddRange(userResult.userlist);//添加人員信息到集合中 } } return userList; } catch (Exception ex) { //Log.Error("獲取釘釘用戶列表異常"); //Log.Error(ex); return new List<userlist>(); } } /// <summary> /// 先根據Token權限獲取部門ID,然后獲取該部門下面的用戶列表 /// </summary> /// <returns></returns> public List<userlist> GetUserInfoListByDepartmentQx() { try { //獲取access_token string access_token = TokenUtil.GetAccessToken(); if (string.IsNullOrEmpty(access_token)) return null; DepartmentPowerEntity departmentpowerentity = DepartmentUtil.GetPowerDepartmentInfo(); if (departmentpowerentity.errcode != 0) return null; List<userlist> userList = new List<userlist>(); foreach (var item in departmentpowerentity.auth_org_scopes.authed_dept) { //根據部門ID獲取部門人員詳情 string url = "https://oapi.dingtalk.com/user/list?access_token=" + access_token + "&department_id=" + item; var client = new DefaultDingTalkClient(url); OapiUserGetDeptMemberRequest req = new OapiUserGetDeptMemberRequest(); req.SetHttpMethod("get"); var retString = client.Execute(req); //Log.Info($"獲取釘釘用戶列表結果:{retString.Body}"); var userResult = JsonConvert.DeserializeObject<UserResult>(retString.Body); if (userResult.errcode == 0 && userResult.userlist != null && userResult.userlist.Count > 0) { userList.AddRange(userResult.userlist);//添加人員信息到集合中 } } return userList; } catch (Exception ex) { //Log.Error("獲取釘釘用戶列表異常"); //Log.Error(ex); return new List<userlist>(); } } /// <summary> /// 遞歸查詢所有的用戶 /// </summary> /// <returns></returns> public List<userlist> GetAllUserInfoListByDepartment() { try { //獲取access_token string access_token = TokenUtil.GetAccessToken(); if (string.IsNullOrEmpty(access_token)) return null; DepartmentPowerEntity departmentpowerentity = DepartmentUtil.GetPowerDepartmentInfo(); if (departmentpowerentity.errcode != 0) return null; for (int i = 0; i < departmentpowerentity.auth_org_scopes.authed_dept.Length; i++) { al.Add(departmentpowerentity.auth_org_scopes.authed_dept[i]); } RecursionDepartment(al); List<userlist> userList = new List<userlist>(); foreach (var m in al) { al2.Add(m); } foreach (var n in al2) { //根據部門ID獲取部門人員詳情 string url = "https://oapi.dingtalk.com/user/list?access_token=" + access_token + "&department_id=" + n; var client = new DefaultDingTalkClient(url); OapiUserGetDeptMemberRequest req = new OapiUserGetDeptMemberRequest(); req.SetHttpMethod("get"); var retString = client.Execute(req); //Log.Info($"獲取釘釘用戶列表結果:{retString.Body}"); var userResult = JsonConvert.DeserializeObject<UserResult>(retString.Body); if (userResult.errcode == 0 && userResult.userlist != null && userResult.userlist.Count > 0) { userList.AddRange(userResult.userlist);//添加人員信息到集合中 } } return userList; } catch (Exception ex) { //Log.Error("獲取釘釘用戶列表異常"); //Log.Error(ex); return new List<userlist>(); } } /// <summary> ///體驗組織————遞歸查詢所有的用戶 /// </summary> /// <returns></returns> public List<userlist> ISV_GetAllUserInfoListByDepartment() { try { //獲取access_token string access_token = TokenUtil.ISV_GetAccessToken(); if (string.IsNullOrEmpty(access_token)) return null; DepartmentPowerEntity departmentpowerentity = DepartmentUtil.ISV_GetPowerDepartmentInfo(); if (departmentpowerentity.errcode != 0) return null; for (int i = 0; i < departmentpowerentity.auth_org_scopes.authed_dept.Length; i++) { al.Add(departmentpowerentity.auth_org_scopes.authed_dept[i]); } RecursionDepartment(al); List<userlist> userList = new List<userlist>(); foreach (var m in al) { al2.Add(m); } foreach (var n in al2) { //根據部門ID獲取部門人員詳情 string url = "https://oapi.dingtalk.com/user/list?access_token=" + access_token + "&department_id=" + n; var client = new DefaultDingTalkClient(url); OapiUserGetDeptMemberRequest req = new OapiUserGetDeptMemberRequest(); req.SetHttpMethod("get"); var retString = client.Execute(req); //SimpleLog.Log.Info($"獲取釘釘用戶列表結果:{retString.Body}"); var userResult = JsonConvert.DeserializeObject<UserResult>(retString.Body); if (userResult.errcode == 0 && userResult.userlist != null && userResult.userlist.Count > 0) { userList.AddRange(userResult.userlist);//添加人員信息到集合中 } } return userList; } catch (Exception ex) { //Log.Error("獲取釘釘用戶列表異常"); //Log.Error(ex); return new List<userlist>(); } } public void RecursionDepartment(ArrayList ids) { ArrayList list = new ArrayList(); //第一次循環所有權限部門Id foreach (var n in ids) { //al第一次循環存有權限部門下面的所有子部門 int[] kk = DepartmentUtil.GetAllAecondaryDepartmentInfo(n.ToString()).sub_dept_id_list; if (kk==null || kk.Length <= 0) continue; for (int i = 0; i < kk.Length; i++) { al2.Add(kk[i]); //循環刷新存放子部門的部門Id集合 list.Add(kk[i]); } } if (list.Count == 0) { return; } RecursionDepartment(list); } /// <summary> /// 根據OA用戶的手機號在釘釘 /// </summary> /// <param name="mobile"></param> /// <returns></returns> public static userlist GetSingleUser(string mobile) { var userlist = UserList; userlist userInfo = new Model.userlist(); foreach (var item in userlist) { if (item.mobile.Equals(mobile)) { userInfo = item; break; } } return userInfo; } /// <summary> /// 將用戶手機號分別映射成該用戶在釘釘里面對應的USERID,便於用戶后面發送短信 /// </summary> /// <param name="mobilelist">將用戶手機號集合</param> /// <returns></returns> public static string MapperUserIDToDingding(List<string> mobilelist) { var dingdinguser = UserList; var list = new List<string>(); foreach (var oa in mobilelist) { foreach (var item in dingdinguser) { if (oa.Equals(item.mobile)) { list.Add(item.userid); continue; } } } return string.Join(",", from u in list select u); } #region 專用於存儲釘釘用戶 private static object LockObject = new object(); private static List<userlist> _userList = null; /// <summary> /// 用戶保存所有用戶信息 /// </summary> public static List<userlist> UserList { get { if (_userList.IsNull()) { lock (LockObject) { if (_userList.IsNull()) { //DingTalkLog.Log.Info($"開始獲取釘釘用戶列表。{_userList?.Count}"); _userList = new UserUtil().GetUserInfoListByDepartment(); // DingTalkLog.Log.Info("獲取釘釘用戶列表。{"++"_userList?.Count}"); } } } return _userList; } } #endregion }
審批接口:
創建審批實例去看審批接口。說一下注冊審批回調接口。上代碼
注冊:
protected void Button1_Click(object sender, EventArgs e) { string _token = TokenUtil.GetAccessToken(); //獲取Token DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/call_back/register_call_back"); OapiCallBackRegisterCallBackRequest request = new OapiCallBackRegisterCallBackRequest(); request.Url = "https://***"; //回調Url request.AesKey = ""; //數據加密密鑰。用於回調數據的加密,長度固定為43個字符,從a-z, A-Z, 0-9共62個字符中選取,您可以隨機生成 request.Token = ""; //加解密需要用到的token List<string> _arr = new List<string>(); _arr.Add("bpms_task_change"); //需要監聽的事件類型,具體填寫方法看這里 https://open-doc.dingtalk.com/microapp/serverapi2/skn8ld _arr.Add("bpms_instance_change"); request.CallBackTag = _arr; OapiCallBackRegisterCallBackResponse response = client.Execute(request, _token); string _str = response.Body; Response.Write(_str); }
當你隨便注冊了幾個監聽事件,想再加幾個,發現提示已被注冊,怎么辦呢? https://ding-doc.dingtalk.com/doc#/serverapi2/pwz3r5
回調的接口代碼,這個要上的話代碼有點多,而且我官方的那個加密解密方法dll在我這報了錯,我就自己copy過來寫了,大概根據官方的那個JAVA去寫,差不多,只是比如.setToken直接去掉Set,.Token=“Token”就可以了。
大概調用接口應該熟悉了,另外建議寫個日志方法,在關鍵的地方加上日志,以便查錯。這里發一個釘釘的Log方法吧
public static void WriteLog(string strMemo) { string directoryPath = HttpContext.Current.Server.MapPath(@"Logs"); string fileName = directoryPath + @"\log" + DateTime.Today.ToString("yyyyMMdd") + ".txt"; if (!Directory.Exists(directoryPath)) Directory.CreateDirectory(directoryPath); StreamWriter sr = null; try { if (!File.Exists(fileName)) { sr = File.CreateText(fileName); } else { sr = File.AppendText(fileName); } sr.WriteLine(DateTime.Now + ": " + strMemo); } catch (Exception ex) { } finally { if (sr != null) sr.Close(); } }