Каналы уведомлений¶
Канал публикует выбранные события заявок туда, где команда уже следит за происходящим: в канал Slack, канал Discord, собственный эндпоинт или командный ящик. Это лента команды. Собственный колокольчик и почта каждого сотрудника (Уведомления) продолжают работать, и канал их никогда не заменяет.
Каналы настраиваются в рабочей области в разделе Automation → Channels, для этого нужно helpdesk-pro.settings. Канал хранит учётные данные и решает, куда уходят факты заявок, поэтому никто другой не может увидеть или изменить его.
Типы каналов¶
| Тип | Отправляет | Что нужно |
|---|---|---|
| Slack | Сообщение Block Kit в один канал Slack через входящий webhook | URL webhook (https://hooks.slack.com/services/…) |
| Discord | Один embed в один канал Discord через webhook канала | URL webhook (https://discord.com/api/webhooks/…) |
| Webhook | Подписанный JSON на ваш адрес | URL и, при желании, секрет подписи |
| Письмо на фиксированные адреса: командный ящик или список рассылки | Один адрес на строку, до 20 |
Дополнения могут регистрировать другие типы, например Microsoft Teams или Mattermost. Они появляются в выборе типа рядом с этими четырьмя (см. Расширение).
Настройка Slack¶
- Перейдите на api.slack.com/apps и выберите Create New App → From scratch. Назовите приложение (например, «Helpdesk») и выберите рабочее пространство.
- В настройках приложения откройте Incoming Webhooks и включите Activate Incoming Webhooks.
- Выберите Add New Webhook to Workspace, укажите канал и нажмите Allow.
- Скопируйте новый URL webhook.
- В рабочей области откройте Automation → Channels → New channel, выберите Slack, вставьте URL, отметьте события и сохраните.
- Нажмите Send a test message. Он должен ответить
200 ok.
Один webhook публикует в один канал Slack. Чтобы публиковать в два, добавьте второй webhook в том же приложении и второй канал здесь.
Настройка Discord¶
- В Discord откройте настройки канала (шестерёнка, Edit Channel), затем Integrations → Webhooks. Нужно право Manage Webhooks.
- Выберите New Webhook, дайте ему имя, затем Copy Webhook URL.
- В рабочей области откройте Automation → Channels → New channel, выберите Discord, вставьте URL, отметьте события и сохраните.
- Нажмите Send a test message. Он должен ответить
204.
Настройка webhook¶
Направьте канал на любой HTTPS-адрес, принимающий JSON POST, и отвечайте любым статусом 2xx. Добавьте секрет подписи (16 символов или больше, например вывод openssl rand -hex 32), чтобы ваш эндпоинт мог проверить, что каждый запрос пришёл с вашего сайта. См. Полезная нагрузка webhook.
Настройка канала email¶
Выберите Email и перечислите адреса, по одному на строку. Каждый адрес получает свою копию, поставленную в очередь и отправленную как любое письмо Helpdesk Pro, с того же адреса From. Шаблон — staff-channel, который тема может переопределить.
Каждое письмо несёт List-Id: "Channel name" <helpdesk-channel-{id}.{your domain}>, чтобы правило ящика могло разложить или пометить их, а также Auto-Submitted: auto-generated. У него нет Reply-To, заголовков группировки и скрытой ссылки на заявку, поэтому ответ на него никогда ничего не публикует в заявке.
Новый сайт начинает с одним каналом email, Team inbox, выключенным и без адреса. В нём отмечены New ticket, Client replied и SLA breached. Чтобы использовать его:
- Откройте его и добавьте адрес вашей команды: общий ящик или список рассылки.
- Отметьте Enabled и сохраните.
Предупреждение
Не используйте email.support_address для канала. Письма канала, отправленные туда, вернулись бы новыми заявками и поместили бы факты для сотрудников в ящик для клиентов.
Рабочая область не включит канал, пока пусто поле, которое ему нужно, поэтому Enable отвечает «Add at least one address», пока адреса нет. Удалите канал Team inbox, если он не нужен; он создаётся только один раз, на сайте без каналов.
Что может отправлять канал¶
Канал отмечает события, которые отправляет. Новый канал начинает с New ticket, Client replied и SLA breached.
| Событие | Когда отправляется | Заголовок |
|---|---|---|
New ticket (ticket.new) |
Заявка создана из любого источника | «New ticket from Ada Lovelace» |
Waiting in triage (ticket.triage) |
Новое обращение попадает в сортировку | «New request from Ada Lovelace is waiting in triage» |
Client replied (client.replied) |
Клиент добавляет публичный ответ | «Ada Lovelace replied» |
Ticket assigned (ticket.assigned) |
Заявка назначена кому-то | «Assigned to Anna» и кто назначил |
Resolved or closed (ticket.resolved) |
Заявка переходит из открытого статуса в решённый или закрытый | «Resolved» или «Closed» |
SLA due soon (sla.warning) |
Цель SLA попадает во время предупреждения | «First response due soon» со сроком |
SLA breached (sla.breached) |
Цель SLA пропущена (не когда найдена после ответа или решения заявки) | «Resolution target breached» со сроком |
Rated Not good (rating.not_good) |
Клиент отвечает «How did we do?» — Not good | «Ada Lovelace rated their request Not good» |
Rule posts (rule.post) |
Срабатывает действие правила Post to channels | «Rule: VIP customers» с сообщением правила |
Новое обращение, ждущее в сортировке, — одновременно новая заявка и обращение на сортировку; каналу, отметившему оба, сообщают один раз, как о сортировке. Канал также охватывает все проекты или их список. Одно событие никогда не отправляется в канал дважды.
Что содержит сообщение¶
Сообщения канала несут только эти факты о заявке, каким бы ни было событие:
- заголовок, номер и тему заявки со ссылкой на неё в рабочей области;
- имя заявителя (или адрес, когда имени нет), проект, статус, приоритет и исполнителя (или «Unassigned»);
- несколько деталей события: кто назначил, срок SLA, сообщение правила;
- название сайта и название события.
Канал никогда не отправляет внутренние заметки, ответы сотрудников, пользовательские поля, журнал активности, вложения, комментарии к оценкам, причины отклонения при сортировке или остальную переписку.
Слова самого клиента по умолчанию выключены. У каждого канала есть параметр Include the first lines of a client's message. Когда он включён, New ticket, Waiting in triage и Client replied также несут первые три строки (не более 280 символов) того, что написал клиент, пропуская цитируемую историю письма. Используется только публичное сообщение, написанное клиентом.
Предупреждение
С этим параметром начало сообщения клиента копируется в Slack, Discord или почтовый ящик и хранится там по правилам хранения этого сервиса, куда ваши настройки удаления и хранения не достают. Клиенты пишут в обращения пароли, сведения о здоровье и номера счетов. Оставляйте параметр выключенным, если канал не приватный для людей, работающих с этими заявками, и упомяните его в уведомлении о конфиденциальности, если включите.
Сообщение строится при отправке, поэтому показывает заявку такой, какая она тогда. Заявка, удалённая до отправки сообщения, не отправляется.
Форматы сообщений¶
- Slack: публикация входящего webhook с верхнеуровневым
textи блоками Block Kit (секция с заголовком и связанной заявкой, секция до десяти полей, выдержка цитатой и строка контекста). Тексты держатся в пределах Slack, а&,<и>экранируются, поэтому ни одна тема не может сложиться в<!channel>. - Discord: публикация Execute Webhook с заголовком в
contentи одним embed со связанной заявкой, фактами в полях, выдержкой и цветом на событие. Строки обрезаются до пределов Discord.allowed_mentionsпуст, поэтому тема «@everyone» никого не пингует. - Webhook: JSON с версией схемы, ниже.
Полезная нагрузка webhook¶
Каждый запрос — POST с Content-Type: application/json, User-Agent: HelpdeskPro/1.0 (Grav) и заголовками:
| Заголовок | Значение |
|---|---|
X-Helpdesk-Event |
Событие канала, например client.replied (channel.test для теста) |
X-Helpdesk-Delivery |
id доставки, например d42, одинаковый при каждой повторной попытке. Используйте его, чтобы игнорировать повтор. |
X-Grav-Signature |
t={unix time},v1={hex}, когда у канала есть секрет подписи |
Тело (схема helpdesk-pro.channel/1):
{
"schema": "helpdesk-pro.channel/1",
"id": "d42",
"event": "client.replied",
"event_label": "Client replied",
"test": false,
"occurred_at": "2026-09-24T09:15:00Z",
"site": { "name": "Acme", "desk_url": "https://acme.test/admin/plugin/helpdesk-pro" },
"title": "Ada Lovelace replied",
"ticket": {
"id": 1042,
"subject": "Can't reset my password",
"url": "https://acme.test/admin/plugin/helpdesk-pro#/t/1042",
"project": { "id": 1, "slug": "support", "name": "Support" },
"status": { "id": 4, "name": "Waiting on us", "category": "waiting_us" },
"priority": { "value": 2, "label": "High" },
"kind": "support",
"requester": { "id": 10, "name": "Ada Lovelace" },
"assignee": { "id": 1, "name": "Anna Agent" }
},
"details": {},
"excerpt": null
}
ticket.assigneeравенnull, когда никто не назначен;ticketравенnullдля тестового сообщения.detailsхранит дополнительные строки события как метка → текст ({"Due": "24 Sep 2026, 10:00 UTC"}).excerptравенnull, если канал не включает первые строки сообщения клиента.- В пределах версии схемы 1 поля только добавляются.
Проверка подписи¶
Шестнадцатеричная строка — HMAC-SHA256 по времени, точке и исходному телу с ключом-секретом. Вычислите её по t + "." + body ровно в полученном виде, сравните за постоянное время и откажите времени, отличающемуся от ваших часов больше чем на пять минут:
$body = file_get_contents('php://input');
$header = $_SERVER['HTTP_X_GRAV_SIGNATURE'] ?? '';
if (preg_match('/^t=(\d+),v1=([0-9a-f]{64})$/', $header, $m) !== 1
|| abs(time() - (int)$m[1]) > 300
|| !hash_equals(hash_hmac('sha256', $m[1] . '.' . $body, getenv('HELPDESK_HOOK_SECRET')), $m[2])) {
http_response_code(401);
exit;
}
$event = json_decode($body, true);
Доставка¶
Ничего не отправляется внутри запроса, вызвавшего событие. После сохранения изменения одна доставка на канал ставится в очередь как задание channel.deliver, которое отправляет её сразу после ответа или из фонового процесса.
- Таймаут. Один запрос может занимать
channels.timeout_seconds(5). Перенаправления не выполняются. - Повторные попытки. Нет ответа, таймаут,
408,429или5xx— повтор через 1, 2 и 4 минуты, доchannels.max_attempts(4) попыток. Любой другой4xxозначает, что настройки канала неверны (отозванный webhook отвечает404или403), поэтому повтора нет. - Сбой. Первая неудачная попытка помечает канал Failing с полученным ответом, и он считается рядом с Channels в боковом меню, пока доставка не пройдёт.
- Пауза. После
channels.pause_after_failures(5) окончательно неудачных доставок подряд канал Paused, и для него больше ничего не ставится в очередь. Resume или сохранение новых настроек запускает его снова. - Выключение. Отключённый канал ничего не отправляет. Установите
channels.enabledвfalse, чтобы выключить все каналы сразу; события, произошедшие за это время, позже не отправляются. - Журнал доставок. Страница каждого канала перечисляет последние доставки (событие, заявка, состояние, попытки, статус, ошибка), хранящиеся
channels.log_days(14). Строки содержат id, но никогда текст сообщения.
Send a test message на странице канала отправляет сообщение сейчас и показывает, что именно ответил эндпоинт (200 ok, 404 no_service, 400 invalid_payload). Канал email сообщает, что ответил почтовый транспорт для каждого адреса. Тест не несёт заявки и не меняет состояние или журнал канала. В редакторе он отправляет то, что на экране, поэтому можно проверить вставленный URL до сохранения.
Секреты¶
URL webhook Slack или Discord — учётные данные: любой, у кого он есть, может публиковать в этот канал. То же с секретом подписи. Оба:
- никогда не возвращаются API или инструментами MCP: они приходят как
••••••••с одним лишь хостом URL рядом, а сохранение, отправляющее маску обратно, сохраняет прежнее значение; - никогда не записываются в журнал: каждая ошибка очищается от секретов канала перед записью, хранением или показом;
- хранятся в базе данных Helpdesk Pro в
user/data/.
Чтобы вообще не хранить секрет в базе, введите env:NAME вместо значения (например, env:HELPDESK_SLACK_URL) и задайте эту переменную окружения для PHP. Она читается при каждой отправке сообщения.
Настройки¶
На вкладке Channels настроек плагина:
| Ключ | По умолчанию | Что делает |
|---|---|---|
channels.enabled |
true |
Отправлять в каналы вообще. |
channels.timeout_seconds |
5 |
Сколько может занимать один запрос (от 1 до 30). |
channels.max_attempts |
4 |
Попыток на сообщение при таймауте, ограничении частоты или ошибке сервера. |
channels.pause_after_failures |
5 |
Окончательно неудачных доставок подряд до паузы канала; 0 никогда не ставит на паузу. |
channels.log_days |
14 |
Сколько хранится журнал доставок. |
API и MCP¶
Каждому маршруту нужно helpdesk-pro.settings, и секреты маскируются в каждом ответе.
| Маршрут | Инструмент MCP | Что делает |
|---|---|---|
GET /helpdesk-pro/channels |
list_channels |
Каждый канал с его состоянием, а в meta — типы, события и значения по умолчанию. |
POST /helpdesk-pro/channels |
create_channel |
{type, name, enabled, settings, project_ids, events, include_excerpt}. project_ids: null охватывает все проекты. |
GET /helpdesk-pro/channels/{id} |
get_channel |
Один канал с десятью последними доставками. |
PATCH /helpdesk-pro/channels/{id} |
update_channel |
Любое поле создания, кроме type, плюс paused: false для возобновления. |
DELETE /helpdesk-pro/channels/{id} |
delete_channel |
Канал и его журнал доставок. |
POST /helpdesk-pro/channels/{id}/test |
test_channel |
Отправляет тестовое сообщение; отвечает {ok, status, response, error, sent_to}. Тело может нести несохранённые settings для проверки. |
state канала — ok, failing, paused, off (отключён), idle (ещё ничего не отправлено) или broken (его тип дополнения больше не установлен).