如何捕获Slack消息按钮点击事件并获取输入值?NodeJS代码排查
无法捕获Slack交互式消息的提交事件
我正在开发一个NodeJS项目,用于连接Slack、发送交互式消息并接收反馈。已成功发送包含输入框和提交按钮的消息,但点击提交后无法捕获事件,代码如下:
发送消息的代码
require("dotenv").config(); const { App } = require("@slack/bolt"); const express = require('express') const app = express() const axios = require('axios'); const APP_PORT = 3001 const LISTEN_PORT = 3002 const { createMessageAdapter } = require('@slack/interactive-messages'); const slackSigningSecret = process.env.SLACK_SIGNING_SECRET; const slackInteractions = createMessageAdapter(slackSigningSecret); app.use('/listen', slackInteractions.requestListener()); (async () => { const server = await slackInteractions.start(LISTEN_PORT ); console.log(`Listening for events on ${server.address().port}`); })(); app.listen(APP_PORT, () => { console.log(`App running on port ${APP_PORT}.`) }) app.get('/survey', async function sendmessage(){ const url = 'https://slack.com/api/chat.postMessage'; const res = await axios.post(url, { channel: '#test', blocks: JSON.stringify([ { type: "section", text: { type: "mrkdwn", text: "Survey" } }, { type: 'input', block_id: 'txt_input', label: { type: 'plain_text', text: 'Response' }, element: { type: 'plain_text_input', action_id: 'text_input', placeholder: { type: 'plain_text', text: 'Your response' }, multiline: true } }, { type: "actions", block_id: "btn_submit", elements: [ { type: "button", text: { type: "plain_text", emoji: true, text: "Submit" }, style: "primary", value: "1" } ] } ]) }, { headers: { authorization: `Bearer ${process.env.SLACK_BOT_TOKEN}`}}); });
添加的事件监听代码
slackInteractions.action({ type: 'button' }, (payload, respond) => { // Logs the contents of the action to the console console.log('payload', payload); }); slackInteractions.action({ type: 'message_action' }, (payload, respond) => { // Logs the contents of the action to the console console.log('payload', payload); });
点击提交按钮后始终无法捕获事件,请问代码存在什么问题?
问题分析与修复方案
你的代码存在以下几个关键问题:
1. 重复启动HTTP服务,导致交互请求路由混乱
你同时启动了两个独立的HTTP服务:
- 调用
slackInteractions.start(LISTEN_PORT)启动了监听3002端口的服务 - 调用
app.listen(APP_PORT)启动了监听3001端口的Express服务
但你仅将Slack交互处理器挂载到了Express的/listen路径下,若Slack后台配置的请求URL指向Express的3001端口,那3002端口的服务完全冗余,还会干扰请求路由逻辑。
2. 错误序列化blocks参数
发送消息时,你用JSON.stringify()手动将blocks数组转为字符串,但axios会自动将请求体序列化为JSON格式,这会导致Slack接收到的是字符串而非预期的数组,虽然消息能显示,但会影响交互事件的正常触发。
3. 按钮缺少action_id属性
Slack的交互事件需要通过action_id匹配对应的监听逻辑,你的提交按钮未设置该属性,导致slackInteractions.action({ type: 'button' })无法捕获到点击事件。
修复后的完整代码
require("dotenv").config(); const express = require('express') const app = express() const axios = require('axios'); const APP_PORT = 3001 const { createMessageAdapter } = require('@slack/interactive-messages'); const slackSigningSecret = process.env.SLACK_SIGNING_SECRET; const slackInteractions = createMessageAdapter(slackSigningSecret); // 将Slack交互请求挂载到Express的/listen路径 app.use('/listen', slackInteractions.requestListener()); // 通过action_id匹配按钮点击事件 slackInteractions.action({ action_id: 'submit_btn' }, (payload, respond) => { // 从payload中获取用户输入的内容 const userResponse = payload.state.values.txt_input.text_input.value; console.log('用户反馈内容:', userResponse); console.log('完整事件数据:', payload); // 可选:给用户发送即时反馈 respond({ text: '感谢你的反馈!' }); }); app.get('/survey', async function sendmessage(){ const url = 'https://slack.com/api/chat.postMessage'; const res = await axios.post(url, { channel: '#test', // 移除手动序列化,直接传入数组 blocks: [ { type: "section", text: { type: "mrkdwn", text: "Survey" } }, { type: 'input', block_id: 'txt_input', label: { type: 'plain_text', text: 'Response' }, element: { type: 'plain_text_input', action_id: 'text_input', placeholder: { type: 'plain_text', text: 'Your response' }, multiline: true } }, { type: "actions", block_id: "btn_submit", elements: [ { type: "button", // 添加action_id用于匹配事件 action_id: "submit_btn", text: { type: "plain_text", emoji: true, text: "Submit" }, style: "primary", value: "1" } ] } ] }, { headers: { authorization: `Bearer ${process.env.SLACK_BOT_TOKEN}`}}); }); // 只启动一次Express服务 app.listen(APP_PORT, () => { console.log(`App running on port ${APP_PORT}.`) })
额外注意事项
- 确保Slack后台的交互式组件请求URL配置为
http://你的服务器地址:3001/listen(本地开发需用ngrok等工具暴露端口) - 验证
SLACK_SIGNING_SECRET和SLACK_BOT_TOKEN的权限,bot需拥有chat:write等相关权限
内容的提问来源于stack exchange,提问作者N.D.H.Vu
相关产品推荐
相关产品推荐

