api

Webhooks

QuantaPay envoie des requêtes HTTP POST à l'URL de webhook configurée lorsque des événements de paiement surviennent. Cela permet à votre serveur de réagir aux paiements en temps réel.

Mis à jour: 08/04/2026

QuantaPay envoie des requêtes HTTP POST à l'URL de webhook configurée lorsque des événements de paiement surviennent. Cela permet à votre serveur de réagir aux paiements en temps réel.

Configuration

Configurez votre webhook dans Paramètres → Paiements → Webhook :

  • Webhook URL : Votre endpoint HTTPS (ex. : https://votresite.com/webhook/quantapay)
  • Webhook Secret Key : Clé générée automatiquement pour la vérification du payload

Payload du Webhook

Lorsqu'un paiement est complété, QuantaPay envoie une requête POST avec Content-Type: application/json :

{
  "key": "your-webhook-secret-key",
  "transaction": {
    "id": "197",
    "biz_id": "QP-20260408-560BF",
    "title": "",
    "description": "",
    "from": "0xCustomerWalletAddress",
    "to": "0xYourWalletAddress",
    "hash": "0xBlockchainTransactionHash",
    "amount": "0.025",
    "amount_fiat": "49.99000000",
    "cryptocurrency": "eth",
    "currency": "usd",
    "external_reference": "your-order-id-123",
    "creation_time": "2026-03-08 10:00:00",
    "status": "C",
    "webhook": "1",
    "vat": "0",
    "billing": "",
    "checkout_id": null,
    "type": "2"
  }
}

Champs de la transaction

ChampTypeDescription
idstringID interne de la transaction QuantaPay.
biz_idstringRéférence de commande QuantaPay (ex. : QP-20260408-560BF).
titlestringTitre de la transaction.
fromstringAdresse de portefeuille du client (expéditeur).
tostringVotre adresse de portefeuille (destinataire).
hashstringHash de la transaction blockchain.
amountstringMontant en cryptomonnaie.
amount_fiatstringMontant en monnaie fiduciaire (8 décimales, ex. : "49.99000000").
cryptocurrencystringCode de la cryptomonnaie (ex. : btc, eth, usdt).
currencystringCode de la devise fiduciaire (ex. : usd, eur, hkd).
external_referencestringVotre ID de commande — fourni lors de la création de la Checkout Session. Utilisez-le pour retrouver votre commande.
creation_timestringHorodatage de création de la transaction (UTC).
statusstringStatut de la transaction : C (complétée).
checkout_idstring|nullID de la Checkout Session associée, ou null.
typestringType de transaction : 1 = paiement direct, 2 = Checkout Session.

Associer les commandes avec external_reference

C'est la méthode recommandée pour lier un paiement QuantaPay à votre propre commande.

Lors de la création d'une Checkout Session, passez l'ID de votre commande dans le champ external_reference :

{
  "order_id": "your-order-id-123",
  "external_reference": "your-order-id-123",
  "price": 49.99,
  "currency": "usd"
}

QuantaPay stocke cette valeur et la retourne inchangée dans le payload du webhook sous transaction.external_reference. Utilisez-la pour retrouver et exécuter la commande correcte.

Vérification de la signature

Le champ key du payload contient votre Webhook Secret Key. Si aucune clé n'est configurée, le système utilise la clé de chiffrement du compte. Configurez toujours une Webhook Secret Key dédiée.

Exemple PHP

$payload = json_decode(file_get_contents('php://input'), true);

$webhook_secret = 'your-webhook-secret-key'; // From Settings

// 1. Verify webhook authenticity
if ($payload['key'] !== $webhook_secret) {
    http_response_code(401);
    die('Invalid webhook signature');
}

$transaction = $payload['transaction'];

// 2. Check payment is complete
if ($transaction['status'] !== 'C') {
    http_response_code(200);
    die('Not completed');
}

// 3. Match your order using external_reference
$your_order_id = $transaction['external_reference'];
$order = find_order($your_order_id);
if (!$order) {
    http_response_code(200);
    die('Order not found');
}

// 4. Verify amount using float comparison (amount_fiat has 8 decimal places)
$paid_amount = floatval($transaction['amount_fiat']);
$expected_amount = floatval($order->total);
if (abs($paid_amount - $expected_amount) > 0.01 || $transaction['currency'] !== $order->currency) {
    http_response_code(200);
    die('Amount mismatch');
}

// 5. Idempotency check — use biz_id as dedup key
if (order_already_fulfilled($transaction['biz_id'])) {
    http_response_code(200);
    die('Already processed');
}

// 6. Mark order as paid
fulfill_order($your_order_id);

http_response_code(200);
echo 'OK';

Exemple Node.js

const express = require('express');
const app = express();
app.use(express.json());

const WEBHOOK_SECRET = 'your-webhook-secret-key';

app.post('/webhook/quantapay', (req, res) => {
  const { key, transaction } = req.body;

  // 1. Verify webhook authenticity
  if (key !== WEBHOOK_SECRET) {
    return res.status(401).send('Invalid signature');
  }

  // 2. Only process completed payments
  if (transaction.status !== 'C') {
    return res.status(200).send('OK');
  }

  // 3. Match your order using external_reference
  const yourOrderId = transaction.external_reference;
  const bizId = transaction.biz_id; // use as dedup key

  console.log(`Payment completed: ${transaction.amount_fiat} ${transaction.currency}`);
  console.log(`Your order: ${yourOrderId}, QuantaPay ref: ${bizId}`);
  console.log(`TX Hash: ${transaction.hash}`);

  // Fulfill order logic here (use biz_id for idempotency)

  res.status(200).send('OK');
});

app.listen(3000);

Test cURL

curl -X POST https://yoursite.com/webhook/quantapay \
  -H "Content-Type: application/json" \
  -d '{
    "key": "your-webhook-secret-key",
    "transaction": {
      "id": "197",
      "biz_id": "QP-20260408-560BF",
      "status": "C",
      "amount": "0.025",
      "amount_fiat": "49.99000000",
      "cryptocurrency": "eth",
      "currency": "usd",
      "external_reference": "your-order-id-123",
      "hash": "0xabc123..."
    }
  }'

Types d'événements

StatutÉvénementDescription
CPaiement complétéLe paiement a été confirmé sur la blockchain avec suffisamment de confirmations.

Remarque : Les webhooks ne sont envoyés que pour les transactions complétées (statut C). Les transactions expirées et en attente ne déclenchent pas de webhooks.

Bonnes pratiques

1. Répondre rapidement

Retournez HTTP 200 dès la réception du webhook. Traitez les tâches lourdes de manière asynchrone.

2. Traitement idempotent

Votre gestionnaire doit être idempotent — traiter le même webhook deux fois ne doit pas entraîner de doublons. Utilisez biz_id comme clé de déduplication.

if (order_already_fulfilled($transaction['biz_id'])) {
    http_response_code(200);
    die('Already processed');
}

3. Vérifier la clé

Vérifiez toujours que le champ key correspond à votre Webhook Secret Key avant traitement.

4. Utiliser HTTPS

Utilisez toujours un endpoint HTTPS pour votre URL de webhook.

5. Tout journaliser

Journalisez tous les webhooks entrants à des fins de débogage et d'audit.

error_log('QuantaPay Webhook: ' . json_encode($payload));

6. Gérer les échecs avec élégance

QuantaPay ne retente pas automatiquement les webhooks échoués. Utilisez l'API get-checkout-session ou get-transactions comme solution de repli pour vérifier le statut du paiement si votre serveur était temporairement indisponible.