FastComments.com


Sa FastComments moguće je pozvati API endpoint kad god se komentar doda, ažurira ili ukloni iz našeg sistema.

To ostvarujemo asinhronim webhooks preko HTTP/HTTPS.


Šta su webhookovi Internal Link

A Webhook je mehanizam, odnosno integracija, između dva sistema gde "proizvođač" (FastComments) okida događaj koji "potrošač" (Vi) preuzima putem API poziva.

Podržani događaji i resursi Internal Link

FastComments podržava webhookove samo za resurs Comment.

Podržavamo webhookove za kreiranje komentara, uklanjanje i ažuriranje.

Svaki od ovih smatra se zasebnim događajem u našem sistemu i kao takav ima različitu semantiku i strukturu za webhook događaje.

Testiranje Internal Link

U Webhooks admin postoje Send Test Payload dugmad za svaki tip događaja (Create, Update, Delete). Događaji Create i Update šalju dummy objekat WebhookComment, dok će testiranje Delete poslati dummy telo zahteva sa samo ID-jem.

Provera payload-ova

Prilikom testiranja vaše webhook integracije, proverite da dolazni zahtevi uključuju sledeće zaglavlja:

  1. token - Vaš API Secret
  2. X-FastComments-Timestamp - Unix timestamp (sekunde)
  3. X-FastComments-Signature - HMAC-SHA256 potpis

Koristite verifikaciju HMAC potpisa da biste osigurali da su payload-ovi autentični.

Alati za testiranje

Možete koristiti alate kao što su webhook.site ili ngrok da pregledate dolazne webhook payload-ove tokom razvoja.

Tipovi događaja

  • Create Event: Pokreće se kada je kreiran novi komentar. Podrazumevana metoda: PUT
  • Update Event: Pokreće se kada je komentar izmenjen. Podrazumevana metoda: PUT
  • Delete Event: Pokreće se kada je komentar obrisan. Podrazumevana metoda: DELETE

Svaki događaj uključuje kompletne podatke komentara u telu zahteva (pogledajte Strukture podataka za format payload-a).

Strukture podataka Internal Link

Jedina struktura koja se šalje putem webhooks je objekat WebhookComment, prikazan u TypeScript-u ispod.

Struktura objekta WebhookComment

Struktura događaja "Create"

Telo zahteva za događaj "create" je objekat WebhookComment.

Struktura događaja "Update"

Telo zahteva za događaj "update" je objekat WebhookComment.

Struktura događaja "Delete"

Telo zahteva za događaj "delete" je objekat WebhookComment.

Change as of Nov 14th 2023
Previously the "delete" event request body only contained the comment id. It now contains the full comment at the time of deletion.
Objekat WebhookComment
Copy CopyRun External Link
1
2interface WebhookComment {
3 /** ID komentara. **/
4 id: string
5 /** ID ili URL koji identifikuje nit komentara. Normalizovano. **/
6 urlId: string
7 /** URL koji pokazuje mesto gde je komentar ostavljen. **/
8 url?: string
9 /** ID korisnika koji je ostavio komentar. Ako je SSO, prefiksovan tenant id-jem. **/
10 userId?: string
11 /** Email korisnika koji je ostavio komentar. **/
12 commenterEmail?: string
13 /** Ime korisnika koje se prikazuje u widgetu za komentare. Sa SSO, može biti displayName. **/
14 commenterName: string
15 /** Neobrađeni tekst komentara. **/
16 comment: string
17 /** Tekst komentara posle parsiranja. **/
18 commentHTML: string
19 /** Eksterni ID komentara. **/
20 externalId?: string
21 /** ID roditeljskog komentara. **/
22 parentId?: string | null
23 /** UTC datum kada je komentar ostavljen. **/
24 date: UTC_ISO_DateString
25 /** Kombinovana vrednost glasova (za - protiv). **/
26 votes: number
27 votesUp: number
28 votesDown: number
29 /** True ako je korisnik bio ulogovan kada je komentarisao, ili ako je verifikovao komentar, ili ako je verifikovao sesiju kada je komentar ostavljen. **/
30 verified: boolean
31 /** Datum kada je komentar verifikovan. **/
32 verifiedDate?: number
33 /** Da li je moderator označio komentar kao pregledan. **/
34 reviewed: boolean
35 /** Lokacija ili base64 kodiranje avatara. Biće base64 samo ako je ta vrednost poslata sa SSO. **/
36 avatarSrc?: string
37 /** Da li je komentar ručno ili automatski označen kao spam? **/
38 isSpam: boolean
39 /** Da li je komentar automatski označen kao spam? **/
40 aiDeterminedSpam: boolean
41 /** Da li u komentaru ima slika? **/
42 hasImages: boolean
43 /** Broj stranice na kojoj se komentar nalazi za sortiranje "Most Relevant". **/
44 pageNumber: number
45 /** Broj stranice na kojoj se komentar nalazi za sortiranje "Oldest First". **/
46 pageNumberOF: number
47 /** Broj stranice na kojoj se komentar nalazi za sortiranje "Newest First". **/
48 pageNumberNF: number
49 /** Da li je komentar odobren automatski ili ručno? **/
50 approved: boolean
51 /** Kod lokalizacije (format: en_us) korisnika kada je komentar napisan. **/
52 locale: string
53 /** @pominjanja napisani u komentaru koja su uspešno parsirana. **/
54 mentions?: CommentUserMention[]
55 /** Domen odakle je komentar. **/
56 domain?: string
57 /** Opcionalna lista ID-jeva moderacijskih grupa povezanih sa ovim komentarom. **/
58 moderationGroupIds?: string[]|null
59}
60

Kada su korisnici označeni u komentaru, informacije se čuvaju u listi koja se zove mentions. Svaki objekat u toj listi ima sledeću strukturu.

Objekat Webhook Mentions
Copy CopyRun External Link
1
2interface CommentUserMention {
3 /** ID korisnika. Za SSO korisnike biće prefiksovan vašim tenant id-jem. **/
4 id: string
5 /** Konačan tekst @mention taga, uključujući simbol @. **/
6 tag: string
7 /** Originalni tekst @mention taga, uključujući simbol @. **/
8 rawTag: string
9 /** Koji tip korisnika je označen. user = FastComments.com account. sso = SSOUser. **/
10 type: 'user'|'sso'
11 /** Ako se korisnik isključi iz notifikacija, ovo će i dalje biti postavljeno na true. **/
12 sent: boolean
13}
14

HTTP metode

Možete konfigurisati HTTP metodu za svaki tip webhook događaja u administratorskom panelu:

  • Create Event: POST ili PUT (podrazumevano: PUT)
  • Update Event: POST ili PUT (podrazumevano: PUT)
  • Delete Event: DELETE, POST, ili PUT (podrazumevano: DELETE)

Pošto svi zahtevi sadrže ID, Create i Update operacije su idempotentne po defaultu (PUT). Ponavljanje istog Create ili Update zahteva ne bi trebalo da kreira duplikate objekata kod vas.

Zaglavlja zahteva

Svaki webhook zahtev uključuje sledeća zaglavlja:

Zaglavlje Opis
Content-Type application/json
token Vaš API Secret
X-FastComments-Timestamp Unix vremenski pečat (sekunde) kada je zahtev potpisan
X-FastComments-Signature HMAC-SHA256 potpis (sha256=<hex>)

Pogledajte Bezbednost i API tokeni za informacije o verifikaciji HMAC potpisa.

Bezbednost i API tokeni Internal Link

FastComments webhook zahtevi uključuju više mehanizama autentifikacije radi bezbednosti.

Zaglavlja koja se šalju

Zaglavlje Opis
token Vaš API Secret (za unazadnu kompatibilnost)
X-FastComments-Timestamp Unix timestamp (sekunde) kada je zahtev potpisan
X-FastComments-Signature HMAC-SHA256 potpis payload-a

Verifikacija HMAC potpisa (Preporučeno)

Toplo preporučujemo verifikaciju HMAC potpisa kako biste osigurali da su webhook payload-ovi autentični i da nisu izmenjeni.

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

Kako se potpis izračunava:

  1. Sastavite: timestamp + "." + JSON_payload_body
  2. Izračunajte HMAC-SHA256 koristeći vaš API Secret kao ključ
  3. Hex-enkodirajte rezultat

Primer verifikacije (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;
    }

    // Proverite da je timestamp recentan (u roku od 5 minuta)
    const now = Math.floor(Date.now() / 1000);
    if (Math.abs(now - parseInt(timestamp, 10)) > 300) {
        return false;  // Prevencija replay napada
    }

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

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

Primer verifikacije (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

    # Proverite da je timestamp recentan
    now = int(time.time())
    if abs(now - int(timestamp)) > 300:
        return False

    # Proverite potpis
    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}"

Primer verifikacije (PHP)

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

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

    // Proverite da je timestamp recentan (u roku od 5 minuta)
    $now = time();
    if (abs($now - intval($timestamp)) > 300) {
        return false;
    }

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

    return hash_equals($expectedSignature, $signature);
}

Nasleđena autentifikacija

Zaglavlje token koje sadrži vaš API Secret se i dalje šalje za unazadnu kompatibilnost. Međutim, preporučujemo migraciju na HMAC verifikaciju za poboljšanu bezbednost, jer štiti od replay napada.


Zaključno

Ovim se završava naša Webhooks dokumentacija.

Nadamo se da ćete smatrati da je FastComments Webhook integracija jednostavna za razumevanje i brza za postavljanje.

Ako smatrate da ste uočili neke nedostatke u našoj dokumentaciji, obavestite nas u nastavku.