SMS notification channel for Laravel & Filament with pluggable operators (Fake, Sabanovin, Smsir).

Maintainers

Package info

github.com/mortezamasumi/fb-sms

pkg:composer/mortezamasumi/fb-sms

Transparency log

Statistics

Installs: 287

Dependents: 2

Suggesters: 0

Stars: 0

Open Issues: 0

v5.1.3 2026-08-12 04:56 UTC

This package is auto-updated.

Last update: 2026-08-12 05:23:55 UTC


README

Latest Version on Packagist GitHub Tests Action Status Total Downloads License

A Laravel notification channel that sends SMS through pluggable operators. It ships with the Sabanovin and Smsir (sms.ir) operators, plus a Fake operator for local development and testing.

Features

  • Drop-in Laravel channel — send via the standard Notification::route('sms', ...)->notify(...) flow
  • Pluggable operators — swap providers through config without touching your notification classes
  • Built-in operatorsSabanovin, Smsir, and a Fake logger for local development
  • Prepend/append text — configure a prefix/suffix (e.g. an opt-out line) applied to every message
  • Recipient fallback — uses routeNotificationFor('sms', $notification), then $notifiable->mobile
  • Lifecycle hooksbeforeSend(), send(), afterSend(), plus succeeded() / failed() on notifications
  • Graceful failure — send/credit errors are caught, logged, and reported to your notification's failed()

Installation

composer require mortezamasumi/fb-sms

Publish the config file:

php artisan vendor:publish --tag="fb-sms-config"

Configuration

// config/fb-sms.php
return [
    // Sabanovin API domain (without scheme)
    'sabanovin_domain' => env('SABANOVIN_DOMAIN', 'api.sabanovin.com'),

    // Sabanovin reports the balance in Toman; multiplied to convert to Rial (1 Toman = 10 Rial)
    'sabanovin_balance_multiplier' => env('SABANOVIN_BALANCE_MULTIPLIER', 10),

    // Active operator class — one of the bundled operators or your own
    'operator' => env('SMS_CHANNEL_OPERATOR', \Mortezamasumi\FbSms\Operators\Fake::class),

    // API key/username used by Sabanovin and Smsir
    'api_key' => env('SMS_CHANNEL_API_KEY', 'key'),

    // SMS line/number used as the sender gateway
    'gateway' => env('SMS_CHANNEL_GATEWAY', 'gateway'),

    // Fixed receiver, overrides the notifiable's phone when set
    'receiver' => env('SMS_CHANNEL_RECEIVER', null),

    // Optional prefix/suffix applied to every message
    'prepend_text' => env('SMS_CHANNEL_PREPEND_TEXT', ''),
    'append_text'  => env('SMS_CHANNEL_APPEND_TEXT', "\n\n\n لغو ۱۱"),
];

Usage

Create a notification and send it through the sms channel:

use Illuminate\Notifications\Notification;

class InvoicePaid extends Notification
{
    public function via(object $notifiable): array
    {
        return ['sms'];
    }

    public function toSms(object $notifiable): string
    {
        return "Your invoice was paid. Amount: {$notifiable->amount}";
    }
}

Send it to a notifiable model that exposes a phone number (either mobile or routeNotificationFor('sms', ...)):

$user->notify(new InvoicePaid());

Or send to a phone number directly:

use Illuminate\Support\Facades\Notification;

Notification::route('sms', '09121234567')->notify(new InvoicePaid());

Recipient resolution

  1. $notifiable->routeNotificationFor('sms', $notification) if it exists, then
  2. $notifiable->mobile if it is set, then
  3. the fb-sms.receiver config value, or
  4. the route value passed to Notification::route('sms', ...).

Success and failure hooks

class InvoicePaid extends Notification
{
    public function succeeded($operator): void
    {
        // $operator->getCode() / getMessage() hold the provider response
    }

    public function failed(\Throwable $exception): void
    {
        // log, alert, retry...
    }
}

Credit lookup

use Mortezamasumi\FbSms\Facades\FbSms;

FbSms::credit(); // '125000' — 'N/A' when the provider is unreachable

Custom operators

Implement your own provider by extending Mortezamasumi\FbSms\Contracts\Operator and implement send() and credit():

use Mortezamasumi\FbSms\Contracts\Operator;

class MyOperator extends Operator
{
    public function send(): void
    {
        // $this->getText()   — message body
        // $this->getTo()     — recipient(s)
        // $this->getGateway()— sender line
        // $this->setCode('1'); $this->setMessage('ok');
    }

    public function credit(): string
    {
        return '10000';
    }
}

Register it via config:

'operator' => env('SMS_CHANNEL_OPERATOR', App\Sms\MyOperator::class),

If your operator needs app-level setup, override public static function initialize(FbSmsServiceProvider $provider): void — it runs once before the operator is first used.

Support policy

PHP Laravel
8.3 12

Testing

composer test

The test suite covers operator responses, recipient resolution, lifecycle hooks, and failure paths using Http::fake() and the bundled Fake operator — no real SMS is sent.

Contributing

Please see CONTRIBUTING for details.

Security

If you discover a security vulnerability, please review our security policy on how to report it.

Changelog

Please see CHANGELOG for recent changes.

License

The MIT License (MIT). See LICENSE.md for details.