C# 企业微信机器人消息推送

1. 创建消息推送机器人

首先在企业微信中创建群聊,然后添加群机器人,获取webhook地址。

2. 基础实现代码

cs 复制代码
using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

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

    public EnterpriseWeChatRobot(string webhookUrl)
    {
        _webhookUrl = webhookUrl;
        _httpClient = new HttpClient();
    }

    /// <summary>
    /// 发送文本消息
    /// </summary>
    public async Task<bool> SendTextMessageAsync(string content, string[] mentionedList = null, string[] mentionedMobileList = null)
    {
        var message = new
        {
            msgtype = "text",
            text = new
            {
                content = content,
                mentioned_list = mentionedList,
                mentioned_mobile_list = mentionedMobileList
            }
        };

        return await SendMessageAsync(message);
    }

    /// <summary>
    /// 发送Markdown消息
    /// </summary>
    public async Task<bool> SendMarkdownMessageAsync(string content)
    {
        var message = new
        {
            msgtype = "markdown",
            markdown = new
            {
                content = content
            }
        };

        return await SendMessageAsync(message);
    }

    /// <summary>
    /// 发送图片消息
    /// </summary>
    public async Task<bool> SendImageMessageAsync(string base64, string md5)
    {
        var message = new
        {
            msgtype = "image",
            image = new
            {
                base64 = base64,
                md5 = md5
            }
        };

        return await SendMessageAsync(message);
    }

    /// <summary>
    /// 发送图文消息
    /// </summary>
    public async Task<bool> SendNewsMessageAsync(Article[] articles)
    {
        var message = new
        {
            msgtype = "news",
            news = new
            {
                articles = articles
            }
        };

        return await SendMessageAsync(message);
    }

    /// <summary>
    /// 发送文件消息
    /// </summary>
    public async Task<bool> SendFileMessageAsync(string mediaId)
    {
        var message = new
        {
            msgtype = "file",
            file = new
            {
                media_id = mediaId
            }
        };

        return await SendMessageAsync(message);
    }

    private async Task<bool> SendMessageAsync(object message)
    {
        try
        {
            var json = JsonSerializer.Serialize(message);
            var content = new StringContent(json, Encoding.UTF8, "application/json");

            var response = await _httpClient.PostAsync(_webhookUrl, content);
            var responseContent = await response.Content.ReadAsStringAsync();

            if (response.IsSuccessStatusCode)
            {
                var result = JsonSerializer.Deserialize<WeChatResponse>(responseContent);
                return result?.errcode == 0;
            }

            Console.WriteLine($"发送失败: {responseContent}");
            return false;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"发送消息异常: {ex.Message}");
            return false;
        }
    }
}

/// <summary>
/// 图文消息文章
/// </summary>
public class Article
{
    public string title { get; set; }
    public string description { get; set; }
    public string url { get; set; }
    public string picurl { get; set; }
}

/// <summary>
/// 企业微信响应
/// </summary>
public class WeChatResponse
{
    public int errcode { get; set; }
    public string errmsg { get; set; }
}

3. 使用示例

cs 复制代码
class Program
{
    static async Task Main(string[] args)
    {
        // 替换为你的webhook地址
        string webhookUrl = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY";
        
        var robot = new EnterpriseWeChatRobot(webhookUrl);

        // 发送文本消息
        bool success1 = await robot.SendTextMessageAsync(
            "Hello, 这是一条测试消息!",
            mentionedList: new[] { "@all" }  // @所有人
        );

        // 发送Markdown消息
        bool success2 = await robot.SendMarkdownMessageAsync(
            "### 项目通知\n" +
            "> **项目**: 企业微信机器人测试\n" +
            "> **状态**: 运行正常\n" +
            "> **时间**: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\n" +
            "> **详情**: [点击查看详情](https://work.weixin.qq.com/)"
        );

        // 发送图文消息
        var articles = new[]
        {
            new Article
            {
                title = "企业微信官方文档",
                description = "查看详细的使用文档",
                url = "https://work.weixin.qq.com/api/doc/90000/90136/91770",
                picurl = "https://res.wx.qq.com/a/wx_fed/assets/res/NTI4MWU5.ico"
            }
        };

        bool success3 = await robot.SendNewsMessageAsync(articles);

        Console.WriteLine($"文本消息发送: {success1}");
        Console.WriteLine($"Markdown消息发送: {success2}");
        Console.WriteLine($"图文消息发送: {success3}");
    }
}

4. 高级功能 - 文件上传

如果需要发送文件消息,需要先上传文件获取media_id:

cs 复制代码
/// <summary>
/// 上传文件到企业微信并获取media_id
/// </summary>
public async Task<string> UploadFileAsync(string filePath)
{
    try
    {
        // 从webhook地址中提取key
        var uri = new Uri(_webhookUrl);
        var key = System.Web.HttpUtility.ParseQueryString(uri.Query)["key"];
        
        string uploadUrl = $"https://qyapi.weixin.qq.com/cgi-bin/webhook/upload_media?key={key}&type=file";

        using var form = new MultipartFormDataContent();
        using var fileContent = new ByteArrayContent(await File.ReadAllBytesAsync(filePath));
        fileContent.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/octet-stream");
        
        form.Add(fileContent, "media", Path.GetFileName(filePath));

        var response = await _httpClient.PostAsync(uploadUrl, form);
        var responseContent = await response.Content.ReadAsStringAsync();

        if (response.IsSuccessStatusCode)
        {
            using var doc = JsonDocument.Parse(responseContent);
            if (doc.RootElement.TryGetProperty("media_id", out var mediaIdElement))
            {
                return mediaIdElement.GetString();
            }
        }

        Console.WriteLine($"文件上传失败: {responseContent}");
        return null;
    }
    catch (Exception ex)
    {
        Console.WriteLine($"文件上传异常: {ex.Message}");
        return null;
    }
}

5. 完整使用示例

cs 复制代码
class Program
{
    static async Task Main(string[] args)
    {
        string webhookUrl = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY";
        var robot = new EnterpriseWeChatRobot(webhookUrl);

        // 1. 发送文本消息并@特定用户
        await robot.SendTextMessageAsync(
            "任务执行完成,请相关同事查看结果。",
            mentionedList: new[] { "张三", "李四" }
        );

        // 2. 发送Markdown格式的告警消息
        await robot.SendMarkdownMessageAsync(
            "🚨 **系统告警**\n" +
            "---\n" +
            "**服务**: API Gateway\n" +
            "**级别**: CRITICAL\n" +
            "**时间**: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\n" +
            "**描述**: 服务响应时间超过阈值\n" +
            "**建议**: 请立即检查服务器状态"
        );

        // 3. 如果有文件需要发送
        // string mediaId = await robot.UploadFileAsync("report.pdf");
        // if (!string.IsNullOrEmpty(mediaId))
        // {
        //     await robot.SendFileMessageAsync(mediaId);
        // }
    }
}

注意事项

bash 复制代码
Webhook地址:确保使用正确的webhook地址,包含有效的key

消息频率限制:企业微信机器人有发送频率限制,请勿频繁发送

安全性:webhook地址包含敏感信息,请妥善保管

异常处理:在实际使用中建议添加更完善的异常处理机制

HTTP客户端:建议使用IHttpClientFactory来管理HttpClient实例
相关推荐
嵌入式-老费4 小时前
Easyx图形库应用(工业自动化领域的应用)
运维·自动化·1024程序员节
小Mei数码说4 小时前
华为Watch GT 6:运动与科技的完美融合
1024程序员节
比奥利奥还傲.4 小时前
不用服务器也能搭博客!Docsify+cpolar的极简方案
1024程序员节
YC运维4 小时前
ELK日志分析系统完整部署与应用指南
1024程序员节
小马哥编程4 小时前
【软考架构】架构风格:针对规则系统体系架构风格,举一个经典案例
1024程序员节
❀͜͡傀儡师5 小时前
Spring Boot 4.0.0-RC1 已经正式发布
1024程序员节·springboot4.0.0·framework7.0.0
fenglllle5 小时前
http trailer 与 http2
http·wireshark·1024程序员节
程序员三明治5 小时前
Spring AOP:注解配置与XML配置双实战
java·后端·spring·代理模式·aop·1024程序员节