跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava

发送 Webhook 到飞书机器人

如何在飞书群聊中创建自定义机器人并获取 Webhook 地址,提供了 Java 和 Python 两种语言实现签名校验及发送富文本消息的代码示例,帮助开发者集成飞书通知功能。

ArchDesign发布于 2026/4/6更新于 2026/9/1188 浏览
发送 Webhook 到飞书机器人

发送 Webhook 到飞书机器人

参考链接 自定义机器人使用指南

创建自定义机器人

  1. 邀请自定义机器人进群。

  2. 获取签名校验 在 安全设置 区域,选择 签名校验。

获取自定义机器人的 webhook 地址 机器人对应的 webhook 地址 格式如下: https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxxxxxxxxxxx 请妥善保存好此 webhook 地址,不要公布在 Gitlab、博客等可公开查阅的网站上,避免地址泄露后被恶意调用发送垃圾消息。

设置自定义机器人的头像、名称与描述,并点击 添加。

在 群机器人 界面点击 添加机器人。在 添加机器人 对话框,找到并点击 自定义机器人。

在右侧 设置 界面,点击 群机器人。

进入目标群组,在群组右上角点击更多按钮,并点击 设置。

选择签名校验后,系统已默认提供了一个秘钥。你也可以点击 重置,更换秘钥。

使用 Java 发送 HTTP POST 到自定义机器人

  1. 计算签名校验,参考官方文档的 SignDemo.java,自定义一个签名函数
private static String genSign(String secret, long timestamp) throws NoSuchAlgorithmException, InvalidKeyException {
    // 把 timestamp+"\n"+密钥当做签名字符串
    String stringToSign = timestamp + "\n" + secret;
    // 使用 HmacSHA256 算法计算签名
    Mac mac = Mac.getInstance("HmacSHA256");
    mac.init(new SecretKeySpec(stringToSign.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
    byte[] signData = mac.doFinal(new byte[]{});
    return new String(Base64.encodeBase64(signData));
}
  1. 计算时间戳 需要注意的是,时间戳是以秒为单位的,并且要配置时区,不可直接使用 System.currentTimeMillis()/1000 来计算秒值
long seconds = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().getEpochSecond();
  1. 创建富文本消息 参考官方文档 发送富文本消息
  • 创建一个 content 对象
private static JSONObject createOuterContent(String title, String message, String detail, String startTime, String endTime) {
    JSONObject result = new JSONObject();
    result.put("post", createPostJsonObject(title, message, detail, startTime, endTime));
    return result;
}
private static JSONObject createPostJsonObject(String title, String message, String detail, String startTime, String endTime) {
    JSONObject result = new JSONObject();
    result.put("zh_cn", createZhCNJsonObject(title, message, detail, startTime, endTime));
    return result;
}
private static JSONObject createZhCNJsonObject(String title, String message, String detail, String startTime, String endTime) {
    JSONObject result = new JSONObject();
    result.put("title", title);
    result.put("content", createContentList(message, detail, startTime, endTime));
    return result;
}
private static JSONArray createContentList(String message, String detail, String startTime, String endTime) {
    JSONArray result = new JSONArray();
    JSONArray item1 = new JSONArray();
    item1.add(createInnerHeadContent("message"));
    item1.add(createInnerTextContent(message));
    result.add(item1);
    JSONArray item2 = new JSONArray();
    item2.add(createInnerHeadContent("detail"));
    item2.add(createInnerTextContent(detail));
    result.add(item2);
    JSONArray item3 = new JSONArray();
    item3.add(createInnerHeadContent("startTime"));
    item3.add(createInnerTextContent(startTime));
    result.add(item3);
    JSONArray item4 = new JSONArray();
    item4.add(createInnerHeadContent("endTime"));
    item4.add(createInnerTextContent(endTime));
    result.add(item4);
    return result;
}
private static JSONObject createInnerHeadContent(String tag) {
    JSONObject result = new JSONObject();
    result.put("tag", "text");
    result.put("text", tag + ": ");
    return result;
}
private static JSONObject createInnerTextContent(String text) {
    JSONObject result = new JSONObject();
    result.put("tag", "text");
    result.put("text", text);
    return result;
}
  • 再创建完整的 json 对象

完整代码如下

Java 版本
public class FeishuWebhook {
    private static final Logger logger = LoggerFactory.getLogger(FeishuWebhook.class);
    public static final String DEFAULT_DATETIME_FORMATTER_STR = "yyyy-MM-dd HH:mm:ss";
    public static final DateTimeFormatter DEFAULT_DATETIME_FORMATTER = DateTimeFormatter.ofPattern(DEFAULT_DATETIME_FORMATTER_STR);

    public static void send(String url, String secret, AlertDO alertDO) {
        logger.info("FeishuWebhook.send, url:{}, alertDO={}", url, alertDO);
        JSONObject requestBody = createRequestBody(secret, alertDO);
        logger.info("requestBody:{}", requestBody);
        JSONObject result = HttpUtils.postForJsonObject(url, null, null, requestBody);
        logger.info("result:{}", result);
    }

    private static String genSign(String secret, long timestamp) throws NoSuchAlgorithmException, InvalidKeyException {
        String stringToSign = timestamp + "\n" + secret;
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(stringToSign.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
        byte[] signData = mac.doFinal(new byte[]{});
        return new String(Base64.encodeBase64(signData));
    }

    private static JSONObject createRequestBody(String secret, AlertDO alertDO) {
        JSONObject requestBody = new JSONObject();
        long seconds = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().getEpochSecond();
        logger.info("seconds:{}", seconds);
        try {
            String sign = genSign(secret, seconds);
            requestBody.put("timestamp", seconds);
            requestBody.put("sign", sign);
            requestBody.put("msg_type", "post");
            String title = "通知";
            String message = alertDO.getMessage();
            String detail = alertDO.getDetail();
            String startTime = DEFAULT_DATETIME_FORMATTER.format(LocalDateTime.ofInstant(alertDO.getStartTime().toInstant(), ZoneId.systemDefault()));
            String endTime = DEFAULT_DATETIME_FORMATTER.format(LocalDateTime.ofInstant(alertDO.getEndTime().toInstant(), ZoneId.systemDefault()));
            requestBody.put("content", createOuterContent(title, message, detail, startTime, endTime));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return requestBody;
    }

    private static JSONObject createOuterContent(String title, String message, String detail, String startTime, String endTime) {
        JSONObject result = new JSONObject();
        result.put("post", createPostJsonObject(title, message, detail, startTime, endTime));
        return result;
    }

    private static JSONObject createPostJsonObject(String title, String message, String detail, String startTime, String endTime) {
        JSONObject result = new JSONObject();
        result.put("zh_cn", createZhCNJsonObject(title, message, detail, startTime, endTime));
        return result;
    }

    private static JSONObject createZhCNJsonObject(String title, String message, String detail, String startTime, String endTime) {
        JSONObject result = new JSONObject();
        result.put("title", title);
        result.put("content", createContentList(message, detail, startTime, endTime));
        return result;
    }

    private static JSONArray createContentList(String message, String detail, String startTime, String endTime) {
        JSONArray result = new JSONArray();
        JSONArray item1 = new JSONArray();
        item1.add(createInnerHeadContent("message"));
        item1.add(createInnerTextContent(message));
        result.add(item1);
        JSONArray item2 = new JSONArray();
        item2.add(createInnerHeadContent("detail"));
        item2.add(createInnerTextContent(detail));
        result.add(item2);
        JSONArray item3 = new JSONArray();
        item3.add(createInnerHeadContent("startTime"));
        item3.add(createInnerTextContent(startTime));
        result.add(item3);
        JSONArray item4 = new JSONArray();
        item4.add(createInnerHeadContent("endTime"));
        item4.add(createInnerTextContent(endTime));
        result.add(item4);
        return result;
    }

    private static JSONObject createInnerHeadContent(String tag) {
        JSONObject result = new JSONObject();
        result.put("tag", "text");
        result.put("text", tag + ": ");
        return result;
    }

    private static JSONObject createInnerTextContent(String text) {
        JSONObject result = new JSONObject();
        result.put("tag", "text");
        result.put("text", text);
        return result;
    }
}
Python 版本

FeishuBotHypertextWithSecret.py

import base64
import hashlib
import hmac
from datetime import datetime
import requests

WEBHOOK_URL = "https://open.feishu.cn/open-apis/bot/v2/hook/xx"
WEBHOOK_SECRET = "ssssssss"

class LarkBot:
    def __init__(self, secret: str) -> None:
        if not secret:
            raise ValueError("invalid secret key")
        self.secret = secret

    def gen_sign(self, timestamp: int) -> str:
        string_to_sign = '{}\n{}'.format(timestamp, self.secret)
        hmac_code = hmac.new(string_to_sign.encode("utf-8"), digestmod=hashlib.sha256).digest()
        sign = base64.b64encode(hmac_code).decode('utf-8')
        return sign

    def send(self) -> None:
        timestamp = int(datetime.now().timestamp())
        sign = self.gen_sign(timestamp)
        params = {
            "timestamp": timestamp,
            "sign": sign,
            "msg_type": "post",
            "content": {
                "post": {
                    "zh_cn": {
                        "title": "项目更新通知",
                        "content": [
                            [{"tag": "text", "text": "项目有更新: "}, {"tag": "a", "text": "请查看", "href": "http://www.example.com/"}, {"tag": "at", "user_id": "ou_18eac8********17ad4f02e8bbbb"}]
                        ]
                    }
                }
            }
        }
        resp = requests.post(url=WEBHOOK_URL, json=params)
        resp.raise_for_status()
        result = resp.json()
        if result.get("code") and result["code"] != 0:
            print(result["msg"])
            return
        print("消息发送成功")

def main():
    bot = LarkBot(secret=WEBHOOK_SECRET)
    bot.send()

if __name__ == '__main__':
    main()

LarkBotWithoutSecret.py

from datetime import datetime
import requests

WEBHOOK_URL = "https://open.feishu.cn/open-apis/bot/v2/hook/sss"

class LarkBot:
    def send(self, content: str) -> None:
        timestamp = int(datetime.now().timestamp())
        params = {
            "timestamp": timestamp,
            "msg_type": "text",
            "content": {"text": content},
        }
        resp = requests.post(url=WEBHOOK_URL, json=params)
        resp.raise_for_status()
        result = resp.json()
        if result.get("code") and result["code"] != 0:
            print(result["msg"])
            return
        print("消息发送成功")

def main():
    bot = LarkBot()
    bot.send(content="我是一只高级鸽子!")

if __name__ == '__main__':
    main()

目录

  1. 发送 Webhook 到飞书机器人
  2. 创建自定义机器人
  3. 使用 Java 发送 HTTP POST 到自定义机器人
  4. 完整代码如下
  5. Java 版本
  6. Python 版本

更多推荐文章

查看全部
  • 学生如何申请及使用 GitHub Copilot 编程助手
  • 基于 uni-app 与 AI 辅助开发扫码点餐小程序
  • FPGA 千兆以太网 SGMII 接口配置实战
  • OpenClaw 开源机器人实现空间记忆,具身智能迎来新突破
  • 2019 年 CSP-S 提高组初赛真题解析:取石子游戏
  • Python 音乐推荐系统:Django+Echarts+协同过滤算法
  • 核心期刊及 SCI 投稿中 AIGC 检测标准与降重策略
  • 拆解 Linux 中的 IP 协议与数据链路层:地址、路由与分片逻辑
  • 基于 Coze 构建专属 AI 应用:从智能体到 Web 部署实战
  • 实用 AI 写作平台推荐:涵盖日常、论文及职场场景
  • Python 本地 AI 问答系统搭建:环境配置与 RAG 实践
  • DevEco Studio 配置构建:HarmonyOS Next 多目标产物定制
  • 2025 年 12 月 GESP C++ 四级真题解析
  • Manacher(马拉车)算法详解:求解最长回文子串
  • 解决 Java 编译报错:源发行版 17 需要目标发行版 17
  • Doubao-Seed-Code 接入 Claude Code 本地开发实战指南
  • 前端 PWA:构建离线可用与可安装 Web 应用
  • 基于 Java SSM 的乡村小学校园官网系统设计与实现
  • 嵌入式 ARM Linux 系统构成:Linux 内核层
  • C++ 模拟实现红黑树 (RBTree)

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online