使用事件API的PHP版Slack应用迁移至Socket Mode实现咨询
PHP版Slack应用Socket Mode迁移本地开发指南
前置准备
- 先到Slack应用管理后台开启Socket Mode,生成App Level Token(必须添加
connections:write权限),这个令牌和你原有xoxb开头的Bot Token是两个独立凭证,不要混淆 - 本地VM环境提前安装php-cli、php-curl扩展,推荐通过composer安装
jolicode/slack-php-api和php-websocket/websocket依赖,无需自行封装WebSocket底层握手、心跳逻辑 - 清空原有Slack后台配置的slash command、interactivity模块的HTTP请求URL,Socket Mode下无需暴露公网端点,Slack会主动通过WebSocket连接推送事件
核心适配逻辑
原有HTTP模式是被动接收Slack请求、返回响应,Socket Mode改为主动维持长连接,接收Slack推送的事件包处理后返回ACK回执即可,原有业务逻辑几乎可以完全复用:
<?php require __DIR__ . '/vendor/autoload.php'; // 两个凭证区分清楚 $appToken = 'xapp-******************'; // 刚生成的App Level Token $botToken = 'xoxb-******************'; // 你原有Bot Token // 第一步:调用接口获取WebSocket连接地址 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://slack.com/api/apps.connections.open'); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer ' . $appToken, 'Content-Type: application/x-www-form-urlencoded' ]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); $res = curl_exec($ch); $connData = json_decode($res, true); if (!$connData['ok']) { die('获取连接地址失败: ' . $connData['error']); } $wsUrl = $connData['url']; // 第二步:建立WebSocket长连接监听事件 $client = new WebSocket\Client($wsUrl); while (true) { try { $message = $client->receive(); $event = json_decode($message, true); // 处理Slack心跳、握手事件无需额外逻辑 if ($event['type'] === 'hello') { continue; } // 所有事件必须先返回ACK回执,否则Slack会重复推送 if (isset($event['envelope_id'])) { $client->send(json_encode([ 'envelope_id' => $event['envelope_id'] ])); } // 原有业务逻辑直接复用 $payload = $event['payload']; switch ($event['type']) { // slash command触发场景,对应你原来打开弹窗的逻辑 case 'slash_commands': if ($payload['command'] === '/你配置的触发命令') { // 直接复用你原有打开对话框的代码 $dialog = [ 'callback_id' => 'git_issue', 'title' => 'Add issue', 'submit_label' => 'Create', 'elements' => [ [ 'type' => 'text', 'label' => 'Name', 'name' => 'name' ], [ 'type' => 'text', 'label' => 'E-mail', 'name' => 'email' ] ], 'trigger_id' => $payload['trigger_id'] ]; $query = [ 'token' => $botToken, 'dialog' => json_encode($dialog) ]; // 你原有调用dialog.open接口的代码完全不变 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://slack.com/api/dialog.open'); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/x-www-form-urlencoded' ]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($query)); $response = curl_exec($ch); } break; // 表单提交交互场景,对应你原有同步GitHub的逻辑 case 'interactive': if ($payload['callback_id'] === 'git_issue') { $submission = $payload['submission']; // 这里直接放你原有同步数据到GitHub的代码即可 } break; } } catch (Exception $e) { // 连接断开自动重连 $client->close(); $client = new WebSocket\Client($wsUrl); } }
本地运行注意事项
- 脚本需要在cli模式下运行,不要放到fpm容器中,直接在VM终端执行
php 你的脚本文件名.php即可,需要常驻后台可以用nohup或者systemd管理进程 - 本地VM只要能连通外网即可测试,不需要公网IP、端口映射
- 原有HTTP请求签名校验逻辑可以移除,Socket Mode的事件通过加密长连接推送,无需额外做签名校验
内容的提问来源于stack exchange,提问作者bhavan k
相关产品推荐
相关产品推荐

