Search by

kstmostofa / laravel-whatsapp

kstmostofa

Dual-backend Laravel package for WhatsApp: Meta Cloud API + bundled whatsapp-web.js sidecar. Ships a Livewire/Flux admin UI, queued jobs, webhooks with HMAC, Eloquent models, broadcasting, and CLI lifecycle commands.

Package info

github.com/kstmostofa/laravel-whatsapp

Homepage

Documentation

pkg:composer/kstmostofa/laravel-whatsapp

Statistics

Installs: 6 236

Dependents: 0

Suggesters: 0

Stars: 242

Open Issues: 0

v1.2.2 2026-11-01 14:05 UTC

This package is auto-updated.

Last update: 2026-11-03 23:49:33 UTC


README

Latest Version PHP Version License

Dual-backend WhatsApp integration for Laravel β€” Meta Cloud API (pure PHP) + whatsapp-web.js sidecar (full personal-account access), with a polished Livewire admin UI and a single WhatsApp:: facade across both.

πŸ“– Full documentation: kstmostofa.github.io/laravel-whatsapp

What you get

Layer What it does
Cloud API client Pure PHP. Templates, media, business profile, phone-number management, several numbers as named accounts, webhooks with HMAC verification.
Web sidecar (bundled Node service) whatsapp-web.js wrapped in a thin HTTP service. Personal-number QR pairing, groups and group admin, status, free-form messages anytime, contact lookup, chat history.
Unified facade WhatsApp::messages()->sendTemplate(...) for Cloud, WhatsApp::web('main')->messages()->sendText(...) for sidecar. WhatsApp::send($to, $body) auto-picks.
Livewire + Flux UI Drop-in admin at /whatsapp β€” Dashboard, Sessions+QR, Compose, Conversations (chat-bubble UI with media, reply, reactions, forward, edit/delete, search, sound, ack ticks, live updates over broadcasting), Groups with member management, Contacts, Webhooks log with replay, Status. Compose includes a template builder. Works with Tailwind, Bootstrap, or no CSS framework at all.
Eloquent models Opt-in WaSession / WaMessage / WaContact / WaWebhookEvent with separate-DB support via WHATSAPP_DB_CONNECTION.
Background bridge whatsapp:web:listen daemon turns sidecar SSE events into Laravel events.
Inbound router WhatsApp::router()->hears('hi', fn ($m) => $m->reply('Hello!')) β€” keyword, regex, button and type routes with middleware, for both backends.
Notifications 'whatsapp' notification channel with a WhatsAppMessage builder β€” text, templates, media, either backend.
Bulk sending WhatsApp::bulk($numbers, $message) β€” queued, rate limited per sender, opt-out list, job batches.
Media + webhook log Optional copies of media on your own disk before WhatsApp expires it, and a replayable log of raw webhook deliveries.
Testing WhatsApp::fake() records every send from both backends, with assertSentTo() and friends.
Health monitoring /whatsapp/status page + php artisan whatsapp:health [--json] for CI/monitoring.

Quick install

composer require kstmostofa/laravel-whatsapp
php artisan vendor:publish --tag=laravel-whatsapp-config
php artisan vendor:publish --tag=laravel-whatsapp-migrations
php artisan migrate

For the Cloud API β€” set in .env:

WHATSAPP_ACCESS_TOKEN=EAAG...permanent-token
WHATSAPP_PHONE_NUMBER_ID=123456789012345
WHATSAPP_BUSINESS_ACCOUNT_ID=987654321098765
WHATSAPP_APP_SECRET=your-meta-app-secret
WHATSAPP_VERIFY_TOKEN=any-string-you-make-up

For the Web sidecar β€” pair your phone:

composer require livewire/livewire livewire/flux           # for the UI
php artisan whatsapp:sidecar:install                       # one-time, ~600 MB Chrome download
php artisan whatsapp:sidecar:start                         # boots in background
php artisan whatsapp:web:listen --all &                    # SSE β†’ Laravel events (run under Supervisor in prod)
# Open http://your-app.test/whatsapp/sessions and click "Start" β†’ scan QR with your phone

Quick example

use Kstmostofa\LaravelWhatsApp\Facades\WhatsApp;
use Kstmostofa\LaravelWhatsApp\Jobs\SendMessage;

// One-line send β€” picks backend by recipient shape
WhatsApp::send('+9665XXXXXXXX', 'Hello from Laravel');           // β†’ Cloud API
WhatsApp::send('966512345678@c.us', 'Hello via personal number'); // β†’ Web sidecar

// Templated business message (Cloud API)
WhatsApp::messages()->sendTemplate('+9665XXXXXXXX', 'order_ready', 'en_US', [
    ['type' => 'body', 'parameters' => [['type' => 'text', 'text' => 'Munir']]],
]);

// Personal-number flow (Web sidecar β€” works for any chat your paired phone can see)
WhatsApp::web('main')->groups()->create('Project X', ['9665XXXXXXXX@c.us']);
WhatsApp::web('main')->messages()->sendImage('9665XXXXXXXX@c.us', ['url' => 'https://…/photo.jpg', 'caption' => 'Hi']);

// Many recipients β€” queued and rate limited
WhatsApp::bulk($numbers, 'Store opens at 10 today')->except($optedOut)->dispatch();

// Or queue a single send
SendMessage::dispatch('+9665XXXXXXXX', 'Queued hello');

// As a Laravel notification
$user->notify(new OrderShipped($order));   // via() => ['whatsapp'], toWhatsApp() => WhatsAppMessage

// In tests
WhatsApp::fake();
WhatsApp::assertSentTo('+9665XXXXXXXX', fn ($m) => str_contains($m->body, 'shipped'));

// Auto-replies β€” declared once in a service provider
WhatsApp::router()->hears('hi|hello', fn ($m) => $m->reply('Hi! How can I help?'));

// Inbound β€” or listen to the raw Laravel events
Event::listen(\Kstmostofa\LaravelWhatsApp\Events\Web\MessageReceived::class, function ($event) {
    Log::info('Got message', ['from' => $event->from(), 'body' => $event->body()]);
});

When to use which backend

Feature Cloud API Web sidecar
Personal-number QR pairing ❌ βœ…
Send to / receive from groups ❌ βœ…
Status / Stories ❌ βœ…
Free-form messages anytime ❌ (templates outside 24h) βœ…
Approved business templates βœ… ❌
Official, no ban risk βœ… ❌ (browser automation β€” ToS gray area)
Scalable to millions βœ… ⚠️ session-bound
No extra runtime on host βœ… ❌ (Node + Chromium)

Most apps use both β€” Cloud API for transactional/template sends at scale, Web sidecar for the features Cloud API doesn't expose.

UI install paths

The admin UI under /whatsapp works on whatever your app already uses:

Your app uses… Set in .env What you get
Tailwind v4 + Vite WHATSAPP_UI_CSS_MODE=vite (default) Smallest tree-shaken bundle. Add 3 @source lines to your app.css.
Anything else (Tailwind v3 / Bootstrap / plain CSS / nothing) WHATSAPP_UI_CSS_MODE=standalone Pre-compiled CSS shipped with the package, served from /whatsapp/_assets/laravel-whatsapp.css (~40 KB gz). No npm/Tailwind needed. Loads only on /whatsapp/* pages β€” your main app stays untouched.
No UI at all skip composer require livewire/flux Headless. Full access to WhatsApp:: facade, Events, Jobs, webhook receiver, all CLI commands.

Full setup details + dark mode + screenshots β†’ docs site.

Artisan commands

Command Purpose
whatsapp:sidecar:install Clone whatsapp-web.js, npm ci, download Chromium
whatsapp:sidecar:start [--foreground] / :stop / :status Lifecycle of the Node process. --foreground is for Supervisor / systemd
whatsapp:web:listen [session] [--all] Long-running: sidecar SSE β†’ Laravel events. --all covers every session in one process
whatsapp:health [--json] [--exit-code] Health probe β€” pipe into cron / monitoring
whatsapp:contacts:sync [session] [--all] Copy Web contacts into wa_contacts β€” safe to schedule
whatsapp:web:sync [session] [--chats=20] [--limit=50] [--chat=…] Import recent chat history into wa_messages
whatsapp:webhooks:replay [id…] [--failed] Re-dispatch logged webhook deliveries
whatsapp:media:prune [--days=] Delete stored media older than the retention window

Production checklist

  • Set strong WHATSAPP_WEB_TOKEN (shared secret between PHP and sidecar)
  • Set WHATSAPP_APP_SECRET (HMAC for Cloud webhook signatures)
  • Wrap /whatsapp/* routes in your own auth middleware: config/laravel-whatsapp.php β†’ ui.middleware
  • Run whatsapp:web:listen --all under Supervisor / systemd
  • Optional: isolate WA data on a separate DB connection (WHATSAPP_DB_CONNECTION=whatsapp)
  • Optional: enable broadcasting (WHATSAPP_BROADCAST=true) + run Laravel Reverb for instant UI updates

Detailed deployment guide β†’ docs/production.

Roadmap

  • Cloud API: messages / templates / media / business profile / phone numbers / webhooks
  • Web sidecar: full whatsapp-web.js surface (text, media, groups, contacts, status)
  • Livewire + Flux admin UI with dark mode, 3 CSS install paths
  • Eloquent persistence with per-package DB connection
  • Health page + CLI command + cached snapshots
  • Avatar + media proxy with server-side caching
  • Bubble actions: edit, delete-for-me, delete-for-everyone, "you deleted this message" placeholder
  • Bulk send job with rate limiting
  • Laravel notification channel + WhatsApp::fake()
  • Chat history import
  • Larastan (level 6) + Pint in CI
  • Native broadcasting integration with Echo channel listeners
  • Template builder in Compose

Status

  • 162 tests passing, 470 assertions (testbench + mocked Guzzle + Livewire smoke tests), plus 59 sidecar tests (npm test in sidecar/)
  • Compatible with Laravel 12 / 13 β€” CI runs the suite on PHP 8.2, 8.3 and 8.4 with Laravel 12, and PHP 8.4 with Laravel 13, plus Pint and Larastan (level 6)
  • PHP minimum: 8.2 on Laravel 12, 8.4 on Laravel 13 (Symfony 8 transitive)
  • Laravel 11 support was dropped in 1.1.0: it is past end of life and has unpatched security advisories
  • Verified end-to-end in Laravel 12 for the 1.0 feature set: QR pairing, inbound webhook β†’ DB β†’ UI bubble, edit, delete, sound, attachments, dark-mode toggle. Features added in 1.1 are covered by the automated tests above

License

MIT. See LICENSE.

Contributing

Issues + PRs welcome at github.com/kstmostofa/laravel-whatsapp. Before submitting, run:

composer check            # Pint style check, Larastan (level 6), and PHPUnit
composer format           # fix code style
cd sidecar && npm test    # sidecar unit tests (no npm install needed)

CI runs the same checks, plus the test suite across PHP 8.2–8.4 and Laravel 12 / 13.

If you change a Blade view, or StandaloneCssCoverageTest fails after a Flux update, rebuild the standalone stylesheet and commit dist/laravel-whatsapp.css:

LARAVEL_WHATSAPP_BUILD_APP=/path/to/laravel-app-with-flux ./dist-src/build.sh