Skip to Content
Sécurité

Sécurité

La sécurité d’une intégration de paiement repose sur quelques principes simples mais stricts. Cette page résume les pratiques attendues côté marchand.

🔑

Vos clés API et vos secrets webhook donnent accès à vos encaissements. Traitez-les comme des mots de passe : jamais dans le code versionné, jamais côté navigateur, jamais dans un dépôt public.

Clés API

  • L’authentification de l’API publique se fait via l’en-tête X-API-Key.
  • Deux préfixes selon l’environnement : kadryza_test_… (sandbox) et kadryza_live_… (production).
  • Une clé n’est affichée qu’une seule fois à la création, depuis le dashboard. Stockez-la immédiatement.
  • Conservez les clés dans des variables d’environnement côté serveur, jamais en dur dans le code.
# ✅ Bon - variable d'environnement, côté serveur export KADRYZA_API_KEY="kadryza_live_•••"
// ❌ À éviter - clé en dur, exposée côté client const kadryza = new Kadryza({ apiKey: 'kadryza_live_abcd…' })

Rotation : en cas de doute (fuite, départ d’un collaborateur), générez une nouvelle clé depuis le dashboard et révoquez l’ancienne. Utilisez des clés distinctes par environnement et par service.

Signature des webhooks

Chaque webhook est signé. Vérifiez toujours la signature avant de traiter l’événement.

  • En-tête : X-Kadryza-Signature au format sha256=<hmac>.
  • Algorithme : HMAC-SHA256 du corps brut de la requête, avec le secret de l’endpoint (64 caractères hexadécimaux) comme clé.
  • Le secret est retourné une seule fois à la création de l’endpoint webhook.
import crypto from 'node:crypto' function verifierSignature(corpsBrut: string, header: string | undefined, secret: string): boolean { if (!header) return false const attendu = 'sha256=' + crypto.createHmac('sha256', secret).update(corpsBrut).digest('hex') const recu = Buffer.from(header) const calcule = Buffer.from(attendu) // timingSafeEqual lève une exception si les longueurs diffèrent : on compare d'abord. if (recu.length !== calcule.length) return false // Comparaison à temps constant pour éviter les attaques temporelles return crypto.timingSafeEqual(recu, calcule) }
⛔

Ne faites jamais confiance au corps d’un webhook sans vérifier X-Kadryza-Signature. Une requête non signée ou mal signée doit être rejetée.

Les webhooks payment_session.* de l’environnement test et les envois transaction.test portent en plus l’en-tête X-Kadryza-Test: true. Pour tout événement, data.environment ou le préfixe de la clé qui a créé l’objet indiquent l’environnement.

Transport (HTTPS)

  • Tous les appels API se font en HTTPS uniquement.
  • Votre URL de réception de webhook doit être publiquement accessible, et en HTTPS pour recevoir des événements live. Kadryza refuse les URL qui pointent vers des adresses privées ou locales.

Idempotence

Le réseau peut rejouer une requête ou une livraison de webhook. Rendez vos traitements idempotents :

  • côté création de paiement, une commande = une reference : en cas de doute après une coupure, relisez la session par sa référence au lieu d’en créer une nouvelle ;
  • côté réception de webhook, dédupliquez sur event_id (en-tête X-Kadryza-Event-ID) ; pour les événements transaction.*, qui n’en ont pas, sur event + data.id + data.status.

La signature ne couvre pas d’horodatage séparé : conserver les event_id déjà traités est aussi votre protection contre le rejeu d’une livraison.

Données sensibles

  • Kadryza ne manipule pas de données de carte bancaire : les paiements passent par le mobile money.
  • Ne stockez aucune clé ni secret réel dans vos exemples, vos logs ou vos tickets de support.
  • Limitez l’accès aux clés live aux seules personnes et services qui en ont besoin.

Signaler une vulnérabilité

Vous avez identifié un problème de sécurité ? Écrivez à contact@kadryza.com en décrivant le problème, sans le divulguer publiquement.