symfony/octopush-notifier
Symfony Notifier transport for Octopush SMS. Configure with an octopush:// DSN using your Octopush email and API key, plus sender and SMS type (LowCost, Premium, World) to send SMS notifications through Octopush.
Install Dependencies (via Composer):
composer require symfony/http-client symfony/notifier
Note: Laravel doesn’t natively support Symfony Notifier, so this is a manual integration.
Configure DSN in .env:
OCTOPUSH_DSN=octopush://USERLOGIN:APIKEY@default?from=SENDER&type=FR
USERLOGIN, APIKEY, SENDER (e.g., YourApp), and type (XXX/FR/WWW).First Use Case: Send an SMS Create a service to bridge Symfony Notifier with Laravel:
// app/Services/OctopushNotifier.php
use Symfony\Component\Notifier\Notifier;
use Symfony\Component\Notifier\Transport\OctopushTransport;
class OctopushNotifier
{
public function send(string $to, string $message): void
{
$dsn = $_ENV['OCTOPUSH_DSN'];
$transport = new OctopushTransport($dsn);
$notifier = new Notifier([$transport]);
$notifier->send(
new \Symfony\Component\Notifier\Message\SmsMessage($message, $to)
);
}
}
Register the Service (Laravel Service Provider):
// app/Providers/AppServiceProvider.php
public function register()
{
$this->app->singleton(OctopushNotifier::class, function ($app) {
return new OctopushNotifier();
});
}
Trigger the SMS (e.g., in a controller or job):
use App\Services\OctopushNotifier;
public function sendWelcomeSms()
{
$notifier = app(OctopushNotifier::class);
$notifier->send('+33612345678', 'Welcome to our app!');
}
For One-Off SMS:
Use the OctopushNotifier service directly in controllers or jobs.
$notifier->send('+33612345678', 'Your OTP is 12345');
For Queued Notifications: Wrap the call in a Laravel job:
// app/Jobs/SendOctopushSms.php
use App\Services\OctopushNotifier;
class SendOctopushSms implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable;
public function handle(OctopushNotifier $notifier)
{
$notifier->send($this->phone, $this->message);
}
}
Dispatch the job:
SendOctopushSms::dispatch('+33612345678', 'Hello!');
For Multi-Channel Notifications:
Extend Symfony’s Notifier to support email/SMS/push in one call (advanced):
$notifier = new Notifier([
new OctopushTransport($_ENV['OCTOPUSH_DSN']),
new MailTransport(new SymfonyMailer()),
]);
$notifier->send(
new MultipartMessage(
new SmsMessage('SMS part', '+33612345678'),
new EmailMessage('Email part', 'user@example.com')
)
);
Laravel Events: Trigger Octopush notifications on Laravel events:
// In an event listener
event(new UserRegistered($user));
SendOctopushSms::dispatch($user->phone, 'Account created!');
Dynamic DSN: Override the DSN per environment or use a config file:
$transport = new OctopushTransport(config('services.octopush.dsn'));
Retry Logic:
Use Laravel’s retry helper for transient failures:
retry(5, function () use ($notifier) {
$notifier->send($phone, $message);
}, 100);
Logging: Log failures for debugging:
try {
$notifier->send($phone, $message);
} catch (\Exception $e) {
\Log::error("Octopush failed: " . $e->getMessage());
}
Symfony Dependency Overhead:
symfony/notifier if only SMS is needed. Use Laravel’s Http facade instead:
Http::withOptions(['auth' => [env('OCTOPUSH_KEY'), '']])
->post('https://api.octopush.com/sms', [
'to' => $phone,
'message' => $message,
'from' => env('OCTOPUSH_FROM'),
'type' => env('OCTOPUSH_TYPE', 'FR'),
]);
DSN Configuration:
type parameter in the DSN (XXX/FR/WWW) must match Octopush’s SMS types. Invalid types will fail silently or return errors.OCTOPUSH_DSN=octopush://login:key@default?from=MyApp&type=FR
Character Limits:
FR). Longer messages auto-split but may incur extra costs.if (mb_strlen($message, 'UTF-8') > 160) {
throw new \InvalidArgumentException('Message too long for Octopush.');
}
Rate Limiting:
use Symfony\Component\Notifier\Exception\TransportException;
try {
$notifier->send($phone, $message);
} catch (TransportException $e) {
if (str_contains($e->getMessage(), 'rate limit')) {
sleep(10); // Wait before retry
retry();
}
}
Testing:
OctopushTransport in PHPUnit:
$transport = $this->createMock(OctopushTransport::class);
$transport->expects($this->once())
->method('send')
->with($this->isInstanceOf(SmsMessage::class));
$notifier = new Notifier([$transport]);
Enable Symfony Debug Mode:
Set SYMFONY_DEBUG=1 in your environment to get detailed errors from the Notifier component.
Check Octopush API Responses:
Use Http::withOptions(['debug' => true]) to inspect raw API responses.
Common Errors:
Invalid DSN: Verify USERLOGIN and APIKEY in the DSN.Unknown sender: Ensure the from parameter in the DSN is approved by Octopush.Quota exceeded: Check your Octopush account balance or upgrade your plan.Custom Transport Options:
Extend OctopushTransport to add Octopush-specific options:
class CustomOctopushTransport extends OctopushTransport
{
public function __construct(string $dsn, array $options = [])
{
parent::__construct($dsn, $options + ['custom_option' => true]);
}
}
Webhook Validation: If using Octopush’s webhooks, validate signatures in Laravel middleware:
public function handle($request, Closure $next)
{
$signature = $request->header('X-Octopush-Signature');
if (!hash_equals($this->generateSignature($request->getContent()), $signature)) {
abort(403);
}
return $next($request);
}
Fallback Providers: Implement a fallback to another SMS provider (e.g., Twilio) if Octopush fails:
try {
$notifier->send($phone, $message);
} catch (\Exception $e) {
$fallbackNotifier->send($phone, $message); // e.g., Twilio
}
Dynamic Sender:
Override the from parameter dynamically:
$transport = new OctopushTransport(
'octopush://login:key@default?type=FR
How can I help you explore Laravel packages today?