C#实现钉钉消息推送过程

 更新时间:2025年07月23日 14:21:46   作者:老农民编程  
本文介绍通过C#实现钉钉消息推送报警数据至群聊的方法,重点讲解机器人设置步骤(建群、添加自定义机器人、配置关键字和Webhook)及C#代码实现,支持文本、Markdown等消息类型,用于设备报警提醒场景

前言

想起之前有个项目需要使用钉钉消息推送报警数据到群里,提醒群里人员知道设备报警。

这篇是通过C#实现钉钉消息推送,因为钉钉机器人设定需设置安全设置,有三个(自定义关键词、加签、IP地址(段)),目前是设置自定义关键词通过C#消息推送。

一、钉钉机器人如何设置

1、钉钉机器人设置需建群(在群里才能机器人)

2、点击群设置,在群管理里点击机器人管理

3、点击添加机器人选择自定义机器人点击添加

4、在添加钉钉机器人时需要确定加密方式有以下几种:

  • 自定义关键字
  • 加签
  • IP地址段

注:因目前所选方式为第一种,所以需输入自定义关键字,如:"报警:"

5、点击完成后,钉钉会给出一个webhook,需复制webhook在C#中使用。

6、如果自定义机器人在群里发送招呼话语,说明已建造设置成功。

二、C#实现钉钉消息推送

1.钉钉消息类型

钉钉消息有六种消息类型,总结如下:

类型是否支持交互关键特性适用场景
文本(text)纯文本,支持@成员简单通知、报警
Markdown支持Markdown格式化复杂内容(如日志报告)
链接(link)标题+图片+跳转链接带缩略图的通知
ActionCard单、多 1-2个可点击按钮审批、任务处理
FeedCard多条链接列表聚合通知(如新闻列表)

2.代码实现

使用C#控制台实现钉钉机器人消息推送。

1)DingTalkRobot类型

钉钉机器人信息推送,代码如下(示例):

using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

public class DingTalkRobot
{
    private readonly string _webhookUrl;
    private readonly HttpClient _httpClient;

    public DingTalkRobot(string webhookUrl)
    {
        _webhookUrl = webhookUrl ?? throw new ArgumentNullException(nameof(webhookUrl));
        _httpClient = new HttpClient();
    }

    /// <summary>
    /// 发送文本消息
    /// </summary>
    /// <param name="content">消息内容</param>
    /// <param name="atMobiles">需要@的手机号数组</param>
    /// <param name="isAtAll">是否@所有人</param>
    public async Task SendTextMessageAsync(string content, string[] atMobiles = null, bool isAtAll = false)
    {
        var message = new
        {
            msgtype = "text",
            text = new
            {
                content = content
            },
            at = new
            {
                atMobiles = atMobiles ?? Array.Empty<string>(),
                isAtAll = isAtAll
            }
        };

        await SendMessageAsync(message);
    }

    /// <summary>
    /// 发送Markdown消息
    /// </summary>
    /// <param name="title">标题</param>
    /// <param name="text">Markdown格式内容</param>
    /// <param name="atMobiles">需要@的手机号数组</param>
    /// <param name="isAtAll">是否@所有人</param>
    public async Task SendMarkdownMessageAsync(string title, string text, string[] atMobiles = null, bool isAtAll = false)
    {
        var message = new
        {
            msgtype = "markdown",
            markdown = new
            {
                title = title,
                text = text
            },
            at = new
            {
                atMobiles = atMobiles ?? Array.Empty<string>(),
                isAtAll = isAtAll
            }
        };

        await SendMessageAsync(message);
    }

    /// <summary>
    /// 发送链接消息
    /// </summary>
    /// <param name="title">标题</param>
    /// <param name="text">内容</param>
    /// <param name="messageUrl">跳转链接</param>
    /// <param name="picUrl">图片链接(可选)</param>
    public async Task SendLinkMessageAsync(string title, string text, string messageUrl, string picUrl = "")
    {
        var message = new
        {
            msgtype = "link",
            link = new
            {
                title = title,
                text = text,
                messageUrl = messageUrl,
                picUrl = picUrl
            }
        };

        await SendMessageAsync(message);
    }

    /// <summary>
    /// 发送 单按钮 ActionCard​消息
    /// </summary>
    /// <param name="title">消息标题,显示在消息顶部</param>
    /// <param name="text">消息内容,支持Markdown语法</param>
    /// <param name="singleTitle">单个按钮的文本(不超过20字符)</param>
    /// <param name="singleUrl">按钮跳转链接(需HTTP/HTTPS)</param>
    /// <param name="atMobiles">需要@的群成员手机号数组</param>
    /// <param name="isAtAll">是否@所有人(慎用)</param>
    /// <returns></returns>
    public async Task SendActionCardAsync(string title, string text, string singleTitle, string singleUrl, string[] atMobiles = null, bool isAtAll = false)
    {
        var message = new
        {
            msgtype = "actionCard",
            actionCard = new
            {
                title = title,
                text = text,
                singleTitle = singleTitle,
                singleURL = singleUrl,
                btnOrientation = "0" // "0"垂直按钮,"1"水平按钮
            },
            at = new
            {
                atMobiles = atMobiles ?? Array.Empty<string>(),
                isAtAll = isAtAll
            }
        };
        await SendMessageAsync(message);
    }

    /// <summary>
    /// 发送 多按钮 ActionCard消息
    /// </summary>
    /// <param name="title">消息标题</param>
    /// <param name="text">消息内容</param>
    /// <param name="buttons">按钮列表(最多2个)</param>
    /// <param name="btnOrientation">按钮排列方向:“0”(垂直,默认) 或 “1”(水平)</param>
    /// <param name="atMobiles">需要@的手机号数组</param>
    /// <param name="isAtAll">是否@所有人</param>
    /// <returns></returns>
    public async Task SendMultiActionCardAsync(string title, string text, List<DingTalkButton> buttons, string btnOrientation = "0", // "0"垂直,"1"水平
    string[] atMobiles = null, bool isAtAll = false)
    {
        var message = new
        {
            msgtype = "actionCard",
            actionCard = new
            {
                title = title,
                text = text,
                btns = buttons.Select(b => new { title = b.Title, actionURL = b.Url }).ToArray(),
                btnOrientation = btnOrientation
            },
            at = new
            {
                atMobiles = atMobiles ?? Array.Empty<string>(),
                isAtAll = isAtAll
            }
        };
        await SendMessageAsync(message);
    }

    /// <summary>
    /// 发送FeedCard消息
    /// </summary>
    /// <param name="links">链接列表(最多5条)</param>
    /// <returns></returns>
    public async Task SendFeedCardAsync(List<FeedCardLink> links)
    {
        var message = new
        {
            msgtype = "feedCard",
            feedCard = new
            {
                links = links.Select(link => new
                {
                    title = link.Title,
                    messageURL = link.MessageUrl,
                    picURL = link.PicUrl
                }).ToArray()
            }
        };
        await SendMessageAsync(message);
    }

    // FeedCard 链接定义类
    public class FeedCardLink
    {
        //链接标题(小于等于64字符)
        public string Title { get; set; }
        //跳转链接(需HTTP/HTTPS)
        public string MessageUrl { get; set; }
        //图片链接(可选,建议尺寸:520x275像素)
        public string PicUrl { get; set; }
    }

    // 按钮定义类
    public class DingTalkButton
    {
        //按钮文本(小于等于20字符)
        public string Title { get; set; }
        //跳转链接(需HTTP/HTTPS)
        public string Url { get; set; }
    }

    private async Task SendMessageAsync(object message)
    {
        var json = Newtonsoft.Json.JsonConvert.SerializeObject(message);
        var content = new StringContent(json, Encoding.UTF8, "application/json");

        var response = await _httpClient.PostAsync(_webhookUrl, content);
        response.EnsureSuccessStatusCode();

        var responseContent = await response.Content.ReadAsStringAsync();
        Console.WriteLine($"钉钉机器人响应: {responseContent}");
    }
}

2)Program类型

钉钉机器人发送消息实现类,代码如下:

using static DingTalkRobot;
using static System.Net.Mime.MediaTypeNames;

public class Program
{
    static async Task Main(string[] args)
    {
        // 实际Webhook URL
        var webhookUrl = "https://oapi.dingtalk.com/robot/send?access_token=ea8b2fe200c23a4ec8a9569c88ca9561d4f7ebe9bb10d1146ed07e49904c0627\r\n";
        var dingTalkRobot = new DingTalkRobot(webhookUrl);

        try
        {
            //关键字 = “报警:” 需在title、content参数加关键字
            //1、发送文本消息(消息长度不超过20kb)
            await dingTalkRobot.SendTextMessageAsync("报警:这是一条测试消息",
                atMobiles: new[] { "13812345678" },
                isAtAll: false);

            //2、发送Markdown消息(1、不支持HTML和复杂表格 2、总长度不超过8192字节)
            await dingTalkRobot.SendMarkdownMessageAsync(
                "报警:项目更新通知",
                "### 项目状态更新\n" +
                "> 项目进度: 80%\n\n" +
                "> 剩余时间: 2天\n\n" +
                "![screenshot](https://example.com/image.png)\n" +
                "###### [查看详情](https://example.com)",
                atMobiles: new[] { "13812345678" });

            //3、发送链接消息(最后两个 跳转链接 图片链接)
            await dingTalkRobot.SendLinkMessageAsync(
                "报警:系统报警通知",
                "生产环境出现异常,请及时处理",
                "https://www.bilibili.com/video/BV1ZU4y1q7sn/?share_source=copy_web&vd_source=ad0206b6bbe094bb6fa542017f2e474b",
                "https://www.bilibili.com/opus/366829175324803541?from=search&spm_id_from=333.337.0.0");

            //4、发送单按钮 ActionCard消息
            await dingTalkRobot.SendActionCardAsync(
                title: "报警:任务审批",
                text: "**申请人**: 张三\n**内容**: 采购申请\n请及时处理!",
                singleTitle: "点击审批",
                singleUrl: "https://example.com/approve?id=123");

            //5、发送多按钮 ActionCard消息
            var buttons = new List<DingTalkButton>
            {
                new DingTalkButton { Title = "同意", Url = "https://example.com/agree" },
                new DingTalkButton { Title = "拒绝", Url = "https://example.com/reject" }
            };

            await dingTalkRobot.SendMultiActionCardAsync(
                title: "报警:请假审批",
                text: "**员工**: 李四\n**天数**: 3天",
                buttons: buttons,
                btnOrientation: "1" // 水平排列按钮
            );

            //6、发送FeedCard消息
            var links = new List<FeedCardLink>
            {
                new FeedCardLink
                {
                    Title = "报警:系统报警",
                    MessageUrl = "https://example.com/alert1",
                    PicUrl = "https://example.com/alert.png"
                },
                new FeedCardLink
                {
                    Title = "报警:新任务",
                    MessageUrl = "https://example.com/task1",
                    PicUrl = "https://example.com/task.png"
                }
            };

            await dingTalkRobot.SendFeedCardAsync(links);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"发送钉钉消息失败: {ex.Message}");
        }
    }
}

3)运行结果

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • C# 并行和多线程编程——并行集合和PLinq

    C# 并行和多线程编程——并行集合和PLinq

    这篇文章主要介绍了C# 并行和多线程编程的相关资料,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下
    2021-02-02
  • .Net(c#)汉字和Unicode编码互相转换实例

    .Net(c#)汉字和Unicode编码互相转换实例

    下面小编就为大家带来一篇.Net(c#)汉字和Unicode编码互相转换实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-02-02
  • C#实现字符串倒序遍历的方法小结

    C#实现字符串倒序遍历的方法小结

    这篇文章主要为大家详细介绍了C#中实现字符串倒序遍历的常见方法,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考下
    2024-02-02
  • C#使用CefSharp控件实现爬虫

    C#使用CefSharp控件实现爬虫

    这篇文章介绍了C#使用CefSharp控件实现爬虫的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • C# WINFORM自定义异常处理方法

    C# WINFORM自定义异常处理方法

    这篇文章主要介绍了一个简单的统一异常处理方法。系统底层出现异常,写入记录文件,系统顶层捕获底层异常,显示提示信息。需要的可以参考一下
    2021-12-12
  • C#实现简单获取扫码枪信息代码

    C#实现简单获取扫码枪信息代码

    本文给大家分享的是使用C#实现简单获取扫码枪信息代码,非常的简单实用,有需要的小伙伴可以参考下。
    2016-07-07
  • c# 委托详解

    c# 委托详解

    本文将通过实例解析对c# 委托进行详细介绍,具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • RSA密钥--JAVA和C#的区别及联系

    RSA密钥--JAVA和C#的区别及联系

    这篇文章主要介绍了关于RSA密钥事件JAVA和C#的区别及联系,文章从RSA语法介绍开始展开详细介绍了C#转JAVA及JAVA转C#,需要的小伙伴可以可以参考一下
    2021-10-10
  • C#实现分页组件的方法

    C#实现分页组件的方法

    这篇文章主要为大家详细介绍了C#实现分页组件的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • C# 中const,readonly,static的使用小结

    C# 中const,readonly,static的使用小结

    这篇文章主要介绍了C# 中使用const,readonly,static的示例,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下
    2021-01-01

最新评论