Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Sms Gateway Laravel Package

misaf/laravel-sms-gateway

Driver-based SMS gateway manager for Laravel with separate first-party packages for providers like Twilio, Vonage, Kavenegar, and more. Switch drivers per request, use Laravel’s HTTP client, listen for sent events, and register custom drivers.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the core plus exactly one driver. The core package ships no providers, so composer require misaf/laravel-sms-gateway alone gets you a manager that throws on first send.

composer require misaf/laravel-sms-gateway
composer require misaf/laravel-sms-gateway-kavenegar   # pick one
php artisan vendor:publish --tag=sms-gateway-config

Where to look first: config/sms-gateway.php. It holds the default driver name and a drivers map with per-provider credentials. Read the driver package's README next — the core README only tells you which packages exist, not the method signatures, and driver-level quirks (sender numbers, template/pattern IDs, line numbers) live there.

First use case: an OTP send. Set the default driver from env, put credentials in .env, then send from a controller or, better, a queued job:

// .env
SMS_GATEWAY_DRIVER=kavenegar
KAVENEGAR_API_KEY=...

// anywhere
$response = SmsGateway::driver()->send($user->phone, 'Your code is 123456');

Two things to confirm before writing app code: (1) the exact manager method name (send / sendMessage / a message object) and (2) the return type — read the driver's source, since it's a one-star package and the README is a feature list rather than an API reference. Nail both down with a tinker session and a real send to your own number before building around it.

Hard gate: PHP 8.3+ and Laravel 13+. This will not install on a Laravel 10/11 app without conflict, so check composer why-not early — that alone rules the package out for most existing projects.

Implementation Patterns

Keep the default driver in config, override per call. The advertised feature is "switch drivers per request," which is useful for failover and for multi-region/multi-tenant apps where different brands have different panel contracts. Prefer:

$driver = config("sms.tenants.{$tenant->id}.driver", config('sms-gateway.default'));
SmsGateway::driver($driver)->send($to, $body);

Don't sprinkle driver('x') literals through controllers — resolve from config or a SmsSender service so a panel migration is a one-line change.

Wrap it in your own small interface. Given the maturity signals (1 star, 0 dependents, a version bump that will track Laravel majors), the pragmatic pattern is to bind your own SmsSender contract and have one adapter class own the package calls, the phone normalization, and the error mapping. If the package stalls, you swap the adapter and nothing else moves.

final class GatewaySmsSender implements SmsSender
{
    public function send(string $to, string $body): void { /* SmsGateway::driver(...)->... */ }
}

Send from a queued job, never inline. Every provider call is an outbound HTTP request with a multi-second timeout. A SendSms job with $tries = 3 and backoff() gives you retries the package almost certainly doesn't provide itself.

Use the events for the audit trail. The package emits SMS-sent events carrying request and response payloads. Register a listener that persists them (driver, recipient, body hash, provider message id, cost) — that's your deliverability debugging and your billing reconciliation. Also log failures there, since a thrown exception on the send path should be caught in the job, not bubble to the user.

Register a log / null driver for local and CI. The custom-driver registration hook is the most valuable extension point in the package. Implement a driver that writes to the log and returns a fake response, register it under local, and set SMS_GATEWAY_DRIVER=log in .env.testing. This keeps your test suite off the network and off your real SMS balance.

Laravel HTTP client access means the underlying calls go through Http:: — so Http::fake() in tests and a global Http::macro for correlation IDs / proxy config will apply to driver traffic. Use that for timeouts and retry middleware rather than trusting per-driver defaults.

Gotchas and Tips

  • Driver package missing = confusing failure. The core resolves a driver name to a class from the driver package; if you set SMS_GATEWAY_DRIVER=plivo and didn't install the Plivo package, you get a resolution error, not a helpful message. Add the driver package to composer.json in the same commit that sets the env var.
  • config:cache will bite you if you read credentials from env inside the config after caching in a deploy script that orders steps wrong. Standard Laravel rule, but more painful here because a stale cache means sends silently go to the wrong panel or fail auth.
  • HTTP 200 with an error body is the norm for regional panels (Ghasedak, IPPanel, Kavenegar, Melipayamak). The package's boolean/response semantics may report success while the provider rejected the message. Always check the provider's own status field in the returned payload, and assert on it in your listener.
  • Phone number format is on you. Iranian panels want 09xxxxxxxxx or 989xxxxxxxxx depending on provider; MessageBird/Plivo want E.164. Normalize at the boundary of your adapter, not at each call site.
  • No rate limiting or throttling in the core. Providers enforce per-second/per-minute caps and will 429 or silently drop. Use Redis::throttle() in the job's middleware, keyed per driver.
  • Version-pin the driver packages ("misaf/laravel-sms-gateway-kavenegar": "^1.0") and pin the core too — with zero dependents, minor releases get limited real-world testing.
  • Vendor risk is the headline. One star, no dependents, and a Laravel-13-only floor means you're an early adopter on a package with a tiny userbase. That's fine for an internal tool or an MVP, but budget for the possibility that you maintain a fork. Keeping the package behind your own SmsSender interface makes that fork a contained, boring job instead of a refactor.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk