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.

Перевірка коректності payload'ів

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

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

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

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

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

Типи подій

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

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

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

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

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

Структура події "Create"

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

Структура події "Update"

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

Структура події "Delete"

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

Зміни станом на 14 листопада 2023 року
Раніше тіло запиту для події "delete" містило лише id коментаря. Тепер воно містить повний коментар на момент видалення.
Об'єкт WebhookComment
Copy CopyRun External Link
1
2interface WebhookComment {
3 /** The id of the comment. **/
4 id: string
5 /** The id or URL that identifies the comment thread. Normalized. **/
6 urlId: string
7 /** The URL that points to where the comment was left. **/
8 url?: string
9 /** The user id that left the comment. If SSO, prefixed with tenant id. **/
10 userId?: string
11 /** The email of the user left the comment. **/
12 commenterEmail?: string
13 /** The name of the user that shows in the comment widget. With SSO, can be displayName. **/
14 commenterName: string
15 /** Raw comment text. **/
16 comment: string
17 /** Comment text after parsing. **/
18 commentHTML: string
19 /** Comment external id. **/
20 externalId?: string
21 /** The id of the parent comment. **/
22 parentId?: string | null
23 /** The UTC date when the comment was left. **/
24 date: UTC_ISO_DateString
25 /** Combined karma (up - down) of votes. **/
26 votes: number
27 votesUp: number
28 votesDown: number
29 /** True if the user was logged in when they commented, or their verified the comment, or if they verified their session when the comment was left. **/
30 verified: boolean
31 /** Date when the comment was verified. **/
32 verifiedDate?: number
33 /** If a moderator marked the comment reviewed. **/
34 reviewed: boolean
35 /** The location, or base64 encoding, of the avatar. Will only be base64 if that was the value passed with SSO. **/
36 avatarSrc?: string
37 /** Was the comment manually or automatically marked as spam? **/
38 isSpam: boolean
39 /** Was the comment automatically marked as spam? **/
40 aiDeterminedSpam: boolean
41 /** Are there images in the comment? **/
42 hasImages: boolean
43 /** The page number the comment is on for the "Most Relevant" sort direction. **/
44 pageNumber: number
45 /** The page number the comment is on for the "Oldest First" sort direction. **/
46 pageNumberOF: number
47 /** The page number the comment is on for the "Newest First" sort direction. **/
48 pageNumberNF: number
49 /** Was the comment approved automatically or manually? **/
50 approved: boolean
51 /** The locale code (format: en_us) of the user when the comment was written. **/
52 locale: string
53 /** The @mentions written in the comment that were successfully parsed. **/
54 mentions?: CommentUserMention[]
55 /** The domain the comment is from. **/
56 domain?: string
57 /** The optional list of moderation group ids associated with this comment. **/
58 moderationGroupIds?: string[]|null
59}
60

Коли користувачів тегають у коментарі, інформація зберігається у списку, названому mentions. Кожен об'єкт у цьому списку має таку структуру.

Об'єкт згадок вебхука
Copy CopyRun External Link
1
2interface CommentUserMention {
3 /** The user id. For SSO users, this will have your tenant id prefixed. **/
4 id: string
5 /** The final @mention tag text, including the @ symbol. **/
6 tag: string
7 /** The original @mention tag text, including the @ symbol. **/
8 rawTag: string
9 /** What type of user was tagged. user = FastComments.com account. sso = SSOUser. **/
10 type: 'user'|'sso'
11 /** If the user opts out of notifications, this will still be set to 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
X-FastComments-Timestamp Unix-мітка часу (секунди), коли запит було підписано
X-FastComments-Signature HMAC-SHA256 підпис (sha256=<hex>)

Див. Безпека та API-токени для інформації про перевірку підпису HMAC.

Безпека та 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 є зрозумілою та швидкою у налаштуванні.

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