susheelbhai / laravel-sms
Multi-provider SMS integration for Laravel applications with notification channel support
Requires
None
Requires (Dev)
- laravel/pint: ^1.0
- orchestra/testbench: ^10.0
- pestphp/pest: ^3.0
- pestphp/pest-plugin-laravel: ^3.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Multi-provider SMS package for Laravel with notification channel support.
Supported Providers
- Fast2SMS — Quick SMS and OTP routes
- MSG91 — Flow API and OTP API
- Mock — Local/testing without API calls
Installation
composer require susheelbhai/laravel-sms php artisan sms:install
Configuration
SMS_ENABLED=1 SMS_PROVIDER=fast2sms SMS_COUNTRY_CODE=91 SMS_TEST_NUMBER=9999999999 FAST2SMS_API_KEY=your_api_key FAST2SMS_SENDER_ID=FSTSMS FAST2SMS_ROUTE=q FAST2SMS_OTP_ROUTE=otp MSG91_AUTH_KEY=your_auth_key MSG91_SENDER_ID=SMSIND MSG91_FLOW_ID=your_flow_id
When APP_ENV is not production, all SMS are redirected to SMS_TEST_NUMBER.
Direct Usage
use Susheelbhai\Sms\Facades\Sms; Sms::send('9876543210', 'Your order is confirmed.'); Sms::sendOtp('9876543210', '482910'); Sms::via('msg91')->send('9876543210', 'Hello from MSG91');
Notification Channel
public function via(object $notifiable): array { $channels = ['database']; if (config('sms.enabled') == 1 && isset($notifiable->phone)) { $channels[] = 'sms'; } return $channels; } public function toSms(object $notifiable): array { return ['message' => 'Your order has been placed.']; } public function toSmsOtp(object $notifiable): array { return ['otp' => $this->otp]; }
Switching Providers
Set SMS_PROVIDER in .env to fast2sms, msg91, or mock.
Mock Provider & Inbox (local testing)
Use the mock provider to test SMS/OTP flows locally without any real SMS account or API keys — like Mailpit, but for SMS.
SMS_ENABLED=1 SMS_PROVIDER=mock
With the mock provider active, messages are not sent to a real gateway.
Instead each message is captured into a file-based inbox
(storage/app/sms_mock) and shown in the SMS tab of the unified message
inbox provided by laravel-basekit:
GET /mock_message?channel=sms # (the old /sms_mock URL redirects here)
There you can view each message (body, recipient, extracted OTP with copy button, type, time), mark read/unread, delete individual messages, search, and clear all — the same feature set as the email inbox.
Captured messages are also available programmatically:
use Susheelbhai\Sms\Support\MockInbox; use Susheelbhai\Sms\Providers\MockProvider; MockInbox::all(); // captured messages (newest first) MockInbox::find($id); // one message MockInbox::delete($id); // delete one MockInbox::markRead($id); // mark read MockInbox::clear(); // empty the inbox MockProvider::$sent; // in-memory log (useful in tests) MockProvider::reset(); // reset the in-memory log
Notes:
- Capture happens only when
SMS_PROVIDER=mock. The inbox UI (in basekit) is registered only whenAPP_ENVis notproduction, so real OTPs are never exposed. - In non-production,
normalizePhone()still redirects the recipient toSMS_TEST_NUMBER; the message body and OTP shown in the inbox are accurate. - Prefer
toSms()(full message body) overtoSmsOtp()when the SMS needs custom wording —toSmsOtp()wraps the code in the genericsms.otp_messagetemplate.