尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

OpenClaw插件开发:为GLM-4.7-Flash扩展钉钉消息通道

OpenClaw插件开发:为GLM-4.7-Flash扩展钉钉消息通道 OpenClaw插件开发为GLM-4.7-Flash扩展钉钉消息通道1. 为什么需要开发钉钉插件上周三凌晨2点我被手机震动惊醒——团队在飞书群里紧急讨论一个线上问题。当我挣扎着打开电脑准备参与排查时突然意识到如果OpenClaw能通过钉钉通知我就能直接用手机语音回复处理方案。这个深夜插曲促使我决定为GLM-4.7-Flash开发钉钉消息通道插件。与飞书相比钉钉在企业服务市场占有率更高。根据我的实践观察钉钉的OAuth2.0授权流程更简洁但消息加解密机制却比飞书复杂得多。开发过程中最让我意外的是钉钉官方文档中至少有3种不同的加解密方案而飞书只有标准AES模式。2. 开发环境准备2.1 基础工具链配置我选择在搭载M2芯片的MacBook Pro上进行开发这里分享几个关键配置细节# 使用nvm管理Node版本钉钉SDK要求Node 18 nvm install 18.20.2 nvm use 18.20.2 # 初始化插件项目目录结构 mkdir dingtalk-channel cd dingtalk-channel npm init -y mkdir -p src/{handlers,services,utils} test特别注意钉钉官方JS SDK与OpenClaw的TypeScript类型定义存在冲突。我通过以下方式解决// tsconfig.json 新增配置 { compilerOptions: { skipLibCheck: true, esModuleInterop: true } }2.2 钉钉开发者账号准备在钉钉开放平台创建应用时有3个关键配置项常被忽略IP白名单必须添加部署服务器的公网IP可通过curl ifconfig.me获取回调域名需要填写OpenClaw网关的完整URL如https://your-domain.com/dingtalk/callback权限范围至少要勾选消息通知和通讯录只读权限建议在开发阶段启用测试企业模式可以绕过部分审核流程。我在首次提交时因为漏选接收员工消息权限导致消息回调失败浪费了两小时排查时间。3. OAuth2.0接入实战3.1 授权流程差异对比与飞书的静默授权不同钉钉采用显式授权页面。以下是核心代码片段// src/services/auth.service.ts import { DingTalkClient } from dtfe/nodesdk; export class AuthService { private client: DingTalkClient; constructor(private readonly config: DingTalkConfig) { this.client new DingTalkClient({ appKey: config.appKey, appSecret: config.appSecret, }); } async getAuthUrl(state: string): Promisestring { return this.client.getAuthorizeUrl({ redirect_uri: this.config.redirectUri, scope: openid, state, response_type: code, }); } }实际开发中发现一个坑点钉钉的redirect_uri必须与开放平台配置完全一致包括末尾的/符号。我通过添加URL规范化处理解决了这个问题// src/utils/url.util.ts export function normalizeUrl(url: string): string { return url.endsWith(/) ? url : ${url}/; }3.2 令牌管理策略钉钉的access_token有效期只有2小时比飞书的48小时短得多。我的解决方案是结合Redis实现自动刷新// src/services/token.service.ts async refreshToken(): Promisevoid { const { access_token, expires_in } await this.client.getAccessToken(); await this.redis.set( dingtalk:access_token, access_token, EX, expires_in - 300 // 提前5分钟过期 ); }在网关启动时注册定时任务// src/index.ts const tokenService new TokenService(); schedule.scheduleJob(*/30 * * * *, () tokenService.refreshToken());4. 消息加解密实现4.1 加解密方案选择钉钉提供三种加解密模式经过测试我选择了最稳定的加密模式3// src/utils/crypto.util.ts import { createCipheriv, createDecipheriv } from crypto; export class DingTalkCrypto { private readonly aesKey: Buffer; constructor(private readonly token: string, encodingAesKey: string) { this.aesKey Buffer.from(${encodingAesKey}, base64); } decrypt(msg: string): string { const decipher createDecipheriv(aes-256-cbc, this.aesKey, this.aesKey.slice(0, 16)); let decrypted decipher.update(msg, base64, utf8); decrypted decipher.final(utf8); return decrypted; } }注意钉钉的encodingAesKey需要补字符才能正确解码这个细节官方文档没有明确说明。4.2 消息处理器实现消息处理的核心是正确解析钉钉的事件格式。以下是我总结的消息类型处理矩阵消息类型处理方式响应要求文本消息直接转发给GLM-4.7-Flash必须5秒内响应事件消息本地处理不转发返回success字符串富文本消息提取文字内容后转发可异步响应实现代码示例// src/handlers/message.handler.ts async handleMessage(event: DingTalkEvent): PromiseResponse { if (event.EventType chat_message) { const question this.extractText(event.Message); const answer await this.glmService.query(question); return { msgtype: text, text: { content: answer } }; } return { code: 200, body: success }; }5. 插件打包与部署5.1 依赖管理技巧钉钉SDK的依赖项较多我通过webpack实现按需打包// webpack.config.js module.exports { externals: { dtfe/nodesdk: commonjs2 dtfe/nodesdk, }, };使用npm pack生成tgz包时务必包含以下文件dingtalk-channel/ ├── package.json ├── dist/ ├── config/ │ └── default.json └── assets/ └── icon.png5.2 与飞书通道的共存配置在openclaw.json中配置多通道时要注意端口冲突问题{ channels: { feishu: { enabled: true, port: 18790 }, dingtalk: { enabled: true, port: 18791 } } }启动时需要分别指定端口openclaw gateway --port 18790 --channel feishu openclaw gateway --port 18791 --channel dingtalk6. 调试与问题排查开发过程中遇到最棘手的问题是消息签名验证失败。通过以下调试步骤最终解决使用ngrok暴露本地服务确保回调地址可访问在代码中添加签名日志console.log(Computed sign:, sign, Received sign:, receivedSign);发现钉钉服务器时间与本地存在3分钟偏差添加时间容差处理const isValid Math.abs(timestamp - Date.now()) 5 * 60 * 1000;最终效果验证插件成功部署后GLM-4.7-Flash可以同时处理来自飞书和钉钉的消息查询。测试期间平均响应时间保持在1.2秒以内完全满足企业即时通讯场景需求。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。
返回列表