企业微信消息推送通用类(仅Text、Markdown、Image、News类型实现,功能完善中)

  1 using xxx.Core.Entity;
  2 using Newtonsoft.Json;
  3 using Newtonsoft.Json.Linq;
  4 using System;
  5 using System.Collections.Generic;
  6 using System.Configuration;
  7 using System.Data;
  8 using System.IO;
  9 using System.Net;
 10 using System.Net.Http;
 11 using System.Text;
 12 using TianYuan.Data.Dapper.Repositories;
 13 
 14 namespace xxx.Common
 15 {
 16     /// <summary>
 17     /// 企微接口调用通用类
 18     /// </summary>
 19     public class WXWorkHelper
 20     {
 21         #region private
 22 
 23         //获取token方法名
 24         const string accessTokenMethod = "/cgi-bin/gettoken";
 25         //发送消息方法名
 26         const string sendMessageMethod = "/cgi-bin/message/send";
 27         //上传方法,支持类型包括图片(image)、语音(oice)、视频(video)、普通文件(file)
 28         const string uploadMethod = "/cgi-bin/media/upload";
 29 
 30         //接口地址
 31         private string apiUrl = "";
 32         //企业应用ID
 33         private string agentId = "";
 34         private string corpId = "";
 35         private string corpSecret = "";
 36 
 37         /// <summary>
 38         /// 兼容多应用
 39         /// </summary>
 40         public WXWorkHelper(AppNameEnum appName)
 41         {
 42             try
 43             {
 44                 //配置信息从数据库中获取
 45                 string sql = "select a.ApiUrl,a.AgentId,a.CorpId,a.CorpSecret from xxx a,yyy b where a.AppId=b.Id and b.AppCode='"+ (int)appName +"'";
 46                 DataTable dt = MySqlHelper.ExecuteDataTable(sql);
 47                 if(dt == null | dt.Rows.Count == 0)
 48                 {
 49                     apiUrl = ConfigurationManager.AppSettings["WXWorkAPIUrl"].ToString();
 50                     agentId = ConfigurationManager.AppSettings["WXWorkAgentId"].ToString();
 51                     corpId = ConfigurationManager.AppSettings["WXWorkCorpId"].ToString();
 52                     corpSecret = ConfigurationManager.AppSettings["WXWorkCorpSecret"].ToString();
 53                 }
 54                 else
 55                 {
 56                     apiUrl = dt.Rows[0]["ApiUrl"].ToString();
 57                     agentId = dt.Rows[0]["AgentId"].ToString();
 58                     corpId = dt.Rows[0]["CorpId"].ToString();
 59                     corpSecret = dt.Rows[0]["CorpSecret"].ToString();
 60                 }
 61             }
 62             catch(Exception ex)
 63             {
 64 
 65             }
 66         }
 67 
 68         #endregion
 69 
 70         #region Send Notification
 71 
 72         /// <summary>
 73         /// 发送Text类消息
 74         /// </summary>
 75         /// <param name="userIdList"></param>
 76         /// <param name="messageContent"></param>
 77         public bool SendTextNotification(string userIdList, string messageContent)
 78         {
 79             return SendNotification(GetBody(MsgTypeEnum.Text, userIdList, messageContent));
 80         }
 81 
 82         /// <summary>
 83         /// 发送Markdown类消息
 84         /// </summary>
 85         /// <param name="userIdList"></param>
 86         /// <param name="messageContent"></param>
 87         public bool SendMarkdownNotification(string userIdList, string messageContent)
 88         {
 89             return SendNotification(GetBody(MsgTypeEnum.Markdown, userIdList, messageContent));
 90         }
 91 
 92         /// <summary>
 93         /// 发送Image类消息
 94         /// </summary>
 95         /// <param name="userIdList"></param>
 96         /// <param name="messageContent"></param>
 97         /// <param name="messageContent"></param>
 98         public bool SendImageNotification(string userIdList, string fileName, byte[] bytes)
 99         {
100             bool isSuccess = false;
101 
102             try
103             {
104                 //获取Token
105                 string accessToken = GetAccessToken();
106                 //上传临时素材
107                 string mediaId = Upload(MediaTypeEnum.image, fileName, bytes, accessToken);
108 
109                 if (mediaId != "")
110                 {
111                     return SendNotification(GetBody(MsgTypeEnum.Image, userIdList, mediaId));
112                 }
113             }
114             catch (Exception ex)
115             {
116 
117             }
118 
119             return isSuccess;
120         }
121 
122         /// <summary>
123         /// 发送News类消息
124         /// </summary>
125         /// <param name="userIdList"></param>
126         /// <param name="list"></param>
127         public bool SendNewsNotification(string userIdList, List<ArticleModel> list)
128         {
129             return SendNotification(GetBody(MsgTypeEnum.News, userIdList, list));
130         }
131 
132         #region 执行发送
133 
134         /// <summary>
135         /// 执行发送消息
136         /// </summary>
137         /// <param name="messageBody">企微要求固定格式body</param>
138         private bool SendNotification(string messageBody)
139         {
140             bool isSuccess = false;
141 
142             try
143             {
144                 using (HttpClient httpClient = new HttpClient { Timeout = TimeSpan.FromMinutes(30) })
145                 {
146                     HttpContent content = new StringContent(messageBody);
147                     content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
148 
149                     string apiMethodUrl = apiUrl + sendMessageMethod + "?access_token=" + GetAccessToken();
150 
151                     HttpResponseMessage response = httpClient.PostAsync(apiMethodUrl, content).Result;
152                     string result = response.Content.ReadAsStringAsync().Result;
153                     if (!string.IsNullOrWhiteSpace(result))
154                     {
155                         var obj = JObject.Parse(result.ToString());
156                         if (obj != null)
157                         {
158                             string code = obj.GetValue("errcode").ToString();
159                             if (code.ToLower() == "0")
160                             {
161                                 isSuccess = true;
162                             }
163                         }
164                     }
165                 }
166             }
167             catch (Exception ex)
168             {
169 
170             }
171 
172             return isSuccess;
173         }
174 
175         #endregion
176 
177         #region 获取消息内容结构
178 
179         /// <summary>
180         /// 获取消息内容结构()
181         /// </summary>
182         /// <param name="msgType"></param>
183         /// <param name="userList"></param>
184         /// <param name="messageContent"></param>
185         /// <returns></returns>
186         private string GetBody(MsgTypeEnum msgType, string userList, object messageContent)
187         {
188             string messageBody = "";
189 
190             switch (msgType)
191             {
192                 case MsgTypeEnum.Text:
193                     messageBody = GetTextBody(userList, (string)messageContent);
194                     break;
195                 case MsgTypeEnum.Image:
196                     messageBody = GetImageBody(userList, (string)messageContent);
197                     break;
198                 case MsgTypeEnum.Markdown:
199                     messageBody = GetMarkdownBody(userList, (string)messageContent);
200                     break;
201                 case MsgTypeEnum.News:
202                     messageBody = GetNewsBody(userList, (List<ArticleModel>)messageContent);
203                     break;
204             }
205 
206             return messageBody;
207         }
208 
209         private string GetTextBody(string userList, string messageContent)
210         {
211             string body = "";
212 
213             TextBody textBody = new TextBody();
214             textBody.touser = userList;
215             textBody.agentid = agentId;
216             textBody.msgtype = "text";
217             textBody.text = new ContentModel(messageContent);
218 
219             body = JsonConvert.SerializeObject(textBody);
220 
221             return body;
222         }
223 
224         private string GetImageBody(string userList, string mediaId)
225         {
226             string body = "";
227 
228             ImageBody imageBody = new ImageBody();
229             imageBody.touser = userList;
230             imageBody.agentid = agentId;
231             imageBody.msgtype = "image";
232             imageBody.image = new ImageModel(mediaId);
233 
234             body = JsonConvert.SerializeObject(imageBody);
235 
236             return body;
237         }
238 
239         private string GetMarkdownBody(string userList, string messageContent)
240         {
241             string body = "";
242 
243             MarkdownBody markdownBody = new MarkdownBody();
244             markdownBody.touser = userList;
245             markdownBody.agentid = agentId;
246             markdownBody.msgtype = "markdown";
247             markdownBody.markdown = new ContentModel(messageContent);
248 
249             body = JsonConvert.SerializeObject(markdownBody);
250 
251             return body;
252         }
253 
254         private string GetNewsBody(string userList, List<ArticleModel> list)
255         {
256             string body = "";
257 
258             NewsBody newsBody = new NewsBody();
259             newsBody.touser = userList;
260             newsBody.agentid = agentId;
261             newsBody.msgtype = "news";
262 
263             NewsModel newsModel = new NewsModel();
264             newsModel.articles = list;
265             newsBody.news = newsModel;
266 
267             body = JsonConvert.SerializeObject(newsBody);
268 
269             return body;
270         }
271 
272         #endregion
273 
274         #endregion
275 
276         #region Upload
277 
278         /// <summary>
279         /// 上传
280         /// </summary>
281         /// <param name="mediaTypeEnum">文件类型</param>
282         /// <param name="fileName">文件名</param>
283         /// <param name="bytes">字节流</param>
284         /// <param name="accessToken"></param>
285         /// <returns></returns>
286         public string Upload(MediaTypeEnum mediaTypeEnum, string fileName, byte[] bytes, string accessToken)
287         {
288             string mediaId = "";
289 
290             try
291             {
292                 using (HttpClient httpClient = new HttpClient { Timeout = TimeSpan.FromMinutes(30) })
293                 {
294                     //方法路径
295                     string apiMethodUrl = apiUrl + uploadMethod + "?access_token=" + accessToken + "&type=" + mediaTypeEnum.ToString();
296 
297                     CookieContainer cookieContainer = new CookieContainer();
298                     HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(apiMethodUrl);
299                     request.CookieContainer = cookieContainer;
300                     request.AllowAutoRedirect = true;
301                     request.Method = "POST";
302                     string boundary = DateTime.Now.Ticks.ToString("X"); // 随机分隔线
303                     request.ContentType = "multipart/form-data;charset=utf-8;boundary=" + boundary;
304 
305                     byte[] itemBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "\r\n");
306                     byte[] endBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
307 
308                     //Header
309                     if(fileName == "")
310                     {
311                         //fileName必填参数
312                         fileName = mediaTypeEnum.ToString();
313                     }
314                     StringBuilder sbHeader = new StringBuilder(string.Format("Content-Disposition:form-data;name=\"media\";filename=\"{0}\";filelength=" + bytes.Length + "\r\nContent-Type:application/octet-stream\r\n\r\n", fileName));
315                     byte[] postHeaderBytes = Encoding.UTF8.GetBytes(sbHeader.ToString());
316 
317                     //请求
318                     using (Stream postStream = request.GetRequestStream())
319                     {
320                         postStream.Write(itemBoundaryBytes, 0, itemBoundaryBytes.Length);
321                         postStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);
322                         postStream.Write(bytes, 0, bytes.Length);
323                         postStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
324                     }
325 
326                     //响应
327                     string responseData = String.Empty;
328                     using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
329                     {
330                         using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
331                         {
332                             responseData = reader.ReadToEnd();
333 
334                             if (!string.IsNullOrWhiteSpace(responseData))
335                             {
336                                 var obj = JObject.Parse(responseData.ToString());
337                                 if (obj != null)
338                                 {
339                                     var data = obj["media_id"].ToString();
340                                     if (!string.IsNullOrWhiteSpace(data))
341                                     {
342                                         mediaId = data.ToString();
343                                     }
344                                 }
345                             }
346                         }
347                     }
348                 }
349             }
350             catch(Exception ex)
351             {
352 
353             }
354 
355             return mediaId;
356         }
357 
358         #endregion
359 
360         #region Get Access Token
361 
362         /// <summary>
363         /// 获取Access Token(企微官方接口,仅CorpId和CorpSecret两个参数)
364         /// </summary>
365         /// <returns></returns>
366         private string GetAccessToken()
367         {
368             string token = "";
369 
370             try
371             {
372                 try
373                 {
374                     using (HttpClient httpClient = new HttpClient { Timeout = TimeSpan.FromMinutes(30) })
375                     {
376                         string apiMethodUrl = apiUrl + accessTokenMethod + "?corpId=" + corpId + "&corpSecret=" + corpSecret;
377 
378                         HttpResponseMessage response = null;
379                         response = httpClient.GetAsync(apiMethodUrl).Result;
380 
381                         string results = response.Content.ReadAsStringAsync().Result;
382                         if (!string.IsNullOrWhiteSpace(results))
383                         {
384                             var obj = JObject.Parse(results.ToString());
385                             if (obj != null)
386                             {
387                                 var data = obj["access_token"].ToString();
388                                 if (!string.IsNullOrWhiteSpace(data))
389                                 {
390                                     token = data.ToString();
391                                 }
392                             }
393                         }
394                     }
395                 }
396                 catch (Exception ex)
397                 {
398 
399                 }
400             }
401             catch (Exception ex)
402             {
403 
404             }
405 
406             return token;
407         }
408 
409         #endregion
410     }
411 
412     #region 枚举
413 
414     /// <summary>
415     /// 应用系统名称
416     /// </summary>
417     public enum AppNameEnum
418     {
419         /// <summary>
420         /// 应用系统1
421         /// </summary>
422         App1 = 1010,
423 
424         /// <summary>
425         /// 应用系统2
426         /// </summary>
427         App2 = 1020,
428 
429         /// <summary>
430         /// 应用系统3
431         /// </summary>
432         App3 = 1030,453     }
454 
455     /// <summary>
456     /// 消息类型,目前仅Text、Markdown和News已实现
457     /// </summary>
458     public enum MsgTypeEnum
459     {
460         /// <summary>
461         /// 文本
462         /// </summary>
463         Text = 1,
464 
465         /// <summary>
466         /// 图片
467         /// </summary>
468         Image = 2,
469 
470         /// <summary>
471         /// 语音
472         /// </summary>
473         Voice = 3,
474 
475         /// <summary>
476         /// 视频
477         /// </summary>
478         Video = 4,
479 
480         /// <summary>
481         /// 文件
482         /// </summary>
483         File = 5,
484 
485         /// <summary>
486         /// 文本卡片
487         /// </summary>
488         TextCard = 6,
489 
490         /// <summary>
491         /// 图文
492         /// </summary>
493         News = 7,
494 
495         /// <summary>
496         /// MP图文
497         /// </summary>
498         MPNews = 8,
499 
500         /// <summary>
501         /// Markdown格式
502         /// </summary>
503         Markdown = 9,
504 
505         /// <summary>
506         /// 小程序
507         /// </summary>
508         Miniprogram = 10,
509 
510         /// <summary>
511         /// 卡片模板
512         /// </summary>
513         TemplateCard = 11,
514     }
515 
516     /// <summary>
517     /// 上传文件类型
518     /// </summary>
519     public enum MediaTypeEnum
520     {
521         /// <summary>
522         /// 图片
523         /// </summary>
524         image = 10,
525 
526         /// <summary>
527         /// 语音
528         /// </summary>
529         voice = 20,
530 
531         /// <summary>
532         /// 视频
533         /// </summary>
534         video = 30,
535 
536         /// <summary>
537         /// 普通文件
538         /// </summary>
539         file = 40,
540     }
541 
542     #endregion
543 
544     #region 实体
545 
546     /// <summary>
547     /// 消息实体基类
548     /// </summary>
549     public class MessageBaseBody
550     {
551         /// <summary>
552         /// 
553         /// </summary>
554         public string agentid { set; get; }
555 
556         /// <summary>
557         /// 
558         /// </summary>
559         public string touser { set; get; }
560 
561         /// <summary>
562         /// 
563         /// </summary>
564         public string msgtype { set; get; }
565     }
566 
567     /// <summary>
568     /// 文本类消息实体
569     /// </summary>
570     public class TextBody : MessageBaseBody
571     {
572         /// <summary>
573         /// 
574         /// </summary>
575         public ContentModel text { set; get; }
576     }
577 
578     /// <summary>
579     /// Markdown类消息实体
580     /// </summary>
581     public class MarkdownBody : MessageBaseBody
582     {
583         /// <summary>
584         /// 
585         /// </summary>
586         public ContentModel markdown { set; get; }
587     }
588 
589     /// <summary>
590     /// 图片类消息实体
591     /// </summary>
592     public class ImageBody : MessageBaseBody
593     {
594         /// <summary>
595         /// 
596         /// </summary>
597         public ImageModel image { set; get; }
598     }
599 
600     /// <summary>
601     /// News类消息实体
602     /// </summary>
603     public class NewsBody : MessageBaseBody
604     {
605         /// <summary>
606         /// 
607         /// </summary>
608         public NewsModel news { set; get; }
609     }
610 
611     /// <summary>
612     /// Content实体
613     /// </summary>
614     public class ContentModel
615     {
616         public ContentModel(string content)
617         {
618             this.content = content;
619         }
620 
621         /// <summary>
622         /// 
623         /// </summary>
624         public string content { set; get; }
625     }
626 
627     /// <summary>
628     /// Image内容实体
629     /// </summary>
630     public class ImageModel
631     {
632         public ImageModel(string mediaId)
633         {
634             this.media_id = mediaId;
635         }
636 
637         /// <summary>
638         /// 
639         /// </summary>
640         public string media_id { set; get; }
641     }
642 
643     /// <summary>
644     /// News内容实体
645     /// </summary>
646     public class NewsModel
647     {
648         /// <summary>
649         /// 
650         /// </summary>
651         public List<ArticleModel> articles { set; get; }
652     }
653 
654     /// <summary>
655     /// News内容结构实体
656     /// </summary>
657     public class ArticleModel
658     {
659         public ArticleModel(string title, string description, string picUrl, string url)
660         {
661             this.title = title;
662             this.description = description;
663             this.picurl = picUrl;
664             this.url = url;
665         }
666 
667         /// <summary>
668         /// 
669         /// </summary>
670         public string title { set; get; }
671 
672         /// <summary>
673         /// 
674         /// </summary>
675         public string description { set; get; }
676 
677         /// <summary>
678         /// 
679         /// </summary>
680         public string picurl { set; get; }
681 
682         /// <summary>
683         /// 
684         /// </summary>
685         public string url { set; get; }
686     }
687 
688     /// <summary>
689     /// Media结构实体
690     /// </summary>
691     public class MediaModel
692     {
693         public MediaModel(string mediaid)
694         {
695             this.media_id = mediaid;
696         }
697 
698         /// <summary>
699         /// 
700         /// </summary>
701         public string media_id { set; get; }
702     }
703 
704     #endregion
705 }

 

posted @ 2022-09-22 15:26  无敌师爷IT技术Blog  阅读(1522)  评论(0编辑  收藏  举报