FastComments.com


FastComments ile sistemimizde bir yorum eklendiğinde, güncellendiğinde veya kaldırıldığında bir API endpoint'i çağırmak mümkündür.

Bunu HTTP/HTTPS üzerinden asenkron webhooks ile gerçekleştiriyoruz.


Webhook'lar Nedir? Internal Link


Webhook, iki sistem arasında bir mekanizma veya entegrasyon olup "üretici" (FastComments) bir olay tetikler ve "tüketici" (Siz) bu olayı bir API çağrısı ile tüketir.


Desteklenen Olaylar ve Kaynaklar Internal Link

FastComments yalnızca Comment kaynağı için webhookları destekler.

Yorum oluşturma, silme ve güncelleme için webhookları destekliyoruz.

Her biri sistemimizde ayrı olaylar olarak kabul edilir ve bu nedenle webhook olayları için farklı semantiklere ve yapılara sahiptir.

Test Etme Internal Link

Webhooks yönetiminde her olay türü (Oluşturma, Güncelleme, Silme) için Send Test Payload düğmeleri vardır. Oluşturma ve Güncelleme olayları sahte bir WebhookComment nesnesi gönderir, Silme'yi test ederken ise yalnızca bir ID içeren sahte bir istek gövdesi gönderilir.

Yükleri Doğrulama

Webhook entegrasyonunuzu test ederken, gelen isteklerin aşağıdaki başlıkları içerdiğini doğrulayın:

  1. token - API Gizli Anahtarınız
  2. X-FastComments-Timestamp - Unix zaman damgası (saniye)
  3. X-FastComments-Signature - HMAC-SHA256 imzası

Yüklerin gerçekliğini sağlamak için HMAC imza doğrulamasını kullanın.

Test Araçları

Geliştirme sırasında gelen webhook yüklerini incelemek için webhook.site veya ngrok gibi araçları kullanabilirsiniz.

Olay Türleri

  • Oluşturma Olayı: Yeni bir yorum oluşturulduğunda tetiklenir. Varsayılan yöntem: PUT
  • Güncelleme Olayı: Bir yorum düzenlendiğinde tetiklenir. Varsayılan yöntem: PUT
  • Silme Olayı: Bir yorum silindiğinde tetiklenir. Varsayılan yöntem: DELETE

Her olay, istek gövdesinde tam yorum verisini içerir (yük formatı için bkz. Veri Yapıları).

Veri Yapıları Internal Link

Webhook'lar aracılığıyla gönderilen tek yapı aşağıda TypeScript olarak özetlenen WebhookComment nesnesidir.

WebhookComment Nesnesi Yapısı

"Create" Olay Yapısı

"create" olayının istek gövdesi bir WebhookComment nesnesidir.

"Update" Olay Yapısı

"update" olayının istek gövdesi bir WebhookComment nesnesidir.

"Delete" Olay Yapısı

"delete" olayının istek gövdesi bir WebhookComment nesnesidir.

14 Kasım 2023 tarihi itibarıyla değişiklik
Önceden "delete" olayının istek gövdesi yalnızca yorum id'sini içeriyordu. Artık silinme anındaki tam yorumu içeriyor.
WebhookComment Nesnesi
Copy CopyRun External Link
1
2interface WebhookComment {
3 /** Yorumun id'si. **/
4 id: string
5 /** Yorum dizisini tanımlayan id veya URL. Normalleştirilmiş. **/
6 urlId: string
7 /** Yorumun bırakıldığı yere işaret eden URL. **/
8 url?: string
9 /** Yorumu bırakan kullanıcı id'si. SSO ise tenant id ile öneklenmiş olur. **/
10 userId?: string
11 /** Yorumu bırakan kullanıcının e-postası. **/
12 commenterEmail?: string
13 /** Yorum bileşeninde görünen kullanıcı adı. SSO ile displayName olabilir. **/
14 commenterName: string
15 /** Ham yorum metni. **/
16 comment: string
17 /** Ayrıştırıldıktan sonra yorum metni. **/
18 commentHTML: string
19 /** Yorumun harici id'si. **/
20 externalId?: string
21 /** Üst yorumun id'si. **/
22 parentId?: string | null
23 /** Yorumun bırakıldığı UTC tarihi. **/
24 date: UTC_ISO_DateString
25 /** Oyların birleşik karması (yukarı - aşağı). **/
26 votes: number
27 votesUp: number
28 votesDown: number
29 /** Kullanıcı yorumu yazarken giriş yaptıysa, yorumu doğruladıysa veya yorum bırakılırken oturumunu doğruladıysa true. **/
30 verified: boolean
31 /** Yorumun doğrulandığı tarih. **/
32 verifiedDate?: number
33 /** Moderatörün yorumu incelendi olarak işaretleyip işaretlemediği. **/
34 reviewed: boolean
35 /** Avatarın konumu veya base64 kodlaması. Sadece SSO ile base64 olarak gönderildiyse base64 olacaktır. **/
36 avatarSrc?: string
37 /** Yorum manuel mi yoksa otomatik olarak spam olarak mı işaretlendi? **/
38 isSpam: boolean
39 /** Yorum otomatik olarak spam olarak mı işaretlendi? **/
40 aiDeterminedSpam: boolean
41 /** Yorumda resimler var mı? **/
42 hasImages: boolean
43 /** Yorumun "En İlgili" sıralama yönü için bulunduğu sayfa numarası. **/
44 pageNumber: number
45 /** Yorumun "En Eski İlk" sıralama yönü için bulunduğu sayfa numarası. **/
46 pageNumberOF: number
47 /** Yorumun "En Yeni İlk" sıralama yönü için bulunduğu sayfa numarası. **/
48 pageNumberNF: number
49 /** Yorum otomatik olarak mı yoksa manuel olarak mı onaylandı? **/
50 approved: boolean
51 /** Yorum yazıldığında kullanıcının yerel kodu (format: en_us). **/
52 locale: string
53 /** Yorumda yazılan ve başarıyla ayrıştırılan @mention'lar. **/
54 mentions?: CommentUserMention[]
55 /** Yorumun geldiği alan adı. **/
56 domain?: string
57 /** Bu yorumla ilişkili isteğe bağlı moderasyon grup id'lerinin listesi. **/
58 moderationGroupIds?: string[]|null
59}
60

Kullanıcılar bir yorumda etiketlendiğinde, bilgiler mentions adlı bir listede saklanır. Bu listedeki her nesnenin yapısı aşağıdaki gibidir.

Webhook Mention Nesnesi
Copy CopyRun External Link
1
2interface CommentUserMention {
3 /** Kullanıcı id'si. SSO kullanıcıları için tenant id ile öneklenmiş olacaktır. **/
4 id: string
5 /** Son @mention etiket metni, @ sembolü dahil. **/
6 tag: string
7 /** Orijinal @mention etiket metni, @ sembolü dahil. **/
8 rawTag: string
9 /** Hangi tür kullanıcı etiketlendi. user = FastComments.com hesabı. sso = SSOUser. **/
10 type: 'user'|'sso'
11 /** Kullanıcı bildirimlerden çıkmış olsa bile bu yine de true olarak ayarlanır. **/
12 sent: boolean
13}
14

HTTP Yöntemleri

Her webhook olay türü için HTTP metodunu yönetici panelinden yapılandırabilirsiniz:

  • Oluşturma Olayı: POST veya PUT (varsayılan: PUT)
  • Güncelleme Olayı: POST veya PUT (varsayılan: PUT)
  • Silme Olayı: DELETE, POST veya PUT (varsayılan: DELETE)

Tüm istekler bir ID içerdiğinden, Create ve Update işlemleri varsayılan olarak idempotenttir (PUT). Aynı Create veya Update isteğinin tekrarlanması, tarafınızda çift nesneler oluşturmamalıdır.

İstek Başlıkları

Her webhook isteği aşağıdaki başlıkları içerir:

Başlık Açıklama
Content-Type application/json
token API Gizli Anahtarınız
X-FastComments-Timestamp İsteğin imzalandığı Unix zaman damgası (saniye)
X-FastComments-Signature HMAC-SHA256 imzası (sha256=<hex>)

HMAC imzasını doğrulama hakkında bilgi için Güvenlik ve API Jetonları sayfasına bakın.

Güvenlik ve API Jetonları Internal Link

FastComments webhook istekleri güvenlik için birden fazla kimlik doğrulama mekanizması içerir.

Gönderilen Başlıklar

Header Açıklama
token API Gizli Anahtarınız (geriye dönük uyumluluk için)
X-FastComments-Timestamp İsteğin imzalandığı Unix zaman damgası (saniye)
X-FastComments-Signature Gönderinin HMAC-SHA256 imzası

HMAC İmza Doğrulaması (Önerilen)

Webhook gönderilerinin orijinal ve değiştirilmemiş olduğunu sağlamak için HMAC imzasını doğrulamanızı şiddetle tavsiye ederiz.

İmza Formatı: sha256=<hex-encoded-signature>

İmzanın nasıl hesaplandığı:

  1. Birleştir: timestamp + "." + JSON_payload_body
  2. Anahtar olarak API Gizli Anahtarınızı kullanarak HMAC-SHA256 hesaplayın
  3. Sonucu hexadecimal (hex) olarak kodlayın

Doğrulama Örneği (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;
    }

    // Zaman damgasının güncel olduğunu doğrula (5 dakika içinde)
    const now = Math.floor(Date.now() / 1000);
    if (Math.abs(now - parseInt(timestamp, 10)) > 300) {
        return false;  // Tekrar oynatma (replay) saldırılarını önlemek için
    }

    // İmzayı doğrula
    const payload = JSON.stringify(req.body);
    const expectedSignature = crypto
        .createHmac('sha256', apiSecret)
        .update(`${timestamp}.${payload}`)
        .digest('hex');

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

Doğrulama Örneği (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

    # Zaman damgasının güncel olduğunu doğrula
    now = int(time.time())
    if abs(now - int(timestamp)) > 300:
        return False

    # İmzayı doğrula
    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}"

Doğrulama Örneği (PHP)

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

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

    // Zaman damgasının güncel olduğunu doğrula (5 dakika içinde)
    $now = time();
    if (abs($now - intval($timestamp)) > 300) {
        return false;
    }

    // İmzayı doğrula
    $payload = json_encode($body, JSON_UNESCAPED_SLASHES);
    $message = $timestamp . '.' . $payload;
    $expectedSignature = 'sha256=' . hash_hmac('sha256', $message, $apiSecret);

    return hash_equals($expectedSignature, $signature);
}

Eski Kimlik Doğrulama

token başlığı, API Gizli Anahtarınızı içeren, geriye dönük uyumluluk için hâlâ gönderilmektedir. Ancak, tekrar oynatma saldırılarına karşı koruma sağladığı için geliştirilmiş güvenlik için HMAC doğrulamasına geçmenizi öneririz.


Sonuç olarak

Bu, Webhooks belgelerimizin sonudur.

Umarız FastComments Webhook entegrasyonunu anlaşılması kolay ve kurulumu hızlı bulursunuz.

Belgelerimizde herhangi bir boşluk tespit ettiğinizi düşünüyorsanız, lütfen aşağıdan bize bildirin.