spatie/interactive-slack-notification-channel
Send interactive Slack notifications from Laravel using Slack Block Kit. Configure a token and optional channel on your Notifiable, post rich messages with buttons/inputs, and use Slack API responses to reply in threads for follow-up order events.
Installation
composer require spatie/interactive-slack-notification-channel
Configure Slack
.env:
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...
SLACK_SIGNING_SECRET=your_signing_secret_here
php artisan vendor:publish --provider="Spatie\SlackNotificationChannel\SlackNotificationChannelServiceProvider"
First Notification
Use Laravel's Notification facade to send a basic message:
use Spatie\SlackNotificationChannel\SlackMessage;
use Illuminate\Support\Facades\Notification;
Notification::route('slack', 'user@email.com')
->notify(new SlackMessage('Hello from Laravel!'));
Verify Check Slack for the message. Ensure the webhook URL is correct and the signing secret is properly configured.
Basic Notifications
Extend Spatie\SlackNotificationChannel\SlackMessage for custom content:
use Spatie\SlackNotificationChannel\SlackMessage;
class OrderShippedNotification extends SlackMessage
{
public function __construct(public string $orderId)
{
$this->title = "Order #{$orderId} Shipped";
$this->content = "Your order has been shipped!";
}
}
Interactive Components Add buttons, modals, or select menus using Slack's block kit:
class ApprovalRequestNotification extends SlackMessage
{
public function toSlackMessage()
{
return [
'blocks' => [
[
'type' => 'section',
'text' => [
'type' => 'mrkdwn',
'text' => 'Approve this request?',
],
],
[
'type' => 'actions',
'elements' => [
[
'type' => 'button',
'text' => [
'type' => 'plain_text',
'text' => 'Approve',
],
'value' => 'approve_request',
'action_id' => 'approve_request',
],
[
'type' => 'button',
'text' => [
'type' => 'plain_text',
'text' => 'Reject',
],
'value' => 'reject_request',
'action_id' => 'reject_request',
],
],
],
],
];
}
}
Routing Notifications Route notifications to specific Slack channels/users:
// Via notification route
Notification::route('slack', '#general-channel')
->notify(new SlackMessage('Team update!'));
// Via user model (if using `HasNotifications`)
$user->routeNotificationFor('slack', '#alerts-channel');
Handling Interactive Events Register a Slack event listener to process button clicks/modals:
use Spatie\SlackNotificationChannel\SlackEvent;
public function handle(SlackEvent $event)
{
if ($event->action->action_id === 'approve_request') {
// Logic for approval
}
}
Register in EventServiceProvider:
protected $listen = [
SlackEvent::class => [
\App\Listeners\HandleSlackInteractions::class,
],
];
Laravel Queues Queue notifications for async delivery:
Notification::route('slack', '#notifications')
->notify(new SlackMessage('Async update!'))
->onQueue('slack');
Dynamic Content Use Laravel's blade-like syntax for dynamic content:
class UserWelcomeNotification extends SlackMessage
{
public function __construct(public User $user)
{
$this->title = "Welcome, {$this->user->name}!";
$this->content = "You've joined our team. Your role: **{$this->user->role}**.";
}
}
Attachments Add file attachments or images:
class ReportNotification extends SlackMessage
{
public function toSlackMessage()
{
return [
'attachments' => [
[
'title' => 'Monthly Report',
'image_url' => 'https://example.com/report.png',
],
],
];
}
}
Testing
Use SlackMessageTestCase for unit tests:
use Spatie\SlackNotificationChannel\Tests\SlackMessageTestCase;
class ApprovalNotificationTest extends SlackMessageTestCase
{
public function test_message_structure()
{
$notification = new ApprovalRequestNotification();
$this->assertEquals('Approve this request?', $notification->title);
}
}
Webhook URL Validation
SLACK_DEBUG in config to log errors:
SLACK_DEBUG=true
Signing Secret Mismatch
Rate Limits
$notification->onQueue('slack')->delay(now()->addSeconds(10));
Interactive Event Delays
SlackEvent::fresh() to re-fetch events if needed:
$event = SlackEvent::fresh($event->payload);
Block Kit Validation
Enable Debug Logging
Add to config/slack-notification-channel.php:
'debug' => env('SLACK_DEBUG', false),
Check logs for raw Slack responses:
tail -f storage/logs/laravel.log | grep slack
Inspect Raw Payloads Dump the raw Slack payload in your event handler:
public function handle(SlackEvent $event)
{
\Log::debug('Raw payload:', $event->payload);
}
Test Locally Use ngrok to expose your local Slack event endpoint:
ngrok http --host=localhost --subdomain=slack-events
Configure Slack’s Event Subscriptions to point to https://slack-events.ngrok.io/slack/events.
Custom Slack Client
Bind a custom GuzzleHttp\Client for advanced HTTP options:
$this->app->bind(\Spatie\SlackNotificationChannel\SlackClient::class, function () {
return new SlackClient(
new GuzzleHttp\Client(['timeout' => 30])
);
});
Override Default Message Structure
Extend Spatie\SlackNotificationChannel\SlackMessage to modify the default toSlackMessage() method:
class CustomSlackMessage extends SlackMessage
{
public function toSlackMessage()
{
return array_merge(
parent::toSlackMessage(),
['mrkdwn_in' => ['text']] // Example: Add global formatting
);
}
}
Add Middleware Attach middleware to notifications for pre/post-processing:
class AddFooterMiddleware
{
public function handle($notifiable, $notification)
{
if ($notification instanceof SlackMessage) {
$notification->content .= "\n\n*Powered by Laravel*";
}
return $notification;
}
}
Register in AppServiceProvider:
Notification::extend('slack', function ($app) {
$channel =
How can I help you explore Laravel packages today?