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

Jet Sms Laravel Package

laravel-notification-channels/jet-sms

Jet SMS notification channel for Laravel. Send SMS messages through the Jet SMS API using Laravel’s notification system, with a simple channel integration for direct or queued notifications.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the channel and publish its config:

composer require laravel-notification-channels/jet-sms
php artisan vendor:publish --provider="NotificationChannels\JetSms\JetSmsServiceProvider"

Version 4.0.0 just shipped — read the diff before you install. The release notes are empty, but a major bump on a package that sat dormant since March 2020 almost certainly carries breaking changes (PHP/Laravel version floor, namespace or service-provider registration, possibly a switch from Guzzle to Http). Before composer require, open the repo's CHANGELOG.md / UPGRADE.md and diff src/ against the 3.x tag. If no notes exist, pin explicitly — composer require laravel-notification-channels/jet-sms:^4.0 — and treat the source as the spec.

The publish step drops config/jet-sms.php (or similarly named) into your app. Open it first — this is the file you will actually live in. Expect keys for the JetSMS API credentials (username/password or API key) and a default sender/originator. Wire those to .env immediately:

JET_SMS_USERNAME=
JET_SMS_PASSWORD=
JET_SMS_FROM=MyApp

Then clear config cache after editing env in any deployed environment:

php artisan config:clear

Your first use case is almost always a transactional SMS — OTP, order confirmation, appointment reminder. Create a notification and add the channel + message builder:

use Illuminate\Notifications\Notification;
use NotificationChannels\JetSms\JetSmsChannel;
use NotificationChannels\JetSms\JetSmsMessage;

class OrderShipped extends Notification
{
    public function via($notifiable)
    {
        return [JetSmsChannel::class];
    }

    public function toJetSms($notifiable)
    {
        return JetSmsMessage::create()
            ->content("Your order {$this->order->id} has shipped.");
    }
}

Attach Notifiable and a routeNotificationForJetSms() method to your model (see below) and you can send with $user->notify(new OrderShipped($order)).

Before wiring this into anything real, send one SMS in tinker against a staging credential. Public documentation is thin, and 4.0.0's silent release means the README may not even match the code you just installed. Verifying one end-to-end send tells you the exact message-builder method names (content vs text, to vs recipient) faster than reading anything else.

Implementation Patterns

Routing phone numbers. The channel resolves the destination through routeNotificationForJetSms() on the notifiable. Implement it explicitly rather than relying on an email-style fallback:

public function routeNotificationForJetSms()
{
    return $this->phone; // store E.164: +359888123456
}

On-demand notifications (no notifiable model) use Notification::route('JetSms', $phone)->notify(...). Check the channel's expected routing key in the source — most channels key off the class basename (JetSms), but confirm, and re-confirm after the 4.0 bump since routing-key changes are a common breaking change in a major.

Per-message sender override. Keep a default sender in config, but pass a sender per message when you have multiple brands or shortcodes:

return JetSmsMessage::create()
    ->from('BrandB')
    ->content('...');

Compose with other channels. The common pattern is SMS as a fallback/parallel path to mail or push:

public function via($notifiable)
{
    return $notifiable->prefers_sms
        ? [JetSmsChannel::class]
        : ['mail', JetSmsChannel::class];
}

This keeps preference logic in the notification, which is easier to test than sprinkling conditionals in controllers.

Always queue. SMS is an external network call. Make the notification implement ShouldQueue so a slow JetSMS endpoint never blocks a request:

class OrderShipped extends Notification implements ShouldQueue
{
    public $tries = 3;
    public $backoff = [10, 60];
}

This is the single highest-value integration tip for this package — the channel itself is not opinionated about queueing.

Bulk / multi-recipient sends. There is no first-class "broadcast to N numbers" API in the channel; loop over notifiables and dispatch the notification per user. If you need one API call for a batch, drop down to the JetSMS HTTP API directly with Http::withBasicAuth(...) rather than fighting the channel abstraction.

Testing. Fake the notification layer, not the HTTP layer:

Notification::fake();

$user->notify(new OrderShipped($order));

Notification::assertSentTo($user, OrderShipped::class, function ($n, $channels) {
    return in_array(JetSmsChannel::class, $channels);
});

For an actual channel-level test, use Http::fake() if 4.0 moved the package onto Laravel's HTTP client (plausible — that's the usual reason an old package gets a major bump); otherwise use Guzzle mock handlers. Verify the outgoing payload shape once and pin it in a test — if 4.0 rewrote the request layer, payload formatting is exactly where a silent regression would hide.

Centralize credentials. If you run multi-tenant with per-tenant JetSMS accounts, do not try to swap config at runtime through the channel. Instead wrap sending in a small service that instantiates the message and calls the JetSMS API directly, and use the notification channel only for the single-account default case.

Gotchas and Tips

4.0.0 breaks the "abandoned" assumption — but verify it. The prior assessment called this a frozen wrapper from March 2020; that is no longer accurate. A major release after a long dormancy is either a genuine revival (new Laravel support, HTTP client modernization) or a drive-by compatibility shim. With no release notes, you cannot tell which from the tag alone. Read src/ — it is small (one channel, one message class, one service provider), so ten minutes settles it. Then pin the exact minor in composer.json.

Assume breakage between 3.x and 4.0 until proven otherwise. The usual suspects: minimum PHP/Laravel version, service-provider discovery entry, namespace moves, composer.json autoload changes, and message-builder method renames. Upgrading an app that already used this package? Run the test suite against a staging credential before deploying; a green unit suite with Notification::fake() will not catch a channel-level break.

Method names may not match the README. This was true at 9 stars and stale; it is at least as true after an undocumented major. Run vendor/laravel-notification-channels/jet-sms/src/ and read JetSmsMessage and JetSmsChannel first. Guessing ->text() when it is ->content() (or vice versa) is the most common first-run failure.

Sender/originator rules bite in production, not staging. Many SMS gateways require alphanumeric senders to be pre-registered, and some countries reject them outright. If staging works and production returns a sender error, the credential or sender is unprovisioned — not a code bug. Always allow the sender to be overridden per message so you can test different origins without a deploy.

Phone format. Do not send raw user input. Normalize to E.164 before it reaches the channel; the package does no validation. A malformed number typically surfaces as a silent no-delivery or a generic API error, which is painful to trace. Validate at the model/request layer.

Failure handling is not free. Check whether the channel throws on a non-2xx API response or swallows it — and check again on 4.0, since exception behaviour is a classic thing to change in a major without documenting it. If it throws, queued retries handle transient failures well — but combine with failed() on the notification to log a terminal failure. If it swallows errors, add your own logging by wrapping notify() in a try/catch or extending the channel. Either way, do not assume "no exception" means "SMS delivered"; JetSMS can accept a message and reject it downstream.

Config caching is a classic trap. After php artisan config:cache, changes to config/jet-sms.php (and .env) require re-caching. If credentials "aren't updating" in production, this is almost always why. Major-version upgrades often rename config keys — if you published the config under 3.x, re-publish or diff it against the new stub, or your new keys will silently fall back to null.

Debugging outbound traffic. The quickest way to see what is actually being sent is to log the HTTP request. If the channel uses Laravel's Http client (more likely post-4.0), register a global Http::beforeSending callback in a local-only service provider. If it still uses Guzzle directly, push a Middleware::history() handler onto the client. Dump the URL, body, and response — nine times out of ten the "bug" is a wrong sender or a wrong destination format.

Extension points. The channel is intended to be swappable: subclass JetSmsChannel if you need to transform the message before dispatch, and subclass JetSmsMessage to add conveniences (->otp($code) composing a standard template). Because the maintenance story is now uncertain rather than dead, still prefer wrapping over patching vendor files — a thin subclass keeps you fork- and upgrade-able. If you subclassed anything under 3.x, re-check the parent signatures before bumping to 4.0; a changed return type or constructor is a fatal, not a warning.

Don't reach for this for OTP scale. If your volume grows, or you need delivery receipts/webhooks, evaluate the raw JetSMS API (or a provider with richer Laravel tooling). The channel gives you Laravel-idiomatic ergonomics, not features — it is a convenience, and treating a small single-maintainer package as infrastructure is how you end up maintaining a fork.

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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager