symfony/nexmo-notifier
Symfony Notifier bridge for Vonage (formerly Nexmo). Sends SMS notifications via the Notifier component, integrating with Symfony’s channel system. Configure Vonage credentials and deliver messages through a Nexmo/Vonage transport in your apps.
Installation Add the package via Composer:
composer require symfony/nexmo-notifier
Ensure symfony/nexmo-notifier is registered in config/nexmo.php (if using Symfony) or manually configure the client in Laravel.
First Use Case: Sending an SMS
Initialize the client in Laravel’s service container (e.g., config/services.php):
'nexmo' => [
'key' => env('NEXMO_KEY'),
'secret' => env('NEXMO_SECRET'),
'api_url' => env('NEXMO_API_URL', 'https://api.nexmo.com'),
],
Register a binding in AppServiceProvider:
$this->app->bind(\Nexmo\Client, function ($app) {
return new \Nexmo\Client(
$app['config']['services.nexmo.key'],
$app['config']['services.nexmo.secret'],
$app['config']['services.nexmo.api_url']
);
});
Send a Test Message
Create a helper class or facade (e.g., NexmoService):
use Nexmo\Client;
use Nexmo\Message\Sms\Message;
class NexmoService {
protected $client;
public function __construct(Client $client) {
$this->client = $client;
}
public function sendSms(string $to, string $message) {
$message = new Message();
$message->setTo($to)
->setFrom(env('NEXMO_FROM_NUMBER'))
->setText($message);
return $this->client->message()->create($message);
}
}
Use it in a controller:
$nexmo = app(NexmoService::class);
$response = $nexmo->sendSms('+1234567890', 'Hello from Laravel!');
SMS Notifications
class SendBulkSmsJob implements ShouldQueue {
use Dispatchable, InteractsWithQueue, Queueable;
public function handle(NexmoService $nexmo) {
foreach ($recipients as $phone) {
$nexmo->sendSms($phone, 'Your message here');
}
}
}
$template = Template::find($id);
$nexmo->sendSms($phone, $template->body);
Voice Calls
Leverage the Voice\Call class for voice notifications:
use Nexmo\Voice\Call;
$call = new Call();
$call->setTo($phone)
->setFrom(env('NEXMO_FROM_NUMBER'))
->setAnswerUrl('https://example.com/voice-answer');
$this->client->voice()->create($call);
Webhooks Validate and process Nexmo webhooks (e.g., for delivery reports):
Route::post('/nexmo/webhook', function (Request $request) {
$validator = new \Nexmo\Validator\WebhookValidator();
if ($validator->validate($request->all())) {
// Handle event (e.g., SMS delivery status)
}
});
try {
$response = $nexmo->sendSms($to, $message);
} catch (\Exception $e) {
Log::error("Nexmo SMS failed: " . $e->getMessage());
}
throttle middleware for API endpoints triggering Nexmo calls.Nexmo\Client in unit tests:
$mock = Mockery::mock(Nexmo\Client::class);
$mock->shouldReceive('message')->andReturnSelf();
$mock->shouldReceive('create')->andReturn(new stdClass());
$this->app->instance(Nexmo\Client::class, $mock);
Deprecation Warnings The package is archived and may not support newer Nexmo API versions. Verify compatibility with Nexmo’s PHP SDK if issues arise.
Webhook Security Always validate webhook signatures to prevent spoofing:
$validator = new \Nexmo\Validator\WebhookValidator();
$validator->setKey(env('NEXMO_WEBHOOK_KEY'));
if (!$validator->validate($request->all())) {
abort(403, 'Invalid webhook signature');
}
Number Formatting
Ensure phone numbers are in E.164 format (e.g., +1234567890). Use a library like libphonenumber for validation:
use libphonenumber\PhoneNumberUtil;
use libphonenumber\PhoneNumberFormat;
$phoneUtil = PhoneNumberUtil::getInstance();
$phone = $phoneUtil->parse($rawPhone, 'US');
$e164 = $phoneUtil->format($phone, PhoneNumberFormat::E164);
API Credentials
Avoid hardcoding credentials. Use Laravel’s .env and validate them in AppServiceProvider:
if (empty(env('NEXMO_KEY')) || empty(env('NEXMO_SECRET'))) {
throw new \RuntimeException('Nexmo credentials not configured.');
}
Enable Debugging: Set the debug flag in the Nexmo client:
$client = new \Nexmo\Client($key, $secret, $apiUrl, [
'debug' => true,
]);
Logs will appear in storage/logs/nexmo.log (if configured).
HTTP Client Errors: Use Guzzle’s middleware to inspect requests/responses:
$client = new \Nexmo\Client($key, $secret, $apiUrl, [
'http_client' => new \GuzzleHttp\Client([
'handler' => \GuzzleHttp\HandlerStack::create([
new \GuzzleHttp\Middleware::tap(function ($request, $options) {
Log::debug('Nexmo Request:', ['url' => $request->getUri(), 'body' => $request->getBody()]);
}),
]),
]),
]);
Custom Responses
Extend the NexmoService to handle custom Nexmo responses:
public function sendSms(string $to, string $message) {
$response = $this->client->message()->create($message);
return new NexmoResponse($response->getMessageId(), $response->getStatus());
}
Retry Logic
Implement exponential backoff for failed requests using Laravel’s retry helper:
try {
$nexmo->sendSms($to, $message);
} catch (\Exception $e) {
retry()->times(3)->later()->catch(\Exception::class, function () {
Log::error("Max retries reached for Nexmo SMS.");
});
}
Event Dispatching Trigger Laravel events after sending messages:
event(new SmsSent($to, $message));
Listen for events in EventServiceProvider:
protected $listen = [
SmsSent::class => [
SendSmsNotification::class,
LogSmsActivity::class,
],
];
How can I help you explore Laravel packages today?