elgibor-solution / laravel-whatsapp-meta
Laravel package for Meta WhatsApp Business Cloud API: templates CRUD, sending messages, multi-account, broadcasts, webhooks.
Installs: 689
Dependents: 0
Suggesters: 0
Security: 0
Stars: 1
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/elgibor-solution/laravel-whatsapp-meta
Requires
- php: >=8.2
- illuminate/http: ^10.0|^11.0|^12.0
- illuminate/queue: ^10.0|^11.0|^12.0
- illuminate/support: ^10.0|^11.0|^12.0
Requires (Dev)
- mockery/mockery: ^1.6
- orchestra/testbench: ^8.0|^9.0|^10.0
- phpunit/phpunit: ^10.0|^11.0
This package is auto-updated.
Last update: 2026-02-09 11:42:02 UTC
README
Laravel package for integrating Meta WhatsApp Business Cloud API, providing:
- CRUD Templates for WhatsApp Business
- Send messages (text, media, template, interactive, location, document)
- Multi-account support (auto-pick default if only one)
- Broadcast to millions of recipients (chunking, scheduling, job queue)
- Webhook to update message status (sent, delivered, read, failed)
- Inbound Tokens for OTP, Vouchers, and mixed-message parsing
- Queue + Retry for reliability
๐ Installation
- Install:
composer require elgibor-solution/laravel-whatsapp-meta:*
- Publish config & migrations:
php artisan vendor:publish --tag=whatsapp-config php artisan vendor:publish --tag=whatsapp-migrations php artisan migrate
- Add to scheduler:
// routes/console.php $schedule->command('whatsapp:broadcast-run')->everyMinute();
โ๏ธ Configuration
Single Account (via .env)
WHATSAPP_SINGLE_ACCOUNT=true WHATSAPP_NAME=default WHATSAPP_PHONE_NUMBER_ID=YOUR_PHONE_ID WHATSAPP_ACCESS_TOKEN=YOUR_LONG_LIVED_TOKEN WHATSAPP_WABA_ID=YOUR_WABA_ID WHATSAPP_WEBHOOK_VERIFY_TOKEN=change-me
Multi Account
If multiple accounts are needed:
- Insert rows into
whatsapp_accountstable (migration provided). - Mark one with
is_default = 1as the default account.
๐ก Routes
All endpoints are available with prefix /whatsapp/*:
GET /whatsapp/webhookโ webhook verificationPOST /whatsapp/webhookโ handle message status updatesPOST /whatsapp/messages/sendโ send a messageGET/POST/PUT/DELETE /whatsapp/templatesโ manage templatesPOST /whatsapp/broadcastsโ create broadcastPOST /whatsapp/broadcasts/{id}/scheduleโ schedule broadcastPOST /whatsapp/broadcasts/{id}/pause|resumeโ control broadcast
๐งฉ Usage via Facade
use WhatsApp; use ESolution\WhatsApp\Models\WhatsappAccount; $acc = WhatsappAccount::resolve(); // 1. Send text WhatsApp::sendText($acc, '08123456789', 'Hello from Cloud API!'); // 2. Send template WhatsApp::sendTemplate($acc, '08123456789', 'order_update', 'en', [ ['type'=>'body','parameters'=>[['type'=>'text','text'=>'John']]] ]); // 3. Send media WhatsApp::sendMedia($acc, '08123456789', 'image', [ 'link'=>'https://example.com/img.jpg', 'caption'=>'Promo' ]); // 4. Send location WhatsApp::sendLocation($acc, '08123456789', -6.2, 106.8, 'Office', 'Jakarta'); // 5. Send interactive WhatsApp::sendInteractive($acc, '08123456789', [ 'type'=>'list', 'header'=>['type'=>'text','text'=>'Menu'], 'body'=>['text'=>'Choose option'], 'footer'=>['text'=>'E-Solution'], 'action'=>[ 'button'=>'View', 'sections'=>[ ['title'=>'Products','rows'=>[ ['id'=>'prod1','title'=>'Product 1','description'=>'Description 1'], ['id'=>'prod2','title'=>'Product 2','description'=>'Description 2'], ]] ] ] ]);
๐ Inbound Tokens (OTP / Vouchers)
Allow users to verify or claim items by sending a unique code back to your WhatsApp Business Number. The system automatically searches for these tokens even if they are buried within a longer message.
1. Create a Token
use ESolution\WhatsApp\Facades\WhatsApp; // Generate an 8-character alphanumeric code (default) $token = WhatsApp::createToken('08123456789', 'otp'); // Generate a 10% discount voucher valid for 1 hour $voucher = WhatsApp::createToken('08123456789', 'voucher', [ 'discount' => '10%', 'campaign' => 'black_friday' ], [ 'expires_in' => 60, 'length' => 12 ]); // Generate a secure UUID token $uuid = WhatsApp::createToken('08123456789', 'secure_claim', [], [ 'format' => 'uuid' ]);
2. Handle Verification
When the user sends a message containing the token (e.g., "Hi, here is my code: ABC-123"), the package fires an event.
Register Listeners:
// app/Providers/EventServiceProvider.php protected $listen = [ 'whatsapp.token.verified' => [ \App\Listeners\LogVerification::class, ], /** OR type-specific listener **/ 'whatsapp.token.verified.voucher' => [ \App\Listeners\ApplyDiscount::class, ], ];
Listener Example:
public function handle($token) { // $token is an instance of ESolution\WhatsApp\Models\WhatsappToken $phone = $token->phone; $metadata = $token->metadata; // ['discount' => '10%', ...] // Perform your logic here }
๐ Template CRUD
$acc = WhatsappAccount::resolve(); // List $list = WhatsApp::listTemplates($acc); // Create $tpl = WhatsApp::createTemplate($acc, [ 'name'=>'promo_aug', 'category'=>'MARKETING', 'language'=>'en', 'components'=>[['type'=>'BODY','text'=>'Hello {{1}}, August promo!']] ]); // Delete WhatsApp::deleteTemplate($acc, 'promo_aug', 'en');
๐ข Broadcast
Create Broadcast
POST /whatsapp/broadcasts { "name": "Promo August", "type": "template", "payload": { "name": "promo_aug", "language": "en", "components": [ { "type": "body", "parameters": [ { "type": "text", "text": "Customer" } ] } ] }, "recipients": ["0811111111","0812222222","0813333333"], "chunk_size": 2000, "rate_per_min": 6000 }
Schedule Broadcast
POST /whatsapp/broadcasts/1/schedule { "scheduled_at": "2025-08-24 22:00:00" }
Run Scheduler
php artisan schedule:run
Broadcasts will be dispatched in chunks using SendBroadcastChunkJob with respect to chunk_size and rate_per_min.
๐ Tech Provider (Partner) Services
For Meta Tech Providers, this package provides specialized services and API endpoints for managing client accounts at scale.
๐ API Endpoints
All routes are prefixed with /whatsapp/ (customizable in config).
๐ฑ Asset Management (Phone Numbers)
GET /accounts/{acc_id}/phone-numbersโ List phone numbers for WABA.GET /accounts/{acc_id}/phone-numbers/{phone_id}โ Get details.POST /accounts/{acc_id}/phone-numbers/{phone_id}/registerโ Register for Cloud API.POST /accounts/{acc_id}/phone-numbers/{phone_id}/verifyโ Verify with SMS code.
๐ WhatsApp Flows
GET /accounts/{acc_id}/flowsโ List all flows.POST /accounts/{acc_id}/flowsโ Create new flow.POST /accounts/{acc_id}/flows/{flow_id}/assetsโ Upload JSON asset.POST /accounts/{acc_id}/flows/{flow_id}/publishโ Publish flow.
๐ Media Management
POST /accounts/{acc_id}/mediaโ Upload media (multipart/form-data).GET /accounts/{acc_id}/media/{media_id}โ Get metadata.DELETE /accounts/{acc_id}/media/{media_id}โ Delete media.
๐ค Onboarding
POST /onboarding/exchange-tokenโ Exchange short-lived FB token.POST /onboarding/debug-tokenโ Get WABA/token info.
๐ค Business Profile
GET /accounts/{acc_id}/profile/{phone_id}โ Get profile.POST /accounts/{acc_id}/profile/{phone_id}โ Update profile fields.
๐ Analytics & Health
GET /accounts/{acc_id}/analyticsโ WABA messaging metrics.GET /accounts/{acc_id}/phone-numbers/{phone_id}/healthโ Quality rating & status.
๐ Inbound Tokens (OTP / Vouchers)
๐ API Endpoints
POST /whatsapp/tokensโ Create a token.POST /whatsapp/tokens/consumeโ Manually verify token from string.
๐ Webhook
- URL:
/whatsapp/webhook - Verify: Meta calls
GET /webhook?hub_mode=subscribe&hub_verify_token=xxx&hub_challenge=1234 - Status: Meta sends
POSTupdates with message status (sent,delivered,read,failed). - Call Permission: Meta sends
POSTupdates with call_permission_reply status (accept,reject). - Forwarding: If
webhook_forward_urlis set for an account, the raw payload is forwarded to that URL via a queued POST request.
Statuses are saved to:
whatsapp_messageswhatsapp_broadcast_recipients
Call permission are broadcast through event:
whatsapp.call_permission.updated
You need to create your own event listener and register it at EventServiceProvider
// app/Providers/EventServiceProvider.php protected $listen = [ 'whatsapp.call_permission.updated' => [ \App\Listeners\HandleCallPermissionUpdated::class, ], ];
โฑ๏ธ Queue & Retry
- Messages are sent via
SendMessageJob. - Broadcasts are handled via
SendBroadcastChunkJob. - Use Redis / SQS / Horizon queues for scaling.
- Automatic retry:
tries = 3,backoff = 30s.
โ Best Practices
- Always use APPROVED templates for outbound messages beyond 24h window.
- Respect WABA tier rate limits.
rate_per_minonly throttles locally. - Media must be public URLs.
- Phone numbers are normalized: leading
0โ62. Adjust if needed. - Store and log Graph API responses for error analysis.
๐งช Testing
The package uses Orchestra Testbench for comprehensive testing.
- Install dev dependencies:
composer install
- Run tests:
./vendor/bin/phpunit
Test coverage includes:
- Unit: Component logic and traits.
- Integration: Database models and migrations.
- Feature: Webhook routes and payload processing.
Support & Hiring
Need professional help or want to move faster? Hire the E-Solution / Elgibor team for integration, audits, or custom features.
๐ง info@elgibor-solution.com
Donations
If this package saves you time, consider supporting development โค๏ธ