parvion/laravel-msg91

A robust Laravel wrapper for MSG91 (v5) supporting OTP, SMS, Email, and WhatsApp with full database logging.

Maintainers

Package info

github.com/AnandKumar2002/laravel-msg91

pkg:composer/parvion/laravel-msg91

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

Stars: 1

Open Issues: 0

dev-main 2026-05-27 16:16 UTC

This package is auto-updated.

Last update: 2026-05-27 16:23:27 UTC


README

A robust, enterprise-grade, API-first Laravel wrapper for MSG91 (v5). This package is strictly designed for API-driven architectures (like headless CMSs), providing comprehensive coverage of MSG91's OTP, SMS, Email, and WhatsApp endpoints without the bloat of frontend UI components. Supports Laravel 10, 11, 12, and 13 with PHP 8.1+.

๐Ÿ“‘ Table of Contents

  1. ๐Ÿš€ Installation
  2. โš™๏ธ Configuration & Logging
  3. โ˜Ž๏ธ Phone Number Formatting
  4. ๐Ÿ“ฑ OTP Features
  5. โœ‰๏ธ SMS Features
  6. ๐Ÿ“ง Email Features
  7. ๐ŸŸข WhatsApp Features
  8. ๐Ÿช Webhooks (DLR)
  9. ๐Ÿงช Testing (Fakes)

๐Ÿš€ Installation

Install the package via composer:

composer require parvion/laravel-msg91

Publish the configuration file (optional, but highly recommended):

php artisan vendor:publish --tag="msg91-config"

Publish the database migration for Activity Logging (Optional):

php artisan vendor:publish --tag="msg91-migrations"
php artisan migrate

โš™๏ธ Configuration & Logging

The package is designed to be entirely driven by your .env file. You don't need to pass templates or sender IDs in your code if you configure them here:

# Core Settings
MSG91_AUTH_KEY="your-real-msg91-auth-key"
MSG91_SENDER_ID="YOURID"
MSG91_COUNTRY_CODE="91"

# Feature Toggles (Turn off channels you don't use to save memory)
MSG91_FEATURE_OTP=true
MSG91_FEATURE_SMS=true
MSG91_FEATURE_EMAIL=true
MSG91_FEATURE_WHATSAPP=true

# Logging (Database & File)
MSG91_LOG_DRIVER="database" # Options: null, log, database, stack

# Granular Logging Control (Only log the channels you want!)
MSG91_LOG_OTP=true
MSG91_LOG_SMS=false     # Disable SMS logs to save database space
MSG91_LOG_EMAIL=true
MSG91_LOG_WHATSAPP=true

โ˜Ž๏ธ Phone Number Formatting

MSG91 requires numbers to include the country code (e.g., 919876543210 for India).

However, you can pass either 10-digit or 12-digit numbers to this package. The built-in formatter automatically checks your MSG91_COUNTRY_CODE setting:

  • Pass 10 digits (9876543210) -> Auto-prepends country code (919876543210).
  • Pass 12 digits or plus sign (+919876543210) -> Formatted correctly for the API (919876543210).

๐Ÿ“ฑ OTP Features

Send an OTP

use Parvion\Msg91\Facades\Msg91;
use Parvion\Msg91\DTOs\OtpData;

$response = Msg91::sendOtp(OtpData::fromArray([
    'mobile' => '919876543210', 
    // 'template_id' => '...' (Optional: automatically pulls from config)
]));

Verify an OTP

// Returns the MSG91 array on success, throws an InvalidOtpException on failure
use Parvion\Msg91\Exceptions\InvalidOtpException;

try {
    Msg91::verifyOtp('919876543210', '123456');
} catch (InvalidOtpException $e) {
    if ($e->isExpired()) {
        // Tell frontend to show "Resend" button
    } elseif ($e->isIncorrect()) {
        // Tell frontend "Wrong code"
    }
}

Resend & Retry

// Standard text resend
Msg91::resendOtp('919876543210');

// Retry via Voice Call (Perfect for users who didn't receive the text)
use Parvion\Msg91\Enums\OtpRetryType;
Msg91::retryOtp('919876543210', OtpRetryType::Voice);

Smart Fallback

// Attempts SMS, if fails tries WhatsApp, then finally Email automatically!
Msg91::fallbackOtp('919876543210', ['sms', 'whatsapp', 'email']);

OTP Analytics & Logs

$analytics = Msg91::getOtpAnalytics(now()->subMonth(), now());
$logs      = Msg91::getOtpLogs(now()->subDays(7), now());

โœ‰๏ธ SMS Features

Send a Single SMS

use Parvion\Msg91\DTOs\SmsData;
use Parvion\Msg91\Enums\SmsRoute;

Msg91::sendSms(SmsData::fromArray([
    'mobile'  => '919876543210',
    'message' => 'Your order #12345 is confirmed!',
    'route'   => SmsRoute::Transactional,
]));

Send Bulk SMS

$recipients = ['919876543210', '919876543211', '919876543212'];

Msg91::sendBulkSms($recipients, SmsData::fromArray([
    'message' => 'HUGE SALE! Everything 50% off today only!',
    'route'   => SmsRoute::Promotional,
]));

Dispatch Background Job (Highly Recommended)

Never make your users wait for an HTTP request to finish.

use Parvion\Msg91\Jobs\SendSmsJob;

// Queues the SMS to be sent by a background worker instantly.
SendSmsJob::dispatch(SmsData::fromArray([
    'mobile'  => '919876543210',
    'message' => 'Your order is confirmed!',
]));

Schedule SMS for the Future

// Sends exactly 2 days from now
Msg91::scheduleSms($smsData, now()->addDays(2));

Trigger MSG91 Campaign Flow

// Trigger a visual Flow built in your MSG91 dashboard
Msg91::triggerFlow('flow_id_abc123', ['customer_name' => 'John Doe'], '919876543210');

SMS Delivery Status & Analytics

$status    = Msg91::checkDeliveryStatus('msg91-request-id-12345');
$analytics = Msg91::getSmsAnalytics(now()->subMonth(), now());

๐Ÿ“ง Email Features

Send a Single Email

use Parvion\Msg91\DTOs\EmailData;

Msg91::sendEmail(EmailData::fromArray([
    'to'         => ['john@example.com'],
    'subject'    => 'Welcome to the platform!',
    'template_id'=> 'your-email-template-id',
    'variables'  => ['name' => 'John'], // Dynamic template injection
]));

Send Bulk Email

$emails = ['user1@example.com', 'user2@example.com', 'user3@example.com'];

Msg91::sendBulkEmail($emails, EmailData::fromArray([
    'subject'    => 'System Maintenance Notice',
    'template_id'=> 'maintenance-template-id',
]));

Email with Strict Validation

// Enforces strict deliverability validation on the MSG91 side
Msg91::sendEmailWithValidation($emailData);

Massive CSV Bulk Send

// Send thousands of emails instantly by uploading a CSV
Msg91::sendEmailWithCsv(storage_path('app/contacts.csv'), $emailData);

Create & Fetch Templates

// Create a new HTML template programmatically
Msg91::createEmailTemplate('Monthly Newsletter', '<h1>Hello World</h1>');

// Fetch all existing templates
$templates = Msg91::getEmailTemplates(['per_page' => 50]);

Email Logs

$logs = Msg91::getEmailLogs(now()->subWeek(), now());

๐ŸŸข WhatsApp Features

Send a Standard WhatsApp Message

use Parvion\Msg91\DTOs\WhatsAppData;

Msg91::sendWhatsApp(WhatsAppData::fromArray([
    'mobile'  => '919876543210',
    'message' => 'Hello from WhatsApp!',
]));

Send an Approved WhatsApp Template

Msg91::sendWhatsAppTemplate(WhatsAppData::fromArray([
    'mobile'      => '919876543210',
    'template_id' => 'your_approved_whatsapp_template_id',
    'variables'   => ['name' => 'John'], 
]));

๐Ÿช Webhooks (Delivery Receipts - DLR)

Instead of polling MSG91 to see if an SMS or OTP was delivered, let MSG91 tell your application automatically.

1. Register the route in your routes/api.php:

use Parvion\Msg91\Http\Controllers\Msg91WebhookController;

Route::post('/msg91/webhook', [Msg91WebhookController::class, 'handle']);

2. Listen for the Laravel Events: When MSG91 pings your webhook, the package will dispatch native events. Create an Event Listener in your app to handle them:

namespace App\Listeners;

use Parvion\Msg91\Events\MessageDeliveryStatusChanged;

class UpdateMessageStatus
{
    public function handle(MessageDeliveryStatusChanged $event)
    {
        // $event->requestId
        // $event->status ('delivered', 'failed', 'sent')
        // $event->rawPayload (The full JSON from MSG91)
        
        // Example: DB::table('messages')->where('request_id', $event->requestId)->update(['status' => $event->status]);
    }
}

๐Ÿงช Testing

The package provides a built-in Msg91Fake for flawless TDD. You will never accidentally spend money or hit real API limits while testing.

use Parvion\Msg91\Facades\Msg91;

public function test_user_registration_sends_otp()
{
    // 1. Swap the real API with our in-memory Fake
    Msg91::fake();

    // 2. Trigger your application logic
    $this->postJson('/api/register', ['phone' => '919876543210']);

    // 3. Assert the exact API call was made!
    Msg91::assertOtpSent('919876543210');
    Msg91::assertSmsNotSent();
    Msg91::assertEmailNotSent();
}

License

The MIT License (MIT). Please see License File for more information.