irwan-runtuwene / driver-whatsapp
WABA On-Premise driver for BotMan
Installs: 1 564
Dependents: 0
Suggesters: 0
Security: 0
Stars: 7
Watchers: 2
Forks: 7
Open Issues: 0
pkg:composer/irwan-runtuwene/driver-whatsapp
Requires
- php: >=7.0
- ext-curl: *
- botman/botman: ^2.0
Requires (Dev)
- botman/studio-addons: ^1.0
- illuminate/contracts: ^5.5
- mockery/mockery: ^1.1
- phpunit/phpunit: ^5.0
README
BotMan driver to connect WhatsApp Business Cloud API with BotMan
WhatsApp Business Cloud API
This driver integrates with the WhatsApp Business Platform via the Cloud API. For API documentation, visit Meta for Developers - WhatsApp Business Platform
API Version: This driver uses v21.0 by default (latest stable as of January 2026). You can configure a different version if needed via WHATSAPP_API_VERSION environment variable.
Note: This driver also maintains backward compatibility with WhatsApp Business On-Premise API.
Installation & Setup
Install via Composer:
composer require irwan-runtuwene/driver-whatsapp
Configuration
BotMan Studio (Laravel)
Add the following entries to your .env file:
# WhatsApp Business Cloud API WHATSAPP_API_VERSION=v21.0 WHATSAPP_PHONE_NUMBER_ID=your_phone_number_id WHATSAPP_ACCESS_TOKEN=your_access_token WHATSAPP_VERIFY_TOKEN=your_verify_token # Optional: Business Account ID WHATSAPP_BUSINESS_ACCOUNT_ID=your_business_account_id # Error handling WHATSAPP_THROW_EXCEPTIONS=true # Media storage WHATSAPP_MEDIA_TEMP_PATH=storage/app/whatsapp/media
Standalone BotMan
Pass configuration array when creating BotMan instance:
$config = [ 'whatsapp' => [ 'api_version' => 'v21.0', 'phone_number_id' => 'your_phone_number_id', 'access_token' => 'your_access_token', 'verify_token' => 'your_verify_token', 'throw_http_exceptions' => true, ] ]; $botman = BotManFactory::create($config);
Legacy On-Premise API Support
For backward compatibility with On-Premise API:
WHATSAPP_PARTNER=https://your-waba-host WHATSAPP_TOKEN=your-bearer-token
Breaking Changes from Previous Version
Migration from On-Premise to Cloud API
If you're upgrading from the previous On-Premise-only version, you'll need to make the following changes:
1. Environment Variables (Required)
Old Configuration:
WHATSAPP_PARTNER=https://your-waba-host WHATSAPP_TOKEN=your-bearer-token
New Configuration:
WHATSAPP_API_VERSION=v21.0 WHATSAPP_PHONE_NUMBER_ID=your_phone_number_id WHATSAPP_ACCESS_TOKEN=your_access_token WHATSAPP_VERIFY_TOKEN=your_verify_token
2. Webhook Payload Structure
The webhook payload structure has changed from On-Premise to Cloud API format:
Old Format (On-Premise):
{
"messages": [{
"from": "1234567890",
"type": "text",
"text": {"body": "Hello"}
}],
"contacts": [...]
}
New Format (Cloud API):
{
"entry": [{
"changes": [{
"value": {
"messages": [{
"from": "1234567890",
"type": "text",
"text": {"body": "Hello"}
}],
"contacts": [...],
"metadata": {...}
}
}]
}]
}
Note: The driver automatically handles both formats, so no code changes are needed on your end.
3. Message ID Access
Old Way:
// This may not work consistently $messageId = $message->getPayload()->get('id');
New Way:
// Reliable for Cloud API $payload = $message->getPayload(); $messageId = $payload->get('messages')[0]['id'] ?? null; // Or from the event directly $messageId = $message->getPayload()->get('entry')[0]['changes'][0]['value']['messages'][0]['id'] ?? null;
4. Media Handling
Media handling has significantly improved but requires different approach:
Old Way (On-Premise):
// Media URLs were directly accessible $mediaUrl = $message->getPayload()->get('image')['url'];
New Way (Cloud API):
// Media requires a two-step process $media = $message->getPayload()->get('media'); if ($media) { $driver = $bot->getDriver(); // Step 1: Get media URL $mediaInfo = $driver->getMediaUrl($media['id']); // Step 2: Download media $driver->downloadMedia($mediaInfo['url'], $savePath); }
5. Interactive Messages (New Feature)
The previous version had limited interactive message support. The new version includes full support:
Buttons (Now Available):
use BotMan\Drivers\Whatsapp\Extensions\ButtonTemplate; use BotMan\Drivers\Whatsapp\Extensions\ElementButton; $template = ButtonTemplate::create('Choose an option:') ->addButton(ElementButton::create('option_1', 'Option 1')) ->addButton(ElementButton::create('option_2', 'Option 2')); $bot->reply($template);
Lists (Now Available):
use BotMan\Drivers\Whatsapp\Extensions\ListTemplate; use BotMan\Drivers\Whatsapp\Extensions\ListSection; use BotMan\Drivers\Whatsapp\Extensions\ListRow; $section = ListSection::create('Products') ->addRow(ListRow::create('prod_1', 'Product 1', 'Description')); $template = ListTemplate::create('Our Products', 'View Catalog') ->addSection($section); $bot->reply($template);
6. Template Messages
Template message structure has changed:
Old Way:
// Limited or no template support
New Way:
use BotMan\Drivers\Whatsapp\Extensions\TemplateMessage; $template = TemplateMessage::create('order_confirmation', 'en_US') ->addBodyParameters(['John Doe', 'ORD-12345', '$99.99']); $bot->reply($template);
7. New Features Not in Previous Version
The following features are entirely new and have no equivalent in the On-Premise version:
- Reactions - React to messages with emojis
- Reply Context - Quote/reply to specific messages
- Mark as Read - Send read receipts
- Contact Messages - Share vCard contacts
- Media Upload - Upload media to WhatsApp CDN
- Webhook Verification - Automatic webhook challenge response
8. Error Response Format
Error responses now use Cloud API format:
Old Format:
{
"errors": {
"code": "...",
"title": "..."
}
}
New Format:
{
"error": {
"message": "...",
"type": "...",
"code": 123,
"fbtrace_id": "..."
}
}
Note: The driver's exception handling automatically adapts to both formats.
Features
✅ Fully Supported
- Text Messages - Send and receive text messages
- Media Messages - Images, videos, audio, documents, stickers
- Interactive Messages
- Buttons (up to 3 buttons)
- Lists (up to 10 items per section)
- Template Messages - Send pre-approved message templates
- Location Messages - Send and receive location data
- Contact Messages - Share contact cards
- Reactions - React to messages with emojis
- Reply Context - Reply to specific messages
- Media Management - Upload and download media files
- Message Status - Mark messages as read
- Webhook Verification - Automatic webhook verification
- WhatsApp Flows - Interactive multi-step experiences with forms and screens
Usage Examples
Text Messages
$botman->hears('hello', function ($bot) { $bot->reply('Hello! How can I help you?'); });
Button Messages
use BotMan\Drivers\Whatsapp\Extensions\ButtonTemplate; use BotMan\Drivers\Whatsapp\Extensions\ElementButton; $botman->hears('menu', function ($bot) { $template = ButtonTemplate::create('Choose an option:') ->addButton(ElementButton::create('option_1', 'Option 1')) ->addButton(ElementButton::create('option_2', 'Option 2')) ->addButton(ElementButton::create('option_3', 'Option 3')); $bot->reply($template); });
List Messages
use BotMan\Drivers\Whatsapp\Extensions\ListTemplate; use BotMan\Drivers\Whatsapp\Extensions\ListSection; use BotMan\Drivers\Whatsapp\Extensions\ListRow; $botman->hears('catalog', function ($bot) { $section = ListSection::create('Products') ->addRow(ListRow::create('prod_1', 'Product 1', 'Description 1')) ->addRow(ListRow::create('prod_2', 'Product 2', 'Description 2')); $template = ListTemplate::create('Our Products', 'View Catalog') ->addSection($section); $bot->reply($template); });
Template Messages
use BotMan\Drivers\Whatsapp\Extensions\TemplateMessage; $botman->hears('order confirmation', function ($bot) { $template = TemplateMessage::create('order_confirmation', 'en_US') ->addBodyParameters(['John Doe', 'ORD-12345', '$99.99']); $bot->reply($template); });
Media Messages
use BotMan\Drivers\Whatsapp\Extensions\MediaTemplate; // Send image $botman->hears('send image', function ($bot) { $media = MediaTemplate::create(MediaTemplate::TYPE_IMAGE) ->link('https://example.com/image.jpg') ->caption('Check this out!'); $bot->reply($media); }); // Send document $botman->hears('send pdf', function ($bot) { $media = MediaTemplate::create(MediaTemplate::TYPE_DOCUMENT) ->link('https://example.com/document.pdf') ->filename('Document.pdf') ->caption('Here is the document'); $bot->reply($media); });
Location Messages
use BotMan\Drivers\Whatsapp\Extensions\LocationMessage; $botman->hears('location', function ($bot) { $location = LocationMessage::create(37.7749, -122.4194) ->name('San Francisco Office') ->address('123 Market St, San Francisco, CA'); $bot->reply($location); });
Reactions
use BotMan\Drivers\Whatsapp\Extensions\ReactionMessage; $botman->receivedMessage(function ($bot, $message) { // React to the message with a thumbs up $messageId = $message->getPayload()->get('messages')[0]['id']; $reaction = ReactionMessage::create($messageId, '👍'); $bot->reply($reaction); });
WhatsApp Flows
WhatsApp Flows allow you to create interactive, multi-step experiences within WhatsApp.
use BotMan\Drivers\Whatsapp\Extensions\FlowTemplate; // Send a flow message $botman->hears('start survey', function ($bot) { $flow = FlowTemplate::create( 'your_flow_id', // Flow ID from WhatsApp Manager 'Start Survey', // Button text 'Please complete our customer satisfaction survey' ) ->header('Customer Survey') ->footer('Takes only 2 minutes') ->navigate('welcome_screen', ['customer_id' => '12345']) ->mode('published'); // or 'draft' for testing $bot->reply($flow); }); // Handle flow responses $botman->receivedMessage(function ($bot, $message) { $payload = $message->getPayload(); if ($flowResponse = $payload->get('flow_response')) { $responseData = json_decode($flowResponse['response_json'], true); // Process the flow response data $bot->reply('Thank you for completing the survey!'); // Access flow data $name = $flowResponse['name']; $data = $responseData; // Contains user's form submissions } }); // Data exchange flow $botman->hears('update profile', function ($bot) { $flow = FlowTemplate::create( 'profile_flow_id', 'Update Profile', 'Update your account information' ) ->dataExchange([ 'current_name' => 'John Doe', 'current_email' => 'john@example.com', ]) ->mode('published'); $bot->reply($flow); });
Reply to Messages
$botman->hears('quote me', function ($bot, $message) { $messageId = $message->getPayload()->get('messages')[0]['id']; // Use the driver to set reply context $driver = $bot->getDriver(); $driver->replyTo($messageId); $bot->reply('This is a reply to your message!'); });
Media Download
$botman->receivedMessage(function ($bot, $message) { $payload = $message->getPayload(); if ($media = $payload->get('media')) { $driver = $bot->getDriver(); // Get media URL $mediaInfo = $driver->getMediaUrl($media['id']); // Download media $savePath = storage_path("app/whatsapp/media/{$media['id']}"); $driver->downloadMedia($mediaInfo['url'], $savePath); $bot->reply('Media downloaded successfully!'); } });
Mark as Read
$botman->receivedMessage(function ($bot, $message) { $messageId = $message->getPayload()->get('messages')[0]['id']; $driver = $bot->getDriver(); $driver->markAsRead($messageId); });
Security Vulnerabilities
If you discover a security vulnerability, please send an e-mail to stefanus.irwant@gmail.com. All security vulnerabilities will be promptly addressed.
License
This driver is open-source software licensed under the MIT license.