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 administratorskom delu za Webhooks postoje Send Test Payload dugmad za svaki tip događaja (Create, Update, Delete). Create i Update događaji šalju probni objekat WebhookComment, dok testiranje Delete šalje testno telo zahteva sa samo ID-jem.

Provera payload-ova

Prilikom testiranja vaše webhook integracije, proverite da dolazni zahtevi sadrže sledeća zaglavlja:

  1. token - Vaš API tajni ključ
  2. X-FastComments-Timestamp - Unix vremenska oznaka (sekunde)
  3. X-FastComments-Signature - HMAC-SHA256 potpis

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

Alati za testiranje

Možete koristiti alate kao što su webhook.site ili ngrok za pregled dolaznih webhook payload-ova tokom razvoja.

Tipovi događaja

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

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


Strukture podataka Internal Link

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

Struktura objekta WebhookComment

Struktura događaja "create"

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

Struktura događaja "update"

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

Struktura događaja "delete"

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

Promena od 14. novembra 2023.
Prethodno je telo zahteva za događaj "delete" sadržavalo samo id komentara. Sada sadrži ceo komentar u trenutku brisanja.
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 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 komentara. Kod SSO, može biti displayName. **/
14 commenterName: string
15 /** Sirov tekst komentara. **/
16 comment: string
17 /** Tekst komentara nakon 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 /** Kombinovani karma (up - down) glasova. **/
26 votes: number
27 votesUp: number
28 votesDown: number
29 /** True ako je korisnik bio prijavljen kada je komentarisao, ili je verifikovao komentar, ili je verifikovao svoju sesiju kada je komentar ostavljen. **/
30 verified: boolean
31 /** Datum kada je komentar verifikovan. **/
32 verifiedDate?: number
33 /** Ako je moderator označio komentar kao pregledan. **/
34 reviewed: boolean
35 /** Lokacija, ili base64 enkodiranje avatara. Biće base64 samo ako je ta vrednost prosleđena sa SSO. **/
36 avatarSrc?: string
37 /** Da li je komentar označen kao spam ručno ili automatski? **/
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 smer sortiranja "Most Relevant". **/
44 pageNumber: number
45 /** Broj stranice na kojoj se komentar nalazi za smer sortiranja "Oldest First". **/
46 pageNumberOF: number
47 /** Broj stranice na kojoj se komentar nalazi za smer sortiranja "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 /** @mentions napisani u komentaru koji su uspešno parsirani. **/
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 nazvanoj 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 /** Finalni 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 nalog. sso = SSOUser. **/
10 type: 'user'|'sso'
11 /** Ako se korisnik odjavi od 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 podrazumevanju (PUT). Ponavljanje istog Create ili Update zahteva ne bi trebalo da stvori duplikate objekata na vašoj strani.

Zaglavlja zahteva

Svaki webhook zahtev sadrži sledeća zaglavlja:

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

Pogledajte Security & API Tokens 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.