FastComments.com


Z FastComments możliwe jest wywołanie punktu końcowego API za każdym razem, gdy komentarz zostanie dodany, zaktualizowany lub usunięty z naszego systemu.

Realizujemy to za pomocą asynchronicznych webhooków przez HTTP/HTTPS.


Czym są webhooki Internal Link


Webhook to mechanizm, lub integracja, pomiędzy dwoma systemami gdzie "producent" (FastComments) wyzwala zdarzenie które "konsument" (Ty) odbiera za pomocą wywołania API.


Obsługiwane zdarzenia i zasoby Internal Link

FastComments obsługuje webhooki tylko dla zasobu Comment.

Obsługujemy webhooki dla tworzenia komentarza, usuwania oraz aktualizacji.

Każde z nich jest w naszym systemie traktowane jako odrębne zdarzenie i w związku z tym ma inną semantykę i inną strukturę zdarzeń webhook.

Testowanie Internal Link

W panelu administracyjnym Webhooks znajdują się przyciski Send Test Payload dla każdego typu zdarzenia (Utworzenie, Aktualizacja, Usunięcie). Zdarzenia Utworzenia i Aktualizacji wysyłają przykładowy obiekt WebhookComment, natomiast testowanie Usunięcia wyśle przykładową treść żądania zawierającą tylko identyfikator.

Weryfikacja treści żądań

Podczas testowania integracji webhooków upewnij się, że przychodzące żądania zawierają następujące nagłówki:

  1. token - Twój sekret API
  2. X-FastComments-Timestamp - Znacznik czasu Unix (w sekundach)
  3. X-FastComments-Signature - Sygnatura HMAC-SHA256

Użyj weryfikacji sygnatury HMAC, aby upewnić się, że treści żądań są autentyczne.

Narzędzia testowe

Możesz użyć narzędzi takich jak webhook.site lub ngrok, aby przejrzeć przychodzące dane webhooków podczas tworzenia.

Typy zdarzeń

  • Zdarzenie utworzenia: Wywoływane, gdy nowy komentarz zostanie utworzony. Domyślna metoda: PUT
  • Zdarzenie aktualizacji: Wywoływane, gdy komentarz jest edytowany. Domyślna metoda: PUT
  • Zdarzenie usunięcia: Wywoływane, gdy komentarz zostanie usunięty. Domyślna metoda: DELETE

Każde zdarzenie zawiera pełne dane komentarza w treści żądania (zobacz Struktury danych dla formatu danych).

Struktury danych Internal Link

Jedyną strukturą wysyłaną przez webhooki jest obiekt WebhookComment, przedstawiony poniżej w TypeScript.

Struktura obiektu WebhookComment

Struktura zdarzenia "create"

Ciało żądania zdarzenia "create" jest obiektem WebhookComment.

Struktura zdarzenia "update"

Ciało żądania zdarzenia "update" jest obiektem WebhookComment.

Struktura zdarzenia "delete"

Ciało żądania zdarzenia "delete" jest obiektem WebhookComment.

Zmiana od 14 listopada 2023
Wcześniej ciało żądania zdarzenia "delete" zawierało tylko identyfikator komentarza. Teraz zawiera pełny komentarz w momencie usunięcia.
Obiekt WebhookComment
Copy CopyRun External Link
1
2interface WebhookComment {
3 /** Id komentarza. **/
4 id: string
5 /** The id or URL that identifies the comment thread. Normalized. **/
6 urlId: string
7 /** URL wskazujący miejsce, gdzie został dodany komentarz. **/
8 url?: string
9 /** Id użytkownika, który dodał komentarz. Jeśli SSO, poprzedzone tenant id. **/
10 userId?: string
11 /** Email użytkownika, który dodał komentarz. **/
12 commenterEmail?: string
13 /** Nazwa użytkownika wyświetlana w widżecie komentarzy. Przy SSO może to być displayName. **/
14 commenterName: string
15 /** Surowy tekst komentarza. **/
16 comment: string
17 /** Tekst komentarza po parsowaniu. **/
18 commentHTML: string
19 /** Zewnętrzny id komentarza. **/
20 externalId?: string
21 /** Id komentarza nadrzędnego. **/
22 parentId?: string | null
23 /** Data w UTC, kiedy komentarz został dodany. **/
24 date: UTC_ISO_DateString
25 /** Suma głosów (up - down). **/
26 votes: number
27 votesUp: number
28 votesDown: number
29 /** Prawda, jeśli użytkownik był zalogowany podczas dodawania komentarza, lub zweryfikował komentarz, albo zweryfikował swoją sesję w momencie dodania komentarza. **/
30 verified: boolean
31 /** Data, kiedy komentarz został zweryfikowany. **/
32 verifiedDate?: number
33 /** Czy moderator oznaczył komentarz jako sprawdzony. **/
34 reviewed: boolean
35 /** Lokalizacja lub kodowanie base64 awatara. Będzie base64 tylko wtedy, gdy taka wartość została przekazana z SSO. **/
36 avatarSrc?: string
37 /** Czy komentarz został oznaczony jako spam ręcznie czy automatycznie? **/
38 isSpam: boolean
39 /** Czy komentarz został automatycznie oznaczony jako spam? **/
40 aiDeterminedSpam: boolean
41 /** Czy w komentarzu są obrazy? **/
42 hasImages: boolean
43 /** Numer strony, na której znajduje się komentarz dla kierunku sortowania "Most Relevant". **/
44 pageNumber: number
45 /** Numer strony, na której znajduje się komentarz dla kierunku sortowania "Oldest First". **/
46 pageNumberOF: number
47 /** Numer strony, na której znajduje się komentarz dla kierunku sortowania "Newest First". **/
48 pageNumberNF: number
49 /** Czy komentarz został zatwierdzony automatycznie czy ręcznie? **/
50 approved: boolean
51 /** Kod lokalizacji (format: en_us) użytkownika w momencie napisania komentarza. **/
52 locale: string
53 /** @mentions napisane w komentarzu, które zostały pomyślnie sparsowane. **/
54 mentions?: CommentUserMention[]
55 /** Domena, z której pochodzi komentarz. **/
56 domain?: string
57 /** Opcjonalna lista id grup moderacji powiązanych z tym komentarzem. **/
58 moderationGroupIds?: string[]|null
59}
60

Gdy użytkownicy są oznaczani w komentarzu, informacje są przechowywane w liście o nazwie mentions. Każdy obiekt w tej liście ma następującą strukturę.

Obiekt wzmianki webhook
Copy CopyRun External Link
1
2interface CommentUserMention {
3 /** Id użytkownika. Dla użytkowników SSO będzie poprzedzony tenant id. **/
4 id: string
5 /** Ostateczny tekst tagu @mention, łącznie z symbolem @. **/
6 tag: string
7 /** Oryginalny tekst tagu @mention, łącznie z symbolem @. **/
8 rawTag: string
9 /** Jaki typ użytkownika został oznaczony. user = konto FastComments.com. sso = SSOUser. **/
10 type: 'user'|'sso'
11 /** Jeśli użytkownik zrezygnuje z powiadomień, ta wartość nadal będzie ustawiona na true. **/
12 sent: boolean
13}
14

Metody HTTP

Możesz skonfigurować metodę HTTP dla każdego typu zdarzenia webhook w panelu administracyjnym:

  • Create Event: POST lub PUT (domyślnie: PUT)
  • Update Event: POST lub PUT (domyślnie: PUT)
  • Delete Event: DELETE, POST lub PUT (domyślnie: DELETE)

Ponieważ wszystkie żądania zawierają ID, operacje Create i Update są domyślnie idempotentne (PUT). Powtórzenie tego samego żądania Create lub Update nie powinno tworzyć zduplikowanych obiektów po Twojej stronie.

Nagłówki żądań

Każde żądanie webhook zawiera następujące nagłówki:

Nagłówek Opis
Content-Type application/json
token Twój sekret API
X-FastComments-Timestamp Znacznik czasu Unix (sekundy) w momencie podpisania żądania
X-FastComments-Signature Podpis HMAC-SHA256 (sha256=<hex>)

Zobacz Security & API Tokens aby uzyskać informacje o weryfikacji podpisu HMAC.


Bezpieczeństwo i tokeny API Internal Link

FastComments webhook requests include multiple authentication mechanisms for security.

Wysyłane nagłówki

Nagłówek Opis
token Twój API Secret (w celu zachowania zgodności wstecznej)
X-FastComments-Timestamp Znacznik czasu Unix (sekundy), kiedy żądanie zostało podpisane
X-FastComments-Signature Podpis HMAC-SHA256 ładunku

Weryfikacja podpisu HMAC (zalecane)

Zdecydowanie zalecamy weryfikację podpisu HMAC, aby upewnić się, że ładunki webhooków są autentyczne i nie zostały zmienione.

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

Jak obliczany jest podpis:

  1. Połącz: timestamp + "." + JSON_payload_body
  2. Oblicz HMAC-SHA256 używając swojego API Secret jako klucza
  3. Zakoduj wynik w hex

Przykład weryfikacji (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;
    }

    // Zweryfikuj, że znacznik czasu jest aktualny (w ciągu 5 minut)
    const now = Math.floor(Date.now() / 1000);
    if (Math.abs(now - parseInt(timestamp, 10)) > 300) {
        return false;  // Zapobieganie atakom powtórzeniowym
    }

    // Verify signature
    const payload = JSON.stringify(req.body);
    const expectedSignature = crypto
        .createHmac('sha256', apiSecret)
        .update(`${timestamp}.${payload}`)
        .digest('hex');

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

Przykład weryfikacji (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

    # Zweryfikuj, że znacznik czasu jest aktualny
    now = int(time.time())
    if abs(now - int(timestamp)) > 300:
        return False

    # Zweryfikuj podpis
    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}"

Przykład weryfikacji (PHP)

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

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

    // Zweryfikuj, że znacznik czasu jest aktualny (w ciągu 5 minut)
    $now = time();
    if (abs($now - intval($timestamp)) > 300) {
        return false;
    }

    // Zweryfikuj podpis
    $payload = json_encode($body, JSON_UNESCAPED_SLASHES);
    $message = $timestamp . '.' . $payload;
    $expectedSignature = 'sha256=' . hash_hmac('sha256', $message, $apiSecret);

    return hash_equals($expectedSignature, $signature);
}

Starsze uwierzytelnianie

Nagłówek token zawierający Twój API Secret wciąż jest wysyłany dla zachowania zgodności wstecznej. Jednak zalecamy przejście na weryfikację HMAC dla lepszego bezpieczeństwa, ponieważ chroni ona przed atakami powtórzeniowymi.


Podsumowanie

To kończy naszą dokumentację Webhooks.

Mamy nadzieję, że integracja FastComments Webhook jest łatwa do zrozumienia i szybka do skonfigurowania.

Jeśli uważasz, że zidentyfikowałeś jakiekolwiek luki w naszej dokumentacji, daj nam znać poniżej.