Skip to content

Вебхуки ​

Pano может сообщать другой системе, когда что-то происходит: игрок регистрируется, открывается тикет, публикуется запись, оплачивается заказ. Вы даёте Pano адрес; Pano отправляет на него подписанный POST.

Создайте вебхук в панели: Настройки -> Вебхуки: название, адрес, события, секрет (показывается один раз). Тест сразу отправляет ping.

События ​

Имена имеют вид источник.тема.глагол. Источник это core или короткое имя плагина.

СобытиеКогда
core.user.registeredИгрок регистрируется
core.user.deletedИгрок удалён в панели
core.ticket.createdОткрыт тикет
core.ticket.repliedВ тикет пришло сообщение (staff показывает, кто написал)
core.post.publishedЗапись опубликована
core.test.pingВы нажали Тест

Плагины добавляют свои, например market.order.paid, market.order.refunded, market.subscription.renewed, market.shipment.shipped. Панель перечисляет все события с примерами.

Подписывайтесь на точные имена, на core.* или market.*, либо на *. Подстановочные знаки никогда не включают core.test.ping.

Полезная нагрузка не содержит адресов электронной почты, IP-адресов и текстов сообщений.

Что вы получаете ​

json
{
  "id": "6c1f1b0e-0d4b-3a5e-9b0e-2f5c7e1a9d11",
  "event": "core.post.published",
  "source": "core",
  "createdAt": 1790000000000,
  "apiVersion": 1,
  "site": { "name": "My server", "url": "https://example.com" },
  "data": { "id": 7, "title": "Hello", "url": "/post/hello", "categoryId": 1, "publishedAt": 1790000000000 }
}

Позже могут появиться новые ключи; не падайте на неизвестном. id стабилен для одного события и одной конечной точки: используйте его, чтобы игнорировать повторы.

Заголовки: X-Pano-Event, X-Pano-Event-Id, X-Pano-Delivery, X-Pano-Attempt, X-Pano-Signature.

Проверьте подпись ​

X-Pano-Signature имеет вид t=<unix-секунды>,v1=<hex>, где v1 это HMAC-SHA256 от <t>.<сырое тело> с вашим секретом. Используйте сырое тело, а не разобранный JSON. Отклоняйте t, старше 300 секунд.

js
import { createHmac, timingSafeEqual } from 'node:crypto';

export function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
  if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
  const expected = createHmac('sha256', secret).update(`${parts.t}.${rawBody}`).digest('hex');
  const a = Buffer.from(expected);
  const b = Buffer.from(parts.v1 ?? '');
  return a.length === b.length && timingSafeEqual(a, b);
}

Подпись можно отключить для конечных точек, которым вы доверяете другим способом. Формат Discord отправляет неподписанный embed.

Повторы ​

Отвечайте любым 2xx в течение 10 секунд. Иначе Pano повторяет, по умолчанию до 8 попыток (от 1 до 20):

  • Задержка растёт с 30 секунд, удваиваясь, до 6 часов, с небольшим разбросом.
  • Retry-After при 429 или 503 учитывается (не более 1 часа).
  • 410 Gone останавливает сразу. Перенаправления не выполняются.
  • После 50 неудач подряд вебхук отключается.

Pano отклоняет адреса, указывающие внутрь его собственной сети. Для локального тестового получателя задайте webhooks.allow-private-targets = true в config.conf (на хостинговом Pano игнорируется).

Журнал ​

Каждая доставка хранится со статусом (PENDING, SENDING, SUCCEEDED, FAILED, DEAD), числом попыток, ответом и временем. Откройте её в панели, чтобы увидеть последний ответ или отправить повторно. Завершённые записи удаляются через 30 дней. До 50 вебхуков на сайт.