如何让Twilio同时向Kommo CRM与谷歌应用发送Webhook?
解决Twilio同时向Kommo CRM和谷歌应用推送Webhook的问题
问题核心
Kommo CRM(原Amo CRM)内置的Twilio集成可收发短信,但无法显示接收的图片。需要实现Twilio同时触发两个Webhook:一个推送至Kommo保留消息接收功能,另一个推送至谷歌应用处理图片。但使用自定义Twilio函数转发后,谷歌应用能正常接收消息,Kommo返回200状态码却不显示消息,推测是X-Twilio-Signature请求头验证失败导致。
原因分析
Kommo的Twilio集成会校验X-Twilio-Signature头,确保请求来自合法的Twilio源。自定义函数转发时,若直接转发原始签名或未生成符合Kommo要求的签名,Kommo会因验证不通过而忽略消息(即使返回200)。此外,原始代码手动解构参数时可能遗漏了图片相关的MediaUrlN、MediaContentTypeN等字段,导致Kommo无法处理带图片的消息。
解决方案
修改Twilio函数,完成以下关键操作:
- 收集Twilio传递的所有请求参数(包括媒体相关字段)
- 针对Kommo的Webhook URL重新生成合法的
X-Twilio-Signature - 同时向Kommo和谷歌应用发起请求,确保两者都能收到完整且合法的消息数据
修改后的代码
const axios = require('axios'); const qs = require('querystring'); const { createHmac } = require('crypto'); // 生成符合Twilio要求的签名 function generateTwilioSignature(authToken, targetUrl, params) { // 按参数名排序并拼接,Twilio签名生成要求参数有序 const sortedParamStr = Object.keys(params) .sort() .map(key => `${key}=${encodeURIComponent(params[key])}`) .join('&'); const signatureBase = targetUrl + sortedParamStr; // 使用HMAC-SHA1生成签名 const hmac = createHmac('sha1', authToken); hmac.update(Buffer.from(signatureBase, 'utf-8')); return `sha1=${hmac.digest('base64')}`; } exports.handler = function(context, event, callback) { const twiml = new Twilio.twiml.MessagingResponse(); // 从Twilio函数环境变量获取Auth Token(避免硬编码) const twilioAuthToken = context.TWILIO_AUTH_TOKEN; // 目标Webhook地址 const kommoWebhook = "https://chatstwilio.amocrm.com/twilio_sms/webhook/twilio_message/incoming"; const googleAppWebhook = "https://script.google.com/macros/s/AKfycbyrFMmuBDpjBIV05vD2utzL9v5au_hlcHbIA4uj7D09JkKW4XiDW9FoW/exec?fn=twiliomedia"; // 收集所有请求参数,包括图片相关字段 const requestParams = { ...event }; // 生成Kommo请求所需的签名头 const kommoSignature = generateTwilioSignature(twilioAuthToken, kommoWebhook, requestParams); // Kommo请求配置:添加签名和正确的Content-Type const kommoRequestConfig = { headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'X-Twilio-Signature': kommoSignature } }; // 谷歌应用请求配置 const googleRequestConfig = { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }; // 并行发送两个请求 Promise.all([ axios.post(kommoWebhook, qs.stringify(requestParams), kommoRequestConfig), axios.post(googleAppWebhook, qs.stringify(requestParams), googleRequestConfig) ]) .then(([kommoRes, googleRes]) => { console.log(`Kommo响应状态:${kommoRes.status}`); console.log(`谷歌应用响应状态:${googleRes.status}`); callback(null, twiml); }) .catch(err => { console.error('请求失败:', err); callback(err); }); };
关键配置步骤
- 添加环境变量:在Twilio函数控制台的"环境变量"中新增
TWILIO_AUTH_TOKEN,值为你的Twilio账户Auth Token(可在Twilio控制台获取)。 - 替换URL:将代码中的
kommoWebhook和googleAppWebhook替换为实际的Webhook地址。 - 部署函数:保存并部署修改后的Twilio函数,将Twilio短信接收的Webhook URL设置为该函数的地址。
验证方法
发送一条带图片的短信到Twilio号码,检查:
- Kommo CRM中是否正常显示消息及图片(若Kommo后续需展示图片,可通过谷歌应用处理后将图片URL同步回Kommo)
- 谷歌应用是否收到包含
MediaUrl0、MediaContentType0等字段的请求参数
内容的提问来源于stack exchange,提问作者Kolya Smith
相关产品推荐
相关产品推荐

