FastComments.com


Mit FastComments ist es möglich, einen API-Endpunkt aufzurufen, wann immer ein Kommentar in unserem System hinzugefügt, aktualisiert oder entfernt wird.

Wir realisieren dies mit asynchronen Webhooks über HTTP/HTTPS.


Was sind Webhooks Internal Link

Ein Webhook ist ein Mechanismus oder eine Integration zwischen zwei Systemen, bei dem der "Produzent" (FastComments) ein Ereignis auslöst das der "Konsument" (Sie) per API-Aufruf verarbeitet.

Unterstützte Ereignisse und Ressourcen Internal Link


FastComments unterstützt Webhooks nur für die Kommentar-Ressource.

Wir unterstützen Webhooks für die Erstellung, Entfernung und Aktualisierung von Kommentaren.

Jedes davon wird in unserem System als separates Ereignis betrachtet und hat daher unterschiedliche Semantik und Strukturen für die Webhook-Ereignisse.


Testen Internal Link

Im Webhooks-Admin gibt es für jeden Ereignistyp Send Test Payload-Schaltflächen (Erstellen, Aktualisieren, Löschen). Die Erstellen- und Aktualisieren-Ereignisse senden ein Dummy-WebhookComment-Objekt, während beim Testen des Lösch-Ereignisses ein Dummy-Anfragekörper mit nur einer ID gesendet wird.

Überprüfung der Payloads

Prüfen Sie beim Testen Ihrer Webhook-Integration, ob die eingehenden Anfragen die folgenden Header enthalten:

  1. token - Ihr API-Secret
  2. X-FastComments-Timestamp - Unix-Zeitstempel (Sekunden)
  3. X-FastComments-Signature - HMAC-SHA256-Signatur

Verwenden Sie die HMAC-Signaturüberprüfung, um sicherzustellen, dass die Payloads authentisch sind.

Test-Tools

Sie können Tools wie webhook.site oder ngrok verwenden, um eingehende Webhook-Payloads während der Entwicklung einzusehen.

Ereignistypen

  • Erstellen-Ereignis: Wird ausgelöst, wenn ein neuer Kommentar erstellt wird. Standardmethode: PUT
  • Aktualisieren-Ereignis: Wird ausgelöst, wenn ein Kommentar bearbeitet wird. Standardmethode: PUT
  • Löschen-Ereignis: Wird ausgelöst, wenn ein Kommentar gelöscht wird. Standardmethode: DELETE

Jedes Ereignis enthält die vollständigen Kommentardaten im Anfragekörper (siehe Datenstrukturen für das Payload-Format).

Datenstrukturen Internal Link

Die einzige Struktur, die per Webhooks gesendet wird, ist das WebhookComment-Objekt, unten in TypeScript dargestellt.

Die Struktur des WebhookComment-Objekts

Die "Create"-Ereignisstruktur

Der "create"-Ereignis-Request-Body ist ein WebhookComment-Objekt.

Die "Update"-Ereignisstruktur

Der "update"-Ereignis-Request-Body ist ein WebhookComment-Objekt.

Die "Delete"-Ereignisstruktur

Der "delete"-Ereignis-Request-Body ist ein WebhookComment-Objekt.

Änderung ab 14. Nov. 2023
Zuvor enthielt der Request-Body des "delete"-Ereignisses nur die Kommentar-ID. Jetzt enthält er den vollständigen Kommentar zum Zeitpunkt der Löschung.
Das WebhookComment-Objekt
Copy CopyRun External Link
1
2interface WebhookComment {
3 /** Die id des Kommentars. **/
4 id: string
5 /** Die id oder URL, die den Kommentar-Thread identifiziert. Normalisiert. **/
6 urlId: string
7 /** Die URL, die auf die Stelle verweist, an der der Kommentar hinterlassen wurde. **/
8 url?: string
9 /** Die Nutzer-id, die den Kommentar hinterlassen hat. Bei SSO mit tenant id vorangestellt. **/
10 userId?: string
11 /** Die E-Mail des Nutzers, der den Kommentar hinterlassen hat. **/
12 commenterEmail?: string
13 /** Der Name des Nutzers, der im Kommentar-Widget angezeigt wird. Bei SSO kann es displayName sein. **/
14 commenterName: string
15 /** Rohkommentartext. **/
16 comment: string
17 /** Kommentartext nach dem Parsen. **/
18 commentHTML: string
19 /** Externe id des Kommentars. **/
20 externalId?: string
21 /** Die id des übergeordneten Kommentars. **/
22 parentId?: string | null
23 /** Das UTC-Datum, an dem der Kommentar hinterlassen wurde. **/
24 date: UTC_ISO_DateString
25 /** Kombinierter Karma-Wert (up - down) der Stimmen. **/
26 votes: number
27 votesUp: number
28 votesDown: number
29 /** Wahr, wenn der Nutzer beim Hinterlassen des Kommentars eingeloggt war, oder den Kommentar verifiziert hat, oder seine Sitzung verifiziert hatte. **/
30 verified: boolean
31 /** Datum, wann der Kommentar verifiziert wurde. **/
32 verifiedDate?: number
33 /** Ob ein Moderator den Kommentar als geprüft markiert hat. **/
34 reviewed: boolean
35 /** Der Ort oder die base64-Codierung des Avatars. Wird nur base64 sein, wenn dieser Wert mit SSO übergeben wurde. **/
36 avatarSrc?: string
37 /** Wurde der Kommentar manuell oder automatisch als Spam markiert? **/
38 isSpam: boolean
39 /** Wurde der Kommentar automatisch als Spam markiert? **/
40 aiDeterminedSpam: boolean
41 /** Gibt es Bilder im Kommentar? **/
42 hasImages: boolean
43 /** Die Seitenzahl, auf der sich der Kommentar bei der Sortierreihenfolge "Most Relevant" befindet. **/
44 pageNumber: number
45 /** Die Seitenzahl, auf der sich der Kommentar bei der Sortierreihenfolge "Oldest First" befindet. **/
46 pageNumberOF: number
47 /** Die Seitenzahl, auf der sich der Kommentar bei der Sortierreihenfolge "Newest First" befindet. **/
48 pageNumberNF: number
49 /** Wurde der Kommentar automatisch oder manuell genehmigt? **/
50 approved: boolean
51 /** Der Locale-Code (Format: en_us) des Nutzers, als der Kommentar geschrieben wurde. **/
52 locale: string
53 /** Die @mentions, die im Kommentar geschrieben und erfolgreich geparst wurden. **/
54 mentions?: CommentUserMention[]
55 /** Die Domain, aus der der Kommentar stammt. **/
56 domain?: string
57 /** Die optionale Liste von Moderationsgruppen-ids, die mit diesem Kommentar verknüpft sind. **/
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.

Das Webhook Mentions-Objekt
Copy CopyRun External Link
1
2interface CommentUserMention {
3 /** Die nutzer-id. Bei SSO-Benutzern wird Ihre tenant id vorangestellt. **/
4 id: string
5 /** Der finale @mention-Tag-Text, inklusive des @-Symbols. **/
6 tag: string
7 /** Der ursprüngliche @mention-Tag-Text, inklusive des @-Symbols. **/
8 rawTag: string
9 /** Welche Art von Benutzer getaggt wurde. user = FastComments.com account. sso = SSOUser. **/
10 type: 'user'|'sso'
11 /** Wenn der Benutzer Benachrichtigungen abbestellt, wird dies trotzdem auf true gesetzt. **/
12 sent: boolean
13}
14

HTTP-Methoden

Sie können die HTTP-Methode für jeden Webhook-Ereignistyp im Admin-Panel konfigurieren:

  • Create-Ereignis: POST oder PUT (Standard: PUT)
  • Update-Ereignis: POST oder PUT (Standard: PUT)
  • Delete-Ereignis: DELETE, POST oder PUT (Standard: DELETE)

Da alle Requests eine ID enthalten, sind Create- und Update-Operationen standardmäßig idempotent (PUT). Die Wiederholung derselben Create- oder Update-Anfrage sollte auf Ihrer Seite keine doppelten Objekte erzeugen.

Request-Header

Jede Webhook-Anfrage enthält die folgenden Header:

Header Beschreibung
Content-Type application/json
token Ihr API Secret
X-FastComments-Timestamp Unix-Zeitstempel (Sekunden), als die Anfrage signiert wurde
X-FastComments-Signature HMAC-SHA256-Signatur (sha256=<hex>)

Siehe Sicherheit & API-Tokens für Informationen zur Verifizierung der HMAC-Signatur.


Sicherheit & API-Token Internal Link

FastComments Webhook-Anfragen enthalten mehrere Authentifizierungsmechanismen zur Sicherheit.

Gesendete Header

Header Beschreibung
token Ihr API Secret (zur Abwärtskompatibilität)
X-FastComments-Timestamp Unix-Zeitstempel (Sekunden), zu dem die Anfrage signiert wurde
X-FastComments-Signature HMAC-SHA256-Signatur der Payload

HMAC-Signaturüberprüfung (empfohlen)

Wir empfehlen dringend, die HMAC-Signatur zu überprüfen, um sicherzustellen, dass Webhook-Payloads authentisch sind und nicht manipuliert wurden.

Signaturformat: sha256=<hex-encoded-signature>

Wie die Signatur berechnet wird:

  1. Verketten: timestamp + "." + JSON_payload_body
  2. Berechne HMAC-SHA256 mit Ihrem API Secret als Schlüssel
  3. Das Ergebnis hexadezimal kodieren

Beispielüberprüfung (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;
    }

    // Überprüfe, ob der Zeitstempel aktuell ist (innerhalb von 5 Minuten)
    const now = Math.floor(Date.now() / 1000);
    if (Math.abs(now - parseInt(timestamp, 10)) > 300) {
        return false;  // Schutz vor Replay-Angriffen
    }

    // Überprüfe Signatur
    const payload = JSON.stringify(req.body);
    const expectedSignature = crypto
        .createHmac('sha256', apiSecret)
        .update(`${timestamp}.${payload}`)
        .digest('hex');

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

Beispielüberprüfung (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

    # Überprüfe, ob der Zeitstempel aktuell ist
    now = int(time.time())
    if abs(now - int(timestamp)) > 300:
        return False

    # Überprüfe Signatur
    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}"

Beispielüberprüfung (PHP)

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

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

    // Überprüfe, ob der Zeitstempel aktuell ist (innerhalb von 5 Minuten)
    $now = time();
    if (abs($now - intval($timestamp)) > 300) {
        return false;
    }

    // Überprüfe Signatur
    $payload = json_encode($body, JSON_UNESCAPED_SLASHES);
    $message = $timestamp . '.' . $payload;
    $expectedSignature = 'sha256=' . hash_hmac('sha256', $message, $apiSecret);

    return hash_equals($expectedSignature, $signature);
}

Legacy-Authentifizierung

Der token-Header, der Ihr API Secret enthält, wird weiterhin zur Abwärtskompatibilität gesendet. Wir empfehlen jedoch, auf die HMAC-Überprüfung umzusteigen, um die Sicherheit zu verbessern, da diese vor Replay-Angriffen schützt.


Zum Abschluss

Dies schließt unsere Webhooks-Dokumentation ab.

Wir hoffen, dass Sie die FastComments-Webhook-Integration leicht verständlich finden und schnell einrichten können.

Wenn Sie der Meinung sind, dass unsere Dokumentation Lücken aufweist, teilen Sie uns dies unten mit.