FastComments.com


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

Постигаме това с помощта на асинхронни webhooks по HTTP/HTTPS.

Какво представляват уебхуковете Internal Link


Уебхук е механизъм, или интеграция, между две системи, при която "произвеждащият" (FastComments) изпраща събитие което "потребителят" (Вие) обработва чрез API повикване.


Поддържани събития и ресурси Internal Link

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

Поддържаме уебхукове при създаване, премахване и при актуализация на коментари.

Всяко от тях се разглежда като отделно събитие в нашата система и поради това има различна семантика и различна структура за събитията на уебхуковете.

Тестване Internal Link

В админ панела за Webhooks има бутони Send Test Payload за всеки тип събитие (Create, Update, Delete). Събитията Create и Update изпращат фиктивен обект WebhookComment, докато при тест на Delete ще бъде изпратено фиктивно тяло на заявката, съдържащо само ID.

Проверка на payload-ите

Когато тествате интеграцията на вашия webhook, уверете се, че входящите заявки включват следните заглавки:

  1. token - Your API Secret
  2. X-FastComments-Timestamp - Unix timestamp (seconds)
  3. X-FastComments-Signature - HMAC-SHA256 signature

Използвайте проверката на HMAC подписа, за да се уверите, че payload-ите са автентични.

Инструменти за тестване

Можете да използвате инструменти като webhook.site или ngrok за да инспектирате входящите webhook payload-ове по време на разработка.

Типове събития

  • Create Event: Се задейства, когато е създаден нов коментар. По подразбиране метод: PUT
  • Update Event: Се задейства, когато коментарът бъде редактиран. По подразбиране метод: PUT
  • Delete Event: Се задейства, когато коментарът бъде изтрит. По подразбиране метод: DELETE

Всяко събитие включва пълните данни на коментара в тялото на заявката (виж Структури от данни за формата на payload-а).


Структури от данни Internal Link

Единствената структура, изпращана чрез уебхукове, е обектът 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 /** The id of the comment. **/
4 id: string
5 /** The id or URL that identifies the comment thread. Normalized. **/
6 urlId: string
7 /** The URL that points to where the comment was left. **/
8 url?: string
9 /** The user id that left the comment. If SSO, prefixed with tenant id. **/
10 userId?: string
11 /** The email of the user left the comment. **/
12 commenterEmail?: string
13 /** The name of the user that shows in the comment widget. With SSO, can be displayName. **/
14 commenterName: string
15 /** Raw comment text. **/
16 comment: string
17 /** Comment text after parsing. **/
18 commentHTML: string
19 /** Comment external id. **/
20 externalId?: string
21 /** The id of the parent comment. **/
22 parentId?: string | null
23 /** The UTC date when the comment was left. **/
24 date: UTC_ISO_DateString
25 /** Combined karma (up - down) of votes. **/
26 votes: number
27 votesUp: number
28 votesDown: number
29 /** True if the user was logged in when they commented, or their verified the comment, or if they verified their session when the comment was left. **/
30 verified: boolean
31 /** Date when the comment was verified. **/
32 verifiedDate?: number
33 /** If a moderator marked the comment reviewed. **/
34 reviewed: boolean
35 /** The location, or base64 encoding, of the avatar. Will only be base64 if that was the value passed with SSO. **/
36 avatarSrc?: string
37 /** Was the comment manually or automatically marked as spam? **/
38 isSpam: boolean
39 /** Was the comment automatically marked as spam? **/
40 aiDeterminedSpam: boolean
41 /** Are there images in the comment? **/
42 hasImages: boolean
43 /** The page number the comment is on for the "Most Relevant" sort direction. **/
44 pageNumber: number
45 /** The page number the comment is on for the "Oldest First" sort direction. **/
46 pageNumberOF: number
47 /** The page number the comment is on for the "Newest First" sort direction. **/
48 pageNumberNF: number
49 /** Was the comment approved automatically or manually? **/
50 approved: boolean
51 /** The locale code (format: en_us) of the user when the comment was written. **/
52 locale: string
53 /** The @mentions written in the comment that were successfully parsed. **/
54 mentions?: CommentUserMention[]
55 /** The domain the comment is from. **/
56 domain?: string
57 /** The optional list of moderation group ids associated with this comment. **/
58 moderationGroupIds?: string[]|null
59}
60

When users are tagged in a comment, the information is stored in a list called mentions. Each object in that list has the following structure.

Обектът за споменавания в Webhook
Copy CopyRun External Link
1
2interface CommentUserMention {
3 /** The user id. For SSO users, this will have your tenant id prefixed. **/
4 id: string
5 /** The final @mention tag text, including the @ symbol. **/
6 tag: string
7 /** The original @mention tag text, including the @ symbol. **/
8 rawTag: string
9 /** What type of user was tagged. user = FastComments.com account. sso = SSOUser. **/
10 type: 'user'|'sso'
11 /** If the user opts out of notifications, this will still be set to true. **/
12 sent: boolean
13}
14

HTTP Methods

Можете да конфигурирате HTTP метода за всеки тип уебхук събитие в администраторския панел:

  • Create Event: POST or PUT (default: PUT)
  • Update Event: POST or PUT (default: PUT)
  • Delete Event: DELETE, POST, or PUT (default: DELETE)

Тъй като всички заявки съдържат ID, операциите Create и Update са идемпотентни по подразбиране (PUT). Повтарянето на една и съща Create или Update заявка не трябва да създава дублирани обекти от ваша страна.

Request Headers

Всяка уебхук заявка включва следните хедъри:

Заглавка Описание
Content-Type application/json
token Your API Secret
X-FastComments-Timestamp Unix timestamp (seconds) when the request was signed
X-FastComments-Signature HMAC-SHA256 signature (sha256=<hex>)

Вижте Сигурност и API токени за информация относно проверката на HMAC подписа.

Сигурност и API токени Internal Link

FastComments webhook requests include multiple authentication mechanisms for security.

Изпращани заглавки

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

Силно препоръчваме да проверявате HMAC подписа, за да се уверите, че payload-ите на webhook-ите са автентични и не са били подправяни.

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

How the signature is computed:

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

Example Verification (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}`;
}

Example Verification (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}"

Example Verification (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 е лесна за разбиране и бърза за настройване.

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