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

使用 Java 和 Python 发送 Webhook 消息至飞书机器人

集成飞书自定义机器人需配置安全设置并获取 Webhook 地址。展示了如何通过 Java 和 Python 实现 HTTP POST 请求发送富文本消息。Java 示例包含签名校验、时间戳计算及 JSON 对象构建逻辑;Python 示例提供带密钥和无密钥两种发送方式。代码涵盖 HmacSHA256 签名算法及标准库调用,确保消息准确送达群组。

SecGuard发布于 2026/3/21更新于 2026/9/1172 浏览
使用 Java 和 Python 发送 Webhook 消息至飞书机器人

发送 webhook 到飞书机器人

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

创建自定义机器人

  1. 邀请自定义机器人进群。
  2. 获取签名校验:在安全设置区域,选择签名校验。
  3. 获取自定义机器人的 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 版本

更多推荐文章

查看全部
  • IDEA 切换 JDK 版本步骤
  • AI Agent 技术架构与落地实践指南
  • MySQL 事务与锁机制详解
  • 基于 AR 眼镜的亲戚称呼助手开发实战
  • Docker 容器内 Java 与 Python 代码运行示例
  • MySQL 事务与锁机制深度解析
  • Django Markdown 渲染中的 XSS 防护实践
  • FPGA 核心硬件资源详解:LUT、FF、BRAM、DSP 与 PLL 解析及综合报告解读
  • AI 大模型本地离线部署指南:GPT4All、LM Studio 与 Ollama 方案
  • 基于C++的多项式曲线拟合代码实现与实战
  • 第五节.Stable Diffusion大模型
  • Windows 本地零代码部署 AI 大模型实战指南
  • AI 产品经理的三重境界与核心能力模型
  • Linux 环境下使用 C++ 实现 Shell 基本功能
  • Stable Diffusion 大模型详解:版本、差异与推荐
  • Linux 信号捕捉与处理机制
  • Windows WSL Ubuntu 安装 OpenClaw 接入飞书与百炼模型指南
  • 前端权限管理实现方案:设计、路由与状态管理
  • DataX-web 安装与使用指南
  • 前端缓存策略最佳实践

相关免费在线工具

  • 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