FastComments.com


Са FastComments-ом могуће је позвати API endpoint кад год се коментар дода, ажурира или уклони из нашег система.

Ово остварујемо помоћу асинхроних webhooks преко HTTP/HTTPS.


Шта су вебхукови Internal Link

Webhook је механизам, или интеграција, између два система где "произвођач" (FastComments) покреће догађај који "потрошач" (Ви) прима путем API позива.

Подржани догађаји и ресурси Internal Link


FastComments подржава вебхукове само за ресурс Comment.

Подржавамо вебхукове за креирање, уклањање и ажурирање коментара.

Сваки од њих се сматра посебним догађајем у нашем систему и као такав има различиту семантику и структуру догађаја вебхука.


Тестирање Internal Link

У администраторском интерфејсу Webhooks-а налазе се дугмад Send Test Payload за сваки тип догађаја (Create, Update, Delete). Create и Update догађаји шаљу пример WebhookComment објекта, док тестирање Delete шаље пример тела захтева које садржи само ID.

Верификација садржаја захтева

Када тестирате интеграцију вебхука, проверите да долазни захтеви садрже следећа заглавља:

  1. token - Ваш API секрет
  2. X-FastComments-Timestamp - Unix временска ознака (у секундама)
  3. X-FastComments-Signature - HMAC-SHA256 потпис

Користите верификацију HMAC потписа да бисте осигурали да су подаци аутентични.

Алати за тестирање

Можете користити алате као што су webhook.site или ngrok да прегледате долазне податке вебхука током развоја.

Типови догађаја

  • Create Event: Окида се када је креиран нови коментар. Подразумевани метод: PUT
  • Update Event: Окида се када је коментар измењен. Подразумевани метод: PUT
  • Delete Event: Окида се када је коментар обрисан. Подразумевани метод: DELETE

Сваки догађај укључује целокупне податке коментара у телу захтева (погледајте Структуре података за формат података).


Структуре података Internal Link

Jedina struktura koja se šalje putem webhook-ova 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.

Promena od 14. novembra 2023.
Ranije 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 za komentare. Kod SSO, može biti displayName. **/
14 commenterName: string
15 /** Sirovi 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 /** Kombinovana 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 enkodovanje avatara. Biće base64 samo ako je ta vrednost prosleđena sa SSO. **/
36 avatarSrc?: string
37 /** Da li je komentar manuelno 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 postoje slike u komentaru? **/
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 manuelno? **/
50 approved: boolean
51 /** Kod lokaliteta (format: en_us) korisnika kada je komentar napisan. **/
52 locale: string
53 /** The @mentions written in the comment that were successfully parsed. **/
54 mentions?: CommentUserMention[]
55 /** Domen odakle je komentar. **/
56 domain?: string
57 /** Opcionalna lista id-jeva grupa za moderaciju 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 pomena Webhook
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 /** Ko je tip korisnika koji 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 podrazumevanoj vrednosti (PUT). Ponavljanje istog Create ili Update zahteva ne bi trebalo da kreira duplikate objekata na vašoj strani.

Zaglavlja zahteva

Svaki webhook zahtev uključuje sledeća zaglavlja:

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

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

Безбедност и API токени Internal Link

FastComments webhook захтеви укључују више механизама аутентификације ради безбедности.

Заглавља која се шаљу

Заглавље Опис
token Ваш API Secret (ради уназадне компатибилности)
X-FastComments-Timestamp Unix временска ознака (у секундама) када је захтев потписан
X-FastComments-Signature HMAC-SHA256 потпис payload-а

Верификација HMAC потписа (Препоручено)

Снажно препоручујемо верификацију HMAC потписа како бисте били сигурни да су webhook payload-ови аутентични и да нису измењени.

Формат потписа: sha256=<hex-encoded-signature>

Како се потпис израчунава:

  1. Конкатенирајте: timestamp + "." + JSON_payload_body
  2. Израчунајте HMAC-SHA256 користећи ваш API Secret као кључ
  3. Хекс-енкодирајте резултат

Пример верификације (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;
    }

    // Проверите да ли је временска ознака свежа (у року од 5 минута)
    const now = Math.floor(Date.now() / 1000);
    if (Math.abs(now - parseInt(timestamp, 10)) > 300) {
        return false;  // Превенција replay напада
    }

    // Проверите потпис
    const payload = JSON.stringify(req.body);
    const expectedSignature = crypto
        .createHmac('sha256', apiSecret)
        .update(`${timestamp}.${payload}`)
        .digest('hex');

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

Пример верификације (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

    # Проверите да ли је временска ознака свежа
    now = int(time.time())
    if abs(now - int(timestamp)) > 300:
        return False

    # Проверите потпис
    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}"

Пример верификације (PHP)

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

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

    // Проверите да ли је временска ознака свежа (у року од 5 минута)
    $now = time();
    if (abs($now - intval($timestamp)) > 300) {
        return false;
    }

    // Проверите потпис
    $payload = json_encode($body, JSON_UNESCAPED_SLASHES);
    $message = $timestamp . '.' . $payload;
    $expectedSignature = 'sha256=' . hash_hmac('sha256', $message, $apiSecret);

    return hash_equals($expectedSignature, $signature);
}

Наслеђена аутентификација

Заглавље token које садржи ваш API Secret и даље се шаље ради уназадне компатибилности. Међутим, препоручујемо прелазак на HMAC верификацију због побољшане безбедности јер штити од replay напада.


У закључку

Овим се завршава наша Webhooks документација.

Надамо се да ће вам интеграција FastComments Webhook бити лака за разумевање и брза за подешавање.

Ако сматрате да сте пронашли било какве недостатке у нашој документацији, јавите нам у наставку.