symfony/ovh-cloud-notifier
Symfony Notifier transport for OVHcloud SMS. Configure an ovhcloud:// DSN with application key/secret, consumer key, service name, optional sender, and an option to remove the STOP clause for non-commercial messages.
Install the Package
composer require symfony/ovh-cloud-notifier
Configure DSN in .env
Add your OVH Cloud credentials to .env:
OVHCLOUD_DSN=ovhcloud://APPLICATION_KEY:APPLICATION_SECRET@default?consumer_key=CONSUMER_KEY&service_name=SERVICE_NAME&sender=SENDER&no_stop_clause=1
Set Up a Laravel Service Provider
Register the OVH Cloud notifier transport in config/services.php:
'ovhcloud' => [
'dsn' => env('OVHCLOUD_DSN'),
],
Create a service provider (e.g., OvhCloudServiceProvider) to bind the transport:
use Symfony\Component\Notifier\Notifier;
use Symfony\Component\Notifier\Transport\OvhCloudTransport;
public function register()
{
$this->app->singleton('ovhcloud.transport', function ($app) {
$dsn = $app['config']['services.ovhcloud.dsn'];
return new OvhCloudTransport($dsn);
});
}
First Use Case: Send an SMS Alert
Use Laravel’s Notifier facade (or Symfony’s Notifier if preferred):
use Symfony\Component\Notifier\Notifier;
use Symfony\Component\Notifier\Message\SmsMessage;
$notifier = new Notifier([app('ovhcloud.transport')]);
$message = new SmsMessage('Your OVH server is down!', 'recipient@example.com');
$notifier->send($message);
Event-Driven Workflows Bind OVH Cloud notifications to Laravel events for reactive processing:
// In a controller or command
event(new OvhServerDownEvent($serverId, $message));
Create a listener:
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class HandleOvhAlert implements ShouldQueue
{
public function handle(OvhServerDownEvent $event)
{
$notifier = new Notifier([app('ovhcloud.transport')]);
$message = new SmsMessage($event->message, 'admin@example.com');
$notifier->send($message);
}
}
Queue-Based Processing Offload OVH notifications to a queue for reliability:
// Dispatch a job to send an SMS
SendOvhSmsJob::dispatch('Your server is down!', 'admin@example.com');
Define the job:
use Illuminate\Bus\Queueable;
use Symfony\Component\Notifier\Notifier;
use Symfony\Component\Notifier\Message\SmsMessage;
class SendOvhSmsJob implements Queueable
{
use Dispatchable, InteractsWithQueue, Queueable;
public function handle()
{
$notifier = new Notifier([app('ovhcloud.transport')]);
$message = new SmsMessage($this->message, $this->recipient);
$notifier->send($message);
}
}
Webhook Integration Create a Laravel route to handle OVH webhooks:
Route::post('/ovh-webhook', [OvhWebhookController::class, 'handle']);
Validate and process the webhook:
use Illuminate\Http\Request;
use Symfony\Component\Notifier\Notifier;
use Symfony\Component\Notifier\Message\SmsMessage;
public function handle(Request $request)
{
// Validate HMAC signature (use spatie/laravel-hmac or custom logic)
if (!$this->validateHmac($request)) {
abort(403);
}
$notifier = new Notifier([app('ovhcloud.transport')]);
$message = new SmsMessage('OVH Alert: ' . $request->alert, 'admin@example.com');
$notifier->send($message);
}
Dynamic Recipient Routing Use Laravel’s service container to dynamically resolve recipients:
$recipients = config('ovh.alert_recipients');
$notifier = new Notifier([app('ovhcloud.transport')]);
foreach ($recipients as $recipient) {
$message = new SmsMessage($event->message, $recipient);
$notifier->send($message);
}
Http Facade: Replace Symfony’s HttpClient with Laravel’s Http facade for HTTP requests if needed.\Log::info('OVH Alert Sent', ['message' => $message->getContent()]);
retry helper for transient failures:
retry(3, function () use ($notifier, $message) {
$notifier->send($message);
}, 100);
OvhCloudTransport in PHPUnit:
$transport = $this->createMock(OvhCloudTransport::class);
$transport->expects($this->once())->method('send');
$notifier = new Notifier([$transport]);
DSN Configuration Errors
consumer_key, service_name).HMAC Validation Bypass
spatie/laravel-hmac or implement custom logic:
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
public function validateHmac(Request $request)
{
$expectedSignature = hash_hmac('sha256', $request->getContent(), config('ovh.hmac_secret'));
return hash_equals($expectedSignature, $request->header('X-Hmac-Sha256'));
}
Rate Limiting
$message->delay(now()->addMinutes(1)); // Space out notifications
Symfony Component Conflicts
symfony/ovh-cloud-notifier.composer.json or use Laravel’s replace directive:
"replace": {
"symfony/http-client": "6.4.*",
"symfony/notifier": "6.4.*"
}
No Stop Clause Misconfiguration
no_stop_clause=1 may violate OVH’s commercial SMS policies.Stateful Processing
visited middleware or a database log:
// In a listener or controller
if (OvhAlert::where('event_id', $event->id)->exists()) {
return; // Skip duplicate
}
OvhAlert::create(['event_id' => $event->id]);
Enable Debug Mode Configure the OVH transport to log requests/responses:
$transport = new OvhCloudTransport($dsn, [
'debug' => true,
]);
Check OVH API Status Verify OVH’s API and SMS service status via their status page before debugging.
Validate Credentials Test credentials manually using OVH’s API documentation or Postman:
curl -X GET "https://api.ovh.com/1.0/auth" \
-H "X-Ovh-Application: $APPLICATION_KEY" \
-H "X-Ovh-ConsumerKey: $CONSUMER_KEY"
Inspect Queue Jobs Monitor failed jobs in Laravel’s queue:
php artisan queue:failed-table
php artisan queue:retry JOB_ID
OvhCloudTransport for additional features (e.g., custom headers):
class CustomOvhCloudTransport extends OvhCloudTransport
{
public function __construct(Dsn $dsn, array $
How can I help you explore Laravel packages today?