FastComments.com


Avec FastComments, il est possible d'appeler un point de terminaison d'API chaque fois qu'un commentaire est ajouté, mis à jour ou supprimé de notre système.

Nous y parvenons grâce à des webhooks asynchrones via HTTP/HTTPS.


Qu'est-ce qu'un webhook ? Internal Link

Un Webhook est un mécanisme, ou une intégration, entre deux systèmes où le "producteur" (FastComments) déclenche un événement que le "consommateur" (Vous) consomme via un appel d'API.

Événements et ressources pris en charge Internal Link


FastComments prend en charge les webhooks uniquement pour la ressource Comment.

Nous prenons en charge les webhooks pour la création, la suppression et la mise à jour des commentaires.

Chacun d'entre eux est considéré comme un événement distinct dans notre système et, en tant que tel, possède des sémantiques différentes et des structures différentes pour les événements webhook.


Tests Internal Link


Dans l'administration Webhooks il y a des boutons Send Test Payload pour chaque type d'événement (Create, Update, Delete). Les événements Create et Update envoient un objet WebhookComment factice, tandis que le test Delete enverra un corps de requête factice contenant juste un ID.

Vérification des charges utiles

Lorsque vous testez votre intégration de webhook, vérifiez que les requêtes entrantes incluent les en-têtes suivants :

  1. token - Votre secret API
  2. X-FastComments-Timestamp - horodatage Unix (secondes)
  3. X-FastComments-Signature - signature HMAC-SHA256

Utilisez la vérification de la signature HMAC pour garantir que les charges utiles sont authentiques.

Outils de test

Vous pouvez utiliser des outils comme webhook.site ou ngrok pour inspecter les charges utiles entrantes des webhooks pendant le développement.

Types d'événements

  • Create Event: Déclenché lorsqu'un nouveau commentaire est créé. Méthode par défaut : PUT
  • Update Event: Déclenché lorsqu'un commentaire est édité. Méthode par défaut : PUT
  • Delete Event: Déclenché lorsqu'un commentaire est supprimé. Méthode par défaut : DELETE

Chaque événement inclut l'ensemble des données du commentaire dans le corps de la requête (voir Structures de données pour le format de la charge utile).


Structures de données Internal Link

La seule structure envoyée via les webhooks est l'objet WebhookComment, décrit en TypeScript ci-dessous.

Structure de l'objet WebhookComment

Structure de l'événement "Create"

Le corps de la requête pour l'événement "create" est un objet WebhookComment.

Structure de l'événement "Update"

Le corps de la requête pour l'événement "update" est un objet WebhookComment.

Structure de l'événement "Delete"

Le corps de la requête pour l'événement "delete" est un objet WebhookComment.

Change as of Nov 14th 2023
Previously the "delete" event request body only contained the comment id. It now contains the full comment at the time of deletion.
Objet WebhookComment
Copy CopyRun External Link
1
2interface WebhookComment {
3 /** L'identifiant du commentaire. **/
4 id: string
5 /** L'identifiant ou l'URL qui identifie le fil de commentaires. Normalisé. **/
6 urlId: string
7 /** L'URL pointant vers l'endroit où le commentaire a été laissé. **/
8 url?: string
9 /** L'identifiant utilisateur qui a laissé le commentaire. Si SSO, préfixé par l'identifiant du tenant. **/
10 userId?: string
11 /** L'email de l'utilisateur ayant laissé le commentaire. **/
12 commenterEmail?: string
13 /** Le nom de l'utilisateur affiché dans le widget de commentaire. Avec SSO, peut être displayName. **/
14 commenterName: string
15 /** Texte brut du commentaire. **/
16 comment: string
17 /** Texte du commentaire après analyse. **/
18 commentHTML: string
19 /** Identifiant externe du commentaire. **/
20 externalId?: string
21 /** L'identifiant du commentaire parent. **/
22 parentId?: string | null
23 /** La date UTC à laquelle le commentaire a été laissé. **/
24 date: UTC_ISO_DateString
25 /** Karma combiné (up - down) des votes. **/
26 votes: number
27 votesUp: number
28 votesDown: number
29 /** Vrai si l'utilisateur était connecté lorsqu'il a commenté, s'il a vérifié le commentaire, ou s'il a vérifié sa session au moment où le commentaire a été laissé. **/
30 verified: boolean
31 /** Date à laquelle le commentaire a été vérifié. **/
32 verifiedDate?: number
33 /** Si un modérateur a marqué le commentaire comme revu. **/
34 reviewed: boolean
35 /** L'emplacement, ou l'encodage base64, de l'avatar. Sera base64 uniquement si cette valeur a été fournie avec le SSO. **/
36 avatarSrc?: string
37 /** Le commentaire a-t-il été marqué comme spam manuellement ou automatiquement ? **/
38 isSpam: boolean
39 /** Le commentaire a-t-il été marqué automatiquement comme spam ? **/
40 aiDeterminedSpam: boolean
41 /** Le commentaire contient-il des images ? **/
42 hasImages: boolean
43 /** Le numéro de page où se trouve le commentaire pour l'option de tri "Most Relevant". **/
44 pageNumber: number
45 /** Le numéro de page où se trouve le commentaire pour l'ordre de tri "Oldest First". **/
46 pageNumberOF: number
47 /** Le numéro de page où se trouve le commentaire pour l'ordre de tri "Newest First". **/
48 pageNumberNF: number
49 /** Le commentaire a-t-il été approuvé automatiquement ou manuellement ? **/
50 approved: boolean
51 /** Le code de locale (format : en_us) de l'utilisateur au moment où le commentaire a été rédigé. **/
52 locale: string
53 /** Les @mentions écrites dans le commentaire qui ont été correctement analysées. **/
54 mentions?: CommentUserMention[]
55 /** Le domaine d'où provient le commentaire. **/
56 domain?: string
57 /** La liste optionnelle des ids de groupe de modération associés à ce commentaire. **/
58 moderationGroupIds?: string[]|null
59}
60

Lorsque des utilisateurs sont tagués dans un commentaire, l'information est stockée dans une liste appelée mentions. Chaque objet de cette liste a la structure suivante.

Objet Mentions du Webhook
Copy CopyRun External Link
1
2interface CommentUserMention {
3 /** L'identifiant de l'utilisateur. Pour les utilisateurs SSO, cet identifiant sera préfixé par votre identifiant de tenant. **/
4 id: string
5 /** Le texte final de la balise @mention, incluant le symbole @. **/
6 tag: string
7 /** Le texte original de la balise @mention, incluant le symbole @. **/
8 rawTag: string
9 /** Type d'utilisateur mentionné. user = compte FastComments.com. sso = SSOUser. **/
10 type: 'user'|'sso'
11 /** Si l'utilisateur refuse les notifications, cette valeur sera quand même définie sur true. **/
12 sent: boolean
13}
14

Méthodes HTTP

Vous pouvez configurer la méthode HTTP pour chaque type d'événement webhook dans le panneau d'administration :

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

Since all requests contain an ID, Create and Update operations are idempotent by default (PUT). Repeating the same Create or Update request should not create duplicate objects on your side.

En-têtes de requête

Chaque requête webhook inclut les en-têtes suivants :

En-tête Description
Content-Type application/json
token Votre secret d'API
X-FastComments-Timestamp Horodatage Unix (secondes) correspondant au moment de la signature de la requête
X-FastComments-Signature Signature HMAC-SHA256 (sha256=<hex>)

Voir Sécurité & jetons d'API pour obtenir des informations sur la vérification de la signature HMAC.

Sécurité et jetons d'API Internal Link

Les requêtes webhook FastComments incluent plusieurs mécanismes d'authentification pour la sécurité.

En-têtes envoyés

En-tête Description
token Votre Secret d'API (pour compatibilité ascendante)
X-FastComments-Timestamp Horodatage Unix (secondes) indiquant quand la requête a été signée
X-FastComments-Signature Signature HMAC-SHA256 de la charge utile

Vérification de la signature HMAC (recommandée)

Nous recommandons fortement de vérifier la signature HMAC pour garantir que les charges utiles des webhooks sont authentiques et n'ont pas été altérées.

Format de la signature : sha256=<hex-encoded-signature>

Comment la signature est calculée :

  1. Concaténez : timestamp + "." + JSON_payload_body
  2. Calculez le HMAC-SHA256 en utilisant votre Secret d'API comme clé
  3. Encodez le résultat en hexadécimal

Exemple de vérification (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;
    }

    // Vérifier que l'horodatage est récent (moins de 5 minutes)
    const now = Math.floor(Date.now() / 1000);
    if (Math.abs(now - parseInt(timestamp, 10)) > 300) {
        return false;  // Prévention des attaques par rejeu
    }

    // Vérifier la signature
    const payload = JSON.stringify(req.body);
    const expectedSignature = crypto
        .createHmac('sha256', apiSecret)
        .update(`${timestamp}.${payload}`)
        .digest('hex');

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

Exemple de vérification (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

    # Vérifier que l'horodatage est récent
    now = int(time.time())
    if abs(now - int(timestamp)) > 300:
        return False

    # Vérifier la signature
    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}"

Exemple de vérification (PHP)

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

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

    // Vérifier que l'horodatage est récent (moins de 5 minutes)
    $now = time();
    if (abs($now - intval($timestamp)) > 300) {
        return false;
    }

    // Vérifier la signature
    $payload = json_encode($body, JSON_UNESCAPED_SLASHES);
    $message = $timestamp . '.' . $payload;
    $expectedSignature = 'sha256=' . hash_hmac('sha256', $message, $apiSecret);

    return hash_equals($expectedSignature, $signature);
}

Authentification héritée

L'en-tête token contenant votre Secret d'API est toujours envoyé pour assurer la compatibilité ascendante. Cependant, nous recommandons de migrer vers la vérification HMAC pour une sécurité renforcée, car elle protège contre les attaques par rejeu.


En conclusion

Cela conclut notre documentation sur les Webhooks.

Nous espérons que vous trouverez l'intégration Webhook de FastComments facile à comprendre et rapide à configurer.

Si vous pensez avoir identifié des lacunes dans notre documentation, faites-nous savoir ci-dessous.