Уведомления
Каналы отправки
| Канал | Функция API | Требование |
|---|---|---|
| Push (внутри системы) | $api->sendPushNotification(...) | Всегда доступно |
| Telegram | $api->sendTelegram(...) | Пользователь привязал Telegram + исходящий TG-канал |
| Email по шаблону | $api->sendEmail(...) | Исходящий SMTP-канал + шаблон |
| SMS | $api->sendSms(...) | Исходящий SMS-канал |
| HTTP-вебхук | $api->sendWebhook(...) | Исходящий webhook-канал |
| Брокер (Kafka / AMQP) | $api->publish(...) | Исходящий kafka/amqp-канал |
| Любой исходящий канал | $api->sendToChannel(...) | Канал в разделе «Каналы → Исходящие» |
sendTelegram и sendEmail уходят через исходящие каналы (раздел «Каналы» → вкладка «Исходящие») с ретраями и историей доставки. По умолчанию берётся канал по умолчанию нужного типа; при нескольких каналах одного типа (например несколько ботов ТГ) целевой канал указывается явно — см. Несколько ботов и каналов.
Push-уведомления
$api->sendPushNotification(
'Заголовок уведомления',
'Текст сообщения',
'/e/it_requests/42', // URL для перехода (необязательно)
[3, 5, 8], // ID пользователей
'system' // категория: 'system' | 'message'
);Уведомления отображаются в колокольчике 🔔 в верхней панели интерфейса.
Telegram
$api->sendTelegram(
'Новая IT-заявка требует вашего внимания',
[3, 5] // ID пользователей с telegram_chat_id
);Сообщение придёт только пользователям, у которых в профиле привязан Telegram-аккаунт.
Ответить напрямую в чат:
$api->replyTelegram($chatId, 'Ваша заявка принята в работу');В скриптах входящих действий ответ по умолчанию уходит через того же бота, который принял сообщение, — при нескольких ботах ТГ выбирать канал вручную не нужно. Явно задать бота можно третьим аргументом (id входящего telegram-канала): $api->replyTelegram($chatId, $text, 5).
Другие типы каналов
Для нетиповых получателей у каждого типа исходящего канала есть свой удобный метод — набор аргументов подобран под канал:
// SMS: номер или массив номеров; $channel — id/название при нескольких провайдерах
$api->sendSms($record['phone'], 'Код: 1234');
// HTTP-вебхук: JSON-payload (HMAC/auth настроены на канале)
$api->sendWebhook(['event' => 'ticket.created', 'id' => $data['id']]);
// брокер: публикация в Kafka/AMQP; $channel обязателен, $key — ключ партиции Kafka
$api->publish(['id' => $data['id'], 'status' => $data['status']], 'kafka');Все три возвращают bool и принимают необязательный выбор канала (id или название; publish — id или тип, канал обязателен). Полные сигнатуры — в справочнике $api.
Несколько ботов и каналов
С единой системой каналов у тенанта может быть несколько исходящих каналов одного типа — например два Telegram-бота (support и sales) или отдельный SMTP для счетов. Без явного указания sendTelegram/sendEmail используют канал по умолчанию соответствующего типа (is_default).
Чтобы отправить через конкретный канал, передайте его id или название третьим аргументом (sendTelegram) / четвёртым (sendEmail):
// конкретный бот по названию исходящего канала
$api->sendTelegram('VIP-обращение принято', [$record['assignee_id']], 'Support Bot');
// либо по id канала
$api->sendTelegram('VIP-обращение принято', [$record['assignee_id']], 7);
// отдельный почтовый канал для счетов
$api->sendEmail('invoice_ready', $record['email'], $params, 'Billing');Если канал не найден
Когда указан конкретный канал, а он не существует или отключён, сообщение не отправляется (ошибка пишется в лог) — система не подменяет его каналом по умолчанию и не уходит «не туда». Fallback на канал по умолчанию/legacy срабатывает только когда аргумент не передан.
Id и название канала видны в разделе Каналы → Исходящие.
Для внешних получателей (webhook, произвольный chat_id/телефон, payload-каналы kafka/amqp/sms) используйте sendToChannel — он шлёт в указанный канал без резолва пользователей:
$api->sendToChannel(7, [
'recipients' => ['79991234567'], // адреса как есть; для Telegram — chat_id
'body' => 'Заявка #' . $data['id'] . ' в работе',
]);Email по шаблону
Создание шаблона
В интерфейсе: Настройки → Шаблоны уведомлений → Создать.
Через API:
POST /api/sys/notification_templates
Authorization: Bearer <admin-token>
Content-Type: application/json
{
"name": "Заявка решена",
"code": "ticket_resolved",
"subject": "Ваша заявка {{ticket_name}} решена",
"body": "<p>Здравствуйте!</p><p>Заявка <b>{{ticket_name}}</b> решена.</p><p>Решение: {{resolution}}</p>"
}| Поле | Описание |
|---|---|
code | Уникальный идентификатор шаблона (используется в скриптах) |
subject | Тема письма, поддерживает |
body | HTML-тело письма, поддерживает |
Отправка из скрипта
$api->sendEmail('ticket_resolved', 'user@example.com', [
'ticket_name' => 'Не работает VPN',
'resolution' => 'Обновлён сетевой драйвер'
]);Переменные и заменяются значениями из третьего аргумента.
Управление шаблонами через API
| Метод | URL | Описание |
|---|---|---|
GET | /api/sys/notification_templates | Список шаблонов |
POST | /api/sys/notification_templates | Создать |
PUT | /api/sys/notification_templates/{id} | Обновить |
DELETE | /api/sys/notification_templates/{id} | Удалить |
Настройка SMTP
Настройки → Интеграции → Email:
MAIL_MAILER=smtp
MAIL_HOST=smtp.example.com
MAIL_PORT=587
MAIL_USERNAME=noreply@example.com
MAIL_PASSWORD=secret
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=noreply@example.com
MAIL_FROM_NAME="Orbita ITSM"Тест отправки:
POST /api/sys/settings/test-email
Authorization: Bearer <admin-token>
Content-Type: application/json
{
"to": "test@example.com"
}Состояние Telegram-бота (для диалогов)
Для создания пошаговых диалогов через Telegram-бота:
// Сохранить состояние на 1 час
$api->setBotState($chatId, 'waiting_for_description');
// Прочитать состояние
$state = $api->getBotState($chatId);
// Очистить
$api->clearBotState($chatId);Пример использования в Incoming Action скрипте:
$state = $api->getBotState($incoming['from_id']);
if ($state === 'waiting_for_description') {
$data['details'] = $incoming['body'];
$api->clearBotState($incoming['from_id']);
} else {
$data['name'] = $incoming['body'];
$api->setBotState($incoming['from_id'], 'waiting_for_description');
$api->replyTelegram($incoming['from_id'], 'Опишите проблему подробнее:');
return; // не создавать запись пока
}