api

Вебхуки

QuantaPay отправляет HTTP POST-запросы на настроенный URL вебхука при возникновении платёжных событий. Это позволяет серверу реагировать на платежи в режиме реального времени.

Обновлено: 08.04.2026

QuantaPay отправляет HTTP POST-запросы на настроенный URL вебхука при возникновении платёжных событий. Это позволяет серверу реагировать на платежи в режиме реального времени.

Настройка

Настройте вебхук в Настройки → Платежи → Вебхук:

  • Webhook URL: HTTPS-эндпоинт (например, https://вашсайт.com/webhook/quantapay)
  • Webhook Secret Key: Автоматически созданный ключ для верификации payload

Payload вебхука

При завершении платежа QuantaPay отправляет POST-запрос с 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"
  }
}

Поля транзакции

ПолеТипОписание
idstringВнутренний ID транзакции QuantaPay.
biz_idstringНомер заказа QuantaPay (например, QP-20260408-560BF).
titlestringЗаголовок транзакции.
fromstringАдрес кошелька клиента (отправитель).
tostringАдрес вашего кошелька (получатель).
hashstringХэш транзакции в блокчейне.
amountstringСумма в криптовалюте.
amount_fiatstringСумма в фиатной валюте (8 знаков после запятой, например, "49.99000000").
cryptocurrencystringКод криптовалюты (например, btc, eth, usdt).
currencystringКод фиатной валюты (например, usd, eur, hkd).
external_referencestringВаш ID заказа — передаётся при создании Checkout Session. Используйте для сопоставления с вашим заказом.
creation_timestringВременная метка создания транзакции (UTC).
statusstringСтатус транзакции: C (завершена).
checkout_idstring|nullID связанной Checkout Session или null.
typestringТип транзакции: 1 = прямой платёж, 2 = Checkout Session.

Сопоставление заказов через external_reference

Это рекомендуемый способ связать платёж QuantaPay с вашим заказом.

При создании Checkout Session передайте ID вашего заказа в поле external_reference:

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

QuantaPay сохраняет это значение и возвращает его без изменений в payload вебхука в transaction.external_reference. Используйте его для поиска и выполнения нужного заказа.

Верификация подписи

Поле key в payload содержит ваш Webhook Secret Key. Если ключ не настроен, система использует ключ шифрования аккаунта. Всегда настраивайте отдельный Webhook Secret Key.

Пример 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';

Пример 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);

Тест 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..."
    }
  }'

Типы событий

СтатусСобытиеОписание
CПлатёж завершёнПлатёж подтверждён в блокчейне с достаточным числом подтверждений.

Примечание: Вебхуки отправляются только для завершённых транзакций (статус C). Истёкшие и ожидающие транзакции не вызывают вебхуки.

Лучшие практики

1. Быстрый ответ

Возвращайте HTTP 200 сразу после получения вебхука. Выполняйте тяжёлую обработку асинхронно.

2. Идемпотентная обработка

Обработчик вебхука должен быть идемпотентным — повторная обработка одного вебхука не должна приводить к дублированию. Используйте biz_id как ключ дедупликации.

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

3. Проверка ключа

Всегда проверяйте, что поле key совпадает с вашим Webhook Secret Key перед обработкой.

4. Использование HTTPS

Всегда используйте HTTPS-эндпоинт для URL вебхука.

5. Логирование

Логируйте все входящие вебхуки для отладки и аудита.

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

6. Обработка сбоев

QuantaPay не повторяет автоматически неудавшиеся вебхуки. Используйте API get-checkout-session или get-transactions для резервной проверки статуса платежа, если ваш сервер был временно недоступен.