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

Nexmo Bundle Laravel Package

javihgil/nexmo-bundle

A Symfony bundle that integrates Nexmo (now Vonage) SMS services into your application, handling client configuration and service wiring so you can send text messages through a simple, dependency-injection-friendly interface.

View on GitHub
Deep Wiki
Context7

Getting Started

Read this first: it is not a Laravel package. javihgil/nexmo-bundle is a Symfony2 bundle — the install path is AppKernel::registerBundles(), config lives in app/config/config.yml under a javihgil_nexmo: key, and the client is exposed as a container service. There is no ServiceProvider, no Facade, no package discovery, and no config/ publish tag. You cannot composer require it into a Laravel app and get a working binding.

Compounding that: the repo is archived, last tagged 2016-03-01, 7 stars, 0 dependents. Its composer.json will pin symfony/symfony or symfony/framework-bundle to a 2.x range and likely a nexmo/client 1.x line — both of which conflict with any modern Laravel (symfony/* ^6/^7) and PHP 8.x. Expect Composer to refuse the install outright.

So the realistic "getting started" is triage, in this order:

  1. composer.json — confirm the framework and PHP constraints. This tells you immediately whether a fork is viable or whether you are only reading it for reference.
  2. DependencyInjection/*Extension.php — the config tree. This is the only place the package defines its knobs (almost certainly api_key / api_secret, possibly from). Copy these key names into your own config/services.php array.
  3. Resources/config/services.yml — the service id and constructor wiring. This is the 10 lines you are actually going to port.
  4. The wrapper class itself — usually a thin thing with a send() / sendText() method that news up Nexmo\Client and forwards arguments.

First use case: treat the bundle as a reference implementation, not a dependency. Read the service definition and constructor, then write the equivalent in App\Providers\NexmoServiceProvider:

$this->app->singleton(\Nexmo\Client::class, fn ($app) => new \Nexmo\Client(
    new \Nexmo\Client\Credentials\Basic(
        config('services.nexmo.key'),
        config('services.nexmo.secret')
    )
));

That is the entire value the bundle was providing. If you genuinely need to run the bundle as-is, it only makes sense inside a legacy Symfony 2.8 app, in which case register it in AppKernel and inject the service by id.

Implementation Patterns

Port, don't depend. The highest-value pattern is a one-afternoon extraction: fork the repo, delete DependencyInjection/, JavihgilNexmoBundle.php, and Resources/config/, keep only the client wrapper, and re-expose it through a Laravel service provider. You keep the method signatures your team already knows and drop 90% of the surface area.

Bind to an interface, not the SDK. Wrap the Nexmo client behind SmsSender / SmsSenderInterface. The bundle era used key+secret auth; Vonage now expects application_id + private_key (JWT) for Voice and Messages API. An interface lets you swap the auth strategy without touching call sites — which you will have to do.

Always queue the send. SMS is external I/O with multi-second tail latency and provider-side throttling. The bundle has no queue awareness at all; it calls through synchronously. In Laravel:

class SendSms implements ShouldQueue
{
    public function __construct(public string $to, public string $text) {}

    public function handle(SmsSender $sms): void
    {
        $sms->send($this->to, $this->text);
    }
}

Check the response body, not the HTTP status. Nexmo's SMS API returns 200 OK even when the message is rejected; the real verdict is messages[0].status ("0" = accepted). Any wrapper ported from a 2016 bundle almost certainly does not do this. Normalize it in your adapter:

$response = $client->sms()->send($message);
$msg = $response->current();
if ($msg->getStatus() !== 0) {
    throw new SmsFailedException($msg->getStatus() . ': ' . $msg->getErrorText());
}

Webhook handling belongs in Laravel routing. Delivery receipts (status, messageId, msisdn) and inbound SMS arrive as GET/POST to a route you define. There is nothing in the bundle for this. Use a dedicated controller, verify the sig parameter (HMAC-SHA256 over the sorted params with your secret), and persist by messageId — that key is what ties a receipt back to whatever row you wrote when you queued the job.

Config shape. Mirror the bundle's parameter names so behaviour is familiar, but source them from env:

// config/services.php
'nexmo' => [
    'key'    => env('NEXMO_KEY'),
    'secret' => env('NEXMO_SECRET'),
    'from'   => env('NEXMO_FROM', 'MyApp'),
],

Test seam. Register a NullSmsSender or a LogSmsSender in the test environment, or $this->mock(SmsSender::class). Never let a feature test hit the network — the bundle offers no fake, and outbound SMS in CI costs real money.

Gotchas and Tips

  • Archived means dead. No security patches, no PHP 8 compatibility, no maintainer. Any CVE in a transitive dependency of a 2016 nexmo/client is permanently yours. Do not ship this to production.
  • Nexmo is Vonage. The brand, SDK namespace (Nexmo\Client → Vonage\Client), and docs all moved. The old nexmo/client package is abandoned in favour of vonage/client. Any code you port should target the current SDK, not the one the bundle pins.
  • Auth model changed. Key/secret still works for SMS but is insufficient for Voice, Verify, and Messages API (application ID + private key, JWT). If you hardcode the bundle's credential shape you will be rewriting it within a quarter.
  • Symfony DI idioms do not translate. Parameter placeholders like %javihgil_nexmo.api_key%, service ids with dots, and tag-based injection have no Laravel equivalent. Do not attempt to "run" the bundle's services.yml through a shim; rewrite the ten lines by hand.
  • Message segmentation is on you. GSM-7 gives 160 chars, 153 per part when concatenated; any non-GSM character (smart quotes, emoji, accented chars from pasted copy) flips the whole message to UCS-2 at 70/67. A 200-char message can silently cost 3 credits. Sanitize and assert length before send.
  • Sender ID / alphanumeric originator. from is often constrained per country — alphanumeric IDs are rejected in the US and Canada, where you need a long code or short code. Validate against destination country rather than assuming the configured from works everywhere.
  • E.164 or nothing. The bundle will happily pass through whatever you give it. Normalize to +44... (no spaces, no 00 prefix) yourself; malformed numbers return a per-message error status, not an exception.
  • config:cache footgun. If you port the bundle's habit of reading credentials at container build time via getParameter(), make sure nothing calls env() outside config/ files — cached config returns null for direct env() calls in application code.
  • Extension point is the config tree. If you fork, keep the Configuration.php tree as the documented contract for keys and defaults, and map it onto a Laravel config array. That is the one piece of the bundle's design worth preserving: a single validated place where credentials and defaults live.
  • Debugging sends. Log the full provider response (including message-id and network) alongside your own correlation id. When someone reports "the SMS never arrived," the first question is always whether it was rejected at submit or accepted-but-undelivered, and only the response body distinguishes them.
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.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log