Search by

sol-parts / symfony-alphasms-notifier

AndriiDidenko

Symfony AlphaSMS Notifier Bridge

Package info

github.com/sol-parts/symfony-alphasms-notifier

Homepage

Type:symfony-notifier-bridge

pkg:composer/sol-parts/symfony-alphasms-notifier

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v7.3.1 2026-10-08 17:42 UTC

This package is auto-updated.

Last update: 2026-10-09 08:57:45 UTC


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_KEY is your AlphaSMS API key;
  • FROM is 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.
    }
}

Resources