FastComments.com


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

Ово постигавамо асинхроним вебхуковима преко HTTP/HTTPS.

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

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

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

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

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

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

Тестирање Internal Link

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

Верификација података захтева

Приликом тестирања ваше webhook интеграције, провјерите да долазни захтјеви садрже сљедећа заглавља:

  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

Једина структура која се шаље преко 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 /** Идентификатор коментара. **/
4 id: string
5 /** Ид или URL који идентификује нит коментара. Нормализовано. **/
6 urlId: string
7 /** URL који показује гдје је коментар остављен. **/
8 url?: string
9 /** Ид корисника који је оставио коментар. Ако је 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 /** Ид родитељског коментара. **/
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 /** Ид корисника. За SSO кориснике, биће са префиксом tenant id. **/
4 id: string
5 /** Коначни @mention таг текст, укључујући @ симбол. **/
6 tag: string
7 /** Оригинални @mention таг текст, укључујући @ симбол. **/
8 rawTag: string
9 /** Који тип корисника је тагован. user = FastComments.com account. 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)

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

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

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

Заглавље Опис
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 потпис података (payload)

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

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

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

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

  1. Concatenate: timestamp + "." + JSON_payload_body
  2. Compute HMAC-SHA256 using your API Secret as the key
  3. Hex-encode the result

Пример верификације (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 интеграција лака за разумјевање и брза за подешавање.

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