FastComments.com


С FastComments е възможно да се извика API endpoint всеки път, когато коментар бъде добавен, актуализиран или премахнат от нашата система.

Постигаме това с помощта на асинхронни webhooks по 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-ите

When testing your webhook integration, verify the incoming requests include the following headers:

  1. token - Вашият API Secret
  2. X-FastComments-Timestamp - Unix timestamp (в секунди)
  3. X-FastComments-Signature - HMAC-SHA256 подпис

Използвайте проверката на HMAC подписа, за да се уверите, че payload-ите са автентични.

Инструменти за тестване

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

Типове събития

  • Create Event: Активира се когато се създаде нов коментар. По подразбиране метод: PUT
  • Update Event: Активира се когато коментарът бъде редактиран. По подразбиране метод: PUT
  • Delete Event: Активира се когато коментарът бъде изтрит. По подразбиране метод: DELETE

Each event includes the full comment data in the request body (see Структури с данни for the payload format).

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


Единствената структура, изпращана чрез webhooks, е обектът 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 /** Идентификаторът на коментара. **/
4 id: string
5 /** Идентификаторът или URL адресът, който идентифицира нишката с коментари. Нормализиран. **/
6 urlId: string
7 /** URL адресът, който сочи към мястото, където е оставен коментарът. **/
8 url?: string
9 /** Идентификаторът на потребителя, който е оставил коментара. Ако е SSO, с префикс tenant id. **/
10 userId?: string
11 /** Имейлът на потребителя, който е оставил коментара. **/
12 commenterEmail?: string
13 /** Името на потребителя, което се показва в comment widget-а. При SSO може да бъде displayName. **/
14 commenterName: string
15 /** Суров текст на коментара. **/
16 comment: string
17 /** Текстът на коментара след парсване. **/
18 commentHTML: string
19 /** Външен идентификатор на коментара. **/
20 externalId?: string
21 /** Идентификаторът на родителския коментар. **/
22 parentId?: string | null
23 /** UTC датата, когато е оставен коментарът. **/
24 date: UTC_ISO_DateString
25 /** Комбинирана карма (up - down) на гласовете. **/
26 votes: number
27 votesUp: number
28 votesDown: number
29 /** Вярно, ако потребителят е бил влязъл, когато е коментирал, ако е верифицирал коментара, или ако е верифицирал сесията си, когато е оставил коментара. **/
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 /** Номерът на страницата, на която се намира коментарът за сортиране "Most Relevant". **/
44 pageNumber: number
45 /** Номерът на страницата, на която се намира коментарът за сортиране "Oldest First". **/
46 pageNumberOF: number
47 /** Номерът на страницата, на която се намира коментарът за сортиране "Newest First". **/
48 pageNumberNF: number
49 /** Коментарът одобрен ли е автоматично или ръчно? **/
50 approved: boolean
51 /** Кодът на локала (формат: en_us) на потребителя, когато е написан коментарът. **/
52 locale: string
53 /** @mentions, написани в коментара, които са успешно парснати. **/
54 mentions?: CommentUserMention[]
55 /** Домейнът, от който е коментарът. **/
56 domain?: string
57 /** Опционален списък с идентификатори на модераторски групи, асоциирани с този коментар. **/
58 moderationGroupIds?: string[]|null
59}
60

Когато потребители са маркирани в коментар, информацията се съхранява в списък, наречен mentions. Всеки обект в този списък има следната структура.

Обектът Webhook Mentions
Copy CopyRun External Link
1
2interface CommentUserMention {
3 /** Идентификаторът на потребителя. За SSO потребителите това ще има префикс с вашия tenant 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 метода за всеки тип webhook събитие в администраторския панел:

  • Create Event: POST or PUT (default: PUT)
  • Update Event: POST or PUT (default: PUT)
  • Delete Event: DELETE, POST, or PUT (default: DELETE)

Тъй като всички заявки съдържат ID, операциите Create и Update са идемпотентни по подразбиране (PUT). Повтарянето на една и съща заявка за Create или Update не би трябвало да създаде дублирани обекти от ваша страна.

Request Headers

Всяка webhook заявка включва следните заглавки:

Хедър Описание
Content-Type application/json
token Вашият API Secret
X-FastComments-Timestamp Unix timestamp (seconds) when the request was signed
X-FastComments-Signature HMAC-SHA256 signature (sha256=<hex>)

Вижте Сигурност и API токени за информация относно проверката на HMAC подписа.


Сигурност и API токени Internal Link

FastComments webhook requests include multiple authentication mechanisms for security.

Изпращани заглавки

Header Description
token Вашият API Secret (за обратна съвместимост)
X-FastComments-Timestamp Unix времеви печат (в секунди), когато заявката е била подписана
X-FastComments-Signature HMAC-SHA256 подпис на полезното съдържание

Силно препоръчваме да проверявате HMAC подписа, за да се уверите, че payload-ите на webhook-ите са автентични и не са били подправяни.

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 атаки
    }

    // Проверете подписа
    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);
}

Наследствено удостоверяване

Хедърът token, съдържащ вашия API Secret, все още се изпраща за обратна съвместимост. Въпреки това препоръчваме миграция към проверка на HMAC за по-добра сигурност, тъй като тя предпазва от replay атаки.

В заключение

Това завършва нашата документация за Webhooks.

Надяваме се, че интеграцията на FastComments Webhook е лесна за разбиране и бърза за настройване.

Ако смятате, че сте открили пропуски в нашата документация, уведомете ни по-долу.