本文目录导读:

- 安装必要的包
- 配置环境变量
- 添加配置到config/services.php
- 创建通知类
- 创建Slack服务类
- 发送通知的示例用法
- 创建自定义通知(高级用法)
- 定义Slack路由(使用Notification::route)
- 事件监听(可选)
- 测试和调试
- 队列优化(推荐)
- 常用Slack消息格式示例
- 注意事项:
我来帮你实现Laravel项目的Slack通知集成,这是一个完整的实现方案:
安装必要的包
安装Slack通知相关的包:
# 安装Slack SDK composer require slack-php/slack-lib # 安装Guzzle HTTP客户端(用于发送请求) composer require guzzlehttp/guzzle # 如果还没有安装通知组件 composer require illuminate/notifications
配置环境变量
在 .env 文件中添加Slack配置:
# Slack Webhook URL(用于发送通知) SLACK_WEBHOOK_URL=https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX # Slack Bot Token(用于高级功能,如发送消息、获取用户信息等) SLACK_BOT_TOKEN=xoxb-xxxxx-xxxxxxxxx-xxxxxxxxxxxxx # 默认Slack频道(可选,用于指定默认接收通知的频道) SLACK_DEFAULT_CHANNEL=general
添加配置到config/services.php
// config/services.php
return [
// ... 其他服务配置
'slack' => [
'webhook_url' => env('SLACK_WEBHOOK_URL'),
'bot_token' => env('SLACK_BOT_TOKEN'),
'default_channel' => env('SLACK_DEFAULT_CHANNEL', 'general'),
],
];
创建通知类
创建基础的通知类:
php artisan make:notification SlackNotification
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\SlackMessage;
class SlackNotification extends Notification implements ShouldQueue
{
use Queueable;
protected $content;
protected $attachments = [];
protected $channel;
public function __construct($content, $attachments = [], $channel = null)
{
$this->content = $content;
$this->attachments = $attachments;
$this->channel = $channel;
}
public function via($notifiable)
{
return ['slack'];
}
public function toSlack($notifiable)
{
$message = (new SlackMessage)
->content($this->content)
->error(); // 或者 ->success() / ->warning()
// 设置频道(如果指定了)
if ($this->channel) {
$message->to($this->channel);
}
// 添加附件
if (!empty($this->attachments)) {
foreach ($this->attachments as $attachment) {
$message->attachment(function ($attach) use ($attachment) {
$attach->title($attachment['title'] ?? '')
->content($attachment['content'] ?? '')
->fields($attachment['fields'] ?? [])
->color($attachment['color'] ?? '#2eb886');
});
}
}
return $message;
}
}
创建Slack服务类
创建一个专门处理Slack操作的service:
php artisan make:service SlackService
<?php
namespace App\Services;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Notification;
use App\Notifications\SlackNotification;
use App\Models\User;
class SlackService
{
protected $client;
protected $webhookUrl;
protected $botToken;
public function __construct()
{
$this->client = new Client();
$this->webhookUrl = config('services.slack.webhook_url');
$this->botToken = config('services.slack.bot_token');
}
/**
* 发送简单文本消息到Slack
*/
public function sendMessage($message, $channel = null)
{
try {
$response = $this->client->post($this->webhookUrl, [
'json' => [
'text' => $message,
'channel' => $channel ?? config('services.slack.default_channel'),
]
]);
return $response->getStatusCode() === 200;
} catch (\Exception $e) {
Log::error('Slack message sending failed: ' . $e->getMessage());
return false;
}
}
/**
* 发送复杂消息(带附件)
*/
public function sendComplexMessage(array $messageData, $channel = null)
{
try {
$payload = array_merge([
'channel' => $channel ?? config('services.slack.default_channel'),
], $messageData);
$response = $this->client->post($this->webhookUrl, [
'json' => $payload
]);
return $response->getStatusCode() === 200;
} catch (\Exception $e) {
Log::error('Slack complex message sending failed: ' . $e->getMessage());
return false;
}
}
/**
* 使用Bot Token发送消息(需要高级权限)
*/
public function sendWithBot($channel, $text, $blocks = [])
{
try {
$response = $this->client->post('https://slack.com/api/chat.postMessage', [
'headers' => [
'Authorization' => 'Bearer ' . $this->botToken,
'Content-Type' => 'application/json',
],
'json' => [
'channel' => $channel,
'text' => $text,
'blocks' => $blocks,
]
]);
$result = json_decode($response->getBody(), true);
if (!$result['ok']) {
Log::error('Slack Bot message failed: ' . ($result['error'] ?? 'Unknown error'));
return false;
}
return true;
} catch (\Exception $e) {
Log::error('Slack Bot message sending failed: ' . $e->getMessage());
return false;
}
}
/**
* 发送文件到Slack
*/
public function sendFile($channel, $filePath, $filename = null)
{
try {
$multipart = [
[
'name' => 'channels',
'contents' => $channel,
],
[
'name' => 'file',
'contents' => fopen($filePath, 'r'),
'filename' => $filename ?? basename($filePath),
],
];
$response = $this->client->post('https://slack.com/api/files.upload', [
'headers' => [
'Authorization' => 'Bearer ' . $this->botToken,
],
'multipart' => $multipart
]);
return json_decode($response->getBody(), true);
} catch (\Exception $e) {
Log::error('Slack file upload failed: ' . $e->getMessage());
return false;
}
}
/**
* 获取Slack用户信息
*/
public function getUserInfo($userId)
{
try {
$response = $this->client->get('https://slack.com/api/users.info', [
'headers' => [
'Authorization' => 'Bearer ' . $this->botToken,
],
'query' => [
'user' => $userId,
]
]);
return json_decode($response->getBody(), true);
} catch (\Exception $e) {
Log::error('Slack user info fetch failed: ' . $e->getMessage());
return null;
}
}
}
发送通知的示例用法
在控制器中使用:
<?php
namespace App\Http\Controllers;
use App\Services\SlackService;
use App\Models\User;
use App\Notifications\SlackNotification;
use Illuminate\Support\Facades\Notification;
class NotificationController extends Controller
{
protected $slackService;
public function __construct(SlackService $slackService)
{
$this->slackService = $slackService;
}
/**
* 发送简单通知
*/
public function sendBasicNotification()
{
// 通过Service发送
$this->slackService->sendMessage(
'用户 ' . auth()->user()->name . ' 刚刚完成了注册。',
'#registration-notifications'
);
// 或者通过 Notification facade 发送
$user = User::find(1);
$notification = new SlackNotification(
'新用户注册: ' . $user->email,
[
[
'title' => '用户详情',
'content' => '新用户成功注册了您的应用',
'fields' => [
'用户名' => $user->name,
'邮箱' => $user->email,
'注册时间' => $user->created_at->toDateTimeString(),
],
'color' => '#36a64f', // 绿色表示成功
]
],
'#user-notifications'
);
$user->notify($notification);
// 或者发送给特定用户
Notification::route('slack', '#general')->notify($notification);
return response()->json(['message' => '通知已发送']);
}
/**
* 发送订单通知
*/
public function sendOrderNotification($order)
{
$notification = new SlackNotification(
"新订单 #{$order->id}",
[
[
'title' => "订单金额: ¥{$order->total}",
'content' => "客户: {$order->customer_name}\n商品数量: {$order->items_count}",
'fields' => [
'订单号码' => $order->order_number,
'支付方式' => $order->payment_method,
'订单状态' => $order->status,
],
'color' => '#F35A00',
]
],
'#orders'
);
// 发送给管理团队
Notification::route('slack', '#admin-orders')->notify($notification);
// 或者通过邮件发送给具体用户
$manager = User::where('role', 'manager')->first();
Notification::send($manager, $notification);
return response()->json(['message' => '订单通知已发送']);
}
}
创建自定义通知(高级用法)
创建更专用的通知类:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\SlackMessage;
class OrderStatusNotification extends Notification
{
use Queueable;
private $order;
private $status;
public function __construct($order, $status)
{
$this->order = $order;
$this->status = $status;
}
public function via($notifiable)
{
return ['slack'];
}
public function toSlack($notifiable)
{
$colors = [
'completed' => '#36a64f',
'pending' => '#ff9900',
'cancelled' => '#ff0000',
];
return (new SlackMessage)
->to('#order-notifications')
->content(trans("slack.order_status.{$this->status}", [
'order_id' => $this->order->id,
]))
->attachment(function ($attachment) use ($colors) {
$attachment
->title("Order #{$this->order->order_number}")
->content($this->order->description ?? '')
->fields([
'Status' => ucfirst($this->status),
'Total' => '$' . number_format($this->order->total, 2),
'User' => $this->order->user->name,
])
->color($colors[$this->status] ?? '#36036a');
})
->warning(); // 可选:success(), error(), info()
}
}
定义Slack路由(使用Notification::route)
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Notification;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
// 定义Slack通知路由
Notification::extend('slack', function ($app) {
return new \Illuminate\Notifications\Channels\SlackWebhookChannel();
});
}
}
事件监听(可选)
如果需要在特定事件时自动发送通知:
<?php
namespace App\Listeners;
use App\Services\SlackService;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendSlackNotificationListener implements ShouldQueue
{
protected $slackService;
public function __construct(SlackService $slackService)
{
$this->slackService = $slackService;
}
public function handle($event)
{
// 根据事件类型发送不同的通知
switch (true) {
case $event instanceof \App\Events\UserRegistered:
$this->slackService->sendMessage(
"🚀 新用户注册: {$event->user->email}",
'#user-registrations'
);
break;
case $event instanceof \App\Events\OrderCompleted:
$this->slackService->sendMessage(
"✅ 订单完成: #{$event->order->order_number}",
'#orders'
);
break;
// 添加更多事件类型...
}
}
}
测试和调试
创建测试方法:
<?php
namespace Tests\Feature;
use Tests\TestCase;
use App\Services\SlackService;
use Illuminate\Support\Facades\Notification;
class SlackNotificationTest extends TestCase
{
public function test_send_slack_message()
{
Notification::fake();
$slackService = new SlackService();
$result = $slackService->sendMessage('Test message', '#test-channel');
$this->assertTrue($result);
}
public function test_send_notification_via_facade()
{
Notification::fake();
$notification = new \App\Notifications\SlackNotification(
'Test notification',
['title' => 'Test', 'content' => 'Test content']
);
Notification::route('slack', '#test')->notify($notification);
Notification::assertSentOnDemand(
SlackNotification::class,
function ($notification, $channels, $notifiable) {
return $notifiable->routes['slack'] === '#test';
}
);
}
}
队列优化(推荐)
对于大规模通知,建议使用队列:
// 在通知类中设置配置队列
class SlackNotification extends Notification implements ShouldQueue
{
use Queueable;
public $connection = 'redis'; // 或 'database'
public $queue = 'slack-notifications';
public $delay = 10; // 延迟10秒
// 失败重试机制
public $tries = 3;
public $timeout = 60;
public function failed(\Exception $e)
{
Log::error('Slack notification failed: ' . $e->getMessage());
// 可以添加失败告警
}
}
常用Slack消息格式示例
// 带表情和格式的消息
$this->slackService->sendComplexMessage([
'text' => "*重要通知*\n订单 #12345 已发货 🎉",
'attachments' => [
[
'color' => '#ff0000',
'blocks' => [
[
'type' => 'section',
'text' => [
'type' => 'mrkdwn',
'text' => "*客户服务通知*\n有新的客户请求需要处理"
]
]
]
]
]
]);
// 带交互按钮的消息
$blocks = [
[
'type' => 'section',
'text' => [
'type' => 'mrkdwn',
'text' => '需要审批新的订单申请'
]
],
[
'type' => 'actions',
'elements' => [
[
'type' => 'button',
'text' => [
'type' => 'plain_text',
'text' => '批准'
],
'style' => 'primary',
'value' => 'approve'
],
[
'type' => 'button',
'text' => [
'type' => 'plain_text',
'text' => '拒绝'
],
'style' => 'danger',
'value' => 'reject'
]
]
]
];
$this->slackService->sendWithBot('#approvals', '新审批请求', $blocks);
注意事项:
- 安全性:不要在代码中硬编码Slack URL和token,始终使用环境变量
- 错误处理:始终添加try-catch和日志记录
- 队列使用:对于大量通知,建议使用队列异步处理
- 限流:注意Slack API的调用限制(每分钟最多几十次请求)
- 测试:在生产环境发送前,先在测试频道测试
这个方案提供了完整的Slack集成功能,可以根据你的具体需求进行调整和扩展。