FastComments.com


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

Ovo postižemo asinhronim webhookovima preko HTTP/HTTPS.


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

A Webhook je mehanizam, odnosno integracija, između dva sistema gdje "proizvođač" (FastComments) pokreće događaj koji "potrošač" (Vi) konzumira putem API poziva.

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

FastComments подржава webhook-ове само за ресурс Comment.

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

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

Тестирање Internal Link

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

Верификација пейлоада

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

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

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

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

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

Врсте догађаја

  • Create Event: Покреће се када се креира нови коментар. Задана метода: PUT
  • Update Event: Покреће се када се коментар уреди. Задана метода: PUT
  • Delete Event: Покреће се када се коментар обрише. Задана метода: DELETE

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

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

Једина структура која се шаље преко webhook-ова је WebhookComment објекат, описан у TypeScript-у испод.

Структура WebhookComment објекта

Структура догађаја "create"

Тијело захтјева за догађај "create" је WebhookComment објекат.

Структура догађаја "update"

Тијело захтјева за догађај "update" је WebhookComment објекат.

Структура догађаја "delete"

Тијело захтјева за догађај "delete" је WebhookComment објекат.

Промјена од 14. новембра 2023.
Претходно је тијело захтјева за догађај "delete" садржало само id коментара. Сада садржи цео коментар у тренутку брисања.
Објекат WebhookComment
Copy CopyRun External Link
1
2interface WebhookComment {
3 /** Id коментара. **/
4 id: string
5 /** Id или URL који идентификује нит коментара. Нормализовано. **/
6 urlId: string
7 /** URL који показује гдје је коментар остављен. **/
8 url?: string
9 /** Id корисника који је оставио коментар. Ако је SSO, биће са префиксом tenant id. **/
10 userId?: string
11 /** Е-пошта корисника који је оставио коментар. **/
12 commenterEmail?: string
13 /** Име корисника које се приказује у видгету за коментаре. Код SSO може бити displayName. **/
14 commenterName: string
15 /** Сирови текст коментара. **/
16 comment: string
17 /** Текст коментара након парсирања. **/
18 commentHTML: string
19 /** Спољни id коментара. **/
20 externalId?: string
21 /** Id родитељског коментара. **/
22 parentId?: string | null
23 /** UTC датум када је коментар остављен. **/
24 date: UTC_ISO_DateString
25 /** Комбинована карма гласова (за - против). **/
26 votes: number
27 votesUp: number
28 votesDown: number
29 /** true ако је корисник био пријављен када је коментарисао, или је верификовао коментар, или ако је верификовао своју сесију када је коментар остављен. **/
30 verified: boolean
31 /** Датум када је коментар верификован. **/
32 verifiedDate?: number
33 /** Ако је модератор означио коментар као прегледан. **/
34 reviewed: boolean
35 /** Локација или base64 енкодовање аватара. Биће base64 само ако је та вриједност прослијеђена преко SSO. **/
36 avatarSrc?: string
37 /** Да ли је коментар ручно или аутоматски означен као спам? **/
38 isSpam: boolean
39 /** Да ли је коментар аутоматски означен као спам? **/
40 aiDeterminedSpam: boolean
41 /** Да ли коментар садржи слике? **/
42 hasImages: boolean
43 /** Број странице на којој се коментар налази за смер сортирања "Most Relevant". **/
44 pageNumber: number
45 /** Број странице на којој се коментар налази за смер сортирања "Oldest First". **/
46 pageNumberOF: number
47 /** Број странице на којој се коментар налази за смер сортирања "Newest First". **/
48 pageNumberNF: number
49 /** Да ли је коментар одобрен аутоматски или ручно? **/
50 approved: boolean
51 /** Локални код (формат: en_us) корисника када је коментар написан. **/
52 locale: string
53 /** @mentions написани у коментару који су успјешно парсирани. **/
54 mentions?: CommentUserMention[]
55 /** Домен са којег долази коментар. **/
56 domain?: string
57 /** Опциона листа id-ева група за модерирање повезаних са овим коментаром. **/
58 moderationGroupIds?: string[]|null
59}
60

Када су корисници означени у коментару, информације се чувају у листи названој mentions. Сваки објекат у тој листи има сљедећу структуру.

Објекат спомињања у webhook-у
Copy CopyRun External Link
1
2interface CommentUserMention {
3 /** Id корисника. За SSO кориснике, биће са префиксом tenant id. **/
4 id: string
5 /** Коначни текст @mention тега, укључујући @ симбол. **/
6 tag: string
7 /** Оригинални текст @mention тега, укључујући @ симбол. **/
8 rawTag: string
9 /** Који тип корисника је означен. user = FastComments.com налог. sso = SSOUser. **/
10 type: 'user'|'sso'
11 /** Ако се корисник одјави са нотификација, ово ће ипак бити постављено на true. **/
12 sent: boolean
13}
14

HTTP методе

Можете конфигурисати HTTP метод за сваки тип webhook догађаја у административном панелу:

  • Догађај "create": POST или PUT (подразумевано: PUT)
  • Догађај "update": POST или PUT (подразумевано: PUT)
  • Догађај "delete": DELETE, POST или PUT (подразумевано: DELETE)

Пошто сви захтјеви садрже ID, операције креирања и ажурирања су подразумевано идемпотентне (PUT). Понављање истог захтјева за креирање или ажурирање не би требало да створи дупликате на вашој страни.

Заглавља захтјева

Сваки webhook захтјев садржи сљедећа заглавља:

Header Description
Content-Type application/json
token Ваш API тајни кључ
X-FastComments-Timestamp Unix временска ознака (секунде) када је захтјев потписан
X-FastComments-Signature HMAC-SHA256 потпис (sha256=<hex>)

Погледајте Сигурност и API токени за информације о провјери HMAC потписа.

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

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

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

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

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

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

Формат потписа: 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 верификацију ради побољшане безбједности јер штити од поновљених напада.


Zaključak

Ovo zaključuje našu dokumentaciju za Webhooks.

Nadamo se da je FastComments Webhook integracija laka za razumijevanje i brza za postavljanje.

Ako smatrate da ste uočili bilo kakve nedostatke u našoj dokumentaciji, obavijestite nas u nastavku.