大家好,我是快乐IT
开发背景
公司有一套较旧的业务系统,对接飞书后在移动端显示一直有问题。但老系统已经不具备二开条件,想改也没法改。可审批通知又不能不发,总不能让业务同学天天盯着电脑等消息吧。
于是我就想,能不能在系统外部挂一层,用一种轻量的方式把飞书推送这件事给解决了——不改动老系统代码,也能让相关人员及时收到审批通知。

软件介绍
飞书模板消息测试工具 是一个基于 .NET 8 WinForm 的桌面应用,填入参数即可一键发送飞书卡片消息,带着跳转按钮直达审批页面。
主要功能:
- 获取Token
— 通过 App ID + App Secret 自动获取飞书 tenant_access_token - 发送卡片消息
— 推送带标题、正文、跳转按钮的互动卡片,适合审批通知场景 - 发送文本消息
— 推送纯文本消息,满足简单通知需求 - 配置自动保存
— App ID、App Secret、User ID、跳转URL 等参数关闭时自动持久化,下次打开无需重填
界面采用左右布局,左侧操作区,右侧品牌区,日志区采用深色终端风格,操作反馈一目了然。
异常处理
- 双击程序没反应或闪退
— 本工具基于 .NET 8 开发,需要安装 .NET 8.0 运行时( windowsdesktop-runtime-8.0.28-win-x64.exe,约55MB)。前往微软官网下载安装后重试。
- 获取Token失败
— 检查 App ID 和 App Secret 是否填写正确,确保飞书应用已创建并审核通过。 - 发送消息返回权限不足
— 飞书应用需开通 im:message:send_as_bot权限,在飞书开放平台后台添加该权限并重新发布应用。 - 消息发送成功但收不到
— 确认 User ID 填写正确, receive_id_type为user_id时需要填写飞书用户的 User ID,不是姓名。
核心开发过程
开发过程中有几点值得分享的点:
Token 自动刷新机制。 飞书的 tenant_access_token 有效期 2 小时,我提前 60 秒标记过期,发送消息前自动检查并刷新,避免因 Token 过期导致发送失败。这个细节很容易被忽略,但一旦上线后偶发失败就很难排查。
飞书API对接
飞书消息发送的核心流程分两步:获取Token → 发送消息。
第一步:获取 tenant_access_token
public async Task<(bool success, string token, string message)> GetTokenAsync() { using var client = new HttpClient(); var body = new { app_id = _appId, app_secret = _appSecret }; var content = new StringContent( JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json"); var response = await client.PostAsync( "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal", content); var result = await response.Content.ReadAsStringAsync(); var json = JObject.Parse(result); if (json["code"]?.Value<int>() == 0) { _accessToken = json["tenant_access_token"]?.Value<string>(); var expire = json["expire"]?.Value<int>() ?? 7200; _tokenExpireTime = DateTime.Now.AddSeconds(expire - 60); // 提前60秒过期 return (true, _accessToken ?? "", "获取Token成功"); } // ...错误处理 }要点:Token 有效期 2 小时,我们提前 60 秒标记过期,并在发送消息前自动刷新:
private async Task<string?> EnsureTokenAsync() { if (_accessToken != null && DateTime.Now < _tokenExpireTime) return _accessToken; // 未过期,复用 var (success, token, _) = await GetTokenAsync(); return success ? token : null; } 第二步:发送互动卡片消息
飞书互动卡片(Interactive Card)支持富文本标题、正文、按钮跳转,非常适合审批通知场景:
var card = new { config = new { wide_screen_mode = true }, header = new { title = new { tag = "plain_text", content = title }, // 可自定义标题 template = "blue" }, elements = new object[] { new { tag = "div", text = new { tag = "plain_text", content = content } }, new { tag = "action", actions = new object[] { new { tag = "button", text = new { tag = "plain_text", content = "点击审批" }, url = url, // 跳转到审批页面 type = "primary" } } } } }; var body = new { receive_id = userId, msg_type = "interactive", content = JsonConvert.SerializeObject(card) }; 调用飞书 /im/v1/messages 接口发送,receive_id_type=user_id 表示按用户ID发送。
互动交流
如果使用过程中遇到问题,欢迎留言交流。也欢迎关注微信公众号【快乐IT】,获取更多实用工具和开发分享。
夜雨聆风