FastComments.com


Med FastComments er det muligt at kalde et API-endpoint, når en kommentar tilføjes, opdateres eller fjernes fra vores system.

Vi opnår dette med asynkrone webhooks over HTTP/HTTPS.


Hvad er Webhooks Internal Link

En Webhook er en mekanisme, eller en integration, mellem to systemer hvor "produceren" (FastComments) udløser en begivenhed som "forbrugeren" (dig) modtager via et API-opkald.

Understøttede hændelser og ressourcer Internal Link


FastComments understøtter kun webhooks for ressourcen Comment.

Vi understøtter webhooks ved oprettelse, fjernelse og opdatering af kommentarer.

Hver af disse betragtes som separate hændelser i vores system og har derfor forskellig semantik og struktur for webhook-hændelserne.


Testning Internal Link

I Webhooks-admin er der Send Test Payload-knapper for hver hændelsestype (Create, Update, Delete). Create- og Update-hændelserne sender et dummy WebhookComment-objekt, mens test af Delete sender en dummy request body med kun et ID.

Bekræftelse af payloads

Når du tester din webhook-integration, skal du kontrollere, at de indkommende forespørgsler indeholder følgende headers:

  1. token - Din API Secret
  2. X-FastComments-Timestamp - Unix-tidsstempel (sekunder)
  3. X-FastComments-Signature - HMAC-SHA256-signatur

Brug HMAC-signaturverificering for at sikre, at payloads er autentiske.

Testværktøjer

Du kan bruge værktøjer som webhook.site eller ngrok til at inspicere indkommende webhook-payloads under udvikling.

Hændelsestyper

  • Create Event: Udløses, når en ny kommentar oprettes. Default method: PUT
  • Update Event: Udløses, når en kommentar redigeres. Default method: PUT
  • Delete Event: Udløses, når en kommentar slettes. Default method: DELETE

Hver hændelse inkluderer hele kommentardataene i request body'en (se Datastrukturer for payload-formatet).

Datastrukturer Internal Link

Den eneste struktur sendt via webhooks er WebhookComment-objektet, beskrevet i TypeScript nedenfor.

WebhookComment-objektets struktur

Strukturen for "create"-begivenheden

Requestbodyen for "create"-begivenheden er et WebhookComment-objekt.

Strukturen for "update"-begivenheden

Requestbodyen for "update"-begivenheden er et WebhookComment-objekt.

Strukturen for "delete"-begivenheden

Requestbodyen for "delete"-begivenheden er et WebhookComment-objekt.

Ændring pr. 14. nov. 2023
Tidligere indeholdt requestbodyen for "delete"-begivenheden kun kommentar-id'et. Den indeholder nu hele kommentaren på tidspunktet for sletningen.
WebhookComment-objektet
Copy CopyRun External Link
1
2interface WebhookComment {
3 /** Id'et på kommentaren. **/
4 id: string
5 /** Id'et eller URL'en, der identificerer kommentartråden. Normaliseret. **/
6 urlId: string
7 /** URL'en, der peger på hvor kommentaren blev efterladt. **/
8 url?: string
9 /** Bruger-id'et der skrev kommentaren. Hvis SSO, præfikset med tenant-id. **/
10 userId?: string
11 /** Emailen på brugeren, der skrev kommentaren. **/
12 commenterEmail?: string
13 /** Navnet på brugeren, som vises i kommentarboksen. Ved SSO kan det være displayName. **/
14 commenterName: string
15 /** Rå kommentartekst. **/
16 comment: string
17 /** Kommentartekst efter parsing. **/
18 commentHTML: string
19 /** Eksternt id for kommentaren. **/
20 externalId?: string
21 /** Id'et på forældrekommentaren. **/
22 parentId?: string | null
23 /** UTC-datoen da kommentaren blev skrevet. **/
24 date: UTC_ISO_DateString
25 /** Kombineret karma (op - ned) fra stemmerne. **/
26 votes: number
27 votesUp: number
28 votesDown: number
29 /** Sandt hvis brugeren var logget ind, da de kommenterede, eller hvis de verificerede kommentaren, eller hvis de bekræftede deres session, da kommentaren blev efterladt. **/
30 verified: boolean
31 /** Dato for hvornår kommentaren blev verificeret. **/
32 verifiedDate?: number
33 /** Hvis en moderator markerede kommentaren som gennemgået. **/
34 reviewed: boolean
35 /** Placeringen, eller base64-enkodningen, af avataren. Vil kun være base64 hvis det var den værdi, der blev sendt med SSO. **/
36 avatarSrc?: string
37 /** Blev kommentaren manuelt eller automatisk markeret som spam? **/
38 isSpam: boolean
39 /** Blev kommentaren automatisk markeret som spam? **/
40 aiDeterminedSpam: boolean
41 /** Er der billeder i kommentaren? **/
42 hasImages: boolean
43 /** Sidenummeret kommentaren er på for sorteringsretningen "Most Relevant". **/
44 pageNumber: number
45 /** Sidenummeret kommentaren er på for sorteringsretningen "Oldest First". **/
46 pageNumberOF: number
47 /** Sidenummeret kommentaren er på for sorteringsretningen "Newest First". **/
48 pageNumberNF: number
49 /** Blev kommentaren godkendt automatisk eller manuelt? **/
50 approved: boolean
51 /** Lokale-koden (format: en_us) for brugeren da kommentaren blev skrevet. **/
52 locale: string
53 /** De @mentions skrevet i kommentaren, som blev korrekt fortolket. **/
54 mentions?: CommentUserMention[]
55 /** Domænet kommentaren kommer fra. **/
56 domain?: string
57 /** Den valgfrie liste over moderationsgruppe-id'er forbundet med denne kommentar. **/
58 moderationGroupIds?: string[]|null
59}
60

Når brugere tagges i en kommentar, gemmes oplysningerne i en liste kaldet mentions. Hvert objekt i den liste har følgende struktur.

Webhook Mentions-objektet
Copy CopyRun External Link
1
2interface CommentUserMention {
3 /** Brugerens id. For SSO-brugere vil dette have dit tenant-id som præfiks. **/
4 id: string
5 /** Den endelige @mention-tagtekst, inklusive @-symbolet. **/
6 tag: string
7 /** Den oprindelige @mention-tagtekst, inklusive @-symbolet. **/
8 rawTag: string
9 /** Hvilken type bruger der blev tagget. user = FastComments.com-konto. sso = SSOUser. **/
10 type: 'user'|'sso'
11 /** Hvis brugeren fravælger notifikationer, vil dette stadig være sat til true. **/
12 sent: boolean
13}
14

HTTP-metoder

Du kan konfigurere HTTP-metoden for hver webhook-begivenhedstype i administrationspanelet:

  • Oprettelsesbegivenhed: POST eller PUT (standard: PUT)
  • Opdateringsbegivenhed: POST eller PUT (standard: PUT)
  • Sletningsbegivenhed: DELETE, POST, eller PUT (standard: DELETE)

Da alle forespørgsler indeholder et ID, er Create- og Update-operationer idempotente som standard (PUT). Gentagelse af samme Create- eller Update-forespørgsel bør ikke oprette dublerede objekter på din side.

Anmodningsoverskrifter

Hver webhook-forespørgsel inkluderer følgende headers:

Header Description
Content-Type application/json
token Din API-secret
X-FastComments-Timestamp Unix-timestamp (sekunder) da forespørgslen blev underskrevet
X-FastComments-Signature HMAC-SHA256-signatur (sha256=<hex>)

Se Sikkerhed & API Tokens for oplysninger om verifikation af HMAC-signaturen.


Sikkerhed og API-tokens Internal Link

FastComments webhook-forespørgsler indeholder flere autentificeringsmekanismer for sikkerhed.

Sendte headere

Header Beskrivelse
token Din API Secret (for bagudkompatibilitet)
X-FastComments-Timestamp Unix-tidsstempel (sekunder) da anmodningen blev signeret
X-FastComments-Signature HMAC-SHA256-signatur af payloaden

HMAC-signaturverifikation (Anbefalet)

Vi anbefaler kraftigt at verificere HMAC-signaturen for at sikre, at webhook-payloads er autentiske og ikke er blevet manipuleret med.

Signaturformat: sha256=<hex-encoded-signature>

Hvordan signaturen beregnes:

  1. Sammenkæd: timestamp + "." + JSON_payload_body
  2. Beregn HMAC-SHA256 ved at bruge din API Secret som nøgle
  3. Hex-enkodér resultatet

Eksempel på verifikation (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;
    }

    // Bekræft at tidsstemplet er nyligt (inden for 5 minutter)
    const now = Math.floor(Date.now() / 1000);
    if (Math.abs(now - parseInt(timestamp, 10)) > 300) {
        return false;  // Forebyggelse af replay-angreb
    }

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

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

Eksempel på verifikation (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

    # Bekræft at tidsstemplet er nyligt
    now = int(time.time())
    if abs(now - int(timestamp)) > 300:
        return False

    # Bekræft 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}"

Eksempel på verifikation (PHP)

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

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

    // Bekræft at tidsstemplet er nyligt (inden for 5 minutter)
    $now = time();
    if (abs($now - intval($timestamp)) > 300) {
        return false;
    }

    // Bekræft signatur
    $payload = json_encode($body, JSON_UNESCAPED_SLASHES);
    $message = $timestamp . '.' . $payload;
    $expectedSignature = 'sha256=' . hash_hmac('sha256', $message, $apiSecret);

    return hash_equals($expectedSignature, $signature);
}

Ældre autentificering

token-headeren, der indeholder din API Secret, sendes stadig for bagudkompatibilitet. Vi anbefaler dog at migrere til HMAC-verifikation for forbedret sikkerhed, da det beskytter mod replay-angreb.



Afslutningsvis

Dette afslutter vores Webhooks-dokumentation.

Vi håber, du synes, at FastComments Webhook-integrationen er nem at forstå og hurtig at sætte op.

Hvis du mener, at du har fundet mangler i vores dokumentation, så lad os det vide nedenfor.