FastComments.com

Με το FastComments είναι δυνατό να κληθεί ένα API endpoint κάθε φορά που ένα σχόλιο προστίθεται, ενημερώνεται ή αφαιρείται από το σύστημά μας.

Αυτό το επιτυγχάνουμε με ασύγχρονα webhooks μέσω HTTP/HTTPS.

Τι είναι τα Webhooks Internal Link

Ένα Webhook είναι ένας μηχανισμός, ή μια ενσωμάτωση, μεταξύ δύο συστημάτων όπου ο "παραγωγός" (FastComments) πυροδοτεί ένα συμβάν που ο "καταναλωτής" (Εσείς) καταναλώνει μέσω κλήσης API.

Υποστηριζόμενα Γεγονότα και Πόροι Internal Link


FastComments υποστηρίζει webhooks μόνο για το resource Comment.

Υποστηρίζουμε webhooks για τη δημιουργία σχολίου, την αφαίρεση και την ενημέρωση.

Κάθε ένα από αυτά θεωρείται ξεχωριστό συμβάν στο σύστημά μας και ως εκ τούτου έχουν διαφορετική σημασιολογία και δομή για τα συμβάντα webhook.


Δοκιμές Internal Link

Στο Webhooks admin υπάρχουν κουμπιά Send Test Payload για κάθε τύπο συμβάντος (Create, Update, Delete). Τα Create και Update συμβάντα στέλνουν ένα dummy αντικείμενο WebhookComment, ενώ η δοκιμή του Delete θα στείλει ένα dummy σώμα αιτήματος με μόνο ένα ID.

Verifying Payloads

Κατά τη δοκιμή της ενσωμάτωσης webhook, επαληθεύστε ότι τα εισερχόμενα αιτήματα περιλαμβάνουν τις ακόλουθες κεφαλίδες:

  1. token - Το μυστικό API σας
  2. X-FastComments-Timestamp - Unix χρονική σφραγίδα (δευτερόλεπτα)
  3. X-FastComments-Signature - HMAC-SHA256 υπογραφή

Χρησιμοποιήστε την επαλήθευση υπογραφής HMAC για να διασφαλίσετε ότι τα payloads είναι γνήσια.

Testing Tools

Μπορείτε να χρησιμοποιήσετε εργαλεία όπως webhook.site ή ngrok για να εξετάσετε τα εισερχόμενα payloads webhook κατά την ανάπτυξη.

Event Types

  • Create Event: Προκαλείται όταν δημιουργείται ένα νέο σχόλιο. Προεπιλεγμένη μέθοδος: PUT
  • Update Event: Προκαλείται όταν επεξεργάζεται ένα σχόλιο. Προεπιλεγμένη μέθοδος: PUT
  • Delete Event: Προκαλείται όταν διαγράφεται ένα σχόλιο. Προεπιλεγμένη μέθοδος: DELETE

Κάθε συμβάν περιλαμβάνει τα πλήρη δεδομένα του σχολίου στο σώμα του αιτήματος (βλέπε Data Structures για τη μορφή του payload).


Δομές δεδομένων Internal Link

Η μόνη δομή που αποστέλλεται μέσω webhooks είναι το αντικείμενο 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 /** Το email του χρήστη που άφησε το σχόλιο. **/
12 commenterEmail?: string
13 /** Το όνομα του χρήστη που εμφανίζεται στο widget σχολίων. Με 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 /** Συνδυασμένο karma (up - down) των ψήφων. **/
26 votes: number
27 votesUp: number
28 votesDown: number
29 /** True αν ο χρήστης ήταν συνδεδεμένος όταν σχολίασε, ή αν επικύρωσε το σχόλιο, ή αν επικύρωσε τη συνεδρία του όταν γράφτηκε το σχόλιο. **/
30 verified: boolean
31 /** Η ημερομηνία κατά την οποία το σχόλιο επικυρώθηκε. **/
32 verifiedDate?: number
33 /** Αν ένας moderator σήμανε το σχόλιο ως ελεγμένο. **/
34 reviewed: boolean
35 /** Η τοποθεσία, ή η κωδικοποίηση base64, του avatar. Θα είναι base64 μόνο αν αυτή ήταν η τιμή που περάστηκε με SSO. **/
36 avatarSrc?: string
37 /** Το σχόλιο επισημάνθηκε χειροκίνητα ή αυτόματα ως spam; **/
38 isSpam: boolean
39 /** Το σχόλιο επισημάνθηκε αυτόματα ως spam; **/
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 /** Οι @αναφορές που γράφτηκαν στο σχόλιο και αναλύθηκαν/επεξεργάστηκαν επιτυχώς. **/
54 mentions?: CommentUserMention[]
55 /** Το domain από το οποίο προέρχεται το σχόλιο. **/
56 domain?: string
57 /** Η προαιρετική λίστα με moderation group ids που σχετίζονται με αυτό το σχόλιο. **/
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.

Το αντικείμενο Mentions του Webhook
Copy CopyRun External Link
1
2interface CommentUserMention {
3 /** Το id χρήστη. Για χρήστες SSO, θα έχει το tenant id ως πρόθεμα. **/
4 id: string
5 /** Το τελικό κείμενο του @mention tag, συμπεριλαμβανομένου του συμβόλου @. **/
6 tag: string
7 /** Το αρχικό κείμενο του @mention tag, συμπεριλαμβανομένου του συμβόλου @. **/
8 rawTag: string
9 /** Τι τύπου χρήστης αναφέρθηκε. user = λογαριασμός FastComments.com. sso = SSOUser. **/
10 type: 'user'|'sso'
11 /** Αν ο χρήστης απενεργοποιήσει τις ειδοποιήσεις, αυτό θα παραμείνει αληθές. **/
12 sent: boolean
13}
14

Μέθοδοι HTTP

Μπορείτε να ρυθμίσετε τη μέθοδο HTTP για κάθε τύπο συμβάντος webhook στο admin panel:

  • Create Event: POST ή PUT (προεπιλογή: PUT)
  • Update Event: POST ή PUT (προεπιλογή: PUT)
  • Delete Event: DELETE, POST ή PUT (προεπιλογή: DELETE)

Εφόσον όλα τα αιτήματα περιέχουν ένα ID, οι λειτουργίες Create και Update είναι idempotent από προεπιλογή (PUT). Η επανάληψη του ίδιου αιτήματος Create ή Update δεν θα πρέπει να δημιουργεί διπλότυπα αντικείμενα στην πλευρά σας.

Κεφαλίδες Αιτήματος

Κάθε αίτημα webhook περιλαμβάνει τις ακόλουθες κεφαλίδες:

Κεφαλίδα Περιγραφή
Content-Type application/json
token Το API Secret σας
X-FastComments-Timestamp Unix χρονοσφραγίδα (δευτερόλεπτα) όταν υπογράφηκε το αίτημα
X-FastComments-Signature Υπογραφή HMAC-SHA256 (sha256=<hex>)

Δείτε Security & API Tokens για πληροφορίες σχετικά με την επαλήθευση της υπογραφής HMAC.


Ασφάλεια και Διακριτικά API Internal Link


Τα αιτήματα webhook του FastComments περιλαμβάνουν πολλούς μηχανισμούς πιστοποίησης για λόγους ασφάλειας.

Κεφαλίδες που αποστέλλονται

Κεφαλίδα Περιγραφή
token Το API Secret σας (για συμβατότητα προς τα πίσω)
X-FastComments-Timestamp Unix timestamp (δευτερόλεπτα) όταν υπογράφηκε το αίτημα
X-FastComments-Signature HMAC-SHA256 υπογραφή του payload

Επαλήθευση Υπογραφής HMAC (Συνιστάται)

Συνιστούμε θερμά την επαλήθευση της υπογραφής HMAC για να διασφαλίσετε ότι τα payloads των webhook είναι αυθεντικά και δεν έχουν παραποιηθεί.

Signature Format: 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;
    }

    // Επαλήθευση ότι το timestamp είναι πρόσφατο (εντός 5 λεπτών)
    const now = Math.floor(Date.now() / 1000);
    if (Math.abs(now - parseInt(timestamp, 10)) > 300) {
        return false;  // Πρόληψη επίθεσης επανάληψης
    }

    // Επαλήθευση υπογραφής
    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

    # Επαλήθευση ότι το timestamp είναι πρόσφατο
    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;
    }

    // Επαλήθευση ότι το timestamp είναι πρόσφατο (εντός 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 για βελτιωμένη ασφάλεια καθώς προστατεύει από επιθέσεις επανάληψης.


Συμπερασματικά

Με αυτό ολοκληρώνεται η τεκμηρίωση των Webhooks.

Ελπίζουμε να βρείτε την ενσωμάτωση Webhook του FastComments εύκολη στην κατανόηση και γρήγορη στη ρύθμιση.

Εάν πιστεύετε ότι έχετε εντοπίσει κενά στην τεκμηρίωσή μας, ενημερώστε μας παρακάτω.