Intégration d'une API de paiement crypto : factures, signatures et webhooks
Un guide pratique pour développeurs : une requête signée pour créer la facture, un endpoint webhook pour recevoir le statut, et les détails de sécurité qui rendent le tout fiable.

Une intégration d'API de paiement crypto repose sur deux éléments : une requête côté serveur qui crée une facture pour chaque commande et renvoie une URL de checkout, et un endpoint webhook qui reçoit des mises à jour de statut signées lorsque le paiement est détecté puis confirmé sur la blockchain. Avec mistKET, les deux sont du simple HTTPS et JSON, signés en HMAC-SHA256 : aucun SDK n'est nécessaire.
Ce guide parcourt le flux complet avec du code, puis aborde les détails de sécurité et de fiabilité qui séparent une démo d'un système en production.
L'architecture d'une API de paiement crypto en un coup d'œil
Toute intégration d'API de paiement crypto suit la même boucle en cinq étapes :
- Commande créée : votre backend appelle
POST /api/v1/invoicesavec le montant, la devise, l'ID de commande et l'URL de callback. - Redirection : vous envoyez le client vers la
checkout_urlrenvoyée. - Paiement : le client choisit un réseau et paie sur la page hébergée ; le taux est verrouillé pendant la durée de vie de la facture.
- Webhook : mistKET envoie en POST
invoice.paid,invoice.confirmedou un événement d'exception à votre URL de callback. - Livraison : vous vérifiez la signature, marquez la commande comme payée et livrez.
Votre API key, votre API secret et votre webhook secret sont émis dans le panneau marchand une fois votre compte approuvé. La référence complète se trouve dans le panneau, rubrique API.
Étape 1 : signer et envoyer la requête de facture
Chaque requête API porte trois en-têtes. La signature est le HMAC-SHA256 en hexadécimal de la chaîne {timestamp}.{raw body} calculé avec votre API secret :
POST /api/v1/invoices
X-Api-Key: mp_live_…
X-Api-Timestamp: 1760000000
X-Api-Signature: hex(hmac_sha256("{ts}.{body}", secret))
{
"amount": "184.50",
"currency": "USD",
"order_id": "2041",
"callback_url": "https://yourstore.com/webhooks/mistket"
} Une version minimale en PHP ressemble à ceci :
$body = json_encode([
'amount' => '184.50', 'currency' => 'USD',
'order_id' => '2041',
'callback_url' => 'https://yourstore.com/webhooks/mistket',
]);
$ts = (string) time();
$sig = hash_hmac('sha256', $ts . '.' . $body, $apiSecret);
// envoyer $body avec X-Api-Key, X-Api-Timestamp, X-Api-Signature Signez exactement les octets que vous envoyez. Réencoder le JSON après la signature (espaces ou ordre des clés différents) est la cause numéro un des erreurs de signature.
Étape 2 : rediriger vers le checkout hébergé
Un appel réussi renvoie 201 Created avec l'UUID de la facture, son statut (new) et une checkout_url. Enregistrez l'UUID avec votre commande et redirigez le client. La page hébergée affiche le montant exact, un QR code, un compte à rebours et le statut en direct, et fonctionne sur mobile. Le client y choisit le réseau (USDT sur TRON, BNB Smart Chain, Ethereum ou Arbitrum, ainsi que TRX, BNB et ETH), sauf si vous fixez le réseau dans l'appel API.
Outre la création de factures, l'API permet de les lister, de les consulter et de les annuler, ce qui est utile lorsqu'un panier change ou qu'une commande est abandonnée.
Étape 3 : recevoir et vérifier les webhooks de paiement crypto
Quand le statut change, mistKET envoie un POST JSON à votre URL de callback avec ces en-têtes :
| En-tête | Rôle |
|---|---|
X-Mistket-Event | Nom de l'événement, par ex. invoice.confirmed |
X-Mistket-Timestamp | Heure Unix utilisée dans la signature |
X-Mistket-Signature | sha256= + HMAC-SHA256 de {timestamp}.{raw body} avec votre webhook secret |
X-Mistket-Delivery | ID de livraison, pratique pour les logs |
Vérification en PHP :
$raw = file_get_contents('php://input');
$ts = $_SERVER['HTTP_X_MISTKET_TIMESTAMP'] ?? '';
$got = $_SERVER['HTTP_X_MISTKET_SIGNATURE'] ?? '';
$exp = 'sha256=' . hash_hmac('sha256', $ts . '.' . $raw, $webhookSecret);
if (!hash_equals($exp, $got) || abs(time() - (int) $ts) > 300) {
http_response_code(401); exit;
}
$event = json_decode($raw, true); Utilisez une comparaison à temps constant (hash_equals en PHP, hmac.compare_digest en Python, crypto.timingSafeEqual en Node.js) et rejetez les timestamps trop anciens pour bloquer les attaques par rejeu. Pour le principe de base, voir la RFC 2104 (HMAC).
Exemple de payload de webhook
Un paiement confirmé arrive sous la forme d'un document JSON compact. Les champs les plus utiles sont l'événement, votre ID de commande, le statut et les montants attendu et reçu :
POST https://yourstore.com/webhooks/mistket
X-Mistket-Event: invoice.confirmed
X-Mistket-Signature: sha256=…
{ "event": "invoice.confirmed", "data": {
"order_id": "2041", "status": "confirmed",
"pay_amount": "184.5", "paid_amount": "184.5",
"pay_currency": "USDT", "network": "TRC20" } } Enregistrez pay_currency et network avec la commande. Ils servent pour la comptabilité et pour les échanges avec le support plus tard.
Vérification en Node.js et Python
La même vérification dans deux autres langages populaires :
// Node.js (Express avec express.raw pour cette route)
const exp = 'sha256=' + crypto.createHmac('sha256', secret)
.update(ts + '.' + rawBody).digest('hex');
const ok = crypto.timingSafeEqual(Buffer.from(exp), Buffer.from(sig));
# Python
exp = 'sha256=' + hmac.new(secret.encode(), f'{ts}.{raw}'.encode(),
hashlib.sha256).hexdigest()
ok = hmac.compare_digest(exp, sig) Dans les deux cas, lisez bien le corps brut de la requête. Beaucoup de frameworks parsent le JSON automatiquement ; une fois parsé puis resérialisé, les octets ne correspondent plus à la signature.
Tester en local
Les webhooks exigent une URL HTTPS publique : un ordinateur portable en local ne peut donc pas les recevoir directement. Deux options pratiques : déployer tôt le handler sur un serveur de staging, ou exposer temporairement votre port local via un outil de tunnel. Créez de petites factures pointant vers le callback de staging, puis consultez les logs de livraison dans le tableau de bord marchand pour voir exactement ce qui a été envoyé et ce que votre serveur a répondu.
Essayez de déclencher chaque type d'événement au moins une fois pendant les tests : paid, confirmed, underpaid et expired. Quand chaque branche de votre handler a tourné avec un vrai webhook, il ne reste presque plus rien pour vous surprendre en production, et vous savez exactement à quoi ressemblent les logs de livraison quand quelque chose tourne mal.
Étape 4 : gérer chaque statut
Le payload d'un webhook contient l'ID de commande, le statut, le montant attendu (pay_amount), le montant reçu (paid_amount), la devise et le réseau. Associez chaque événement à une action :
| Événement | Signification | Action habituelle |
|---|---|---|
invoice.paid | Transfert détecté, confirmations en attente | Afficher « paiement reçu, confirmation en cours » |
invoice.confirmed | Nombre de confirmations requis atteint | Marquer comme payé et livrer |
invoice.underpaid | En dessous de votre tolérance | Attendre le complément ou contacter le client |
invoice.overpaid | Plus que prévu | Livrer ; décider du sort de la différence |
invoice.expired | Aucun paiement valide dans les délais | Libérer le stock, laisser la commande impayée |
La tolérance de sous-paiement, les paiements partiels qui s'additionnent et les paiements tardifs dans un délai de grâce sont gérés par mistKET ; votre code ne réagit qu'au résultat final.
Fiabilité : nouvelles tentatives et idempotence
Si votre endpoint est indisponible ou renvoie une erreur, les webhooks sont renvoyés avec back-off pendant des heures. Vous recevrez donc parfois le même événement deux fois. Rendez votre handler idempotent par ID de commande :
- Répondez rapidement par un 2xx, puis traitez le travail lourd dans une file d'attente.
- Avant de livrer, vérifiez si la commande est déjà marquée comme payée.
- Journalisez l'ID de livraison et l'événement pour tracer les incidents ; le tableau de bord affiche aussi les logs de livraison des webhooks.
Check-list de sécurité
Une intégration d'API de paiement crypto manipule de l'argent : traitez-la comme n'importe quel code de paiement.
- Gardez l'API secret et le webhook secret uniquement côté serveur, jamais dans le code front-end ni dans une application mobile.
- Restreignez l'accès à l'API avec la liste d'IP autorisées du panneau.
- Rejetez les requêtes hors d'une courte fenêtre de timestamp.
- Réglez l'expiration des factures selon votre logique de réservation de stock.
- Traitez les montants comme des chaînes ou des décimaux, jamais comme des floats.
Pour aller plus loin
Voilà l'intégration complète d'une API de paiement crypto : une requête signée, un webhook vérifié et une table des statuts. Pour la vision non technique du même flux, lisez comment accepter les paiements crypto sur un site web. Vous construisez un bot plutôt qu'un site ? Consultez accepter des paiements crypto dans un bot Telegram. Demandez vos clés API sur Telegram @mistnetwork, consultez l'exemple dans la section développeurs et gérez vos clés depuis l'espace marchand.


