FastComments.com


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

Nous réalisons cela à l'aide de 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 de ceux-ci est considéré comme un événement distinct dans notre système et, à ce titre, possède des sémantiques et des structures différentes pour les événements de webhook.


Tests Internal Link

Dans l'interface d'administration des 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 de Delete enverra un corps de requête factice contenant uniquement un ID.

Vérification des charges utiles

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

  1. token - Votre secret d'API
  2. X-FastComments-Timestamp - Horodatage Unix (secondes)
  3. X-FastComments-Signature - Signature HMAC-SHA256

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

Outils de test

Vous pouvez utiliser des outils comme webhook.site ou ngrok pour inspecter les charges utiles des webhooks entrants 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 modifié. 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'intégralité 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 de l'événement "create" est un objet WebhookComment.

Structure de l'événement "update"

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

Structure de l'événement "delete"

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

Modification du 14 nov. 2023
Auparavant, le corps de la requête de l'événement "delete" ne contenait que l'id du commentaire. Il contient maintenant le commentaire complet au moment de la suppression.
L'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'ID de l'utilisateur qui a laissé le commentaire. Si SSO, préfixé par l'ID du locataire. **/
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 commentaires. 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'ID 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é, si son commentaire a été vérifié, ou s'il a vérifié sa session lorsque 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 examiné. **/
34 reviewed: boolean
35 /** L'emplacement ou l'encodage base64 de l'avatar. Sera en base64 uniquement si cette valeur a été fournie avec 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 /** Y a-t-il des images dans le commentaire ? **/
42 hasImages: boolean
43 /** Le numéro de page sur lequel se trouve le commentaire pour la direction de tri "Most Relevant". **/
44 pageNumber: number
45 /** Le numéro de page sur lequel se trouve le commentaire pour la direction de tri "Oldest First". **/
46 pageNumberOF: number
47 /** Le numéro de page sur lequel se trouve le commentaire pour la direction 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 groupes 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.

L'objet de mentions du webhook
Copy CopyRun External Link
1
2interface CommentUserMention {
3 /** L'ID de l'utilisateur. Pour les utilisateurs SSO, votre ID de locataire sera préfixé. **/
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 /** Quel type d'utilisateur a été tagué. user = compte FastComments.com. sso = SSOUser. **/
10 type: 'user'|'sso'
11 /** Si l'utilisateur se désinscrit des notifications, ceci restera quand même défini à 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 :

  • Événement « create » : POST ou PUT (par défaut : PUT)
  • Événement « update » : POST ou PUT (par défaut : PUT)
  • Événement « delete » : DELETE, POST ou PUT (par défaut : DELETE)

Puisque toutes les requêtes contiennent un ID, les opérations Create et Update sont idempotentes par défaut (PUT). Répéter la même requête Create ou Update ne devrait pas créer d'objets en double de votre côté.

En-têtes de requête

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

Header Description
Content-Type application/json
token Votre secret d'API
X-FastComments-Timestamp Timestamp Unix (secondes) indiquant le moment où la requête a été signée
X-FastComments-Signature Signature HMAC-SHA256 (sha256=<hex>)

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


Sécurité et jetons d'API Internal Link

FastComments webhook requests include multiple authentication mechanisms for security.

En-têtes envoyés

En-tête Description
token Votre API Secret (pour rétrocompatibilité)
X-FastComments-Timestamp Timestamp 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 afin de vous assurer que les charges utiles des webhooks sont authentiques et n'ont pas été modifiées.

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

Comment la signature est calculée :

  1. Concaténer : timestamp + "." + JSON_payload_body
  2. Calculer HMAC-SHA256 en utilisant votre API Secret comme clé
  3. Encoder 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 le timestamp 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 le timestamp 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 le timestamp 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 API Secret est toujours envoyé pour des raisons de rétrocompatibilité. Toutefois, nous recommandons de migrer vers la vérification HMAC pour une meilleure sécurité, car elle protège contre les attaques par rejeu.

En conclusion

Ceci 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.