PHP项目飞书与Slack机器人

wen PHP项目 1

本文目录导读:

PHP项目飞书与Slack机器人

  1. 飞书机器人实现
  2. Slack Bot实现
  3. 统一通知服务
  4. 配置与使用
  5. 最佳实践建议

我来帮你介绍在PHP项目中集成飞书(Feishu/Lark)和Slack机器人的实现方案。

飞书机器人实现

基础配置

<?php
namespace App\Services\Bot;
class FeishuBot
{
    private $webhookUrl;
    private $secret;
    public function __construct($webhookUrl, $secret = null)
    {
        $this->webhookUrl = $webhookUrl;
        $this->secret = $secret;
    }
    /**
     * 发送消息
     */
    public function sendMessage($content, $msgType = 'text')
    {
        $data = [
            'msg_type' => $msgType,
            'content' => $this->buildContent($content, $msgType)
        ];
        // 如果需要签名
        if ($this->secret) {
            $data['timestamp'] = time();
            $data['sign'] = $this->generateSign($data['timestamp']);
        }
        return $this->request($data);
    }
    /**
     * 生成签名
     */
    private function generateSign($timestamp)
    {
        $stringToSign = $timestamp . "\n" . $this->secret;
        return base64_encode(hash_hmac('sha256', '', $stringToSign, true));
    }
    /**
     * 构建内容
     */
    private function buildContent($content, $msgType)
    {
        switch ($msgType) {
            case 'text':
                return ['text' => $content];
            case 'post':
                return $this->buildPostContent($content);
            case 'interactive':
                return $content; // 直接传入卡片JSON
            default:
                return ['text' => $content];
        }
    }
    /**
     * 发送请求
     */
    private function request($data)
    {
        $ch = curl_init($this->webhookUrl);
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
            CURLOPT_POSTFIELDS => json_encode($data),
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 5
        ]);
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        return [
            'code' => $httpCode,
            'data' => json_decode($response, true)
        ];
    }
}

使用示例

// 简单文本消息
$bot = new FeishuBot('https://open.feishu.cn/open-apis/bot/v2/hook/xxx');
$bot->sendMessage('这是一条测试消息');
// 富文本消息
$bot->sendMessage([ => '系统通知',
    'content' => [
        [['tag' => 'text', 'text' => '项目部署成功']],
        [['tag' => 'a', 'text' => '查看详情', 'href' => 'http://example.com']]
    ]
], 'post');
// 消息卡片
$card = [
    'config' => ['wide_screen_mode' => true],
    'header' => [
        'title' => ['tag' => 'plain_text', 'content' => '错误提醒'],
        'template' => 'red'
    ],
    'elements' => [
        ['tag' => 'markdown', 'content' => '**错误信息:** 数据库连接失败']
    ]
];
$bot->sendMessage($card, 'interactive');

Slack Bot实现

使用Webhook发送消息

<?php
namespace App\Services\Bot;
class SlackBot
{
    private $webhookUrl;
    private $token;
    public function __construct($webhookUrl = null, $token = null)
    {
        $this->webhookUrl = $webhookUrl;
        $this->token = $token;
    }
    /**
     * 通过Webhook发送消息
     */
    public function sendViaWebhook($message)
    {
        $data = is_array($message) ? $message : ['text' => $message];
        $ch = curl_init($this->webhookUrl);
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
            CURLOPT_POSTFIELDS => json_encode($data),
            CURLOPT_RETURNTRANSFER => true
        ]);
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        return $httpCode === 200;
    }
    /**
     * 通过API发送消息(需要Bot Token)
     */
    public function sendMessage($channel, $text, $blocks = [])
    {
        $data = [
            'channel' => $channel,
            'text' => $text
        ];
        if (!empty($blocks)) {
            $data['blocks'] = $blocks;
        }
        return $this->apiRequest('chat.postMessage', $data);
    }
    /**
     * Slack API请求
     */
    private function apiRequest($method, $data)
    {
        $url = "https://slack.com/api/{$method}";
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/json',
                "Authorization: Bearer {$this->token}"
            ],
            CURLOPT_POSTFIELDS => json_encode($data),
            CURLOPT_RETURNTRANSFER => true
        ]);
        return json_decode(curl_exec($ch), true);
    }
    /**
     * 发送Block Kit消息
     */
    public function sendBlockMessage($channel, $blocks)
    {
        return $this->sendMessage($channel, ' ', $blocks);
    }
}

Slack Block Kit示例

// 创建丰富的消息
$blocks = [
    [
        'type' => 'header',
        'text' => ['type' => 'plain_text', 'text' => '部署通知']
    ],
    [
        'type' => 'section',
        'fields' => [
            ['type' => 'mrkdwn', 'text' => "*状态:*\n✅ 成功"],
            ['type' => 'mrkdwn', 'text' => "*环境:*\n生产"],
            ['type' => 'mrkdwn', 'text' => "*版本:*\nv2.1.0"],
            ['type' => 'mrkdwn', 'text' => "*时间:*\n2024-01-01 10:00"]
        ]
    ],
    [
        'type' => 'actions',
        'elements' => [
            [
                'type' => 'button',
                'text' => ['type' => 'plain_text', 'text' => '查看日志'],
                'url' => 'https://logs.example.com',
                'style' => 'primary'
            ],
            [
                'type' => 'button',
                'text' => ['type' => 'plain_text', 'text' => '回滚'],
                'style' => 'danger',
                'confirm' => [
                    'title' => ['type' => 'plain_text', 'text' => '确认回滚'],
                    'text' => ['type' => 'mrkdwn', 'text' => '确定要回滚吗?'],
                    'confirm' => ['type' => 'plain_text', 'text' => '确认'],
                    'deny' => ['type' => 'plain_text', 'text' => '取消']
                ]
            ]
        ]
    ]
];
$bot = new SlackBot(null, 'xoxb-your-bot-token');
$bot->sendBlockMessage('#deployments', $blocks);

统一通知服务

<?php
namespace App\Services;
class NotificationService
{
    private $channels = [];
    /**
     * 添加通知渠道
     */
    public function addChannel($name, $bot)
    {
        $this->channels[$name] = $bot;
    }
    /**
     * 发送通知到所有渠道
     */
    public function notifyAll($message, $channel = null)
    {
        $results = [];
        foreach ($this->channels as $name => $bot) {
            if ($channel && $name !== $channel) {
                continue;
            }
            try {
                $bot->sendMessage($message);
                $results[$name] = true;
            } catch (\Exception $e) {
                $results[$name] = false;
                // 记录日志
                Log::error("Notification failed for {$name}: " . $e->getMessage());
            }
        }
        return $results;
    }
}

配置与使用

// config/bots.php
return [
    'feishu' => [
        'webhook' => env('FEISHU_WEBHOOK_URL'),
        'secret' => env('FEISHU_SECRET', null)
    ],
    'slack' => [
        'webhook' => env('SLACK_WEBHOOK_URL'),
        'token' => env('SLACK_BOT_TOKEN')
    ]
];
// 使用示例
$notification = new NotificationService();
// 添加飞书机器人
$notification->addChannel('feishu', new FeishuBot(
    config('bots.feishu.webhook'),
    config('bots.feishu.secret')
));
// 添加Slack机器人
$notification->addChannel('slack', new SlackBot(
    config('bots.slack.webhook')
));
// 发送通知
$notification->notifyAll('系统部署完成!');

最佳实践建议

  1. 错误处理:添加重试机制和错误日志
  2. 消息格式化:统一消息格式,支持Markdown
  3. 速率限制:注意各平台的API调用限制
  4. 安全配置:敏感信息使用环境变量
  5. 异步发送:考虑使用消息队列

需要我详细说明某个特定功能或提供更多使用场景示例吗?

抱歉,评论功能暂时关闭!