FastComments.com


За допомогою FastComments можна викликати кінцеву точку API щоразу, коли коментар додається, оновлюється або видаляється з нашої системи.

Ми реалізуємо це за допомогою асинхронних вебхуків через HTTP/HTTPS.

Що таке вебхуки Internal Link

Вебхук — це механізм або інтеграція між двома системами, де "виробник" (FastComments) ініціює подію яку "споживач" (Ви) обробляє через виклик API.

Підтримувані події та ресурси Internal Link

FastComments підтримує вебхуки лише для ресурсу Comment.

Ми підтримуємо вебхуки для створення коментаря, видалення та оновлення.

Кожен із цих випадків вважається окремою подією в нашій системі і тому має різну семантику та структуру подій вебхука.

Тестування Internal Link

В адмінці Webhooks є кнопки Send Test Payload для кожного типу подій (Create, Update, Delete). Події Create та Update відправляють демонстраційний об'єкт WebhookComment, тоді як при тестуванні Delete буде надіслано тестове тіло запиту, що містить лише ID.

Перевірка вхідних даних

Під час тестування інтеграції вебхуків переконайтеся, що вхідні запити містять наступні заголовки:

  1. token - Ваш секрет API
  2. X-FastComments-Timestamp - Unix-мітка часу (у секундах)
  3. X-FastComments-Signature - підпис HMAC-SHA256

Використовуйте перевірку підпису HMAC, щоб переконатися в автентичності вхідних даних.

Інструменти для тестування

Ви можете використовувати інструменти, такі як webhook.site або ngrok, щоб переглядати вхідні дані вебхуків під час розробки.

Типи подій

  • Create Event: Викликається, коли створюється новий коментар. Метод за замовчуванням: PUT
  • Update Event: Викликається, коли коментар редагується. Метод за замовчуванням: PUT
  • Delete Event: Викликається, коли коментар видаляється. Метод за замовчуванням: DELETE

Кожна подія містить повні дані коментаря в тілі запиту (див. Структури даних для формату даних).

Структури даних Internal Link

Єдина структура, яку надсилають через вебхуки — це об'єкт WebhookComment, описаний нижче на TypeScript.

Структура об'єкта WebhookComment

The "Create" Event Structure

Тіло запиту події "create" є об'єктом WebhookComment.

The "Update" Event Structure

Тіло запиту події "update" є об'єктом WebhookComment.

The "Delete" Event Structure

Тіло запиту події "delete" є об'єктом WebhookComment.

Change as of Nov 14th 2023
Previously the "delete" event request body only contained the comment id. It now contains the full comment at the time of deletion.
Об'єкт WebhookComment
Copy CopyRun External Link
1
2interface WebhookComment {
3 /** Ідентифікатор коментаря. **/
4 id: string
5 /** Id або URL, що ідентифікує тред коментарів. Нормалізований. **/
6 urlId: string
7 /** URL, який вказує, де залишено коментар. **/
8 url?: string
9 /** Id користувача, який залишив коментар. Якщо SSO, з префіксом id орендаря. **/
10 userId?: string
11 /** Email користувача, який залишив коментар. **/
12 commenterEmail?: string
13 /** Ім'я користувача, що відображається у віджеті коментарів. Для SSO може бути displayName. **/
14 commenterName: string
15 /** Сирий текст коментаря. **/
16 comment: string
17 /** Текст коментаря після парсингу. **/
18 commentHTML: string
19 /** Зовнішній id коментаря. **/
20 externalId?: string
21 /** Id батьківського коментаря. **/
22 parentId?: string | null
23 /** Дата в UTC, коли було залишено коментар. **/
24 date: UTC_ISO_DateString
25 /** Комбінована карма голосів (up - down). **/
26 votes: number
27 votesUp: number
28 votesDown: number
29 /** True, якщо користувач був увійшов у систему під час коментування, або якщо коментар підтверджено, або якщо вони верифікували свою сесію в момент залишення коментаря. **/
30 verified: boolean
31 /** Дата, коли коментар було підтверджено. **/
32 verifiedDate?: number
33 /** Чи позначив модератор коментар як переглянутий. **/
34 reviewed: boolean
35 /** Розташування або base64-код аватару. Буде в base64 лише якщо таке значення було передано з SSO. **/
36 avatarSrc?: string
37 /** Чи було коментар позначено як спам вручну або автоматично? **/
38 isSpam: boolean
39 /** Чи було коментар автоматично позначено як спам? **/
40 aiDeterminedSpam: boolean
41 /** Чи містить коментар зображення? **/
42 hasImages: boolean
43 /** Номер сторінки, на якій знаходиться коментар для сортування «Найбільш релевантні». **/
44 pageNumber: number
45 /** Номер сторінки, на якій знаходиться коментар для сортування «Спочатку найстаріші». **/
46 pageNumberOF: number
47 /** Номер сторінки, на якій знаходиться коментар для сортування «Спочатку найновіші». **/
48 pageNumberNF: number
49 /** Чи було коментар схвалено автоматично чи вручну? **/
50 approved: boolean
51 /** Код локалі (формат: en_us) користувача під час написання коментаря. **/
52 locale: string
53 /** @mention'и, написані в коментарі, які було успішно розпарсено. **/
54 mentions?: CommentUserMention[]
55 /** Домен, звідки походить коментар. **/
56 domain?: string
57 /** Опційний список id груп модерації, пов'язаних з цим коментарем. **/
58 moderationGroupIds?: string[]|null
59}
60

When users are tagged in a comment, the information is stored in a list called mentions. Each object in that list has the following structure.

Об'єкт згадок вебхука
Copy CopyRun External Link
1
2interface CommentUserMention {
3 /** Id користувача. Для SSO-користувачів тут буде префікс з id орендаря. **/
4 id: string
5 /** Остаточний текст @mention тегу, включаючи символ @. **/
6 tag: string
7 /** Початковий текст @mention тегу, включаючи символ @. **/
8 rawTag: string
9 /** Який тип користувача було зазначено. user = FastComments.com account. sso = SSOUser. **/
10 type: 'user'|'sso'
11 /** Якщо користувач відмовився від сповіщень, це все одно буде встановлено в true. **/
12 sent: boolean
13}
14

HTTP Methods

Ви можете налаштувати HTTP-метод для кожного типу подій вебхука в адмін-панелі:

  • Create Event: POST або PUT (за замовчуванням: PUT)
  • Update Event: POST або PUT (за замовчуванням: PUT)
  • Delete Event: DELETE, POST, або PUT (за замовчуванням: DELETE)

Оскільки всі запити містять ID, операції Create та Update за замовчуванням ідемпотентні (PUT). Повторне надсилання того ж запиту Create або Update не має створювати дублікати об'єктів у вас.

Request Headers

Кожний запит вебхука містить такі заголовки:

Header Description
Content-Type application/json
token Ваш API Secret
X-FastComments-Timestamp Unix-мітка часу (секунди), коли запит було підписано
X-FastComments-Signature Підпис HMAC-SHA256 (sha256=<hex>)

See Безпека та API токени for information on verifying the HMAC signature.

Безпека та API-токени Internal Link

FastComments webhook requests include multiple authentication mechanisms for security.

Headers Sent

Header Description
token Your API Secret (for backwards compatibility)
X-FastComments-Timestamp Unix timestamp (seconds) when the request was signed
X-FastComments-Signature HMAC-SHA256 signature of the payload

We strongly recommend verifying the HMAC signature to ensure webhook payloads are authentic and haven't been tampered with.

Signature Format: sha256=<hex-encoded-signature>

How the signature is computed:

  1. Concatenate: timestamp + "." + JSON_payload_body
  2. Compute HMAC-SHA256 using your API Secret as the key
  3. Hex-encode the result

Example Verification (Node.js)

const crypto = require('crypto');

function verifyWebhookSignature(req, apiSecret) {
    const timestamp = req.headers['x-fastcomments-timestamp'];
    const signature = req.headers['x-fastcomments-signature'];

    if (!timestamp || !signature) {
        return false;
    }

    // Перевірити, що мітка часу є актуальною (протягом 5 хвилин)
    const now = Math.floor(Date.now() / 1000);
    if (Math.abs(now - parseInt(timestamp, 10)) > 300) {
        return false;  // Запобігання повторним атакам (replay attacks)
    }

    // Перевірка підпису
    const payload = JSON.stringify(req.body);
    const expectedSignature = crypto
        .createHmac('sha256', apiSecret)
        .update(`${timestamp}.${payload}`)
        .digest('hex');

    return signature === `sha256=${expectedSignature}`;
}

Example Verification (Python)

import hmac
import hashlib
import time
import json

def verify_webhook_signature(headers, body, api_secret):
    timestamp = headers.get('X-FastComments-Timestamp')
    signature = headers.get('X-FastComments-Signature')

    if not timestamp or not signature:
        return False

    # Перевірте, що мітка часу є актуальною
    now = int(time.time())
    if abs(now - int(timestamp)) > 300:
        return False

    # Перевірка підпису
    payload = json.dumps(body, separators=(',', ':'))
    message = f"{timestamp}.{payload}"
    expected = hmac.new(
        api_secret.encode(),
        message.encode(),
        hashlib.sha256
    ).hexdigest()

    return signature == f"sha256={expected}"

Example Verification (PHP)

function verifyWebhookSignature($headers, $body, $apiSecret) {
    $timestamp = $headers['X-FastComments-Timestamp'] ?? null;
    $signature = $headers['X-FastComments-Signature'] ?? null;

    if (!$timestamp || !$signature) {
        return false;
    }

    // Перевірте, що мітка часу є актуальною (протягом 5 хвилин)
    $now = time();
    if (abs($now - intval($timestamp)) > 300) {
        return false;
    }

    // Перевірка підпису
    $payload = json_encode($body, JSON_UNESCAPED_SLASHES);
    $message = $timestamp . '.' . $payload;
    $expectedSignature = 'sha256=' . hash_hmac('sha256', $message, $apiSecret);

    return hash_equals($expectedSignature, $signature);
}

Legacy Authentication

The token header containing your API Secret is still sent for backwards compatibility. However, we recommend migrating to HMAC verification for improved security as it protects against replay attacks.


На завершення

Цим завершується наша документація Webhooks.

Ми сподіваємося, що інтеграція FastComments Webhook є зрозумілою та швидкою у налаштуванні.

Якщо ви вважаєте, що виявили будь-які прогалини в нашій документації, повідомте нас нижче.