sol-parts / symfony-alphasms-notifier
Symfony AlphaSMS Notifier Bridge
Package info
github.com/sol-parts/symfony-alphasms-notifier
Type:symfony-notifier-bridge
pkg:composer/sol-parts/symfony-alphasms-notifier
Requires
- php: >=8.2
- symfony/http-client: ^6.4|^7.0
- symfony/http-foundation: ^6.4|^7.0
- symfony/notifier: ^7.3
- symfony/remote-event: ^6.4|^7.0
- symfony/webhook: ^6.4|^7.0
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Provides AlphaSMS integration for Symfony Notifier. The package supports SMS, Viber with SMS fallback, account balance checks, and delivery-status webhooks.
Installation
composer require sol-parts/symfony-alphasms-notifier
Standalone usage
The transport can be used without the Symfony Full Stack Framework:
use SolParts\SymfonyAlphaSmsNotifier\AlphaSmsOptions; use SolParts\SymfonyAlphaSmsNotifier\AlphaSmsTransport; use Symfony\Component\Notifier\Message\SmsMessage; $transport = new AlphaSmsTransport('api-key', 'ExampleShop'); $options = (new AlphaSmsOptions())->id(100500); $message = new SmsMessage( phone: '+380771234567', subject: 'Your order has been shipped.', options: $options, ); $sentMessage = $transport->send($message); dump($sentMessage->getMessageId()); // '100500' dump($sentMessage->getInfo()); // The complete decoded AlphaSMS API response.
Checking the balance
$balance = $transport->balance(); dump($balance); // '125.50 UAH'
Checking a delivery status
Pass the client-side message id — the one you set through AlphaSmsOptions::id()
or the one the transport generated and returned as the sent message id. The
gateway-side msg_id is not accepted here and yields a "Message not found"
error.
$status = $transport->status($sentMessage->getMessageId()); dump($status); // [ // 'id' => '175743824636625', // 'msg_id' => '1419790613', // 'type' => 'sms', // 'status' => 'DELIVERED', // 'updated' => '2024-01-31T12:34:00+02:00', // ]
Only DELIVERED, READ, REPLIED and PARTIALLY DELIVERED mean the message
reached the recipient. Every other value — ACCEPTED included — is either
intermediate or a failure: a message sitting in ACCEPTED long after updated
has not been delivered.
Polling is meant for one-off diagnostics. To track delivery continuously, set
the hook option and let the gateway push status changes to your webhook.
Symfony Full Stack Framework
Add the AlphaSMS DSN to your environment:
# .env.local ALPHASMS_DSN=alphasms://API_KEY@default?from=ExampleShop
Register the transport factory:
# config/services.yaml services: SolParts\SymfonyAlphaSmsNotifier\AlphaSmsTransportFactory: autowire: true tags: ['texter.transport_factory']
Configure the texter transport:
# config/packages/notifier.yaml framework: notifier: texter_transports: alphasms: '%env(ALPHASMS_DSN)%'
Where:
API_KEYis your AlphaSMS API key;FROMis your registered sender name.
URL-encode the API key and sender name if they contain characters reserved in a URI.
Inject Symfony's TexterInterface to send a message:
use Symfony\Component\Notifier\Message\SmsMessage; use Symfony\Component\Notifier\TexterInterface; final class OrderNotifier { public function __construct( private readonly TexterInterface $texter, ) { } public function sendShippingNotice(string $phone): void { $this->texter->send(new SmsMessage( $phone, 'Your order has been shipped.', )); } }
Message options
Use AlphaSmsOptions to configure an AlphaSMS message:
use SolParts\SymfonyAlphaSmsNotifier\AlphaSmsOptions; use Symfony\Component\Notifier\Message\SmsMessage; $options = (new AlphaSmsOptions()) ->id(100500) ->sms_lifetime(172800) ->short_link(true) ->hook('https://example.com/webhook/alpha_sms'); $message = new SmsMessage( phone: '+380771234567', subject: 'Track your shipment: https://example.com/orders/100500', options: $options, );
To try Viber first and fall back to SMS when delivery is unavailable, enable
viber_if_possible() and add the Viber options you need:
$options = (new AlphaSmsOptions()) ->viber_if_possible(true) ->viber_text('Ваше замовлення готове до видачі. Дякуємо за покупку!') ->viber_image('https://example.com/images/message.png') ->viber_link('https://example.com/orders/100500') ->viber_button('View order') ->viber_lifetime(172800);
The optional viber_text() sets a separate Viber body. When omitted or blank,
the SMS body is used. SMS fallback always keeps the original SMS body.
The transport derives the AlphaSMS viber_type from the options actually set,
so a plain text Viber message is a single call:
$options = (new AlphaSmsOptions())->viber_if_possible(true);
AlphaSMS accepts only viber_lifetime for the viber+sms type, so
sms_lifetime() is ignored while viber_if_possible(true) is set.
Delivery-status webhook
Register the AlphaSMS request parser:
# config/services.yaml services: notifier.webhook.request_parser.alpha_sms: class: SolParts\SymfonyAlphaSmsNotifier\Webhook\AlphaSmsRequestParser
Configure the webhook routing and use your AlphaSMS API key as the signing secret:
# config/packages/framework.yaml framework: webhook: routing: alpha_sms: service: notifier.webhook.request_parser.alpha_sms secret: '%env(ALPHASMS_WEBHOOK_SECRET)%'
The resulting endpoint is /webhook/alpha_sms. Add a consumer for the parsed
SMS events:
use Symfony\Component\RemoteEvent\Attribute\AsRemoteEventConsumer; use Symfony\Component\RemoteEvent\Consumer\ConsumerInterface; use Symfony\Component\RemoteEvent\Event\Sms\SmsEvent; use Symfony\Component\RemoteEvent\RemoteEvent; #[AsRemoteEventConsumer('alpha_sms')] final class AlphaSmsEventConsumer implements ConsumerInterface { public function consume(RemoteEvent $event): void { if (!$event instanceof SmsEvent) { return; } // Handle the delivery status. } }