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

使用Python Flask与Slack API处理交互式消息按钮点击的问题

解决方案:Slack应用临时消息交互与OAuth授权问题处理

问题1:获取原消息内容并发送

临时消息的交互payload本身不携带原消息,但你可以在第一次发送临时消息时,把原消息内容嵌入到按钮的value字段中,这样点击Confirm时就能从payload里拿到原消息。

修改步骤:

  1. 命令处理端点(用户发送命令时触发):捕获用户输入的原消息,发送带自定义value的临时消息
@app.route('/slack/command/', methods=['POST'])
def handle_command():
    # 拿到用户输入的原消息内容
    original_text = request.form['text']
    user_id = request.form['user_id']
    channel_id = request.form['channel_id']

    # 发送带Confirm/Cancel按钮的临时消息
    client.chat_postEphemeral(
        channel=channel_id,
        user=user_id,
        text="确认发送这条消息吗?",
        attachments=[
            {
                "actions": [
                    {
                        "name": "confirm",
                        "text": "Confirm",
                        "type": "button",
                        "value": original_text  # 把原消息存到按钮的value里
                    },
                    {
                        "name": "cancel",
                        "text": "Cancel",
                        "type": "button",
                        "value": "cancel"
                    }
                ]
            }
        ]
    )
    return "", 200
  1. 交互处理端点:从payload的actions[0]['value']取出原消息,执行发送/删除操作
payload = request.form["payload"]
payload = json.loads(payload)
if payload['type'] == 'interactive_message':
    action = payload['actions'][0]['name']
    original_message = payload['actions'][0]['value']
    channel_id = payload['channel']['id']
    message_ts = payload['message_ts']

    if action == 'confirm':
        # 发送原消息到目标频道
        client.chat_postMessage(channel=channel_id, text=original_message)
    elif action == 'cancel':
        # 删除临时消息
        client.chat_delete(channel=channel_id, ts=message_ts)

问题2:OAuth2授权与API调用权限修复

你的授权端点逻辑有误,且不需要每次发消息都调用授权接口——授权只在用户首次安装应用时执行一次,之后用存储的token调用API即可。

修改步骤:

  1. 修复授权端点:用户安装应用时,Slack会以GET请求将code参数传到你设置的回调URL,而非POST payload
@app.route('/slack/authorize/', methods=['GET'])
def get_auth_token():
    code = request.args.get('code')
    if not code:
        return "缺少授权code", 400
    
    # 调用oauth_v2_access换取bot token(优先用bot token发消息)
    result = client.oauth_v2_access(
        client_id=CLIENT_ID,
        client_secret=SIGNING_SECRET,
        code=code,
        redirect_uri="你的授权回调URL"  # 必须与Slack应用后台设置的一致
    )

    # 把bot_token存入数据库(比如Redis/SQLite),后续调用API时取出使用
    bot_token = result['bot_token']
    # 示例存储逻辑:save_token_to_db(team_id=result['team']['id'], token=bot_token)
    
    return "授权成功", 200
  1. 调用API时使用存储的token:从数据库取出对应团队的bot_token,传入chat_postMessage
# 从数据库取出当前团队的bot token
bot_token = get_token_from_db(team_id=payload['team']['id'])

# 发送消息时指定token
client.chat_postMessage(
    channel=channel_id,
    text=original_message,
    token=bot_token
)

问题3:满足3秒内响应要求

Slack要求交互端点必须在3秒内返回200响应,否则会提示错误。可以用异步线程处理后续的消息发送/删除操作,先立刻返回确认响应:

import threading

def process_action(action, original_message, channel_id, message_ts, bot_token):
    if action == 'confirm':
        client.chat_postMessage(channel=channel_id, text=original_message, token=bot_token)
    elif action == 'cancel':
        client.chat_delete(channel=channel_id, ts=message_ts, token=bot_token)

# 在交互处理端点中
payload = json.loads(request.form["payload"])
action = payload['actions'][0]['name']
original_message = payload['actions'][0]['value']
channel_id = payload['channel']['id']
message_ts = payload['message_ts']
bot_token = get_token_from_db(payload['team']['id'])

# 启动线程处理业务逻辑,立刻返回200
threading.Thread(
    target=process_action,
    args=(action, original_message, channel_id, message_ts, bot_token)
).start()

return "", 200  # 必须在3秒内返回

内容的提问来源于stack exchange,提问作者Priyanka

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 18:23:10