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"
}