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 Smpp Laravel Package

franzose/laravel-smpp

franzose/laravel-smpp is a Laravel package for sending SMS messages over the SMPP protocol, giving PHP applications a clean, framework-friendly way to integrate bulk messaging and SMS delivery into their projects.

View on GitHub
Deep Wiki
Context7

Getting Started

franzose/laravel-smpp is a thin Laravel wrapper around the onlinecity/php-smpp client. It gives you a configured SMPP connection and a facade so you can push SMS through an SMSC without hand-rolling socket code. v1.5 is a compatibility release — it adds Laravel 11 support via PR #20 — so the install story is the same as before, just valid on modern Laravel.

Minimum steps:

composer require franzose/laravel-smpp
php artisan vendor:publish --provider="Franzose\Smpp\SmppServiceProvider"

Then fill in config/smpp.php:

return [
    'default' => 'main',
    'connections' => [
        'main' => [
            'host'     => env('SMPP_HOST'),
            'port'     => env('SMPP_PORT', 2775),
            'login'    => env('SMPP_LOGIN'),
            'password' => env('SMPP_PASSWORD'),
            'sender'   => env('SMPP_SENDER'),
            'mode'     => SmppClient::TRANSCEIVER,
            'debug'    => env('SMPP_DEBUG', false),
            'timeout'  => 10000,
        ],
    ],
];

First use case — a single transactional send from a controller or job:

use Franzose\Smpp\Facades\Smpp;

Smpp::sendMessage('+491234567890', 'Your verification code is 1234');

Where to look first, in order:

  1. config/smpp.php — connection shape, mode, timeout, debug.
  2. The facade and its bound service class under vendor/franzose/laravel-smpp/src — confirm the exact send method signature for your version before writing wrappers.
  3. The underlying onlinecity/php-smpp Client/SmppClient source — most real-world behaviour (encoding, concatenation, DLRs) lives there, not in the wrapper.

Verify the pipe before building on it: send one message to a test number with debug => true and confirm both the submit_sm and the submit_sm_resp in the log. SMPP failures are often silent at the Laravel layer.

Implementation Patterns

Wrap the facade behind your own contract. The package exposes a concrete service; injecting the facade directly makes tests painful. Define SmsSender with send(string $to, string $message): void, implement it with the facade, bind it in a service provider, and inject that everywhere. This is the single highest-value refactor and it costs ten minutes.

Notification channel. For anything user-facing, add a SmsChannel and a toSms() method on your notifications. It keeps message construction next to the notification and lets you swap providers later:

public function toSms($notifiable): string
{
    return "Your code is {$this->code}";
}

Always queue sends. SMPP is blocking socket I/O against an external system. Doing it inline in a request ties up a PHP-FPM worker for the duration of the TCP handshake, bind, submit and response — and longer if the SMSC stalls. A queued job with $tries = 3 and backoff() gives you retries and keeps response times flat.

Multiple connections for failover or provider split. The default key plus named connections means you can register a second SMSC and select at runtime. Wrap selection in your service: try the primary, catch the connection exception, fall back to the secondary. Keep the credentials per-connection in .env rather than in config, and remember config:cache freezes whatever you resolved.

Bulk sends: chunk, throttle, and cap concurrency. SMSC providers enforce throughput limits (often 10–50 msg/sec per bind, and sometimes per-sender). Queue one job per chunk of ~100, usleep() between submits, and never fan out to more workers than your provider's window. Exceeding the limit typically surfaces as ESME_RTHROTTLED on submit_sm_resp rather than a clean exception.

Log every send with the message ID. Capture the message_id returned by submit_sm and store it against your domain record. It is the only key you'll have for reconciling delivery receipts and for arguing with the provider about a missing message. Persist to, sender, message_id, status, and the raw response.

Delivery receipts are a separate concern. DLRs arrive asynchronously as deliver_sm PDUs on the same bind, which means a fire-and-forget TRANSMITTER connection will never see them. Either use TRANSCEIVER and a long-running artisan command that reads the socket, or accept that your first implementation only knows "submitted" and not "delivered". Decide this up front — retrofitting a listener is a bigger job than it looks.

Gotchas and Tips

No built-in fake. There is no Smpp::fake() here. Tests must either bind a stub implementation of your SmsSender contract (preferred), or Smpp::shouldReceive('sendMessage') on the facade. Do not let tests reach a real SMSC — CI will hang for the timeout duration and then fail with an opaque socket error.

Encoding and length are not what you think. GSM-7 gives you 160 chars in a single PDU; one non-GSM character (é, €, Cyrillic, CJK) pushes the whole message to UCS-2 at 70 chars. The wrapper does not silently split long messages — segmentation is done with UDH by the php-smpp client, and behaviour varies by version. Measure with mb_strlen against the correct alphabet and either split yourself or verify concatenation empirically. Silent truncation is a real failure mode.

Timeout is a hang, not an error. The timeout value is in milliseconds and applies to socket operations. A large value plus a wedged SMSC equals stuck queue workers that eventually hit max_execution_time with no useful trace. Set it to something modest (5000–10000), rely on job-level retries, and add a retry_after on the queue connection that exceeds the timeout.

A TRANSMITTER bind cannot receive. Switching mode also changes what the client is allowed to do. If you set TRANSCEIVER to get DLRs, you now own a persistent connection that needs reconnect logic — SMSCs drop idle binds after 30–60 seconds. That's a daemon concern, not a request concern; run it under Supervisor.

env() only works inside config/smpp.php. Standard Laravel rule, but it bites here because the config is often edited to add per-environment sender IDs. After php artisan config:cache, any env() call outside config files returns null — and a null sender or login produces a ESME_RBINDFAIL or a bare authentication error rather than a config error.

Provider IP allowlisting. Most SMSCs reject the bind from an unrecognised source IP. Local development will frequently fail to connect at all — that's expected, not a bug in the package. Build a small artisan smpp:ping command that opens the bind and closes it so you can validate credentials and firewall rules independently of your application code.

Laravel 11 notes for this release. v1.5's only change is the illuminate/support constraint widening to include Laravel 11. There are no API changes, deprecations, or config additions — an upgrade from v1.4 should be a no-op at the application layer. Two things to check anyway: the package relies on service-provider auto-discovery, so confirm it still registers in bootstrap/providers.php-era Laravel 11 apps (run php artisan about or config('smpp')); and confirm your PHP version meets whatever Laravel 11 requires, since the wrapper inherits the framework's floor. If you're on Laravel 10, stay on v1.4 — there is no reason to move.

Release cadence is slow. The package is a thin, low-churn wrapper. Budget for the possibility that you outgrow it (complex DLR handling, provider-specific TLVs, high-volume tuning) and may end up using onlinecity/php-smpp directly. Because you wrapped everything behind your own SmsSender contract in the first pattern, that migration stays contained.

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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource