ajit-das / laravel-msg91
Laravel notification channels for MSG91 SMS, WhatsApp and OTP, with fluent message builders.
Fund package maintenance!
Requires
- php: ^8.3
- guzzlehttp/guzzle: ^7.8
- illuminate/contracts: ^10.48.9||^11.0||^12.0||^13.0
- illuminate/http: ^10.48.9||^11.0||^12.0||^13.0
- illuminate/notifications: ^10.48.9||^11.0||^12.0||^13.0
- illuminate/support: ^10.48.9||^11.0||^12.0||^13.0
Requires (Dev)
- larastan/larastan: ^2.9||^3.0
- laravel/pint: ^1.29
- orchestra/testbench: ^8.22||^9.0||^10.0||^11.0
- pestphp/pest: ^2.36||^4.6||^5.0
- pestphp/pest-plugin-arch: ^2.7||^4.0||^5.0
- pestphp/pest-plugin-laravel: ^2.4||^4.1||^5.0
- pestphp/pest-plugin-type-coverage: ^2.5||^4.0||^5.0
- phpstan/extension-installer: ^1.4
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is not auto-updated.
Last update: 2026-09-26 00:30:11 UTC
README
Laravel Msg91
Laravel notification channels for MSG91 SMS, WhatsApp and OTP, with fluent message builders.
Installation
Requires PHP 8.3+ and Laravel 10.48, 11, 12, or 13.
You can install the package via Composer:
composer require ajit-das/laravel-msg91
Publish the config file:
php artisan vendor:publish --tag="laravel-msg91-config"
Set MSG91_AUTH_KEY. For WhatsApp, set the integrated number and template namespace. For OTP, set the template id. MSG91_DRIVER=log writes payloads to the log instead of calling MSG91, which is the right setting for local and staging.
Usage
Send an SMS through the Flow API:
use Madgeek\Msg91\Facades\Msg91; Msg91::sms() ->to('9876543210') ->template('sms_template_id') ->shortUrl() ->variable('VAR1', 'Ajit') ->send();
Send a WhatsApp template:
Msg91::whatsapp() ->to('9876543210') ->template('order_shipped') ->language('en') ->namespace('template_namespace') ->body('Ajit', 'ORD-1') ->send();
Send a WhatsApp session message after the recipient has replied. These do not use a template:
Msg91::whatsapp()->to('9876543210')->text('Hello')->send(); Msg91::whatsapp() ->to('9876543210') ->buttons('Choose one') ->reply('yes', 'Yes') ->reply('no', 'No') ->send(); Msg91::whatsapp() ->to('9876543210') ->listMessage('Pick a slot', 'Options') ->section('Morning', [ ['id' => '9', 'title' => '9 AM', 'description' => 'First slot'], ]) ->send(); Msg91::whatsapp()->to('9876543210')->requestLocation('Please share your location')->send(); Msg91::whatsapp()->to('9876543210')->product('catalog_id', 'product_id', 'Blue shirt')->send(); Msg91::whatsapp() ->to('9876543210') ->productList('catalog_id', 'Browse the catalog') ->heading('Shop') ->products('Shoes', 'sku-1', 'sku-2') ->send(); Msg91::whatsapp() ->to('9876543210') ->payment('Complete the payment below.') ->item('Shirt', 499, 1) ->send(); $balance = Msg91::whatsapp()->balance();
heading(), headingImage(), and footnote() add an interactive header or footer. from() overrides the configured integrated number.
Send, verify, or resend an OTP:
Msg91::otp()->to('9876543210')->template('otp_template')->send(); Msg91::otp()->verify('9876543210', '123456'); Msg91::otp()->resend('9876543210');
Local numbers are prefixed with country_code from config/msg91.php (default 91).
Notifications
Use msg91-sms and msg91-whatsapp from a notification. Return the phone number from routeNotificationForMsg91Sms() or routeNotificationForMsg91Whatsapp() when the message does not set to() itself.
use Illuminate\Notifications\Notification; use Madgeek\Msg91\Facades\Msg91; use Madgeek\Msg91\Messages\SmsMessage; use Madgeek\Msg91\Messages\WhatsAppMessage; class OrderShipped extends Notification { public function via(object $notifiable): array { return ['msg91-sms', 'msg91-whatsapp']; } public function toMsg91Sms(object $notifiable): SmsMessage { return Msg91::sms()->template('sms_template_id')->variable('VAR1', 'Ajit'); } public function toMsg91Whatsapp(object $notifiable): WhatsAppMessage { return Msg91::whatsapp()->template('order_shipped')->body('Ajit'); } }
Testing
Msg91::fake() records messages and does not call MSG91:
Msg91::fake(); Msg91::sms()->to('9876543210')->template('sms_template_id')->send(); Msg91::assertSmsSent(fn (SmsMessage $message) => $message->to === '919876543210');
Msg91::assertWhatsAppSent() and Msg91::assertOtpSent() cover the other channels. assertOtpSent() receives an OtpMessage with action (send, verify, or resend), to, template, and otp.
Check a real configuration locally with the log driver:
php artisan msg91:test sms 9876543210 --template=sms_template_id php artisan msg91:test whatsapp 9876543210 --template=order_shipped php artisan msg91:test otp 9876543210
Successful sends dispatch Madgeek\Msg91\Events\MessageSending and MessageSent. Failures dispatch MessageFailed and then throw AuthenticationException or RequestFailedException.
Contributing
Thank you for considering contributing to Laravel Msg91! Please review our contributing guide to get started.
Credits
License
Laravel Msg91 is open-sourced software licensed under the MIT license.