You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何捕获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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 02:20:55