Documentation Index
Fetch the complete documentation index at: https://docs.crypto-cash.world/llms.txt
Use this file to discover all available pages before exploring further.
Fiat Webhooks
Примітка: усі числові значення, суми та ідентифікатори в прикладах є ілюстративними та наведені лише для демонстрації.
Огляд
Fiat Module використовує webhook-и Crypto-Cash, які надсилаються мерчанту після зміни статусу транзакції. Вони працюють лише якщо на Fiat API key налаштований параметр webhookUrl. Якщо webhookUrl не заданий, webhook-и не надсилаються.
URL для сповіщень у платіжного провайдера та webhookUrl на Fiat API key — це різні речі. webhookUrl на Fiat API key — це адреса, на яку Crypto-Cash надсилає свої події мерчанту.
Ключові параметри
| Параметр | Значення |
|---|
| Ціль webhook Crypto-Cash | webhookUrl, налаштований на Fiat API key |
| HTTP-метод | POST |
| Доставка | Асинхронна |
| Формат даних | application/json |
Як працюють webhook-и
Користувач відкриває платіжний віджет
↓
Платіжний провайдер обробляє платіж
↓
Платіжний провайдер надсилає webhook у Crypto-Cash
↓
Crypto-Cash перевіряє підпис провайдера
↓
Crypto-Cash оновлює статус транзакції
↓
Crypto-Cash формує payment-подію
↓
Якщо на Fiat API key налаштований webhookUrl,
Crypto-Cash надсилає webhook асинхронно
Webhook-и Crypto-Cash
Webhook-и Crypto-Cash надсилаються після payment-подій. Вони працюють лише якщо на Fiat API key налаштований webhookUrl.
При зміні статусу транзакції система формує payment-подію та асинхронно надсилає webhook на налаштований webhookUrl. Якщо webhookUrl не налаштований, webhook не надсилається.
HTTP-формат:
Method: POST
Content-Type: application/json
Кожен webhook містить поле signature у тілі payload. Мерчант використовує Fiat API key, щоб переконатися, що webhook надісланий Crypto-Cash і не був змінений.
Webhook payload і підпис зберігаються для аудиту та історії.
Типи подій
| Подія | Коли надсилається | Тип |
|---|
payment::created | Транзакцію створено | Проміжне |
payment::waiting | Статус змінився на Waiting | Проміжне |
payment::paid | Статус змінився на Paid | Фінальне |
payment::failed | Статус змінився на Fail | Фінальне |
payment::canceled | Статус змінився на Canceled | Фінальне |
Проміжні події (payment::created, payment::waiting) означають, що транзакція в роботі й можливі подальші зміни статусу.
Фінальні події (payment::paid, payment::failed, payment::canceled) означають, що транзакція досягла термінального стану:
| Фінальна подія | Значення |
|---|
payment::paid | Криптовалюту успішно відправлено на адресу гаманця |
payment::failed | Платіж не був завершений |
payment::canceled | Платіж скасовано |
Що має перевірити мерчант
При отриманні webhook Crypto-Cash:
- Перевірити поле
signature за допомогою Fiat API key (див. розділ «Підпис webhook»).
- Прочитати
event.event_type, щоб визначити подію.
- Прочитати
event.data — там повний стан транзакції.
- Обробити подію залежно від того, проміжна вона чи фінальна.
Поле id унікальне для кожної доставки webhook. Використовуйте його для дедуплікації обробки на своїй стороні.
Підпис webhook Crypto-Cash
Кожен webhook Crypto-Cash містить поле signature у тілі payload.
Підпис формується за ідентифікатором і вмістом webhook:
payload = { id, delivered_at, event }
Мерчант перевіряє підпис так: перескладає той самий payload з отриманого webhook, виключаючи поле signature, і перевіряє його за допомогою Fiat API key.
Спосіб перевірки залежить від типу Fiat API key:
ED25519 — перевірте отриманий signature, використовуючи publicKey Fiat API.
LEGACY — перескладіть очікуване значення signature, використовуючи privateKey Fiat API, і порівняйте його з отриманим.
Використовуйте ту саму пару Fiat API key, яка використовується для підписаних запитів мерчанта в API. Приватний ключ має залишатися на стороні мерчанта — не надсилайте його у відповідях на webhook, у логах або в зверненнях до підтримки.
Приклади payload
payment::created
{
"id": "webhook-id",
"delivered_at": "2026-04-16T10:00:01.000Z",
"event": {
"event_type": "payment::created",
"timestamp": "2026-04-16T10:00:01.000Z",
"data": {
"id": "crypto-cash-transaction-id",
"externalId": "merchant-order-id",
"status": "New",
"fiatCurrency": "SGD",
"fiatAmount": "51",
"currency": "USDT",
"network": "TRC20",
"address": "wallet-address",
"cryptoAmount": null,
"exchangeRate": null,
"paymentMethod": null,
"hash": null,
"buyId": null,
"withdrawId": null,
"customerId": null,
"merchantEarning": null,
"merchantId": "merchant-id",
"createdAt": "2026-04-16T10:00:00.000Z",
"updatedAt": "2026-04-16T10:00:00.000Z"
}
},
"signature": "signature"
}
payment::waiting
{
"id": "webhook-id",
"delivered_at": "2026-04-16T10:00:15.000Z",
"event": {
"event_type": "payment::waiting",
"timestamp": "2026-04-16T10:00:15.000Z",
"data": {
"id": "crypto-cash-transaction-id",
"externalId": "merchant-order-id",
"status": "Waiting",
"fiatCurrency": "SGD",
"fiatAmount": "51",
"currency": "USDT",
"network": "TRC20",
"address": "wallet-address",
"cryptoAmount": null,
"exchangeRate": null,
"paymentMethod": "card",
"hash": null,
"buyId": "provider-operation-id",
"withdrawId": null,
"customerId": "customer-id",
"merchantEarning": null,
"merchantId": "merchant-id",
"createdAt": "2026-04-16T10:00:00.000Z",
"updatedAt": "2026-04-16T10:00:10.000Z"
}
},
"signature": "signature"
}
payment::paid
{
"id": "webhook-id",
"delivered_at": "2026-04-16T10:07:30.000Z",
"event": {
"event_type": "payment::paid",
"timestamp": "2026-04-16T10:07:30.000Z",
"data": {
"id": "crypto-cash-transaction-id",
"externalId": "merchant-order-id",
"status": "Paid",
"fiatCurrency": "SGD",
"fiatAmount": "51",
"currency": "USDT",
"network": "TRC20",
"address": "wallet-address",
"cryptoAmount": "50.12",
"exchangeRate": "1.02",
"paymentMethod": "card",
"hash": "blockchain-hash",
"buyId": "provider-operation-id",
"withdrawId": "provider-withdraw-id",
"customerId": "customer-id",
"merchantEarning": "0.9306",
"merchantId": "merchant-id",
"createdAt": "2026-04-16T10:00:00.000Z",
"updatedAt": "2026-04-16T10:07:00.000Z"
}
},
"signature": "signature"
}
payment::failed
{
"id": "webhook-id",
"delivered_at": "2026-04-16T10:02:05.000Z",
"event": {
"event_type": "payment::failed",
"timestamp": "2026-04-16T10:02:05.000Z",
"data": {
"id": "crypto-cash-transaction-id",
"externalId": "merchant-order-id",
"status": "Fail",
"fiatCurrency": "SGD",
"fiatAmount": "51",
"currency": "USDT",
"network": "TRC20",
"address": "wallet-address",
"cryptoAmount": null,
"exchangeRate": null,
"paymentMethod": "card",
"hash": null,
"buyId": "provider-operation-id",
"withdrawId": null,
"customerId": "customer-id",
"merchantEarning": null,
"merchantId": "merchant-id",
"createdAt": "2026-04-16T10:00:00.000Z",
"updatedAt": "2026-04-16T10:02:00.000Z"
}
},
"signature": "signature"
}
payment::canceled
{
"id": "webhook-id",
"delivered_at": "2026-04-16T10:03:05.000Z",
"event": {
"event_type": "payment::canceled",
"timestamp": "2026-04-16T10:03:05.000Z",
"data": {
"id": "crypto-cash-transaction-id",
"externalId": "merchant-order-id",
"status": "Canceled",
"fiatCurrency": "SGD",
"fiatAmount": "51",
"currency": "USDT",
"network": "TRC20",
"address": "wallet-address",
"cryptoAmount": null,
"exchangeRate": null,
"paymentMethod": "card",
"hash": null,
"buyId": "provider-operation-id",
"withdrawId": null,
"customerId": "customer-id",
"merchantEarning": null,
"merchantId": "merchant-id",
"createdAt": "2026-04-16T10:00:00.000Z",
"updatedAt": "2026-04-16T10:03:00.000Z"
}
},
"signature": "signature"
}