FastComments.com


Met FastComments is het mogelijk een API-eindpunt aan te roepen telkens wanneer een reactie aan ons systeem wordt toegevoegd, bijgewerkt of verwijderd.

Wij realiseren dit met asynchrone webhooks via HTTP/HTTPS.


Wat zijn Webhooks Internal Link

Een Webhook is een mechanisme, of een integratie, tussen twee systemen waar de "producent" (FastComments) een gebeurtenis die de "consument" (U) via een API-aanroep verwerkt.

Ondersteunde gebeurtenissen en bronnen Internal Link


FastComments ondersteunt webhooks alleen voor de Comment resource.

We ondersteunen webhooks voor comment-creatie, -verwijdering en bij comment-updates.

Elk van deze wordt in ons systeem als een apart evenement beschouwd en heeft daardoor verschillende semantiek en structuren voor de webhook events.


Testen Internal Link

In de Webhooks-admin zijn Send Test Payload-knoppen voor elk evenementstype (Create, Update, Delete). De Create- en Update-events sturen een dummy WebhookComment-object, terwijl bij het testen van Delete een dummy verzoekbody wordt gestuurd met alleen een ID.

Payloads verifiëren

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

  1. token - Uw API-secret
  2. X-FastComments-Timestamp - Unix-tijdstempel (seconden)
  3. X-FastComments-Signature - HMAC-SHA256-handtekening

Gebruik de HMAC-handtekeningverificatie om te controleren of de payloads authentiek zijn.

Testtools

U kunt tools zoals webhook.site of ngrok gebruiken om binnenkomende webhook-payloads tijdens de ontwikkeling te inspecteren.

Evenementtypen

  • Create Event: Wordt geactiveerd wanneer een nieuwe reactie wordt aangemaakt. Standaardmethode: PUT
  • Update Event: Wordt geactiveerd wanneer een reactie wordt bewerkt. Standaardmethode: PUT
  • Delete Event: Wordt geactiveerd wanneer een reactie wordt verwijderd. Standaardmethode: DELETE

Elk evenement bevat de volledige reactiedata in de verzoekbody (zie Gegevensstructuren voor het payload-formaat).

Datastructuren Internal Link

De enige structuur die via webhooks wordt verzonden is het WebhookComment-object, hieronder in TypeScript uiteengezet.

De structuur van het WebhookComment-object

De structuur van het "Create"-event

Het request body van het "create" event is een WebhookComment-object.

De structuur van het "Update"-event

Het request body van het "update" event is een WebhookComment-object.

De structuur van het "Delete"-event

Het request body van het "delete" event is een WebhookComment-object.

Wijziging per 14 nov 2023
Voorheen bevatte het request body van het "delete" event alleen de comment id. Het bevat nu de volledige opmerking op het moment van verwijdering.
Het WebhookComment-object
Copy CopyRun External Link
1
2interface WebhookComment {
3 /** De id van de opmerking. **/
4 id: string
5 /** De id of URL die de commentdraad identificeert. Genormaliseerd. **/
6 urlId: string
7 /** De URL die wijst naar waar de opmerking is achtergelaten. **/
8 url?: string
9 /** De gebruikers-id die de opmerking heeft geplaatst. Bij SSO voorafgegaan door de tenant-id. **/
10 userId?: string
11 /** Het e-mailadres van de gebruiker die de opmerking plaatste. **/
12 commenterEmail?: string
13 /** De naam van de gebruiker die in de comment-widget wordt weergegeven. Bij SSO kan dit displayName zijn. **/
14 commenterName: string
15 /** Ruwe tekst van de opmerking. **/
16 comment: string
17 /** Tekst van de opmerking na verwerking. **/
18 commentHTML: string
19 /** Externe id van de opmerking. **/
20 externalId?: string
21 /** De id van de bovenliggende opmerking. **/
22 parentId?: string | null
23 /** De UTC-datum waarop de opmerking is geplaatst. **/
24 date: UTC_ISO_DateString
25 /** Gecombineerde karma (up - down) van stemmen. **/
26 votes: number
27 votesUp: number
28 votesDown: number
29 /** Waar als de gebruiker was ingelogd toen hij reageerde, of als hij de opmerking heeft geverifieerd, of als hij zijn sessie had geverifieerd toen de opmerking werd geplaatst. **/
30 verified: boolean
31 /** Datum waarop de opmerking is geverifieerd. **/
32 verifiedDate?: number
33 /** Of een moderator de opmerking als beoordeeld heeft gemarkeerd. **/
34 reviewed: boolean
35 /** De locatie, of base64-codering, van de avatar. Zal alleen base64 zijn als dat de waarde was die bij SSO werd meegegeven. **/
36 avatarSrc?: string
37 /** Is de opmerking handmatig of automatisch als spam gemarkeerd? **/
38 isSpam: boolean
39 /** Is de opmerking automatisch als spam gemarkeerd? **/
40 aiDeterminedSpam: boolean
41 /** Bevat de opmerking afbeeldingen? **/
42 hasImages: boolean
43 /** Het paginanummer waarop de opmerking staat voor de sorteerrichting "Most Relevant". **/
44 pageNumber: number
45 /** Het paginanummer waarop de opmerking staat voor de sorteerrichting "Oldest First". **/
46 pageNumberOF: number
47 /** Het paginanummer waarop de opmerking staat voor de sorteerrichting "Newest First". **/
48 pageNumberNF: number
49 /** Is de opmerking automatisch of handmatig goedgekeurd? **/
50 approved: boolean
51 /** De lococode (formaat: en_us) van de gebruiker toen de opmerking werd geschreven. **/
52 locale: string
53 /** De @mentions in de opmerking die succesvol zijn geparsed. **/
54 mentions?: CommentUserMention[]
55 /** Het domein waar de opmerking vandaan komt. **/
56 domain?: string
57 /** De optionele lijst met moderatiegroep-ids die aan deze opmerking zijn gekoppeld. **/
58 moderationGroupIds?: string[]|null
59}
60

Wanneer gebruikers worden getagd in een opmerking, wordt die informatie opgeslagen in een lijst genaamd mentions. Elk object in die lijst heeft de volgende structuur.

Het Webhook Mentions-object
Copy CopyRun External Link
1
2interface CommentUserMention {
3 /** De gebruikers-id. Voor SSO-gebruikers wordt hier uw tenant-id aan voorafgegaan. **/
4 id: string
5 /** De uiteindelijke @mention-tagtekst, inclusief het @-symbool. **/
6 tag: string
7 /** De oorspronkelijke @mention-tagtekst, inclusief het @-symbool. **/
8 rawTag: string
9 /** Welk type gebruiker werd genoemd. user = FastComments.com-account. sso = SSOUser. **/
10 type: 'user'|'sso'
11 /** Als de gebruiker zich afmeldt voor meldingen, blijft dit toch op true staan. **/
12 sent: boolean
13}
14

HTTP-methoden

U kunt de HTTP-methode voor elk webhook-eventtype configureren in het beheerpaneel:

  • Create Event: POST of PUT (standaard: PUT)
  • Update Event: POST of PUT (standaard: PUT)
  • Delete Event: DELETE, POST of PUT (standaard: DELETE)

Aangezien alle verzoeken een ID bevatten, zijn Create- en Update-bewerkingen standaard idempotent (PUT). Het herhalen van hetzelfde Create- of Update-verzoek zou geen dubbele objecten aan uw kant moeten aanmaken.

Request Headers

Elk webhook-verzoek bevat de volgende headers:

Header Beschrijving
Content-Type application/json
token Your API Secret
X-FastComments-Timestamp Unix timestamp (seconds) when the request was signed
X-FastComments-Signature HMAC-SHA256-handtekening (sha256=<hex>)

Zie Security & API Tokens voor informatie over het verifiëren van de HMAC-handtekening.

Beveiliging & API-tokens Internal Link

FastComments webhookverzoeken bevatten meerdere authenticatiemechanismen voor beveiliging.

Verzonden headers

Header Beschrijving
token Uw API Secret (voor achterwaartse compatibiliteit)
X-FastComments-Timestamp Unix-timestamp (seconden) wanneer het verzoek werd ondertekend
X-FastComments-Signature HMAC-SHA256-handtekening van de payload

HMAC-handtekeningverificatie (aanbevolen)

We raden sterk aan de HMAC-handtekening te verifiëren om ervoor te zorgen dat webhook-payloads authentiek zijn en niet zijn gewijzigd.

Handtekeningformaat: sha256=<hex-encoded-signature>

Hoe de handtekening wordt berekend:

  1. Samenvoegen: timestamp + "." + JSON_payload_body
  2. Bereken HMAC-SHA256 met uw API Secret als sleutel
  3. Hex-encodeer het resultaat

Voorbeeldverificatie (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;
    }

    // Controleer of de timestamp recent is (binnen 5 minuten)
    const now = Math.floor(Date.now() / 1000);
    if (Math.abs(now - parseInt(timestamp, 10)) > 300) {
        return false;  // Ter voorkoming van replay-aanvallen
    }

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

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

Voorbeeldverificatie (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

    # Controleer of de timestamp recent is
    now = int(time.time())
    if abs(now - int(timestamp)) > 300:
        return False

    # Verifieer handtekening
    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}"

Voorbeeldverificatie (PHP)

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

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

    // Controleer of de timestamp recent is (binnen 5 minuten)
    $now = time();
    if (abs($now - intval($timestamp)) > 300) {
        return false;
    }

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

    return hash_equals($expectedSignature, $signature);
}

Verouderde authenticatie

De token-header die uw API Secret bevat, wordt nog steeds verzonden voor achterwaartse compatibiliteit. We raden echter aan over te stappen op HMAC-verificatie voor verbeterde beveiliging, omdat dit beschermt tegen replay-aanvallen.


Tot slot

Hiermee is onze Webhooks-documentatie afgerond.

We hopen dat je de FastComments Webhook-integratie gemakkelijk te begrijpen vindt en snel kunt instellen.

Als je denkt dat er hiaten in onze documentatie zitten, laat het ons hieronder weten.