发送webhook到飞书机器人

发送webhook到飞书机器人

发送webhook到飞书机器人

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

创建自定义机器人

  1. 邀请自定义机器人进群。
  2. 获取签名校验
    在 安全设置 区域,选择 签名校验。

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

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

使用java发送http post到自定义机器人

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

完整代码如下

java版本

publicclassFeishuWebhook{privatestaticfinalLogger logger =LoggerFactory.getLogger(FeishuWebhook.class);publicstaticfinalStringDEFAULT_DATETIME_FORMATTER_STR="yyyy-MM-dd HH:mm:ss";publicstaticfinalDateTimeFormatterDEFAULT_DATETIME_FORMATTER=DateTimeFormatter.ofPattern(DEFAULT_DATETIME_FORMATTER_STR);publicstaticvoidsend(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);}privatestaticStringgenSign(String secret,long timestamp)throwsNoSuchAlgorithmException,InvalidKeyException{//把timestamp+"\n"+密钥当做签名字符串String stringToSign = timestamp +"\n"+ secret;//使用HmacSHA256算法计算签名Mac mac =Mac.getInstance("HmacSHA256"); mac.init(newSecretKeySpec(stringToSign.getBytes(StandardCharsets.UTF_8),"HmacSHA256"));byte[] signData = mac.doFinal(newbyte[]{});returnnewString(Base64.encodeBase64(signData));}privatestaticJSONObjectcreateRequestBody(String secret,AlertDO alertDO){JSONObject requestBody =newJSONObject();long seconds =LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().getEpochSecond(); logger.info("seconds:{}", seconds);// int seconds = 1734515343;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;}privatestaticJSONObjectcreateOuterContent(String title,String message,String detail,String startTime,String endTime){JSONObject result =newJSONObject(); result.put("post",createPostJsonObject(title, message, detail, startTime, endTime));return result;}privatestaticJSONObjectcreatePostJsonObject(String title,String message,String detail,String startTime,String endTime){JSONObject result =newJSONObject(); result.put("zh_cn",createZhCNJsonObject(title, message, detail, startTime, endTime));return result;}privatestaticJSONObjectcreateZhCNJsonObject(String title,String message,String detail,String startTime,String endTime){JSONObject result =newJSONObject(); result.put("title", title); result.put("content",createContentList(message, detail, startTime, endTime));return result;}privatestaticJSONArraycreateContentList(String message,String detail,String startTime,String endTime){JSONArray result =newJSONArray();JSONArray item1 =newJSONArray(); item1.add(createInnerHeadContent("message")); item1.add(createInnerTextContent(message)); result.add(item1);JSONArray item2 =newJSONArray(); item2.add(createInnerHeadContent("detail")); item2.add(createInnerTextContent(detail)); result.add(item2);JSONArray item3 =newJSONArray(); item3.add(createInnerHeadContent("startTime")); item3.add(createInnerTextContent(startTime)); result.add(item3);JSONArray item4 =newJSONArray(); item4.add(createInnerHeadContent("endTime")); item4.add(createInnerTextContent(endTime)); result.add(item4);return result;}privatestaticJSONObjectcreateInnerHeadContent(String tag){JSONObject result =newJSONObject(); result.put("tag","text"); result.put("text", tag+": ");return result;}privatestaticJSONObjectcreateInnerTextContent(String text){JSONObject result =newJSONObject(); 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"classLarkBot:def__init__(self, secret:str)->None:ifnot secret:raise ValueError("invalid secret key") self.secret = secret defgen_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 defsend(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"])returnprint("消息发送成功")defmain(): 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"classLarkBot:defsend(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"])returnprint("消息发送成功")defmain(): bot = LarkBot() bot.send(content="我是一只高级鸽子!")if __name__ =='__main__': main()

Read more

Moon VR Video Player中文版下载地址及使用教程:支持8K/12K+多音轨外挂字幕 Moon VR Video Player中文版、Moon VR播放器下载、VR视频播放器推荐、Ste

Moon VR Video Player中文版下载地址及使用教程:支持8K/12K+多音轨外挂字幕 Moon VR Video Player中文版、Moon VR播放器下载、VR视频播放器推荐、Ste

Moon VR Video Player中文版下载地址及使用教程:支持8K/12K+多音轨外挂字幕 关键词:Moon VR Video Player中文版、Moon VR播放器下载、VR视频播放器推荐、SteamVR播放器、多音轨外挂字幕播放器、8K 12K VR播放 作为一个长期折腾的开发者,这段时间一直在找一款真正稳定、格式兼容性强、支持多音轨和外挂字幕的VR播放器。市面上不少播放器要么格式支持有限,要么在8K以上直接卡顿,更别说复杂场景下的字幕和音轨切换。 这次测试的是 Moon VR Video Player(月亮播放器)v835 + 2.8.18 中文版,整体体验确实比很多常见播放器更完整。下面做一次系统梳理,方便需要的朋友参考。 下载地址 链接:https://pan.quark.cn/s/7c80590579cf 一、

DankDroneDownloader:大疆无人机固件自由下载终极指南

DankDroneDownloader:大疆无人机固件自由下载终极指南 【免费下载链接】DankDroneDownloaderA Custom Firmware Download Tool for DJI Drones Written in C# 项目地址: https://gitcode.com/gh_mirrors/da/DankDroneDownloader 想要完全掌控你的大疆无人机固件版本吗?厌倦了厂商限制固件选择权的做法?DankDroneDownloader(简称DDD)正是你需要的解决方案!这个免费开源的C#工具让你重新获得固件下载的完全自由,支持大疆全系列无人机和配件。 🚀 打破限制,重获控制权 大疆等无人机厂商常常移除旧版固件,限制用户只能使用最新版本。但很多时候,旧版固件更加稳定,或者包含某些新版移除的实用功能。DDD解决了这个痛点,为你提供完整的固件版本历史存档。 核心优势: * 支持大疆无人机全系列固件下载 * 提供Windows桌面应用程序 * 与第三方刷写工具完美兼容 * 持续更新的固件库 📋 全面支持的设备列表 DDD目前

大疆无人机常见故障提示及应对指南

大疆无人机常见故障提示及应对指南

大疆无人机在使用过程中,故障提示主要通过 DJI Fly/DJI GO 4 App 弹窗、机身指示灯状态及遥控器提示音三种方式呈现。以下按「连接通信类」「传感系统类」「动力系统类」「图传相机类」「电池电源类」五大核心场景,整理常见故障提示、核心原因及分步解决办法,帮助快速定位并处理问题。 北京云升智维科技有限责任公司是一家专业从事电子设备维修第三方服务企业,我们拥有深厚的电路原理知识和丰富的维修经验,能够为各种设备和电路板提供专业的检测和维修服务。我们的服务范围广泛,包括但不限于电路板、工控主板、工业机械、医疗设备、精密仪器、大地测量仪器及驱动器等。我们拥有一支技术过硬,经验丰富的维修团队,精通各类设备维修,结合多年实战维修经验,快速准确诊断故障,提高维修效率,为客户节省35%及以上维修成本及时间成本,我们致力于为客户提供高质量、可靠的服务,确保设备的稳定运行。我们坚持诚实守信、笃行致远的原则,以确保客户满意。 一、连接通信类故障提示 核心表现:App 提示连接异常,遥控器与无人机无法联动,

OpenClaw对接飞书机器人高频踩坑实战指南:从插件安装到回调配对全解析

前言 当前企业办公场景中,将轻量级AI框架OpenClaw与飞书机器人结合,能够快速实现智能交互、流程自动化等功能。然而,在实际对接过程中,开发者常常因权限配置、环境依赖、回调设置等细节问题陷入反复试错。本文以“问题解决”为核心,梳理了10个典型踩坑点,每个问题均配套原因分析、排查步骤和实操案例。同时,补充高效调试技巧与功能扩展建议,帮助开发者系统性地定位并解决对接障碍,提升落地效率。所有案例基于Windows 11环境、OpenClaw最新稳定版及飞书开放平台最新界面验证,解决方案可直接复用。 一、前置准备(快速自查) 为避免基础环境问题浪费时间,建议在开始前确认以下三点: * OpenClaw已正确安装,终端执行 openclaw -v 可查看版本(建议使用最新版,旧版本可能存在插件兼容风险)。 * Node.js版本不低于v14,npm版本不低于v6,通过 node -v 和 npm -v 验证,防止因依赖版本过低导致插件安装失败。 * 飞书账号需具备企业开发者权限(企业账号需管理员授权,个人账号默认具备)