Чем мы можем помочь?

Кратко опишите вопрос; мы ответим по электронной почте.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.
На главную

Вебхуки: события на ваш сервер

Подписанные вебхуки и REST hooks reactive.chat: события, заголовки, тело, проверка HMAC-SHA256, повторы, тайм-ауты, отключение и примеры проверки на PHP, Node и Python.

Вебхуки сообщают серверу, что происходит в чате: новый разговор, новое сообщение, передача команде, оценка. Есть два способа:

События

Разговоры из поиска по сайту (Smart Answer) вызывают события, только когда становятся видны как чат.

Настройка подписанного вебхука

В аккаунте в Настройки → Интеграции → Вебхуки (право: управление интеграциями):

При сохранении тестовый вызов не отправляется. После включения до начала поступления событий может пройти около 15 секунд; события до включения задним числом не доставляются.

Доставка

POST /rc-webhook HTTP/1.1
Host: hooks.your-company.com
Content-Type: application/json; charset=utf-8
User-Agent: reactive.chat-webhook/1.0
X-RC-Event: csat.submitted
X-RC-Delivery: 01JAB3C4D5E6F7G8H9JKMNPQRS
X-RC-Timestamp: 1792503600
X-RC-Signature: sha256=3f0a1c...

{"id":"01JAB3C4D5E6F7G8H9JKMNPQRS","event":"csat.submitted","ts":1792503600,"site_key":"ABCDEFGHJKLMNPQRSTUVWX12","conversation_id":"01JAB2...","session_id":"s_...","visitor_id":"v_...","data":{"score":5,"comment":"Very helpful"}}

Заголовки:

Тело:

Проверка подписи

Проверяйте до любой обработки: время не старше 300 секунд, подпись по сырому телу, сравнение с постоянным временем.

PHP:

<?php
$geheim = getenv('RC_WEBHOOK_SECRET');
$body   = file_get_contents('php://input');
$ts     = $_SERVER['HTTP_X_RC_TIMESTAMP'] ?? '';
$sig    = $_SERVER['HTTP_X_RC_SIGNATURE'] ?? '';

if (!ctype_digit($ts) || abs(time() - (int) $ts) > 300) { http_response_code(401); exit; }
$soll = 'sha256=' . hash_hmac('sha256', $ts . '.' . $body, $geheim);
if (!hash_equals($soll, $sig)) { http_response_code(401); exit; }

$ereignis = json_decode($body, true);
// detect duplicates: remember $ereignis['id']
http_response_code(204);

Node.js (Express):

const crypto = require('crypto');
app.post('/rc-webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const ts = req.get('X-RC-Timestamp') || '';
  const sig = req.get('X-RC-Signature') || '';
  if (!/^\d+$/.test(ts) || Math.abs(Date.now() / 1000 - Number(ts)) > 300) return res.sendStatus(401);
  const soll = 'sha256=' + crypto.createHmac('sha256', process.env.RC_WEBHOOK_SECRET)
    .update(ts + '.' + req.body.toString('utf8')).digest('hex');
  if (sig.length !== soll.length || !crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(soll))) {
    return res.sendStatus(401);
  }
  const ereignis = JSON.parse(req.body.toString('utf8'));
  res.sendStatus(204);
  verarbeiteSpaeter(ereignis);   // respond quickly, work afterwards
});

Python (Flask):

import hmac, hashlib, os, time
from flask import request, abort

@app.post("/rc-webhook")
def rc_webhook():
    ts = request.headers.get("X-RC-Timestamp", "")
    sig = request.headers.get("X-RC-Signature", "")
    body = request.get_data()                      # raw bytes
    if not ts.isdigit() or abs(time.time() - int(ts)) > 300:
        abort(401)
    soll = "sha256=" + hmac.new(os.environ["RC_WEBHOOK_SECRET"].encode(),
                                ts.encode() + b"." + body, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(soll, sig):
        abort(401)
    return "", 204

Ответы, повторы, отключение

Быстро отвечайте кодом 2xx, а обработку выполняйте после. Тайм-ауты: 4 секунды на установление соединения, 10 секунд всего. Перенаправления не выполняются.

События старше часа больше не доставляются. Если ошибки накапливаются (5 за 60 секунд), доставка на вашу цель приостанавливается на 30 секунд; затем задания повторяются. Чат никогда не ждёт вебхук.

Порядок доставок не гарантируется. При необходимости сортируйте по ts или seq сообщений из API.

REST hooks (Zapier, Make, n8n)

Инструменты автоматизации сами подписывают свои цели через серверный API. Этим можно пользоваться и напрямую:

curl -X POST https://reactive.chat/v1/hooks \
  -H "Authorization: Bearer rc_live_..." \
  -H "Content-Type: application/json" \
  -d '{"event":"message.created","target_url":"https://hooks.your-company.com/rc","source":"n8n"}'

Доставка REST hook:

POST https://hooks.your-company.com/rc
Content-Type: application/json
User-Agent: reactive.chat-n8n/1.0
X-RC-Event: message.created
X-RC-Delivery: 01JAB3...

{"event":"message.created","delivery_id":"01JAB3...","data":{"name":"message.created","ts":1792503600123,"site_key":"...","conversation_id":"...","session_id":"...","visitor_id":"...","message":{"id":"...","seq":7,"kind":"text","direction":"in","author_type":"bot","author_name":"Assistant","via":null,"body":"…","redacted":false,"ts":1792503600120}}}

Чего нет

Далее: Серверный API

Обновлено: