Вебхуки
QuantaPay отправляет HTTP POST-запросы на настроенный URL вебхука при возникновении платёжных событий. Это позволяет серверу реагировать на платежи в режиме реального времени.
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"
}
}
Поля транзакции
| Поле | Тип | Описание |
|---|---|---|
id | string | Внутренний ID транзакции QuantaPay. |
biz_id | string | Номер заказа QuantaPay (например, QP-20260408-560BF). |
title | string | Заголовок транзакции. |
from | string | Адрес кошелька клиента (отправитель). |
to | string | Адрес вашего кошелька (получатель). |
hash | string | Хэш транзакции в блокчейне. |
amount | string | Сумма в криптовалюте. |
amount_fiat | string | Сумма в фиатной валюте (8 знаков после запятой, например, "49.99000000"). |
cryptocurrency | string | Код криптовалюты (например, btc, eth, usdt). |
currency | string | Код фиатной валюты (например, usd, eur, hkd). |
external_reference | string | Ваш ID заказа — передаётся при создании Checkout Session. Используйте для сопоставления с вашим заказом. |
creation_time | string | Временная метка создания транзакции (UTC). |
status | string | Статус транзакции: C (завершена). |
checkout_id | string|null | ID связанной Checkout Session или null. |
type | string | Тип транзакции: 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 для резервной проверки статуса платежа, если ваш сервер был временно недоступен.