gr8shivam / laravel-sms-api
A modern, flexible Laravel package for integrating any SMS gateway with REST API support
Installs: 37 989
Dependents: 0
Suggesters: 0
Security: 0
Stars: 100
Watchers: 7
Forks: 33
Open Issues: 0
pkg:composer/gr8shivam/laravel-sms-api
Requires
- php: ^8.1
- ext-json: *
- ext-mbstring: *
- guzzlehttp/guzzle: ^7.8
- illuminate/support: ^10.0|^11.0|^12.0
Requires (Dev)
- orchestra/testbench: ^8.0|^9.0
- phpunit/phpunit: ^10.0|^11.0
README
Laravel SMS API
A modern, flexible Laravel package for integrating any SMS gateway that provides a REST API. Perfect for Laravel 10+ applications with full support for notifications, multiple gateways, and modern authentication methods.
โญ Star this repo to show support!
๐ Table of Contents
- Features
- Requirements
- Installation
- Quick Start
- Configuration
- Usage
- Advanced Features
- Real Provider Examples
- Testing
- Changelog
- Support
โจ Features
- โ Universal Compatibility - Works with any REST API SMS provider
- โ Multiple Gateways - Configure and switch between multiple SMS providers
- โ Laravel Notifications - Full integration with Laravel's notification system
- โ Modern Auth - Support for Bearer tokens, API keys, Basic Auth, and custom headers
- โ Bulk SMS - Send to multiple recipients in a single call
- โ JSON & Form Data - Support for both JSON payloads and form-encoded requests
- โ Request Wrapping - Handle complex API structures with wrapper support
- โ Type Safe - Built with PHP 8.1+ strict types
- โ Dependency Injection - Modern Laravel service container integration
- โ Comprehensive Logging - Built-in request/response logging
- โ Easy Testing - Mock-friendly architecture
๐ Requirements
- PHP 8.1 or higher
- Laravel 10.x, 11.x, or 12.x
- Guzzle HTTP Client 7.8+
๐ฆ Installation
1. Install via Composer
composer require gr8shivam/laravel-sms-api
2. Publish Configuration
php artisan vendor:publish --provider="Gr8Shivam\SmsApi\SmsApiServiceProvider"
This creates config/sms-api.php in your application.
3. Configure Your Gateway
Edit config/sms-api.php and add your SMS provider credentials (see Configuration below).
๐ Quick Start
Send Your First SMS
use Gr8Shivam\SmsApi\SmsApiFacade as SmsApi; // Simple usage SmsApi::sendMessage("9876543210", "Hello from Laravel!"); // Or using helper smsapi("9876543210", "Hello from Laravel!");
Send to Multiple Recipients
SmsApi::sendMessage(["9876543210", "9876543211"], "Hello everyone!");
Get Response
$response = SmsApi::sendMessage("9876543210", "Hello!") ->response(); $statusCode = SmsApi::sendMessage("9876543210", "Hello!") ->getResponseCode(); $isSuccess = SmsApi::sendMessage("9876543210", "Hello!") ->isSuccessful(); // Returns true for 2xx status codes
โ๏ธ Configuration
Open config/sms-api.php after publishing.
Global Settings
return [ // Default country code (added to numbers automatically) 'country_code' => env('SMS_API_COUNTRY_CODE', '91'), // Default gateway to use 'default' => env('SMS_API_DEFAULT_GATEWAY', 'your_gateway'), // HTTP client timeouts 'timeout' => env('SMS_API_TIMEOUT', 30), 'connect_timeout' => env('SMS_API_CONNECT_TIMEOUT', 10), // Optional message validation 'validation' => [ 'enabled' => env('SMS_API_VALIDATION_ENABLED', false), 'max_length' => env('SMS_API_MAX_LENGTH', 1000), ], ];
Basic Gateway Configuration
For simple GET/POST requests:
'your_gateway' => [ 'method' => 'POST', // GET, POST, PUT, PATCH, DELETE 'url' => 'https://api.smsgateway.com/send', 'params' => [ 'send_to_param_name' => 'mobile', // Your provider's "to" param name 'msg_param_name' => 'message', // Your provider's "message" param name 'others' => [ 'api_key' => env('SMS_GATEWAY_KEY'), 'sender_id' => env('SMS_SENDER_ID'), ], ], 'headers' => [ 'Accept' => 'application/json', ], 'add_code' => true, // Automatically add country code ],
Advanced Gateway Configuration
For JSON requests with complex structures:
'advanced_gateway' => [ 'method' => 'POST', 'url' => 'https://api.provider.com/v2/send', 'params' => [ 'send_to_param_name' => 'recipient', 'msg_param_name' => 'text', 'others' => [ 'priority' => 'high', 'ttl' => 3600, ], ], 'headers' => [ 'Authorization' => 'Bearer ' . env('SMS_API_TOKEN'), 'Content-Type' => 'application/json', ], 'json' => true, // Send as JSON payload 'jsonToArray' => true, // Send single number as array: ["9876543210"] 'wrapper' => 'data', // Wrap payload in {"data": {...}} 'wrapperParams' => [ 'campaign_id' => 'welcome_sms', ], 'add_code' => true, ],
Result payload example:
{
"data": [
{
"recipient": ["919876543210"],
"text": "Your message",
"campaign_id": "welcome_sms"
}
],
"priority": "high",
"ttl": 3600
}
Authentication Methods
1. Bearer Token (Most Modern APIs)
'gateway' => [ 'headers' => [ 'Authorization' => 'Bearer ' . env('SMS_API_TOKEN'), ], ],
In .env:
SMS_API_TOKEN=your_bearer_token_here
2. API Key in Header
'gateway' => [ 'headers' => [ 'X-API-Key' => env('SMS_API_KEY'), ], ],
3. Basic Authentication
'gateway' => [ 'headers' => [ 'Authorization' => 'Basic ' . base64_encode(env('SMS_USERNAME') . ':' . env('SMS_PASSWORD')), ], ],
4. API Key in Parameters
'gateway' => [ 'params' => [ 'others' => [ 'api_key' => env('SMS_API_KEY'), ], ], ],
Special Parameters
json (boolean)
Send parameters as JSON payload instead of query string or form data.
'json' => true,
jsonToArray (boolean)
When json is true, controls whether a single mobile number is sent as:
true:["9876543210"](array)false:"9876543210"(string)
'jsonToArray' => false,
wrapper (string)
Wraps the JSON request in a named object. Required by some providers.
'wrapper' => 'sms', // Creates: {"sms": [{...}]}
wrapperParams (array)
Adds parameters inside the wrapper (separate from regular params).
'wrapperParams' => [ 'campaign' => 'summer_sale', 'priority' => 1, ],
add_code (boolean)
Automatically prepend country code to phone numbers.
'add_code' => true, // 9876543210 becomes 919876543210
๐ฑ Usage
Using Helper Function
The smsapi() helper provides the most convenient way to send SMS.
Basic Usage
// Quick send smsapi("9876543210", "Welcome to our platform!"); // Or smsapi()->sendMessage("9876543210", "Welcome!");
With Extra Parameters
smsapi("9876543210", "Your OTP is 1234", [ 'template_id' => 'OTP_TEMPLATE', 'priority' => 'high' ]);
With Custom Headers
smsapi("9876543210", "Hello", [], [ 'X-Custom-Header' => 'value', 'X-Request-ID' => uniqid() ]);
Using Different Gateway
smsapi()->gateway('backup_gateway') ->sendMessage("9876543210", "Message via backup gateway");
Using Different Country Code
smsapi()->countryCode('1') // USA ->sendMessage("5551234567", "Hello from USA!");
Bulk SMS
$recipients = ["9876543210", "9876543211", "9876543212"]; smsapi($recipients, "Bulk message to all!");
With Wrapper Parameters
smsapi()->addWrapperParams([ 'campaign' => 'newsletter', 'tracking_id' => '12345' ]) ->sendMessage("9876543210", "Newsletter message");
Method Chaining
smsapi() ->gateway('primary_gateway') ->countryCode('91') ->addWrapperParams(['campaign' => 'promo']) ->sendMessage("9876543210", "Promotional offer!", [ 'template_id' => 'PROMO_123' ]);
Using Facade
The facade provides the same functionality with explicit imports.
use Gr8Shivam\SmsApi\SmsApiFacade as SmsApi; // Basic usage SmsApi::sendMessage("9876543210", "Hello!"); // With gateway selection SmsApi::gateway('gateway_name') ->sendMessage("9876543210", "Hello!"); // With country code SmsApi::countryCode('44') // UK ->sendMessage("7911123456", "Hello from UK!"); // Bulk SMS SmsApi::sendMessage( ["9876543210", "9876543211"], "Bulk message" ); // Get response $response = SmsApi::sendMessage("9876543210", "Test") ->response(); // Get status code $code = SmsApi::sendMessage("9876543210", "Test") ->getResponseCode(); // Check success $success = SmsApi::sendMessage("9876543210", "Test") ->isSuccessful();
Using Notifications
Laravel SMS API integrates seamlessly with Laravel's notification system.
Step 1: Add Route to Your Model
In your User model (or any Notifiable model):
use Illuminate\Notifications\Notifiable; class User extends Authenticatable { use Notifiable; /** * Route notifications for SMS API channel */ public function routeNotificationForSmsApi() { return $this->phone; // Return the phone number column } }
Step 2: Create Notification
php artisan make:notification WelcomeNotification
namespace App\Notifications; use Illuminate\Notifications\Notification; use Gr8Shivam\SmsApi\Notifications\SmsApiChannel; use Gr8Shivam\SmsApi\Notifications\SmsApiMessage; class WelcomeNotification extends Notification { public function via($notifiable) { return [SmsApiChannel::class]; } public function toSmsApi($notifiable) { return (new SmsApiMessage) ->content("Welcome {$notifiable->name}!"); } }
Step 3: Send Notification
$user = User::find(1); $user->notify(new WelcomeNotification());
Advanced Notification Examples
With Parameters:
public function toSmsApi($notifiable) { return (new SmsApiMessage) ->content("Your OTP is: {$this->otp}") ->params([ 'template_id' => 'OTP_VERIFY', 'priority' => 'high' ]); }
With Headers:
public function toSmsApi($notifiable) { return (new SmsApiMessage) ->content($this->message) ->params(['campaign' => 'marketing']) ->headers(['X-Campaign-ID' => '12345']); }
Unicode Message:
public function toSmsApi($notifiable) { return (new SmsApiMessage) ->content("เคจเคฎเคธเฅเคคเฅ! Welcome") ->unicode(); }
Using Static Constructor:
public function toSmsApi($notifiable) { return SmsApiMessage::create("Hello {$notifiable->name}!") ->addParam('template_id', 'WELCOME_001') ->addHeader('X-Priority', 'high'); }
Return String (Shorthand):
public function toSmsApi($notifiable) { return "Welcome to our platform!"; // Automatically converted to SmsApiMessage }
๐ฅ Advanced Features
1. Safe Sending Helper
Use send_sms() for operations where you want to catch exceptions:
if (send_sms("9876543210", "Hello!")) { echo "SMS sent successfully!"; } else { echo "SMS failed. Error logged."; }
2. Response Handling
$sms = smsapi()->sendMessage("9876543210", "Hello!"); // Get raw response $response = $sms->response(); // Get status code $code = $sms->getResponseCode(); // Check if successful if ($sms->isSuccessful()) { // 2xx status code }
3. Message Validation
$message = new SmsApiMessage("Your message here"); // Get message length $length = $message->length(); // Check if empty if ($message->isEmpty()) { // Handle empty message } // Estimate SMS segments (for cost calculation) $segments = $message->estimateSegments(); // Returns 1, 2, 3... // Get preview $preview = $message->preview(50); // First 50 characters
Enable validation in config:
'validation' => [ 'enabled' => true, 'max_length' => 1000, ],
Then validate:
try { $message->validate(); } catch (\InvalidArgumentException $e) { // Handle validation error }
4. Dynamic Gateway Selection
$gateway = $user->isPremium() ? 'premium_gateway' : 'basic_gateway'; smsapi()->gateway($gateway) ->sendMessage($user->phone, "Relevant message");
5. Environment-based Configuration
// .env SMS_API_DEFAULT_GATEWAY=twilio SMS_API_COUNTRY_CODE=1 SMS_API_TIMEOUT=60 TWILIO_ACCOUNT_SID=your_sid TWILIO_AUTH_TOKEN=your_token TWILIO_FROM_NUMBER=+15551234567
6. Multiple Recipients Handling
// Array of numbers $recipients = User::where('notify_sms', true) ->pluck('phone') ->toArray(); smsapi($recipients, "Important announcement!");
7. Logging
All requests and responses are automatically logged using Laravel's logging system:
// Check logs/laravel.log for: // [INFO] SMS Gateway Response Code: 200 // [INFO] SMS Gateway Response Body: {...} // [ERROR] SMS Gateway Response Code: 400 // [ERROR] SMS Gateway Response Body: {...}
๐ Real Provider Examples
Twilio
'twilio' => [ 'method' => 'POST', 'url' => 'https://api.twilio.com/2010-04-01/Accounts/' . env('TWILIO_ACCOUNT_SID') . '/Messages.json', 'params' => [ 'send_to_param_name' => 'To', 'msg_param_name' => 'Body', 'others' => [ 'From' => env('TWILIO_FROM_NUMBER'), ], ], 'headers' => [ 'Authorization' => 'Basic ' . base64_encode(env('TWILIO_ACCOUNT_SID') . ':' . env('TWILIO_AUTH_TOKEN')), ], 'add_code' => true, ],
Usage:
smsapi()->gateway('twilio')->sendMessage("5551234567", "Hello from Twilio!");
MSG91
'msg91' => [ 'method' => 'POST', 'url' => 'https://control.msg91.com/api/v2/sendsms', 'params' => [ 'send_to_param_name' => 'to', 'msg_param_name' => 'message', 'others' => [ 'authkey' => env('MSG91_AUTH_KEY'), 'sender' => env('MSG91_SENDER_ID'), 'route' => '4', 'country' => '91', ], ], 'json' => true, 'wrapper' => 'sms', 'add_code' => false, ],
Usage:
smsapi()->gateway('msg91')->sendMessage("9876543210", "Hello from MSG91!");
AWS SNS (via REST API)
'aws_sns' => [ 'method' => 'POST', 'url' => 'https://sns.us-east-1.amazonaws.com/', 'params' => [ 'send_to_param_name' => 'PhoneNumber', 'msg_param_name' => 'Message', 'others' => [ 'Action' => 'Publish', ], ], 'headers' => [ 'Authorization' => 'AWS4-HMAC-SHA256 ...', // Use AWS SDK for proper signing ], 'add_code' => true, ],
Nexmo/Vonage
'nexmo' => [ 'method' => 'POST', 'url' => 'https://rest.nexmo.com/sms/json', 'params' => [ 'send_to_param_name' => 'to', 'msg_param_name' => 'text', 'others' => [ 'api_key' => env('NEXMO_API_KEY'), 'api_secret' => env('NEXMO_API_SECRET'), 'from' => env('NEXMO_FROM'), ], ], 'json' => true, 'add_code' => true, ],
Generic Bearer Token API
'generic_api' => [ 'method' => 'POST', 'url' => 'https://api.smsprovider.com/v1/send', 'params' => [ 'send_to_param_name' => 'to', 'msg_param_name' => 'message', 'others' => [ 'sender' => 'YourApp', ], ], 'headers' => [ 'Authorization' => 'Bearer ' . env('SMS_BEARER_TOKEN'), 'Content-Type' => 'application/json', 'Accept' => 'application/json', ], 'json' => true, 'add_code' => true, ],
๐งช Testing
Running Tests
composer test
Writing Tests
use Gr8Shivam\SmsApi\Tests\AbstractTestCase; use Gr8Shivam\SmsApi\SmsApiFacade as SmsApi; class MyFeatureTest extends AbstractTestCase { /** @test */ public function it_sends_sms() { $this->mockSmsGateway(200, 'Success'); $response = SmsApi::sendMessage("9876543210", "Test"); $this->assertEquals(200, $response->getResponseCode()); $this->assertTrue($response->isSuccessful()); } }
๐ Changelog
See CHANGELOG.md for version history and breaking changes.
Latest Version: 4.0.0
- PHP 8.1+ and Laravel 10+ support
- Modern type hints and strict types
- Bearer token and modern auth support
- Optional message validation
- Enhanced notification system
- Comprehensive test suite
๐ Troubleshooting
SMS Not Sending
- Check logs:
storage/logs/laravel.log - Verify config: Ensure gateway credentials are correct
- Test manually:
php artisan tinker >>> smsapi()->sendMessage("YOUR_NUMBER", "Test")->response();
Invalid Response
$sms = smsapi()->sendMessage("9876543210", "Test"); dd([ 'code' => $sms->getResponseCode(), 'response' => $sms->response(), 'success' => $sms->isSuccessful() ]);
Configuration Not Loading
php artisan config:clear php artisan cache:clear
๐ก Best Practices
- Store credentials in
.env, never hardcode - Use queued notifications for bulk SMS:
$user->notify(new WelcomeNotification()); // Use ShouldQueue trait
- Implement retry logic for critical messages
- Monitor costs using
estimateSegments() - Test with mock gateway before production
- Log all SMS for audit trail
๐ค Support
- Issues: GitHub Issues
- Documentation: README.md
๐ Credits
Developed by Shivam Agarwal
๐ License
MIT License - see LICENSE file for details.
โญ Show Your Support
If this package helps you, please give it a star on GitHub!
Made with โค๏ธ for the Laravel community