Development of a 1C-Bitrix notification module

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1177
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    747
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

Notification Module Development for 1C-Bitrix

The standard \Bitrix\Main\Mail\Event::send() mechanism covers basic scenarios: an email after registration, an order confirmation. But as soon as the business wants push notifications, Telegram, WhatsApp, SMS — all with a unified delivery log, statuses, and retries — the built-in tooling runs out. Every new channel is connected differently, logs are scattered, and testing is painful.

Module Architecture

The vendor.notifications module is built on the concepts of a channel and an event. An event is something that happened in the system. A channel is a delivery method. One event can be dispatched through multiple channels simultaneously.

ORM tables:

  • b_vendor_notif_event — event types: id, code, name, description, default_channels (JSON), is_active
  • b_vendor_notif_template — message templates: id, event_code, channel, subject, body, body_html, lang, variables_schema
  • b_vendor_notif_queue — send queue: id, event_code, channel, recipient, payload (JSON), status (pending/sent/failed), attempts, created_at, sent_at, error
  • b_vendor_notif_subscription — user subscriptions: id, user_id, event_code, channel, is_active

Delivery Channels

Each channel implements the ChannelInterface:

interface ChannelInterface
{
    public function getName(): string;
    public function send(Notification $notification): SendResult;
    public function supports(string $recipient): bool;
}

Implementations:

  • EmailChannel — via \Bitrix\Main\Mail\Mail::send() with custom SMTP settings or PHPMailer
  • SmsChannel — adapters for different providers (SMS.ru, SMSC, Twilio): unified interface, provider is a configuration parameter
  • TelegramChannel — Telegram Bot API, sendMessage method, supports Markdown and inline buttons
  • PushChannel — web push via the Web Push Protocol (web-push-php library), subscriptions stored in b_vendor_notif_push_subscription
  • InternalChannel — in-site inbox notifications, stored in b_vendor_notif_inbox, displayed on the site via AJAX

Event Dispatcher

Sending a notification from code is a single line:

\Vendor\Notifications\Dispatcher::dispatch('order_paid', [
    'user_id'      => $userId,
    'order_id'     => $orderId,
    'order_sum'    => $order->getPrice(),
    'order_number' => $order->getField('ACCOUNT_NUMBER'),
]);

The dispatcher determines which channels to use (based on event settings), builds messages from templates, substitutes variables, and enqueues jobs into b_vendor_notif_queue.

Asynchronous Sending and Retries

Sending immediately at the moment of the event is bad practice: an HTTP request to Telegram can hang, blocking the order save operation. The queue is processed by a Bitrix agent:

// In the module installer
\CAgent::AddAgent(
    '\Vendor\Notifications\QueueProcessor::run();',
    'vendor.notifications',
    'N',
    60, // every 60 seconds
);

public static function run(): string
{
    $items = NotifQueueTable::getList([
        'filter' => ['STATUS' => 'pending', '<=ATTEMPTS' => 3],
        'limit'  => 50,
        'order'  => ['CREATED_AT' => 'ASC'],
    ])->fetchAll();

    foreach ($items as $item) {
        $channel = ChannelRegistry::get($item['CHANNEL']);
        $result  = $channel->send(Notification::fromQueue($item));

        if ($result->isSuccess()) {
            NotifQueueTable::update($item['ID'], ['STATUS' => 'sent', 'SENT_AT' => new DateTime()]);
        } else {
            NotifQueueTable::update($item['ID'], [
                'ATTEMPTS' => $item['ATTEMPTS'] + 1,
                'STATUS'   => $item['ATTEMPTS'] >= 3 ? 'failed' : 'pending',
                'ERROR'    => $result->getError(),
            ]);
        }
    }

    return '\Vendor\Notifications\QueueProcessor::run();';
}

After 3 failed attempts the job is set to failed status and appears in the dashboard for manual review.

User Subscription Management

In their personal account, users see a list of available events and can disable individual channels. Settings are stored in b_vendor_notif_subscription. Before enqueuing, the dispatcher checks whether the user has unsubscribed from this event type on this channel.

Templating

Message bodies are rendered via Twig. Variables are passed from the event payload. Templates support filters: |price for amount formatting, |date for localized dates. HTML emails support inline styles via Emogrifier.

Admin Interface

  • Event list with default channel configuration
  • Template editor with preview (test variable substitution)
  • Send log with filtering by status, channel, date, recipient
  • Delivery statistics by channel
  • Test notification send to a specified address

Development Timeline

Phase Timeline
Architecture, ORM tables, channel interfaces 2 days
Email and SMS channels 2 days
Telegram and Push channels 2 days
Internal notifications (inbox) 1 day
Dispatcher, queue, retry agent 2 days
User subscription management 1 day
Templating (Twig + Emogrifier) 1 day
Admin interface + send log 2 days
Testing 1 day

Total: 14 working days. Adding extra channels (Viber, VK, WhatsApp Business API) — 1–2 days per channel.