MiniShop3: Notification Center — Революция в управлении уведомлениями

Доброго времени суток дорогой друг. Уверен что ты соскучился по новым релизам. Ведь прошел целый день, с момента прошлого релиза.

Рад вам представить очередное крупное обновление, которое я ранее не анонсировал.



Notification Center — новая подсистема MiniShop3, которая полностью переосмысливает подход к уведомлениям в интернет-магазинах. Теперь email, Telegram, SMS и любые другие каналы управляются из единого интерфейса с гибкой настройкой правил отправки.



Проблема: Хаос в настройках уведомлений



В предыдущих версиях MiniShop настройки email-уведомлений были «вшиты» в статусы заказов. Каждый статус содержал поля для темы и тела письма — отдельно для клиента и менеджера. Это создавало ряд проблем:

  • Смешение ответственности — статус заказа отвечал и за бизнес-логику, и за уведомления
  • Ограниченность — только email, добавить Telegram или SMS было невозможно без костылей
  • Сложность аудита — чтобы понять, какие уведомления отправляются, нужно было проверять каждый статус
  • Дублирование — одинаковые шаблоны копировались между статусами

Решение: Notification Center



Notification Center — это отдельная страница в админке MiniShop3, где все настройки уведомлений собраны в одном месте.

Ключевые возможности:

  • Единый интерфейс — Все уведомления магазина в одной таблице
  • Мультиканальность — Email, Telegram, SMS и кастомные каналы
  • Гибкие правила — Событие + Статус + Получатель + Канал
  • Визуальные фильтры — Быстрый поиск по любому параметру
  • Расширяемость — Добавляйте свои каналы через плагины

Архитектура системы



Схема работы уведомлений

Как и в minishop2 срабатывает событие изменения статуса заказа, которое запускает цепочку событий

  1. Загружает конфигурации из БД (msNotificationConfig)
  2. Определяет получателей (клиент, менеджер)
  3. Выбирает каналы для каждого получателя
  4. Диспатчит уведомления в каналы

Интерфейс канала уведомлений

Каждый канал реализует простой интерфейс ChannelInterface:

<?php
namespace MiniShop3\Notifications;

use MiniShop3\Model\msOrder;

interface ChannelInterface
{
    /**
     * Отправить уведомление через канал
     */
    public function send(Notification $notification, array $recipient, msOrder $order): bool;

    /**
     * Уникальный идентификатор канала
     */
    public function getName(): string;

    /**
     * Проверить, настроен ли канал и готов к работе
     */
    public function isAvailable(): bool;

    /**
     * Список системных настроек, необходимых каналу
     */
    public function getRequirements(): array;
}


Встроенные каналы



Email Channel (работает из коробки)

Email-канал использует встроенный PHPMailer из MODX и работает сразу после установки:

class EmailChannel implements ChannelInterface
{
    public function getName(): string
    {
        return 'email';
    }

    public function isAvailable(): bool
    {
        // Доступен, если настроен emailsender в MODX
        return !empty($this->modx->getOption('emailsender'));
    }

    public function getRequirements(): array
    {
        return ['emailsender'];
    }
}

Telegram Channel (готов к подключению)

Для Telegram достаточно указать токен бота в системных настройках:

class TelegramChannel implements ChannelInterface
{
    public function getName(): string
    {
        return 'telegram';
    }

    public function isAvailable(): bool
    {
        return !empty($this->modx->getOption('ms3_telegram_bot_token'));
    }

    public function getRequirements(): array
    {
        return ['ms3_telegram_bot_token'];
    }

    public function send(Notification $notification, array $recipient, msOrder $order): bool
    {
        $message = $notification->toTelegram($recipient['type']);
        $chatId = $recipient['telegram_chat_id'];

        // Отправка через Telegram Bot API
        return $this->sendMessage($chatId, $message);
    }
}

Подключение кастомного канала



Создать свой канал уведомлений — просто. Рассмотрим пример интеграции с Viber.

Шаг 1: Создайте класс канала

<?php
// core/components/mycomponent/src/Notifications/ViberChannel.php

namespace MyComponent\Notifications;

use MODX\Revolution\modX;
use MiniShop3\Model\msOrder;
use MiniShop3\Notifications\ChannelInterface;
use MiniShop3\Notifications\Notification;

class ViberChannel implements ChannelInterface
{
    protected modX $modx;

    public function __construct(modX $modx)
    {
        $this->modx = $modx;
    }

    public function getName(): string
    {
        return 'viber';
    }

    public function isAvailable(): bool
    {
        // Проверяем наличие токена Viber
        $token = $this->modx->getOption('mycomponent_viber_token');
        return !empty($token);
    }

    public function getRequirements(): array
    {
        return ['mycomponent_viber_token'];
    }

    public function send(Notification $notification, array $recipient, msOrder $order): bool
    {
        // Получаем Viber ID получателя
        $viberId = $recipient['viber_id'] ?? null;
        if (empty($viberId)) {
            return false;
        }

        // Формируем сообщение
        $placeholders = $notification->getPlaceholders();
        $text = "Заказ #{$placeholders['id']}: статус изменён на {$placeholders['status_name']}";

        // Отправляем через Viber API
        return $this->sendViberMessage($viberId, $text);
    }

    protected function sendViberMessage(string $viberId, string $text): bool
    {
        $token = $this->modx->getOption('mycomponent_viber_token');

        $payload = [
            'receiver' => $viberId,
            'type' => 'text',
            'text' => $text,
        ];

        $ch = curl_init('https://chatapi.viber.com/pa/send_message');
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/json',
                'X-Viber-Auth-Token: ' . $token,
            ],
            CURLOPT_POSTFIELDS => json_encode($payload),
            CURLOPT_RETURNTRANSFER => true,
        ]);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        return $httpCode === 200;
    }
}

Шаг 2: Зарегистрируйте канал через плагин MODX

Создайте плагин на событие msOnRegisterNotificationChannels:

<?php
// Плагин: MyViberNotifications
// Событие: msOnRegisterNotificationChannels

use MyComponent\Notifications\ViberChannel;

/** @var MiniShop3\Notifications\NotificationManager $manager */
$manager = $scriptProperties['manager'];

// Регистрируем наш канал
$manager->registerChannel(new ViberChannel($modx));

Шаг 3: Добавьте системную настройку

Создайте системную настройку mycomponent_viber_token с токеном вашего Viber-бота.

Готово! Канал Viber появится в Notification Center и будет доступен для настройки уведомлений.

События для разработчиков



Notification Center предоставляет события для расширения функциональности:

  • msOnRegisterNotificationChannels — Регистрация кастомных каналов
  • msOnBeforeSendNotification — Перед отправкой (можно отменить или модифицировать)
  • msOnAfterSendNotification — После отправки (для логирования, аналитики)

Пример: Логирование всех уведомлений

<?php
// Плагин: LogNotifications
// Событие: msOnAfterSendNotification

$notification = $scriptProperties['notification'];
$recipient = $scriptProperties['recipient'];
$results = $scriptProperties['results'];

$order = $notification->getOrder();

$modx->log(
    modX::LOG_LEVEL_INFO,
    "[Notifications] Order #{$order->get('id')}: " .
    json_encode($results)
);

Пример: Отмена уведомления по условию

<?php
// Плагин: ConditionalNotifications
// Событие: msOnBeforeSendNotification

$notification = $scriptProperties['notification'];
$recipientType = $scriptProperties['recipientType'];

$order = $notification->getOrder();

// Не отправлять уведомления для тестовых заказов
if ($order->get('test_mode')) {
    $modx->event->output = false; // Отменяем отправку
    return;
}

// Не отправлять менеджеру ночью
if ($recipientType === 'manager') {
    $hour = (int) date('H');
    if ($hour >= 23 || $hour < 8) {
        $modx->event->output = false;
        return;
    }
}

Интеграция с очередями (Scheduler)



Для высоконагруженных магазинов Notification Center поддерживает отложенную отправку через компонент Scheduler:

// В системных настройках:
ms3_use_scheduler = true

// Уведомления будут добавляться в очередь
// и отправляться фоновым процессом

Это позволяет:
  • Не блокировать оформление заказа на время отправки
  • Повторять неудачные попытки отправки
  • Регулировать нагрузку на внешние сервисы
Scheduler, кстати тоже получил крупное обновление. Добавлены новые фичи, закрыты дыры, улучшена адаптация к MODX3 и MiniShop3

Внимание. Устаревшие поля email-уведомлений удалены из статусов заказов

Удалённые поля msOrderStatus:
- email_user, email_manager
- subject_user, subject_manager
- body_user, body_manager


Современный интерфейс







Notification Center построен на Vue 3 + PrimeVue — том же стеке, что и другие современные разделы MiniShop3:

  • Мгновенная фильтрация без перезагрузки страницы
  • Цветовые бейджи статусов с автоматическим контрастом текста
  • Модальные окна создания и редактирования
  • Адаптивная таблица с сортировкой

Заключение



Notification Center — это не просто улучшение, а полное переосмысление подхода к уведомлениям в e-commerce. Централизация, мультиканальность и расширяемость делают MiniShop3 готовым к интеграции с любыми современными каналами коммуникации.

Хочу сказать спасибо @Наумов Алексей — это была его идея, я лишь скромно реализовал ее.

Open Source живёт благодаря вам

MiniShop3 развивается силами сообщества. Если Notification Center и предыдущие обновления оказались полезны — поддержите проект. Минимальная цель: 20 000 ₽ на декабрь.

Все наши реквизиты есть на специальной странице.
Николай Савин
1 час назад
modx.pro
34
+5
Поблагодарить автора Отправить деньги

Комментарии: 1

Николай Савин
1 час назад
0
Как всегда обновленный транспортный пакет ждет вас в релизах
    Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
    1