wallacemartinss/filament-whatsapp-conector
composer require wallacemartinss/filament-whatsapp-conector
php artisan vendor:publish --tag="filament-evolution-config"
php artisan vendor:publish --tag="filament-evolution-migrations"
php artisan migrate
panel() method in your Filament Panel Provider:
FilamentEvolutionPlugin::make()
->whatsappInstanceResource()
->viewMessageHistory()
->viewWebhookLogs()
.env:
EVOLUTION_URL=https://your-evolution-api.com
EVOLUTION_API_KEY=your_api_key
EVOLUTION_WEBHOOK_URL=https://your-app.com/api/webhooks/evolution
EVOLUTION_WEBHOOK_SECRET=your_secret_key
php artisan queue:work
Send a WhatsApp message from a Filament resource:
use WallaceMartinss\FilamentEvolution\Actions\SendWhatsappMessageAction;
public function table(Table $table): Table
{
return $table
->actions([
SendWhatsappMessageAction::make()
->numberFrom('phone') // Auto-fill from record
->instanceFrom('whatsapp_instance_id'),
]);
}
Create & Connect:
Multi-Instance Handling:
// Get all connected instances
$instances = Whatsapp::getConnectedInstances();
// Use specific instance
Whatsapp::sendText($instanceId, '5511999999999', 'Hello!');
From Filament UI:
// In a page header
protected function getHeaderActions(): array
{
return [
SendWhatsappMessageAction::make()
->number('5511999999999')
->instance(1)
->message('Default message'),
];
}
From Business Logic:
class NotificationService
{
use CanSendWhatsappMessage;
public function sendOrderConfirmation(Order $order)
{
$this->sendWhatsappText(
$order->customer_phone,
"Your order #{$order->id} is confirmed!"
);
if ($order->has_invoice) {
$this->sendWhatsappDocument(
$order->customer_phone,
storage_path("app/invoices/{$order->invoice}.pdf"),
"invoice_{$order->invoice}.pdf",
"Your invoice is attached."
);
}
}
}
Handle Incoming Events:
// routes/web.php
Route::post('/api/webhooks/evolution', [EvolutionWebhookController::class, 'handle']);
// Controller
public function handle(Request $request)
{
return Whatsapp::handleWebhook($request);
}
Process Webhook Events:
// Listen for message events
event(new WhatsappMessageReceived($messageData));
Reply Buttons:
Whatsapp::sendWhatsappButtons(
'5511999999999',
'Choose an option:',
[
['type' => 'reply', 'title' => 'Yes', 'payload' => 'confirm'],
['type' => 'reply', 'title' => 'No', 'payload' => 'cancel'],
],
'Survey',
'Please select an option'
);
PIX Payments:
Whatsapp::sendWhatsappPix(
'5511999999999',
'Pay your invoice:',
'00020126500014BR.GOV.BCB.PIX0114+55119999999995204000053039865802BR5913Your Company Name6009SAO PAULO62070503***63041234',
'Invoice Payment',
'Payment due: R$100.00'
);
.env:
EVOLUTION_TENANCY_ENABLED=true
EVOLUTION_TENANCY_COLUMN=team_id
// Automatically scopes to current tenant
$tenantInstances = Whatsapp::getConnectedInstances();
// Dispatch jobs for async sending
SendWhatsappMessage::dispatch($instanceId, $number, 'text', 'Hello!');
php artisan queue:work --once for debugging.SendWhatsappMessageAction::make()
->disk('s3') // Use S3 for uploads
->allowedTypes([MessageTypeEnum::IMAGE, MessageTypeEnum::DOCUMENT]);
Whatsapp::sendImage($instanceId, '5511999999999', storage_path('app/images/product.jpg'), 'Check this out!');
// In FailedJob.php
public function handle()
{
$job = $this->job;
if ($job instanceof SendWhatsappMessage) {
$job->release(5); // Retry after 5 seconds
}
}
try {
Whatsapp::sendText($instanceId, $number, $message);
} catch (\Exception $e) {
Log::error("WhatsApp send failed: {$e->getMessage()}");
}
// tests/Feature/WhatsAppTest.php
public function test_webhook_received()
{
$response = $this->postJson('/api/webhooks/evolution', [
'event' => 'message',
'data' => [...],
]);
$response->assertOk();
$this->assertDatabaseHas('whatsapp_webhook_logs', [...]);
}
Whatsapp::shouldReceive('sendText')
->once()
->with($instanceId, $number, $message);
foreach ($customers as $customer) {
SendWhatsappMessage::dispatch($instanceId, $customer->phone, 'text', $message);
}
// config/filament-evolution.php
'queue' => [
'enabled' => true,
'connection' => 'redis',
'name' => 'whatsapp',
'delay' => 1000, // 1 second delay between jobs
],
QR Code Expiry:
EVOLUTION_QRCODE_EXPIRES (default: 30 seconds).Webhook Verification:
public function handle(Request $request)
{
if (!Whatsapp::verifyWebhook($request)) {
abort(403, 'Invalid signature');
}
return Whatsapp::handleWebhook($request);
}
File Size Limits:
Multi-Tenancy Conflicts:
EVOLUTION_TENANCY_COLUMN matches your tenant model’s key.tenancy config in filament-evolution.php.Queue Stuck Jobs:
failed_jobs table for stuck WhatsApp jobs.php artisan queue:retry all
Interactive Messages (v2.4.0+):
How can I help you explore Laravel packages today?