当前位置: 首页 > news >正文

利用云函数做一个钉钉机器人提醒功能教程

今天在业务开发中帮助客户实现了一个通过钉钉实时提醒平台订单的功能,发现还挺好使的,而且接入也比较简单,分享一下,这个功能的泛用性挺强的,基本所有的需要实时提醒通知一类的都可以通过这个来实现。

首先就是你需要有一个企业的钉钉(实测钉钉甚至都不需要认证),然后在钉钉开放平台创建一个应用并添加机器人应用能力,最后发布一下,前置条件就搞定了。

接近进入钉钉APP创建一个群(企业钉钉创建完成后会默认有一个全体人员的群,可以直接使用),然后右上方进入群设置,下滑可以看到机器人,添加我们刚刚创建的机器人,最后进入机器人列表点击我们刚刚添加的机器人可以看到一个webhook,复杂一下,前置任务就都完成了。

接着就是云函数代码部分,可以参考一下代码:

'use strict';const crypto = require('crypto');/** * 钉钉机器人配置:Webhook、加签、可选内部密钥。 * @type {{ WEBHOOK: string, SIGN_SECRET: string, INTERNAL_SECRET: string }} */const DINGTALK_CONFIG = { WEBHOOK: '', SIGN_SECRET: '', INTERNAL_SECRET: ''};/** * 为钉钉加签机器人拼接 timestamp、sign。 * @param {string} webhookUrl 原始 Webhook * @param {string} secret 加签密钥 * @returns {string} 完整 URL */function buildSignedWebhookUrl(webhookUrl, secret) { const timestamp = Date.now(); const stringToSign = `${timestamp}\n${secret}`; const hmac = crypto.createHmac('sha256', secret); hmac.update(stringToSign); const sign = encodeURIComponent(hmac.digest('base64')); const sep = webhookUrl.includes('?') ? '&' : '?'; return `${webhookUrl}${sep}timestamp=${timestamp}&sign=${sign}`;}/** * 解析出本次请求使用的完整 Webhook URL(含加签参数)。 * @returns {string} 空字符串表示未配置 */function getWebhookRequestUrl() { const webhookUrl = String(DINGTALK_CONFIG.WEBHOOK || '').trim(); if (!webhookUrl) { return ''; } const secret = String(DINGTALK_CONFIG.SIGN_SECRET || '').trim(); return secret ? buildSignedWebhookUrl(webhookUrl, secret) : webhookUrl;}/** * 校验服务端互调密钥(配置了才校验)。 * @param {Object} args 入参 * @returns {boolean} 是否通过 */function checkInternalSecret(args) { const expected = String(DINGTALK_CONFIG.INTERNAL_SECRET || '').trim(); if (!expected) { return true; } const got = String((args && args.internalSecret) || '').trim(); return got === expected;}/** * 金额格式化为两位小数展示。 * @param {number|string|null|undefined} v 元 * @returns {string} */function formatAmountYuan(v) { if (v == null || v === '') { return '-'; } const n = Number(v); if (!Number.isFinite(n)) { return String(v); } return n.toFixed(2);}/** * 组装新订单提醒的正文(Markdown)。 * @param {Object} p * @param {string} p.businessLabel * @param {string} p.orderNo * @param {number|string} [p.amountYuan] * @param {string} p.mobileText * @param {string} [p.userId] * @param {string} p.timeStr * @returns {string} */function buildOrderCardMarkdown(p) { const { businessLabel, orderNo, amountYuan, mobileText, userId, timeStr } = p; const blocks = [ `## 新订单 · ${businessLabel}`, '', '> 后台有新的订单,请注意查看。', '', '---', '', `**订单号**\n\n\`${orderNo}\``, '', `**应付金额**\n\n**¥ ${formatAmountYuan(amountYuan)}**`, '', `**用户手机**\n\n${mobileText}` ]; if (userId) { blocks.push('', `**用户标识**\n\n\`${userId}\``); } blocks.push('', '---', '', `*${timeStr}*`); return blocks.join('\n');}/** * POST 任意钉钉机器人消息体。 * @param {Object} body msgtype 及对应字段 * @returns {Promise<{ errCode: number|string, errMsg: string, detail?: Object }>} */async function postToDingTalk(body) { const url = getWebhookRequestUrl(); if (!url) { return { errCode: 'CONFIG', errMsg: 'WEBHOOK 未配置' }; } try { const httpRes = await uniCloud.httpclient.request(url, { method: 'POST', contentType: 'json', data: body, dataType: 'json', timeout: 10000 }); const status = httpRes.status; const data = httpRes.data; if (status !== 200 || (data && data.errcode !== 0)) { console.error( '[dingtalk-notify-co] webhook failed', status, data && JSON.stringify(data) ); return { errCode: 'UPSTREAM', errMsg: 'dingtalk webhook failed', detail: data }; } return { errCode: 0, errMsg: 'ok' }; } catch (e) { console.error('[dingtalk-notify-co] request error', e && e.message ? e.message : e); return { errCode: 'UPSTREAM', errMsg: e && e.message ? e.message : 'request error' }; }}module.exports = { /** * 新订单创建后向管理员推送简要提醒(用户端通常只留了手机号,完整信息在管理后台查看)。 * 本地调试:在 dingtalk-notify-co.param.js 里调用本方法并传入模拟参数即可。 * @param {Object} args * @param {string} args.businessLabel 业务名称,如「工商注册」「代理记账」 * @param {string} args.orderNo 订单号 * @param {number|string} [args.amountYuan] 金额(元) * @param {string} [args.userId] 用户标识(后台查单用) * @param {string} [args.contactMobile] 用户下单时填写的手机号 * @param {string} [args.internalSecret] 与 DINGTALK_CONFIG.INTERNAL_SECRET 一致时方可调用(若已填写该配置) * @returns {Promise<{ errCode: number|string, errMsg: string }>} */ async notifyOrderCreated(args = {}) { if (!checkInternalSecret(args)) { return { errCode: 'FORBIDDEN', errMsg: 'forbidden' }; } if (!getWebhookRequestUrl()) { return { errCode: 0, errMsg: 'skipped_no_webhook' }; } const { businessLabel, orderNo, amountYuan, userId, contactMobile } = args || {}; if (!businessLabel || !orderNo) { return { errCode: 'PARAM_INVALID', errMsg: '缺少 businessLabel 或 orderNo' }; } const mobileText = String(contactMobile || '').trim() || '(未填写)'; const timeStr = new Date().toLocaleString('zh-CN', { hour12: false }); const cardText = buildOrderCardMarkdown({ businessLabel, orderNo, amountYuan, mobileText, userId, timeStr }); return postToDingTalk({ msgtype: 'markdown', markdown: { title: `新订单 · ${businessLabel}`, text: cardText } }); }};

钉钉消息是以md格式来进行的,所以使用场景还是挺方便的,编辑起来也很简单。将webhook的链接放入就行了,其他两个参数可以不填写,当然如果为了信息安全,配置一下更好。

http://www.jsqmd.com/news/684195/

相关文章:

  • Qwen3.5-2B赋能前端开发:自动生成JavaScript组件代码与文档
  • RWKV7-1.5B-world保姆级教程:Gradio界面日志导出功能,用于对话质量人工评估
  • 往前走,做更好的自己
  • JetBrains IDE试用期重置终极指南:2026年免费解锁30天完整功能
  • 大一新生组队玩转CUIT智能车:从零到跑完赛道,我们的STM32电磁循迹调车全记录
  • 别再死记硬背命令了!用Conda+Fastp+Bowtie2搞定ATAC-seq上游分析(附完整代码与避坑记录)
  • 【2026最新】英文论文降AI率怎么做?6大主流工具实测盘点,这3个坑千万别踩!
  • ESP32玩转网络转发:除了做中继,你的AP+STA模式还能这样用(附IoT项目思路)
  • 建第四个 AI 爬虫逆向 500 人交流群
  • 保姆级教程:用K210和MaixPy IDE从零搭建人脸识别系统(附完整代码与模型下载)
  • 从Wi-Fi到6G:拆解太赫兹频率梳在下一代通信中的关键角色
  • DRV8301上电自检与SPI通信失败的硬件排查指南(VDD_SPI、EN_GATE、PVDD一个都不能少)
  • 告别格式错乱!英文论文降AI率全攻略:6款免费/好用工具实测红黑榜
  • SQL中如何查找特定的空值行:WHERE IS NULL深度解析
  • 告别内核打印:用devmem2在嵌入式Linux上直接读写寄存器的保姆级教程
  • [特殊字符] Meixiong Niannian画图引擎跨平台适配:ARM64服务器/NVIDIA Jetson边缘设备部署
  • 新中新身份证阅读器SDK避坑指南:解决SynIDCardAPI.dll调用中的5个常见问题
  • 字符串匹配算法:KMP 算法详解
  • 从一次订单失败回滚看Seata AT模式:一个真实微服务事务的完整生命周期
  • Redis--基础知识点--29--Redis瓶颈
  • 名画检测数据集412张VOC+YOLO格式
  • Phi-3.5-mini-instruct政务应用:公文起草辅助+政策条款关联检索系统
  • Jimeng AI Studio实战:VLOOKUP函数在大数据处理中的应用
  • 避坑指南:Keil5开发LPC17XX时,UART中断与字节超时处理的那些‘坑’
  • 别慌!投稿后Editorial Manager状态卡在‘Under Review’?这几种情况帮你读懂编辑心思
  • Java:chain.doFilter
  • 别再死记公式!图解双轮差速机器人运动学:从v和ω到左右轮速的直观理解
  • 语音识别化技术中的声学模型语言模型与解码器
  • 5分钟快速上手LeRobot:让AI机器人控制变得简单如Python编程!
  • 保姆级教程:用ESP32和MicroPython给1.8寸ST7735屏做个网络时钟(附完整代码包)