Skip to main content
Les webhooks permettent de recevoir des notifications en temps réel sur les transactions initiées par vos clients, sans avoir à interroger régulièrement l’API. Lygos envoie automatiquement une requête HTTP POST à votre URL configurée à chaque événement sélectionné.

Configuration des Webhooks

Configuration dans le Dashboard

Vous pouvez configurer vos webhooks directement depuis votre dashboard Lygos dans la section Configurations.

URL du Webhook

L’URL du webhook doit être :
  • Sécurisée : Utilisez HTTPS avec un certificat SSL valide
  • Accessible publiquement : L’URL doit être accessible depuis Internet
  • Valide : Format d’URL correct (ex: https://my-webhook-url.com/lygos)
Les webhooks avec des URLs non sécurisées (HTTP) ou avec des certificats SSL invalides seront rejetés pour des raisons de sécurité.

Description du Webhook

Vous pouvez ajouter une description optionnelle pour vous souvenir de l’usage de chaque webhook (ex: “Webhook pour tag et lien de paiement”).

Sécurité et Authentification

Authentification HMAC-SHA256

Lygos utilise l’algorithme HMAC avec SHA256 pour signer tous les webhooks envoyés. Cette signature permet de vérifier que les requêtes proviennent bien de Lygos et n’ont pas été modifiées en transit.

Clé Secrète

Lors de la création d’un webhook, vous recevrez par email une clé secrète unique que vous devrez conserver précieusement. Cette clé est utilisée pour vérifier l’authenticité des webhooks.
Gardez votre clé secrète confidentielle. Ne la partagez jamais et ne la commitez pas dans votre dépôt de code.
Vous pouvez régénérer votre clé secrète à tout moment depuis le dashboard. La régénération invalide immédiatement l’ancienne clé.

Headers des Webhooks

Chaque webhook envoyé par Lygos contient les headers suivants :
  • X-Signature : Signature HMAC-SHA256 calculée à partir du body et du timestamp
  • X-Timestamp : Timestamp Unix (en millisecondes) de la requête
  • Content-Type : application/json
Exemple de headers reçus :
X-Signature: a1b2c3d4e5f6789...
X-Timestamp: 1234567890244
Content-Type: application/json

Vérification de la Signature

Pour vérifier l’authenticité d’un webhook :
  1. Récupérez les headers X-Signature et X-Timestamp
  2. Concaténez le body de la requête (en string) avec le timestamp
  3. Calculez le HMAC-SHA256 de cette chaîne en utilisant votre clé secrète
  4. Comparez le résultat avec la valeur de X-Signature
  5. Si les valeurs correspondent, le webhook est authentique

Exemples de Code

Node.js / JavaScript

const crypto = require("crypto");

function verifyWebhookSignature(body, signature, timestamp, secretKey) {
  // Concaténer le body (string) avec le timestamp
  const payload = JSON.stringify(body) + timestamp;

  // Calculer le HMAC-SHA256
  const expectedSignature = crypto
    .createHmac("sha256", secretKey)
    .update(payload)
    .digest("hex");

  // Comparer les signatures (comparaison sécurisée)
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

// Utilisation
const body = req.body;
const signature = req.headers["x-signature"];
const timestamp = req.headers["x-timestamp"];
const secretKey = process.env.WEBHOOK_SECRET_KEY;

if (verifyWebhookSignature(body, signature, timestamp, secretKey)) {
  // Webhook authentique, traiter la requête
  console.log("Webhook authentifié");
} else {
  // Signature invalide, rejeter la requête
  res.status(401).send("Signature invalide");
}

Python

import hmac
import hashlib
import json

def verify_webhook_signature(body, signature, timestamp, secret_key):
    # Concaténer le body (string) avec le timestamp
    payload = json.dumps(body, separators=(',', ':')) + str(timestamp)

    # Calculer le HMAC-SHA256
    expected_signature = hmac.new(
        secret_key.encode('utf-8'),
        payload.encode('utf-8'),
        hashlib.sha256
    ).hexdigest()

    # Comparer les signatures (comparaison sécurisée)
    return hmac.compare_digest(signature, expected_signature)

# Utilisation
body = request.json
signature = request.headers.get('X-Signature')
timestamp = request.headers.get('X-Timestamp')
secret_key = os.environ.get('WEBHOOK_SECRET_KEY')

if verify_webhook_signature(body, signature, timestamp, secret_key):
    # Webhook authentique, traiter la requête
    print('Webhook authentifié')
else:
    # Signature invalide, rejeter la requête
    return 'Signature invalide', 401

Types d’Événements Disponibles

Vous pouvez sélectionner les types d’événements pour lesquels vous souhaitez recevoir des notifications :

Marketplace

  • marketplace_deposit_completed - Dépôt marketplace réussi
  • marketplace_deposit_failed - Dépôt marketplace échoué
  • marketplace_deposit_submitted - Dépôt marketplace soumis

Lien de Paiement

  • payment_link_deposit_completed - Dépôt de lien de paiement réussi
  • payment_link_deposit_failed - Dépôt de lien de paiement échoué
  • payment_link_deposit_submitted - Dépôt de lien de paiement soumis

Passerelle de Paiement

  • gateway_deposit_completed - Dépôt passerelle réussi
  • gateway_deposit_failed - Dépôt passerelle échoué
  • gateway_deposit_submitted - Dépôt passerelle soumis

Structure du Payload

Chaque webhook reçu contient les informations suivantes dans le body de la requête :
{
  "operationId": "uuid",
  "status": "string",
  "amount": "number",
  "buyer": {
    "name": "string",
    "email": "string",
    "phoneNumber": "string",
    "country": "string",
    "operator": "string"
  }
}

Champs du Payload

  • operationId (UUID) : Identifiant unique de l’opération (format UUID)
  • status (string) : Statut de la transaction (voir Statuts possibles)
  • amount (number) : Montant de la transaction
  • buyer (object, optionnel) : Informations sur l’acheteur
    • name (string) : Nom de l’acheteur
    • email (string) : Email de l’acheteur
    • phoneNumber (string) : Numéro de téléphone de l’acheteur
    • country (string) : Pays de l’acheteur (ex: “CMR”)
    • operator (string) : Opérateur Mobile Money utilisé (ex: “MTN_MOMO_CMR”)
Le champ buyer peut être absent pour certaines transactions. Assurez-vous de gérer ce cas dans votre code.

Statuts Possibles

Les statuts suivants peuvent être renvoyés dans le webhook :
  • INITIATED - Transaction initiée, en attente de traitement
  • DEPOSIT_PENDING - Dépôt en cours de traitement
  • DEPOSIT_COMPLETED - Dépôt complété avec succès
  • DEPOSIT_FAILED - Dépôt échoué
  • DEPOSIT_REJECTED - Dépôt rejeté
  • PAYOUT_PAID - Paiement sortant effectué
  • MANUAL_PAYOUT - Paiement sortant manuel

Exemples de Payloads

Exemple 1 : Transaction réussie avec buyer

{
  "operationId": "550e8400-e29b-41d4-a716-446655440000",
  "status": "DEPOSIT_COMPLETED",
  "amount": 10000,
  "buyer": {
    "name": "Jean Dupont",
    "email": "[email protected]",
    "phoneNumber": "237657843901",
    "country": "CMR",
    "operator": "MTN_MOMO_CMR"
  }
}

Exemple 2 : Transaction en attente sans buyer

{
  "operationId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
  "status": "DEPOSIT_PENDING",
  "amount": 5000
}

Exemple 3 : Paiement sortant

{
  "operationId": "6ba7b812-9dad-11d1-80b4-00c04fd430c8",
  "status": "PAYOUT_PAID",
  "amount": 15000
}

Bonnes Pratiques

  1. Validation : Validez toujours les données reçues dans le webhook
  2. Idempotence : Utilisez operationId pour éviter de traiter deux fois le même événement
  3. Sécurité : Vérifiez toujours la signature des webhooks en utilisant votre clé secrète (voir Sécurité et Authentification)
  4. Variables d’environnement : Stockez votre clé secrète dans des variables d’environnement, ne la commitez jamais dans votre code
  5. Vérification du timestamp : Vérifiez que le timestamp n’est pas trop ancien pour éviter les attaques de replay (recommandé)
  6. Gestion d’erreurs : Répondez avec un code HTTP 200 même en cas d’erreur de traitement pour éviter les tentatives de retry
  7. Logging : Enregistrez tous les webhooks reçus pour le débogage et l’audit