1. 程式人生 > >釘釘通用介面

釘釘通用介面

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Threading;

namespace Dingding
{
    public  class DingApi
    {
        /// <summary>  
        /// 訪問AccessToken  
        /// </summary>  
        public class HCAccessToken
        {
            /// <summary>  
            /// 票據的值  
            /// </summary>  
            public string Value { get; set; }

            /// <summary>  
            /// 票據的開始時間  
            /// </summary>  
            public DateTime Begin { get; set; } = DateTime.Parse("1970-01-01");
        }
        /// <summary>  
        /// 訪問ticket  
        /// </summary>  
        public class HCAccessticket
        {
            /// <summary>  
            /// 票據的值  
            /// </summary>  
            public string Value { get; set; }

            /// <summary>  
            /// 票據的開始時間  
            /// </summary>  
            public DateTime Begin { get; set; } = DateTime.Parse("1970-01-01");
        }
        public static HCAccessToken HCToken = new HCAccessToken();
        public static HCAccessticket HCticket = new HCAccessticket();
        #region 更新AccessToken 
        /// <summary>  
        ///更新票據  
        /// </summary>  
        /// <param name="forced">true:強制更新.false:按快取是否到期來更新</param>  
        public static void UpdateAccessToken(bool forced = false)
        {
            //ConstVars.CACHE_TIME是快取時間(常量,也可放到配置檔案中),這樣在有效期內則直接從快取中獲取票據,不需要再向伺服器中獲取。  
            if (!forced && HCToken.Begin.AddMinutes(100) >= DateTime.Now)
            {//沒有強制更新,並且沒有超過快取時間  
                return;
            }
            GetAccessToken();
        }
        #endregion
        #region 更新ticket  
        /// <summary>  
        ///更新票據  
        /// </summary>  
        /// <param name="forced">true:強制更新.false:按快取是否到期來更新</param>  
        public static void Updateticket(bool forced = false)
        {
            //ConstVars.CACHE_TIME是快取時間(常量,也可放到配置檔案中),這樣在有效期內則直接從快取中獲取票據,不需要再向伺服器中獲取。  
            if (!forced && HCticket.Begin.AddMinutes(100) >= DateTime.Now)
            {//沒有強制更新,並且沒有超過快取時間  
                return;
            }
            Get_jsapi_ticket();
        }
        #endregion


        #region 自定義機器人
        // public static string webhook = "https://oapi.dingtalk.com/robot/send?access_token=6c82bc8ba63652cfa77f5e7d67d42a66327c5ce9a3fd8eb577bf382f9cd2f96e";
         public static string webhook = ConfigurationManager.AppSettings["webhook"];
       // public static string webhook = "https://oapi.dingtalk.com/robot/send?access_token=f781cb8870971aebd4497b9ab7a1f79fbbda110f745e24e1c102947c64b5e029";
        #region 機器人傳送Text資訊
        /// <summary>
        /// 機器人傳送Text資訊
        /// </summary>
        /// <param name="content">傳送內容</param>
        /// <param name="Mobiles">手機號</param>
        /// <param name="isAtAll">是否@所有人</param>
        /// <returns></returns>
        public static string RobotSentText(string content, string[] Mobiles, bool isAtAll)
        {
            var json = new
            {
                msgtype = "text",
                text = new
                {
                    content = content
                },
                at = new
                {
                    atMobiles = Mobiles
                },
                isAtAll = isAtAll
            };
            var dataStr = JsonConvert.SerializeObject(json);
            string result = HttpPost(webhook, dataStr);
            return result;
        }
        #endregion

        #region 機器人傳送Link資訊
        /// <summary>
        /// 機器人傳送Link資訊
        /// </summary>
        /// <param name="Title">訊息標題</param>
        /// <param name="Text">訊息內容 </param>
        /// <param name="picUrl">圖片地址</param>
        /// <param name="MessageUrl">點選訊息跳轉的URL</param>
        /// <returns></returns>
        public static string RobotSentLink(string Title, string Text, string picUrl, string MessageUrl)
        {
            var json = new
            {
                msgtype = "link",
                link = new
                {
                    text = Text,
                    title = Title,
                    picUrl = picUrl,
                    messageUrl = MessageUrl
                }
            };
            var dataStr = JsonConvert.SerializeObject(json);
            string result = HttpPost(webhook, dataStr);
            return result;
        }


        #endregion

        #region 機器人傳送markdown資訊
        /// <summary>
        /// 機器人傳送markdown資訊
        /// </summary>
        /// <param name="Title">首屏標題</param>
        /// <param name="Text">Markdown格式訊息</param>
        /// <param name="Mobiles">手機號</param>
        /// <param name="isAtAll">是否@所有人</param>
        /// <returns></returns>
        public static string RobotSentMarkdown(string Title, string Text, string[] Mobiles, bool isAtAll)
        {

            var json = new
            {
                msgtype = "markdown",
                markdown = new
                {
                    title = Title,
                    text= "### "+Title+ "\n"+ ">" + Text+ "\n\n"
                    //   text = "### 智慧環衛\n" +
                    //"> 系統實現了地圖的瀏覽、顯示等常規的GIS功能,並實現了環衛部件基本資訊的瀏覽、查詢以及視覺化顯示,並對城市部件的突發事件做到及時響應,並實現了已知的位置前往事發地點的最短路徑分析,減少了事件處理前不必要的時間浪費。 目標系統已經在實際生活中應用,做到了簡單、高效的部件管理和實時的事件響應。環衛設施管理包括對垃圾桶、公廁、中轉站等重要環衛設施進行資訊化管理,基本管理內容包括基於地圖標註、更新、刪除、查詢環衛設施分佈情況,及時登記環衛設施維修維護情況。並可以和RFID卡進行對接,對每個環衛設施建立身份證。\n\n" +
                    //"> ![screenshot](http://zrsoft.cn/images/banner18.jpg)\n" +
                    //"> ###### 10點20分發布 [詳情](http://zrsoft.cn/huanwei.html) \n"
                },
                at = new
                {
                    atMobiles = Mobiles
                },
                isAtAll = isAtAll
            };
            var dataStr = JsonConvert.SerializeObject(json);
            string result = HttpPost(webhook, dataStr);
            return result;
        }


        #endregion

        #region 機器人傳送FeedCard資訊
        /// <summary>
        /// 機器人傳送FeedCard資訊
        /// </summary>
        /// <param name="links">List<Models.FeedCardLinks></param>
        /// <returns></returns>
        public static string RobotSentFeedCard(List<Models.FeedCardLinks> links)
        {
            var json = new
            {
                msgtype = "feedCard",
                feedCard = new
                {
                    links = (from r in links
                             select r).ToArray()
                }
            };
            var dataStr = JsonConvert.SerializeObject(json);
            string result = HttpPost(webhook, dataStr);
            return result;
        }


        #endregion


        #endregion

        #region 請求方式
        ManualResetEvent allDone = new ManualResetEvent(false);
        public string PostJson(string url, string data, Dictionary<string, string> headers = null)
        {
            string _headers = string.Empty;
            string _strResult = null;
            byte[] byteData = Encoding.UTF8.GetBytes(data);
            allDone.Reset();
            if (headers != null)
            {
                foreach (var item in headers)
                {
                    _headers = _headers + item.Key + "=" + item.Value + "&";
                }
                _headers = _headers.Substring(0, _headers.Length - 1);
            }

            HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url + (headers == null ? "" : "?") + _headers);

            httpWebRequest.Method = "POST";
            httpWebRequest.ContentType = "application/json";
            httpWebRequest.BeginGetRequestStream((result) =>
            {
                try
                {
                    HttpWebRequest request = (HttpWebRequest)result.AsyncState;
                    using (Stream requestStream = request.EndGetRequestStream(result))
                    {
                        requestStream.Write(byteData, 0, byteData.Length);
                    }
                    request.BeginGetResponse(a =>
                    {
                        try
                        {
                            var reponse = request.EndGetResponse(a);
                            using (StreamReader reader = new StreamReader(reponse.GetResponseStream(), System.Text.Encoding.UTF8))
                            {
                                _strResult = reader.ReadToEnd();
                            }
                            allDone.Set();
                        }
                        catch (Exception)
                        {
                            _strResult = null;
                            allDone.Set();
                            //throw;
                        }
                    }, null);
                }
                catch (Exception)
                {
                    _strResult = null;
                    allDone.Set();
                }
            }, httpWebRequest);


            allDone.WaitOne();
            _headers = string.Empty;
            return _strResult;


        }
        public static string HttpGet(string Url, string DataStr)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url + (DataStr == "" ? "" : "?") + DataStr);
            request.Method = "GET";
            request.ContentType = "application/json;charset=UTF-8";

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream myResponseStream = response.GetResponseStream();
            StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
            string retString = myStreamReader.ReadToEnd();
            myStreamReader.Close();
            myResponseStream.Close();

            return retString;
        }
        public static string HttpPost(string Url, string postDataStr)
        {

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
            request.Method = "POST";
            request.ContentType = "application/json;charset=utf-8 ";
            Stream myRequestStream = request.GetRequestStream();
            StreamWriter myStreamWriter = new StreamWriter(myRequestStream, Encoding.GetEncoding("utf-8"));
            myStreamWriter.Write(postDataStr);

            myStreamWriter.Close();

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            //response.Cookies = cookie.GetCookies(response.ResponseUri);
            Stream myResponseStream = response.GetResponseStream();
            StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
            string retString = myStreamReader.ReadToEnd();
            myStreamReader.Close();
            myResponseStream.Close();

            return retString;
        }

        public static string PostFile(string url, string fileWithPath)
        {
            var result = string.Empty;
            var request = (HttpWebRequest)WebRequest.Create(url);
            var boundary = "----------" + DateTime.Now.Ticks.ToString("x");
            request.ContentType = "multipart/form-data; boundary=" + boundary;
            request.Method = "POST";
            using (Stream requestStream = request.GetRequestStream())
            {
                byte[] boundarybytes = Encoding.UTF8.GetBytes("--" + boundary + "\r\n");
                byte[] trailer = Encoding.UTF8.GetBytes("\r\n--" + boundary + "–-\r\n");
                var filename = Path.GetFileName(fileWithPath);
                using (FileStream fs = new FileStream(fileWithPath, FileMode.Open, FileAccess.Read))
                {
                    byte[] bArr = new byte[fs.Length];
                    fs.Read(bArr, 0, bArr.Length);
                    requestStream.Write(boundarybytes, 0, boundarybytes.Length);
                    var header = $"Content-Disposition:form-data;name=\"media\";filename=\"{filename}\"\r\nfilelength=\"{fs.Length}\"\r\nContent-Type:application/octet-stream\r\n\r\n";
                    byte[] postHeaderBytes = Encoding.UTF8.GetBytes(header.ToString());
                    requestStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);
                    fs.Close();
                    requestStream.Write(bArr, 0, bArr.Length);
                    requestStream.Write(trailer, 0, trailer.Length);
                }
            }
            var response = (HttpWebResponse)request.GetResponse();
            var responseStream = response.GetResponseStream();
            using (var streamReader = new StreamReader(response.GetResponseStream()))
            {
                result = streamReader.ReadToEnd();
            }
            return result;
        }
        #endregion

        #region 主要類


        public class AccessTokenlist
        {
            /// <summary>
            /// 錯誤碼
            /// </summary>
            public string errcode { get; set; }
            /// <summary>
            /// 錯誤資訊
            /// </summary>
            public string errmsg { get; set; }
            /// <summary>
            /// access_token
            /// </summary>
            public string access_token { get; set; }

        }

        public class Message
        {
            /// <summary>
            /// 錯誤碼
            /// </summary>
            public string errcode { get; set; }
            /// <summary>
            /// 錯誤資訊
            /// </summary>
            public string errmsg { get; set; }
            /// <summary>
            /// messageId
            /// </summary>
            public string messageId { get; set; }
            /// <summary>
            /// invalidparty
            /// </summary>
            public string invalidparty { get; set; }
        }

        public class TextMsgModelmarkdown
        {
            public string agentid { get; set; }
            public string touser { get; set; }
            public string msgtype { get; set; }
            public markdown markdown { get; set; }
        }
        public class CreateGroup2
        {
            /// <summary>
            /// 錯誤碼
            /// </summary>
            public string errcode { get; set; }
            /// <summary>
            /// 錯誤資訊
            /// </summary>
            public string errmsg { get; set; }
            /// <summary>
            /// access_token
            /// </summary>
            public string chatid { get; set; }

        }
        public class markdown
        {

            public string title { get; set; }
            public string text { get; set; }
        }
        public class text
        {

            public string content { get; set; }
        }
        #endregion

        #region 獲取唯一憑證token(已測試)
        public static string JTToken;



        public static string GetAccessToken()
        {

            string corpid = "corpid="+ ConfigurationManager.AppSettings["corpId"]+"&corpsecret="+ConfigurationManager.AppSettings["corpSecret"];
            string result = HttpGet("https://oapi.dingtalk.com/gettoken/", corpid);
            AccessTokenlist token = JsonConvert.DeserializeObject<AccessTokenlist>(result);
            HCToken.Value = token.access_token;
            HCToken.Begin = DateTime.Now;
            JTToken = token.access_token;
            return JTToken;
        }
        #endregion

        #region 獲取jsapi_ticket(已測試)
        public class Get_jsapi_ticketM
        {
            public string type { get; set; }
            public string ticket { get; set; }
        }
        public static string JTticket;
        public static string Get_jsapi_ticket()
        {
            //UpdateAccessToken();
            string url = string.Format("https://oapi.dingtalk.com/get_jsapi_ticket?access_token={0}&type=jsapi", JTToken);
            string result = HttpGet(url, "");
            Get_jsapi_ticketM token = JsonConvert.DeserializeObject<Get_jsapi_ticketM>(result);
            result= token.ticket;
            //HCticket.Value = token.ticket;
            //HCticket.Begin = DateTime.Now;
            JTticket = result;
            return result;
        }
        #endregion
        #region 獲取隨機碼
        /// <summary>
        ///開發者在web頁面使用釘釘容器提供的jsapi時,需要驗證呼叫許可權,並以引數signature標識合法性
        ///簽名生成的規則:
        ///List keyArray = sort(noncestr, timestamp, jsapi_ticket, url);
        /// String str = assemble(keyArray);
        ///signature = sha1(str);
        /// </summary>
        /// <param name="noncestr">隨機字串,自己隨便填寫即可</param>
        /// <param name="sTimeStamp">當前時間戳,具體值為當前時間到1970年1月1號的秒數</param>
        /// <param name="jsapi_ticket">獲取的jsapi_ticket</param>
        /// <param name="url">當前網頁的URL,不包含#及其後面部分</param>
        /// <param name="signature">生成的簽名</param>
        /// <returns>0 成功,2 失敗</returns>
        public static string GenSigurate(string noncestr, string sTimeStamp, string jsapi_ticket, string url)
            {


                //例如:
                //noncestr = Zn4zmLFKD0wzilzM
                //jsapi_ticket = mS5k98fdkdgDKxkXGEs8LORVREiweeWETE40P37wkidkfksDSKDJFD5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcKIDU8l
                //timestamp = 1414588745
                //url = http://open.dingtalk.com

                //步驟1.sort()含義為對所有待簽名引數按照欄位名的ASCII 碼從小到大排序(字典序)
                //注意,此處是是按照【欄位名】的ASCII字典序,而不是引數值的字典序(這個細節折磨我很久了)
                //0:jsapi_ticket 1:noncestr 2:timestamp 3:url;

                //步驟2.assemble()含義為根據步驟1中獲的引數欄位的順序,使用URL鍵值對的格式(即key1 = value1 & key2 = value2…)拼接成字串
                //string assemble = "jsapi_ticket=3fOo5UfWhmvRKnRGMmm6cWwmIxDMCnniyVYL2fqcz1I4GNU4054IOlif0dZjDaXUScEjoOnJWOVrdwTCkYrwSl&noncestr=CUMT1987wlrrlw×tamp=1461565921&url=https://jackwangcumt.github.io/home.html";
                string assemble = string.Format("jsapi_ticket={0}&noncestr={1}×tamp={2}&url={3}", jsapi_ticket, noncestr, sTimeStamp, url);
                //步驟2.sha1()的含義為對在步驟2拼接好的字串進行sha1加密。
                SHA1 sha;
                ASCIIEncoding enc;
                string hash = "";

                sha = new SHA1CryptoServiceProvider();
                enc = new ASCIIEncoding();
                byte[] dataToHash = enc.GetBytes(assemble);
                byte[] dataHashed = sha.ComputeHash(dataToHash);
                hash = BitConverter.ToString(dataHashed).Replace("-", "");
                hash = hash.ToLower();



                return hash;

            }
         
            public static string GetSign(string ticket, string noceStr, string timeStamp, string url)
        {            
            string plain = string.Format("noncestr={1}×tamp={2}&jsapi_ticket={0}&url={3}", JTticket, noceStr, timeStamp, url);
            try
            {
                byte[] bytes = Encoding.UTF8.GetBytes(plain);
                byte[] digest = SHA1.Create().ComputeHash(bytes);
                string digestBytesString = BitConverter.ToString(digest).Replace("-", "").ToLower();
                return digestBytesString.ToLower();

            }
            catch (Exception e)
            {
                throw;
            }
        }
        #endregion

        #region 通過CODE換取使用者身份

        public static string GetUserabout(string Code)
        {
            string url = string.Format("https://oapi.dingtalk.com/user/getuserinfo?access_token={0}&code={1}", GetAccessToken(), Code);
            string result = HttpGet(url, "");
            GetUserInfoModel model = Newtonsoft.Json.JsonConvert.DeserializeObject<GetUserInfoModel>(result);
            return model.userid;
        }

        #endregion
        #region 獲取企業自定義空間
        public class GetSpaceId
        {
            /// <summary>
            /// 錯誤碼
            /// </summary>
            public string errcode { get; set; }
            /// <summary>
            /// 錯誤資訊
            /// </summary>
            public string errmsg { get; set; }
            /// <summary>
            /// access_token
            /// </summary>
            public string spaceid { get; set; }
        }
        public static string GetSpace(string domain)
        {
            string url = string.Format("https://oapi.dingtalk.com/cspace/get_custom_space?access_token={0}&domain={1}&agent_id={2}", JTToken, domain, "136369019");
            string result = HttpGet(url, "");
            GetSpaceId model = Newtonsoft.Json.JsonConvert.DeserializeObject<GetSpaceId>(result);
            return model.spaceid;
        }

        #endregion

        #region 授權使用者訪問企業下的自定義空間
        public class GetUserJurisdiction
        {
            /// <summary>
            /// 錯誤碼
            /// </summary>
            public string errcode { get; set; }
            /// <summary>
            /// 錯誤資訊
            /// </summary>
            public string errmsg { get; set; }
        }
        public static string GetJurisdiction(string Id)
        {
            string url = string.Format("https://oapi.dingtalk.com/cspace/grant_custom_space?access_token={0}&domain=ABC123&agent_id={1}&type=add&userid={2}&path=/&fileids=&duration=600", JTToken,"136369019",Id);
            string result = HttpGet(url, "");
            GetUserJurisdiction model = Newtonsoft.Json.JsonConvert.DeserializeObject<GetUserJurisdiction>(result);
            return model.errcode;
        }

        #endregion

        #region 建立一個群(已測試)
        public class CreateQModel
        {
            public string name { get; set; }
            public string owner { get; set; }
            public string[] useridlist { get; set; }
        }
        /// <summary>
        /// 建立會話
        /// </summary>
        /// <param name="name">群名稱</param>
        /// <param name="owner">群主userId</param>
        /// <param name="useridlist">群成員列表UserId用,隔開即可,每次最多操作40人,群人數上限為1000</param>
        /// <returns>返回群會話的Id</returns>
        public static string CreateGroup(string name, string owner, string[] useridlist)
        {
            string url = string.Format("https://oapi.dingtalk.com/chat/create?access_token={0}", GetAccessToken());
            var msgModel = new CreateQModel
            {
                name = name,
                owner = owner,
                useridlist = useridlist

            };
            var dataStr = JsonConvert.SerializeObject(msgModel);
            string result = HttpPost(url, dataStr);
            CreateGroup2 token = JsonConvert.DeserializeObject<CreateGroup2>(result);
            return token.chatid;
        }
        #endregion

        #region 獲取群會話(已測試)
        public class GetChatM
        {
            public string chatid { get; set; }
        }
        /// <summary>
        /// 獲取群會話
        /// </summary>
        /// <param name="chatid">群會話的id</param>
        /// <returns>name 群名稱 owner 群主userid  useridlist 群成員userId列表   </returns>
        public static string GetChat(string chatid)
        {
            string url = string.Format("https://oapi.dingtalk.com/chat/get?access_token={0}&chatid={1}", GetAccessToken(), chatid);


            string result = HttpGet(url, "");
            return result;
        }
        #endregion

        #region 傳送群訊息 markdown訊息(已測試)
        public class MessageateModel
        {
            public string chatid { get; set; }
            public string msgtype { get; set; }
            public markdown markdown { get; set; }


        }
        /// <summary>
        ///  傳送群訊息 markdown訊息
        /// </summary>
        /// <param name="chatid">會話Id</param>
        /// <param name="title">標題</param>
        /// <param name="text">內容</param>
        /// <returns></returns>
        public static string SendGroupMessageate(string chatid, string title, string text)
        {
            string url = string.Format("https://oapi.dingtalk.com/chat/send?access_token={0}", GetAccessToken());
            var msgModel = new MessageateModel
            {
                chatid = chatid,

                msgtype = "markdown",
                markdown = new markdown()
                {
                    title = title,
                    text = text
                },

            };
            var dataStr = JsonConvert.SerializeObject(msgModel);
            string result = HttpPost(url, dataStr);
            return result;
        }
        #endregion

        #region 建立成員(已測試)
        public class CreteUserModel
        {
            public string userid { get; set; }
            public string name { get; set; }
            public string[] department { get; set; }
            public string mobile { get; set; }

        }
        /// <summary>
        /// 建立成員
        /// </summary>
        /// <param name="userid">員工唯一標識ID</param>
        /// <param name="name">成員名稱</param>
        /// <param name="department">陣列型別,數組裡面值為整型,成員所屬部門id列表</param>
        /// <param name="mobile">手機號碼,企業內必須唯一</param>
        /// <returns></returns>
        public static string CreateUser(string userid, string name, string[] department, string mobile)
        {
            string url = string.Format("https://oapi.dingtalk.com/user/create?access_token={0}", GetAccessToken());
            var msgModel = new CreteUserModel
            {
                userid = userid,
                name = name,
                department = department,
                mobile = mobile
            };
            var dataStr = JsonConvert.SerializeObject(msgModel);
            string result = HttpPost(url, dataStr);
            return result;
        }
        #endregion



        #region 刪除成員(已測試)
        public class DeleteUserModel
        {
            public string userid { get; set; }

        }
        /// <summary>
        /// 刪除成員
        /// </summary>
        /// <param name="userid">員工唯一標識ID</param>
        /// <returns></returns>
        public static string DeleteUser(string userid)
        {
            string url = string.Format("https://oapi.dingtalk.com/user/delete?access_token={0}&userid={1}", GetAccessToken(), userid);


            string result = HttpGet(url, "");
            return result;
        }
        #endregion

        #region 批量刪除成員(已測試)
        public class batchdelete
        {
            public string[] useridlist { get; set; }

        }
        /// <summary>
        /// 批量刪除成員
        /// </summary>
        /// <param name="useridlist">員工唯一標識ID  "useridlist":["zhangsan","lisi"]</param>
        /// <returns></returns>
        public static string DeleteUser(string[] useridlist)
        {
            string url = string.Format("https://oapi.dingtalk.com/user/batchdelete?access_token={0}", GetAccessToken());
            var msgModel = new batchdelete
            {
                useridlist = useridlist,

            };
            var dataStr = JsonConvert.SerializeObject(msgModel);
            string result = HttpPost(url, dataStr);
            return result;
        }
        #endregion

        #region 獲取成員詳情(已測試)
        public class UserGetModel
        {
            public string userid { get; set; }

        }
        /// <summary>
        /// 獲取成員詳情
        /// </summary>
        /// <param name="userid">員工UserId</param>
        /// <returns>返回成員詳情</returns>
        public static string GetUserList(string userid)
        {
            string url = string.Format("https://oapi.dingtalk.com/user/get?access_token={0}&userid={1}", GetAccessToken(), userid);

            string result = HttpGet(url, "");
            return result;
        }
        #endregion

        #region 獲取管理員列表(已測試)
        public class UserGetadmin
        {
            public long department_id { get; set; }

        }
        /// <summary>
        /// 獲取部門成員
        /// </summary>
        /// <param name="department_id">獲取的部門id</param>
        /// <returns></returns>
        public static string simplelist(long department_id)
        {
            string url = string.Format("https://oapi.dingtalk.com/user/simplelist?access_token={0}&department_id={1}", GetAccessToken(), department_id);

            string result = HttpGet(url, "");
            return result;
        }
        #endregion

        #region 獲取部門成員詳情(已測試)
        public class UserListModel
        {
            public long department_id { get; set; }
            public long offset { get; set; }
            public int size { get; set; }

        }
        /// <summary>
        ///  獲取部門成員詳情
        /// </summary>
        /// <param name="department_id">獲取的部門id</param>
        /// <param name="offset"> 支援分頁查詢,與size引數同時設定時才生效,此引數代表偏移量</param>
        /// <param name="size">支援分頁查詢,與offset引數同時設定時才生效,此引數代表分頁大小,最大100</param>
        /// <returns></returns>
        public static string GetUserabout(long department_id, long offset, int size)
        {
            string url = string.Format("https://oapi.dingtalk.com/user/list?access_token={0}&department_id={1}&offset={2}&size={3}", GetAccessToken(), department_id, offset, size);


            string result = HttpGet(url, "");
            return result;
        }
        #endregion

        #region 獲取部門詳情(已測試)
        public class department
        {
            public string id { get; set; }

        }
        /// <summary>
        /// 獲取部門詳情
        /// </summary>
        /// <param name="id">部門id</param>
        /// <returns></returns>
        public static string Getdepartment(string id)
        {
            string url = string.Format("https://oapi.dingtalk.com/department/get?access_token={0}&id={1}", GetAccessToken(), id);

            string result = HttpGet(url, "");
            return result;
        }
        #endregion

        #region 建立部門(已測試)
        public class Createdepartment
        {
            public string name { get; set; }

            public string parentid { get; set; }

        }
        /// <summary>
        /// 建立部門
        /// </summary>
        /// <param name="name">部門名稱</param>
        /// <param name="parentid">父部門id,根部門為1</param>
        /// <returns>id建立的部門id</returns>
        public static string Getdepartment(string name, string parentid)
        {
            string url = string.Format("https://oapi.dingtalk.com/department/create?access_token={0}", GetAccessToken());
            var msgModel = new Createdepartment
            {
                name = name,
                parentid = parentid

            };
            var dataStr = JsonConvert.SerializeObject(msgModel);
            string result = HttpPost(url, dataStr);
            return result;
        }
        #endregion

        #region 刪除部門(已測試)
        public class DeletedepartmentM
        {
            public long id { get; set; }
        }
        /// <summary>
        /// 刪除部門
        /// </summary>
        /// <param name="id">部門id。(注:不能刪除根部門;不能刪除含有子部門、成員的部門)</param>
        /// <returns></returns>
        public static string Deletedepartment(long id)
        {
            string url = string.Format("https://oapi.dingtalk.com/department/delete?access_token={0}&id={1}", GetAccessToken(), id);


            string result = HttpGet(url, "");
            return result;
        }
        #endregion

        #region 查詢部門的所有上級父部門路徑(已測試)
        public class SearchHdepartmentM
        {
            public long id { get; set; }
        }
        /// <summary>
        /// 查詢部門的所有上級父部門路徑
        /// </summary>
        /// <param name="id">部門id。(注:不能刪除根部門;不能刪除含有子部門、成員的部門)</param>
        /// <returns>parentIds該部門的所有父部門id列表</returns>
        public static string SearchHdepartment(long id)
        {
            string url = string.Format("https://oapi.dingtalk.com/department/list_parent_depts_by_dept?access_token={0}&id={1}", JTToken, id);

            string result = HttpGet(url, "");
            return result;
        }
        #endregion

        #region 查詢指定使用者的所有上級父部門路徑(已測試)
        public class SearchUdepartmentM
        {
            public string userId { get; set; }
        }
        /// <summary>
        /// 查詢指定使用者的所有上級父部門路徑
        /// </summary>
        /// <param name="userId">希望查詢的使用者的id</param>
        /// <returns> parentIds 該部門的所有父部門id列表 </returns>
        public static string SearchUdepartment(string userId)
        {
            string url = string.Format("https://oapi.dingtalk.com/department/list_parent_depts?access_token={0}&userId={1}", GetAccessToken(), userId);

            string result = HttpGet(url, "");
            return result;
        }
        #endregion

        #region 獲取企業員工人數(已測試)
        public class GetUserCountM
        {
            public int onlyActive { get; set; }
        }
        /// <summary>
        /// 獲取企業員工人數
        /// </summary>
        /// <param name="id">部門id。(注:不能刪除根部門;不能刪除含有子部門、成員的部門)</param>
        /// <returns>count 企業員工數量 </returns>
        public static string GetUserCount(int onlyActive)
        {
            string url = string.Format("https://oapi.dingtalk.com/user/get_org_user_count?access_token={0}&onlyActive={1}", GetAccessToken(), onlyActive);

            string result = HttpGet(url, "");
            return result;
        }
        #endregion

        #region 獲取最近4天考勤打卡資料(已測試)
        public class AttendanceModel
        {
            public string userId { get; set; }
            public string workDateFrom { get; set; }
            public string workDateTo { get; set; }
            //public string[] useridlist { get; set; }

        }

        public static string Attendance(string UserID, DateTime StarTime, DateTime EndTime)
        {

            string url = string.Format("https://oapi.dingtalk.com/attendance/list?access_token={0}", GetAccessToken());
            var msgModel = new AttendanceModel
            {
                workDateFrom = Convert.ToString(StarTime).Replace("/", "-"),
                workDateTo = EndTime.ToString().Replace("/", "-"),
                userId = UserID,
            };

            var dataStr = JsonConvert.SerializeObject(msgModel);
            string result = HttpPost(url, dataStr);
            return result;

        }
        #endregion

        #region 傳入釘釘Id 給人員 發訊息
        /// <summary>
        /// 釘釘發訊息
        /// </summary>
        /// <param name="UserId">釘釘Id</param>
        /// <param name="title">標題</param>
        /// <param name="Content">內容</param>
        /// <returns></returns>
        public static string DingMessage(string UserId, string title, string Content)
        {
            string result = SendMessagemarkdown("132516265", UserId, title, Content);
            Message token = JsonConvert.DeserializeObject<Message>(result);            
            return token.errcode+";"+token.errmsg;
        }
        #endregion

        #region 以微應用的形式通知到個人(一天50條,內容不能重複,此介面有限流政策具體內容請參考官網)(已測試)
        /// <summary>
        /// 以微應用的形式通知到個人
        /// </summary>
        /// <param name="agentid">企業應用id,這個值代表以哪個應用的名義傳送訊息</param>
        /// <param name="touser">員工id列表(訊息接收者,多個接收者用|分隔)</param>
        /// <param name="title">標題</param>
        /// <param name="text">內容</param>
        /// <returns>messageId 標識企業訊息的id,字串,最長128個字元 </returns>       
        public static string SendMessagemarkdown(string agentid, string touser, string title, string text)
        {
            string url = string.Format("https://oapi.dingtalk.com/message/send?access_token={0}", JTToken);
            var msgModel = new TextMsgModelmarkdown
            {
                agentid = agentid,
                //Toparty = "32760351"
                touser = touser,
                msgtype = "markdown",
                markdown = new markdown()
                {
                    title = title,
                    text = text
                },
            };
            var dataStr = JsonConvert.SerializeObject(msgModel);
            string result = Core.Utils.HttpPost(url, dataStr);
            return result;
        }
        #endregion

        #region 測試 擴充套件發企業通知
        //public static string TestFXX()
        //{
        //    IDingTalkClient client = new DefaultDingTalkClient("https://eco.taobao.com/router/rest");
        //    CorpMessageCorpconversationAsyncsendRequest req = new CorpMessageCorpconversationAsyncsendRequest();
        //    req.Msgtype = "text";
        //    req.AgentId = 132516265;
        //    req.UseridList = "142558190626104277";
        //    req.DeptIdList = "58109347";
        //    req.ToAllUser = false;
        //    req.Msgcontent = "{\"message_url\": \"\",\"head\": {\"bgcolor\": \"FFBBBBBB\",\"text\": \"頭部標題\"},\"body\": {\"title\": \"正文標題\",\"form\": [{\"key\": \"姓名:\",\"value\": \"張三\"},{\"key\": \"愛好:\",\"value\": \"打球、聽音樂\"}],\"rich\": {\"num\": \"15.6\",\"unit\": \"元\"},\"content\": \"大段文字大段文字大段文字大段文字大段文字大段文字大段文字大段文字大段文字大段文字大段文字大段文字\",\"image\": \"\",\"file_count\": \"3\",\"author\": \"李四 \"}}";
        //    CorpMessageCorpconversationAsyncsendResponse rsp = client.Execute(req, JTToken);
        //    //Console.WriteLine(rsp.Body);
        //    return rsp.Body;
        //}
        #endregion

        #region 獲取企業通知訊息已讀未讀狀態(已測試)
        public class list_message_statusM
        {

            public string messageId { get; set; }


        }
        /// <summary>
        /// 獲取企業通知訊息已讀未讀狀態
        /// </summary>
        /// <param name="messageId">訊息id</param>
        /// <returns>read 已讀人員 unread 未讀人員</returns>
        public static string list_message_status(string messageId)
        {
            string url = string.Format("https://oapi.dingtalk.com/message/list_message_status?access_token={0}", GetAccessToken());
            var msgModel = new list_message_statusM
            {
                messageId = messageId,

            };
            var dataStr = JsonConvert.SerializeObject(msgModel);
            string result = Core.Utils.HttpPost(url, dataStr);
            return result;
        }
        #endregion

        #region 建立微應用(已測試)
        public class CreatemicroappM
        {
            public string appIcon { get; set; }
            public string appName { get; set; }
            public string appDesc { get; set; }
            public string homepageUrl { get; set; }
            public string pcHomepageUrl { get; set; }
            public string ompLink { get; set; }
            //public string[] useridlist { get; set; }

        }
        /// <summary>
        /// 建立微應用
        /// </summary>
        /// <param name="appIcon">微應用的圖示。需要呼叫上傳介面將圖示上傳到釘釘伺服器後獲取到的mediaId</param>
        /// <param name="appName">微應用的名稱。長度限制為1~10個字元</param>
        /// <param name="appDesc">微應用的描述。長度限制為1~20個字元</param>
        /// <param name="homepageUrl">微應用的移動端主頁,必須以http開頭或https開頭</param>
        /// <param name="ompLink">微應用的OA後臺管理主頁,必須以http開頭或https開頭 可不填</param>
        /// <param name="pcHomepageUrl">微應用的PC端主頁,必須以http開頭或https開頭,如果不為空則必須與homepageUrl的域名一致 可不填</param>
        /// <returns>id 建立的微應用id</returns>
        public static string Createmicroapp(string appIcon, string appName, string appDesc, string homepageUrl, string ompLink, string pcHomepageUrl)
        {
            string url = string.Format("https://oapi.dingtalk.com/microapp/create?access_token={0}", GetAccessToken());
            var msgModel = new CreatemicroappM
            {
                appIcon = appIcon,
                appName = appName,
                appDesc = appDesc,
                homepageUrl = homepageUrl,
                ompLink = ompLink,
                pcHomepageUrl = pcHomepageUrl
            };
            var dataStr = JsonConvert.SerializeObject(msgModel);
            string result = Core.Utils.HttpPost(url, dataStr);
            return result;
        }
        #endregion

        #region 獲取通訊錄許可權(已測試)


        public static string Scopes()
        {
            string url = string.Format("https://oapi.dingtalk.com/auth/scopes?access_token={0}", GetAccessToken());
            string result = Core.Utils.HttpGet(url, "");
            return result;
        }
        #endregion

        #region 自定義機器人@人(已測試)

        public class RobotSentM
        {

            public string content { get; set; }

            public bool isAtAll { get; set; }
            public string msgtype { get; set; }
            public at at { get; set; }
            public text text { get; set; }
        }
        public class at
        {
            public string[] atMobiles { get; set; }

        }
        /// <summary>
        /// 自定義機器人@人
        /// </summary>
        /// <param name="content">訊息內容</param>
        /// <param name="atMobiles">被@人的手機號</param>
        /// <param name="isAtAll">@所有人時:true,否則為:false</param>
        /// <param name="url">在機器人管理頁面獲取webhook</param>
        /// <returns></returns>
        public static string RobotSent(string content, string[] atMobiles, bool isAtAll, string webhook)
        {

            var msgModel = new RobotSentM
            {
                msgtype = "text",

                isAtAll = isAtAll,
                text = new text()
                {
                    content = content
                },
                at = new at()
                {
                    atMobiles = atMobiles,
                }
            };
            var dataStr = JsonConvert.SerializeObject(msgModel);
            string result = HttpPost(webhook, dataStr);
            return result;
        }
        #endregion

        #region 上傳媒體檔案(圖片 1MB支援jpg格式 語音 2MB不超過60s AMR格式 普通檔案 10MB)(已測試)

        public class UploadMediaRequestModel
        {

            public string FileName { get; set; }
            public string multipart { get; set; }
            public string type { get; set; }
        }
        public class uploadmediaG
        {

            public string media_id { get; set; }

            public string type { get; set; }
            public string created_at { get; set; }
        }
        /// <summary>
        /// 上傳媒體檔案
        /// </summary>
        /// <param name="FileName">位置Server.MapPath("~/Content/images/1505888395.png")</param>
        /// <param name="MediaType">型別</param>
        /// <returns>media_id 媒體檔案上傳後獲取的唯一標識  type 媒體檔案型別,分別有圖片(image)、語音(voice)、普通檔案(file) created_at 媒體檔案上傳時間戳</returns>
        public static string uploadmedia(string FileName, string type)
        {
            string url = string.Format("https://oapi.dingtalk.com/media/upload?access_token={0}&type={1}", GetAccessToken(), type);


            string result = PostFile(url, FileName);
            uploadmediaG token = JsonConvert.DeserializeObject<uploadmediaG>(result);

            return result;
        }
        #endregion

        #region 獲取媒體檔案(已測試)
        public class downloadFileM
        {
            public string media_id { get; set; }

        }
        /// <summary>
        /// 獲取媒體檔案
        /// </summary>
        /// <param name="media_id">媒體檔案的唯一標示</param>
        /// <param name="Address">下載地址</param>
        /// <returns></returns>
        public static string downloadFile(string media_id, string Address)
        {

            string url = string.Format("https://oapi.dingtalk.com/media/downloadFile?access_token={0}&media_id={1}", JTToken, media_id);

            string result = HttpGet(url, "");
            WebClient clint = new WebClient();
            clint.DownloadFile(url, Address);
            if (File.Exists(Address))
                return "{\"errcode\": 0,\"errmsg\": \"ok\"}";
            else
            {
                return result;
            }

        }
        #endregion

        #region 傳送檔案給指定使用者(已測試)
        public class SendFileM
        {
            public string agentid { get; set; }
            public string touser { get; set; }
            public string msgtype { get; set; }
            public file file { get; set; }
        }

        public class file
        {
            public string media_id { get; set; }

        }
        /// <summary>
        /// 傳送檔案給指定使用者
        /// </summary>
        /// <param name="agentid">企業應用id,這個值代表以哪個應用的名義傳送訊息</param>
        /// <param name="touser">員工id列表(訊息接收者,多個接收者用|分隔)</param>
        /// <param name="media_id">媒體檔案Id</param>
        /// <returns></returns>
        public static string SendFile(string agentid, string touser, string media_id)
        {

            //media_id = System.Web.HttpUtility.UrlEncode(media_id);
            //file_name = System.Web.HttpUtility.UrlEncode(file_name);
            string url = string.Format("https://oapi.dingtalk.com/message/send?access_token={0}", JTToken);
            var msgmodel = new SendFileM()
            {
                agentid = agentid,
                touser = touser,
                msgtype = "file",

                file = new file()
                {
                    media_id = media_id
                }

            };

            var datastr = JsonConvert.SerializeObject(msgmodel);
            string result = HttpPost(url, datastr);

            return result;
        }
        #endregion

        #region 單步檔案上傳(已測試)

        public class singleM
        {

            public string media_id { get; set; }


        }
        /// <summary>
        /// 上傳媒體檔案
        /// </summary>
        /// <param name="FileName">位置Server.MapPath("~/Content/images/1505888395.png")</param>
        /// <param name="MediaType">型別</param>
        /// <returns>media_id 媒體檔案上傳後獲取的唯一標識  type 媒體檔案型別,分別有圖片(image)、語音(voice)、普通檔案(file) created_at 媒體檔案上傳時間戳</returns>
        public static string single(string FileName, string agent_id, int file_size)
        {
            string url = string.Format("https://oapi.dingtalk.com/file/upload/single?access_token={0}&agent_id={1}&file_size={2}", JTToken, agent_id, file_size);


            string result = PostFile(url, FileName);
            uploadmediaG token = JsonConvert.DeserializeObject<uploadmediaG>(result);

            return result;
        }
        #endregion



    }
   
    class GetUserInfoModel
    {
        public string userid { get; set; }

        public string deviceId { get; set; }

        public string is_sys { get; set; }

        public string sys_level { get; set; }

        internal string errcode { get; set; }

    }
}