using DingTalk.Api; using DingTalk.Api.Request; using DingTalk.Api.Response; using HH.WCS.Hexafluo; using HH.WCS.Hexafluo.util; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Security.Cryptography; using System.Text; namespace HanHe.Message { public class DingTalk { private static string accessToken; private static long agentId = 3102234123; private static string appKey = "dingexkbjfylqdmj4o7q"; private static string appSecret = "L4c4hvobmpucyiYyHrY_f0L1xMMhJDsXcAOaQ88orLlEG4ENC-MN-9M5en1DODCb"; private static DateTime expiresIn = DateTime.Now; private static List department = new List(); private static List userlist = new List(); private static bool param = false; //public static bool Init(long agentId, string appKey, string appSecret) //{ // if (agentId > 0 && !string.IsNullOrEmpty(appKey) && !string.IsNullOrEmpty(appSecret)) // { // DingTalk.agentId = agentId; // DingTalk.appKey = appKey; // DingTalk.appSecret = appSecret; // if (!GetToken()) // { // DingTalk.agentId = 0; // DingTalk.appKey = ""; // DingTalk.appSecret = ""; // } // else // { // return true; // } // } // return false; //} public static bool InitTest(long agentId, string appKey, string appSecret) { if (agentId > 0 && !string.IsNullOrEmpty(appKey) && !string.IsNullOrEmpty(appSecret)) { return GetToken(appKey, appSecret, false); } return false; } /// /// 获取所有部门名称 /// /// public static List GetDepartment() { List names = new List(); if (department.Count > 0) { department.ForEach(d => names.Add(d.Name)); } return names; } /// /// 根据部门名称发送消息 /// /// 部门名称 /// 消息内容 /// public static MessageResult SendMessageToParty(string deptName, string content) { MessageResult result = new MessageResult(); if (string.IsNullOrEmpty(accessToken)) { result.Errcode = -1; result.Errmsg = "不合法的token"; } else { //获取部门id var deptId = CheckDepartment(deptName); if (deptId == "0") { result.Errcode = -2; result.Errmsg = "不存在的部门"; } else { result = SendMessage(deptId, content, true); } } return result; } public static MessageResult SendMessageToUser(string userName, string content) { MessageResult result = new MessageResult(); if (string.IsNullOrEmpty(accessToken)) { result.Errcode = -1; result.Errmsg = "不合法的token"; } else { //获取人员id var userId = CheckUser(userName); if (userId == "0") { result.Errcode = -2; result.Errmsg = "不存在的人员"; } else { result = SendMessage(userId, content, false); } } return result; } #region 内部方法 private static bool GetToken(string appKey = "", string appSecret = "", bool init = true) { if (string.IsNullOrEmpty(appKey)) { appKey = DingTalk.appKey; } if (string.IsNullOrEmpty(appSecret)) { appSecret = DingTalk.appSecret; } DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken"); OapiGettokenRequest request = new OapiGettokenRequest(); request.Appkey = appKey; request.Appsecret = appSecret; request.SetHttpMethod("GET"); OapiGettokenResponse response = client.Execute(request); if (response.Errcode == 0) { //40089 不合法的corpid或corpsecret if (init) { param = true; accessToken = response.AccessToken; ListDepartment(); ListUser(); } return true; } return false; } /// /// 获取部门列表 /// /// 父Id private static void ListDepartment(string id = "") { IDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/department/list"); OapiDepartmentListRequest request = new OapiDepartmentListRequest(); request.Id = id; request.FetchChild = true; request.SetHttpMethod("GET"); OapiDepartmentListResponse response = client.Execute(request, accessToken); if (response.Errcode == 0) { //40014 不合法的access_token department = response.Department; } else { LogHelper.Info("钉钉", response.Errmsg); } } /// /// 根据部门名称获取部门id /// /// private static string CheckDepartment(string deptName) { string id = "0"; if (string.IsNullOrEmpty(deptName)) { if (department.Count > 0) { var list = department.Where(a => a.Parentid == 1).ToList(); if (list.Count > 0) { id = string.Join(",", list.Select(a => a.Id.ToString()).ToArray()); } } } else { if (department.Count > 0) { for (int i = 0; i < department.Count; i++) { if (department[i].Name == deptName) { id = department[i].Id.ToString(); break; } } } } return id; } private static string CheckUser(string userName) { string id = "0"; if (userlist.Count > 0) { for (int i = 0; i < userlist.Count; i++) { if (userlist[i].Name == userName) { id = userlist[i].Userid; break; } } } return id; } private static MessageResult SendMessage(string id, string content, bool party) { OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request(); request.AgentId = agentId; request.ToAllUser = false; if (party) { request.DeptIdList = id;//123,456 } else { request.UseridList = id;//zhangsan,lisi } OapiMessageCorpconversationAsyncsendV2Request.MsgDomain msg = new OapiMessageCorpconversationAsyncsendV2Request.MsgDomain(); msg.Msgtype = "text"; msg.Text = new OapiMessageCorpconversationAsyncsendV2Request.TextDomain() { Content = content }; request.Msg_ = msg; return SendMessage(request); //response.Errcode=88 ding talk error[subcode=40014,submsg=不合法的access_token] } private static MessageResult SendMessage(OapiMessageCorpconversationAsyncsendV2Request request) { IDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2"); OapiMessageCorpconversationAsyncsendV2Response response = client.Execute(request, accessToken); if (response.Errcode == 88 && DingTalk.param) { //token过期 if (GetToken()) { return SendMessage(request); } } return new MessageResult { Errcode = response.Errcode, Errmsg = response.Errmsg }; } public static void GetSendProgress(long taskId = 23017959620) { IDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/message/corpconversation/getsendprogress"); OapiMessageCorpconversationGetsendprogressRequest request = new OapiMessageCorpconversationGetsendprogressRequest(); request.AgentId = agentId; request.TaskId = taskId; OapiMessageCorpconversationGetsendprogressResponse response = client.Execute(request, accessToken); } private static void GetDeptMember(string deptId) { IDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/getDeptMember"); OapiUserGetDeptMemberRequest req = new OapiUserGetDeptMemberRequest(); req.DeptId = deptId;//93688589 req.SetHttpMethod("GET"); OapiUserGetDeptMemberResponse rsp = client.Execute(req, accessToken); } private static void ListUser() { var list = new List(); department.ForEach(d => { if (d.Id > 1) { list.AddRange(Simplelist(d.Id)); } }); userlist = list.Distinct(new UserIdComparer()).ToList(); } private static List Simplelist(long deptId) { var list = new List(); IDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/simplelist"); OapiUserSimplelistRequest request = new OapiUserSimplelistRequest(); request.DepartmentId = deptId; request.Offset = 0; request.Size = 50; request.SetHttpMethod("GET"); OapiUserSimplelistResponse response = client.Execute(request, accessToken); //60020 访问ip不在白名单之中,request ip=117.71.57.100 if (response.Errcode == 0) { //response.HasMore list.AddRange(response.Userlist); while (response.HasMore) { request.Offset += 50; response = client.Execute(request, accessToken); if (response.Errcode == 0) { list.AddRange(response.Userlist); } } } return list; } #endregion } public class UserIdComparer : IEqualityComparer { public bool Equals(OapiUserSimplelistResponse.UserlistDomain x, OapiUserSimplelistResponse.UserlistDomain y) { if (x == null) return y == null; return x.Userid == y.Userid; } public int GetHashCode(OapiUserSimplelistResponse.UserlistDomain obj) { if (obj == null) return 0; return obj.Userid.GetHashCode(); } } public class MessageResult { public long Errcode { get; set; } public string Errmsg { get; set; } } public class DingDingHelper { private static readonly HttpHelper apiHelper = new HttpHelper(); string appkey = "dingitwnepteor0s0ywq"; string appsecret = "6_jqU2EZYdfzz2Vx08PoOIsM3V3zWrQeNi3BkAP37pKMsWChJbRpxcWTaued_BhZ"; string agentid = "3102306110";// string corpId = "";//企业号 string AccessToken = String.Empty; #region 通过免登授权码和access_token获取用户的userid public string GetUserIdByCode(string code) { GetToken(); if (string.IsNullOrWhiteSpace(AccessToken) || string.IsNullOrWhiteSpace(code)) return ""; try { string AccessUrl = string.Format("https://oapi.dingtalk.com/user/getuserinfo?access_token={0}&code={1}", AccessToken, code); //请求获取token GET方式 Newtonsoft.Json.Linq.JToken json = Newtonsoft.Json.Linq.JToken.Parse(apiHelper.Get(AccessUrl, null)); return json["userid"].ToString(); } catch (Exception ex) { return ""; } } #endregion #region 根据手机号获取用户id /// /// 根据手机号获取用户id /// /// 用户手机号 /// public string GetUserIdByPhoneNumber(string phoneNumber) { GetToken(); if (string.IsNullOrWhiteSpace(AccessToken) || string.IsNullOrWhiteSpace(phoneNumber)) return ""; string MessageUrl = String.Format("https://oapi.dingtalk.com/user/get_by_mobile?access_token={0}&mobile={1}", AccessToken, phoneNumber); try { var sr = apiHelper.Get(MessageUrl, null); //Newtonsoft.Json.Linq.JToken json = Newtonsoft.Json.Linq.JToken.Parse(sr); return sr;// json["userid"].ToString(); } catch (Exception ex) { return ""; } } #endregion #region 根据用户id获取用户详细信息 /// /// 根据用户id获取用户详细信息 /// /// 用户id /// public string GetUseInfoByUid(string userid) { GetToken(); if (string.IsNullOrWhiteSpace(AccessToken) || string.IsNullOrWhiteSpace(userid)) return ""; try { string AccessUrl = string.Format("https://oapi.dingtalk.com/user/get?access_token={0}&userid={1}", AccessToken, userid); //请求获取token GET方式 return apiHelper.Get(AccessUrl, null); } catch (Exception ex) { return ""; } } #endregion #region 获取TOKEN public void GetToken() { if (string.IsNullOrWhiteSpace(AccessToken)) { string AccessUrl = string.Format("https://oapi.dingtalk.com/gettoken?appkey={0}&appsecret={1}", appkey, appsecret); //请求获取token GET方式 Newtonsoft.Json.Linq.JToken json = Newtonsoft.Json.Linq.JToken.Parse(apiHelper.Get(AccessUrl, null)); AccessToken = json["access_token"].ToString(); } } #endregion #region 消息推送 /// /// 文本消息推送(Text格式) /// /// 推送内容 /// 用户id,多个用户用,隔开(如:123,456) public string SendTextMessageToUser(string text, string userid_list) { GetToken(); if (string.IsNullOrWhiteSpace(AccessToken) || string.IsNullOrWhiteSpace(text) || string.IsNullOrWhiteSpace(userid_list)) return ""; string MessageUrl = String.Format("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2?access_token={0}", AccessToken); var json_req = SendCommonText(text, userid_list); //var json_req = SendCommonTextAndTitle("销售订单管理系统", content.ToString(), txtusesid.Text); //var json_req = SendCardMsg("销售订单管理系统", content.ToString(), "查看详情", "https://ding-doc.dingtalk.com/", txtusesid.Text); string jsonRequest = JsonConvert.SerializeObject(json_req);//将对象转换为json //POST请求 消息推送 var sr = apiHelper.Post(MessageUrl, jsonRequest); return sr; } /// /// 文本消息推送(MarkDown格式) /// /// 提醒用户的标题 /// 提醒内容(支持markdown文本解析) /// 用户id,多个用户用,隔开(如:123,456) /// public string SendMarkDownMessageToUser(string title, string text, string userid_list) { GetToken(); if (string.IsNullOrWhiteSpace(AccessToken) || string.IsNullOrWhiteSpace(text) || string.IsNullOrWhiteSpace(userid_list)) return ""; string MessageUrl = String.Format("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2?access_token={0}", AccessToken); //var json_req = SendCommonText(text, userid_list); var json_req = SendCommonTextAndTitle(title, text, userid_list); //var json_req = SendCardMsg("销售订单管理系统", content.ToString(), "查看详情", "https://ding-doc.dingtalk.com/", txtusesid.Text); string jsonRequest = JsonConvert.SerializeObject(json_req);//将对象转换为json //POST请求 消息推送 var sr = apiHelper.Post(MessageUrl, jsonRequest); return sr; } /// /// 文本消息推送(MarkDown格式) /// /// 提醒用户的标题 /// 提醒内容(支持markdown文本解析) /// 链接文本 /// 链接地址 /// 用户id,多个用户用,隔开(如:123,456) /// public string SendActionCardMessageToUser(string title, string text, string linkText, string linkUrl, string userid_list) { GetToken(); if (string.IsNullOrWhiteSpace(AccessToken) || string.IsNullOrWhiteSpace(text) || string.IsNullOrWhiteSpace(userid_list)) return ""; string MessageUrl = String.Format("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2?access_token={0}", AccessToken); var json_req = SendCardMsg(title, text, linkText, linkUrl, userid_list); string jsonRequest = JsonConvert.SerializeObject(json_req);//将对象转换为json //POST请求 消息推送 var sr = apiHelper.Post(MessageUrl, jsonRequest); return sr; } #endregion #region 推送消息类型 /// /// 推送普通文本内容 /// /// /// /// public object SendCommonText(string content, string usesid) { return new { userid_list = usesid, //接受推送userid,不同用户用|分割 //dept_id_list = "127577105", //接受推送部门id agent_id = agentid,//应用Id to_all_user = "true", msg = new { msgtype = "text", text = new { content = content.ToString() }//内容text } }; } /// /// 推送markdown内容 /// /// /// /// /// public object SendCommonTextAndTitle(string _title, string _content, string usesid) { return new { userid_list = usesid, //接受推送userid,不同用户用|分割 dept_id_list = "", //接受推送部门id agent_id = agentid,//应用Id msg = new { msgtype = "markdown",//推送类型 markdown = new { title = _title, text = _content//内容text } } }; } /// /// 推送action_card格式内容 /// /// 标题 /// 内容 /// 链接标题 /// 链接地址 /// /// public object SendCardMsg(string _title, string _content, string _single_title, string _single_url, string usesid) { return new { userid_list = usesid, //接受推送userid,不同用户用|分割 //dept_id_list = "", //接受推送部门id agent_id = agentid,//应用Id msg = new { msgtype = "action_card", action_card = new { title = _title,//提示信息 markdown = _content, single_title = _single_title, single_url = _single_url } } }; } #endregion #region 群机器人 推送消息 static void SendMarkdownMessage(string webhookUrl, string accessToken, string secret, string title, string markdownContent, string phone) { long timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds(); string sign = ComputeSignature(secret, timestamp); string url = $"{webhookUrl}?access_token={accessToken}×tamp={timestamp}&sign={sign}"; using (HttpClient client = new HttpClient()) { List Mobiles = new List() { phone }; var pay = new { at = new { atMobiles = Mobiles, isAtAll = false }, msgtype = "text", text = new { content = markdownContent } }; var payload = new { msgtype = "text", text = new { content = markdownContent } }; //string jsonPayload = Newtonsoft.Json.JsonConvert.SerializeObject(payload); string jsonPayload = Newtonsoft.Json.JsonConvert.SerializeObject(pay); var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); var response = apiHelper.Post(url, jsonPayload); LogHelper.DanInfo("钉钉通知", "返回" + response); } } static void SendMarkdownMessageItem(string webhookUrl, string accessToken, string secret, string title, string markdownContent, string phone) { long timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds(); string sign = ComputeSignature(secret, timestamp); string url = $"{webhookUrl}?access_token={accessToken}×tamp={timestamp}&sign={sign}"; using (HttpClient client = new HttpClient()) { List Mobiles = new List() { phone }; var pay = new { msgtype = "markdown", markdown = new { title = $"&立库物料统计信息推送 \n\n 时间:{DateTime.Now.ToString()}", text = markdownContent } }; //string jsonPayload = Newtonsoft.Json.JsonConvert.SerializeObject(payload); string jsonPayload = Newtonsoft.Json.JsonConvert.SerializeObject(pay); var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); var response = apiHelper.Post(url, jsonPayload); LogHelper.DanInfo("钉钉通知", "返回" + response); } } static string ComputeSignature(string secret, long timestamp) { string stringToSign = $"{timestamp}\n{secret}"; byte[] secretBytes = Encoding.UTF8.GetBytes(secret); byte[] stringToSignBytes = Encoding.UTF8.GetBytes(stringToSign); using (var hmac = new HMACSHA256(secretBytes)) { byte[] hashBytes = hmac.ComputeHash(stringToSignBytes); return Convert.ToBase64String(hashBytes); } } /// /// 钉钉通知 /// /// 发送的内容 /// 手机账号(非必填) public void button1_Click(string JqrValue = "", string phone = "") { LogHelper.DanInfo("钉钉通知", JqrValue); string webhookUrl = "https://oapi.dingtalk.com/robot/send"; string accessToken = "649df1073bd448eb79aefb47dd2230d0dd473e956b180043fed2b6bb375230dc"; string secret = "SECb92cff4f862c0d5a40b2f523c8129f8f5552774e8bdd1e37d01577a1488812cc"; string markdownContent = JqrValue; string title = "Markdown Message"; SendMarkdownMessage(webhookUrl, accessToken, secret, title, markdownContent, phone); } public void button1_ClickItem(string JqrValue = "", string phone = "") { LogHelper.DanInfo("钉钉通知", JqrValue); string webhookUrl = "https://oapi.dingtalk.com/robot/send"; string accessToken = "142c5e3f2b3fe25a12ccf2407338b85cad03684dc4c748eb68547e6e1e163503"; string secret = "SECb18f01af065d707d9e35568f0212ae7f6a49cf58a0e426fe42f94d5194af769f"; string markdownContent = JqrValue; string title = "Markdown Message"; SendMarkdownMessageItem(webhookUrl, accessToken, secret, title, markdownContent, phone); } #endregion } }