C#发送钉钉通知机器人

编程

某个项目,测试环境下,通知开发组人员各种情况,比如给测试额外信息支持之类,就想到了用钉钉机器人通知。
不过官方只有py和java,php的,没有c#。这里写一套仅供参考。注释都在代码里面了。重点在签名和发送那块。其他可忽略!

吐槽一下,文中有java 和 php就被自动定义关键字“java”和“php”了!c#却没有被带入关键字!果然是四等人!

/// <summary>

/// 返回结果 不是重点,仅仅是完整性

/// </summary>

/// <typeparam name="T"></typeparam>

public class Result<T>

{

/// <summary>

/// 状态

/// </summary>

public bool Status;

/// <summary>

/// 状态代码

/// </summary>

public long StatusCode;

/// <summary>

/// 消息

/// </summary>

public String Message = string.Empty;

/// <summary>

/// 数据

/// </summary>

public T Data;

/// <summary>

/// 错误详情 用于调试获取错误详细信息, 可不写

/// </summary>

public string ErrorDetail = "";

}

/// <summary>

/// 运营通知接口,这个不是核心可以不看

/// </summary>

public interface IOperationNotification

{

/// <summary>

/// 发送通知

/// </summary>

/// <param name="msg"></param>

/// <returns></returns>

Result<string> Send(string msg);

}

/// <summary>

/// 钉钉运营通知 重点在内

/// </summary>

public class DingDingOperationNotification : IOperationNotification

{

/// <summary>

/// 钉钉结果,这是钉钉的官方返回结果结构,没错errcode就是0

/// </summary>

public class dingdingResult

{

public int errcode { get; set; }

public string errmsg { get; set; }

}

/// <summary>

/// 钉钉发送通知,调用入口

/// </summary>

/// <param name="msg"></param>

/// <returns></returns>

public Result<string> Send(string msg)

{

if (msg.NullEmpty()) {

// 这是个扩展方法,用一段错误信息string直接构成一个错误返回结构

// 这个真的是方便用,但是首次创造的时候 经理妹妹看不懂。其他一些同事也看不懂

// 还有个用成功结果数据构成成功结果的扩展方法

// 这类扩展多了 会都出现在点符号后的提示中。要注意命名

return "没有发送内容".FailRes<string>();

}

var send_res = this.SendToDingDing(msg);

var res_x = send_res.ToObject<dingdingResult>();

if (res_x.errcode == 0)

{

// 还有个用成功结果数据构成成功结果的扩展方法

// 这里是 Result<string> 字符串是成功的结果,不是错误信息

return "ok".SuccRes();

}

else

{

return res_x.errmsg.FailRes<string>();

}

}

/// <summary>

/// 发送到钉钉 机器人 重点方法 链接构成,数据构成

/// TOKEN 要更换成相应的

/// </summary>

/// <param name="msg"></param>

/// <returns></returns>

public string SendToDingDing(string msg)

{

string main_url = "https://oapi.dingtalk.com/robot/send?access_token=TOKEN";

// 这里要参考官方文档制定发送内容的允许关键字

string data = $"{{"msgtype": "text","text": {{"content": "验证信息:{msg}"}}}}";

var sign = TransEx.sign();// 签名是重点

// 必须urlcode

var urlcode_sign = HttpUtility.UrlEncode(sign.Item2);

// 组成格式

string fin_url = $"{main_url}&timestamp={sign.Item1}&sign={urlcode_sign}";

// 这里用了 扩展方式的post,可以自己定义

// 用最终url字符串做扩展直接post这个url, 主要是方便用,特方便

var res = fin_url.HttpPost(data: data);

return res;

}

/// <summary>

/// 时间戳1970年

/// </summary>

/// <param name="time"></param>

/// <returns></returns>

public TimeSpan GetTimeSpan1970(DateTime time)

{

return time - new DateTime(1970, 01, 01, 0, 0, 0, 0);

}

/// <summary>

/// 元年时间戳

/// </summary>

/// <param name="time"></param>

/// <returns></returns>

public TimeSpan GetTimeSpan(DateTime time)

{

return time - new DateTime();

}

/// <summary>

/// 时间戳转长整型

/// </summary>

/// <param name="time"></param>

/// <returns></returns>

public long GetLongTimeSpan(DateTime time)

{

var timestamp = time.GetTimeSpan1970();

long long_timestamp = Convert.ToInt64(Math.Round(timestamp.TotalMilliseconds));

return long_timestamp;

}

/// <summary>

/// 钉钉签名-- 这里超级重要 --

/// </summary>

/// <returns></returns>

public Tuple<long, string> sign()

{

// 钉钉用的是utc时间做时间戳,不是本地时间

long timestamp = DateTime.UtcNow.GetLongTimeSpan();

// 官方给你的secret

string secret = "SECRET";

Encoding code = UTF8Encoding.UTF8;//utf8

var secret_byte = code.GetBytes(secret);

string string_to_sign = $"{timestamp}

{secret}";//看官方,签名组成法

// 签名转字节

var string_to_sign_enc = code.GetBytes(string_to_sign);

// 散列加密用HMAC SHA256,用的key就是secret字节组

byte[] hash = new HMACSHA256(secret_byte).ComputeHash(string_to_sign_enc);

// 要base64

var base64Code = Convert.ToBase64String(hash);

return new Tuple<long, string>(timestamp, base64Code);

}

/// <summary>

/// 钉钉post

/// </summary>

/// <param name="url"></param>

/// <param name="data"></param>

/// <param name="contentType"></param>

/// <returns></returns>

public string HttpPost(string url, string data = "", string contentType = "application/json")

{

string res = "";

var t = Task.Run(async () =>

{

using (HttpClient client = new HttpClient())

{

try

{

var uri = url;

HttpRequestMessage req = new HttpRequestMessage(new HttpMethod("POST"), uri);

req.Content = new StringContent(data);

req.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentType);

return await client.SendAsync(req).Result.Content.ReadAsStringAsync();

//return client.GetAsync(uri).Result.Content.ReadAsStringAsync();

}

catch (Exception ex)

{

return await Task.Run<string>(() => { return ex.Message; });

}

}

});

Task.WaitAll(t);

res = t.Result;

return res;

}

/// <summary>

/// 成功的结果

/// </summary>

/// <typeparam name="T"></typeparam>

/// <param name="data"></param>

/// <param name="msg"></param>

/// <returns></returns>

public static Result<T> SuccRes<T>(this T data, string msg = "")

{

return new Result<T>() { Data = data, Message = msg, Status = true, StatusCode = 1 };

}

/// <summary>

/// 失败的结果

/// </summary>

/// <typeparam name="T"></typeparam>

/// <param name="msg">失败消息</param>

/// <param name="errCode">错误代码,通常为-1,指定前端重新登录时用401(仅用于公众号用户中心接口上)</param>

/// <param name="errDetail">错误明细</param>

/// <returns></returns>

public static Result<T> FailRes<T>(this string msg, int errCode = -1, string errDetail = "")

{

return new Result<T>() { Data = default(T), Message = msg, Status = false, StatusCode = errCode, ErrorDetail = errDetail };

}

}

/// <summary>

/// 运营管理

/// </summary>

public class OperationManager

{

/// <summary>

/// 创建通知器

/// </summary>

/// <returns></returns>

public static IOperationNotification CreateNotification()

{

return new DingDingOperationNotification();

}

}

 

以上是 C#发送钉钉通知机器人 的全部内容, 来源链接: utcz.com/z/518328.html

回到顶部