# Webhook URL

## Опис

Завдання цього функціоналу — передати дані про оплачений рахунок на сервер продавця. Це потрібно, щоб автоматично обробити платіж у магазині продавця й видати товар або послугу вашому покупцеві.

WH URL встановлюється індивідуально для кожного проєкту у вигляді посилання на скрипти й обробники платежів усередині магазину продавця. Адреса має бути на https і на доменному імені: IP-адреси не приймаються, сертифікат перевіряється під час кожного надсилання.

Щоразу, коли статус рахунку змінюється на «Оплачений» (Paid), сервіс надсилає POST запит на цей URL у такому форматі:

```json
{
   "wallet":{
      "id":"47aa71e2-07a0-482e-9172-7114d7376ba0",
      "name":"usdt-tron",
      "blockchain":"tron",
      "cryptocurrency":"usdt",
      "address":"TKbstUwMzLrfTAGL4erYb7gc7ghmHQ9zG7"
   },
   "project":{
      "id":"9deea1e2-0c08-41a3-bdc2-a34eada3892d",
      "name":"My project",
      "commissionPayer":"seller",
      "commissionRate":1
   },
   "invoice":{
      "id":"a4c9e2ee-9a03-43e5-a1a1-00caf679d16a",
      "uid":"AFhygKX21ecd",
      "createDatetime":"2024-02-26 13:29:24",
      "timeToPayDatetime":"2024-02-27 01:29:24",
      "commissionFiatUSD":0.05,
      "amountFiatUSD":5.02,
      "amountFiat":5,
      "calcAmountFiat":5.02,
      "currencyFiat":"USD",
      "description":null,
      "serviceData":null,
      "status":"paid"
   },
   "payment":{
      "id":"f986ad8d-2298-473d-982a-efbc817b975d",
      "amount":5.02,
      "hash":"74763b65e43bcc9492a6ce9a7f26fbfdbd7635aecd3454420b5e9534cba50ee6",
      "transactionDatetime":"2024-02-26 13:32:57"
   }
}
```

Сповіщення надсилається за будь-якого переходу рахунку в статус «Оплачений» — і коли сервіс знайшов платіж автоматично, і коли продавець прив’язав платіж до рахунку вручну.

## Параметри запиту

| Параметр | Опис |
| --- | --- |
| `wallet.id` | ID гаманця у форматі UUID |
| `wallet.name` | Назва гаманця |
| `wallet.blockchain` | Блокчейн криптогаманця |
| `wallet.cryptocurrency` | Криптовалюта гаманця |
| `wallet.address` | Адреса криптогаманця |
| `project.id` | ID проєкту у форматі UUID |
| `project.name` | Назва проєкту |
| `project.commissionPayer` | Платник комісії |
| `project.commissionRate` | Розмір комісії у % |
| `invoice.id` | ID рахунку у форматі UUID |
| `invoice.uid` | ID рахунку (для покупця) |
| `invoice.createDatetime` | Дата й час створення рахунку (UTC) |
| `invoice.timeToPayDatetime` | Дата й час, до якого рахунок дійсний для покупця (UTC). Пошук платежів за рахунком триває ще 1 годину після цієї позначки — з огляду на повільні мережі. Тому сповіщення може надійти за рахунком, який уже відображався як прострочений |
| `invoice.commissionFiatUSD` | Сума комісії сервісу. Розраховується відносно суми `invoice.amountFiatUSD` |
| `invoice.amountFiatUSD` | Сума у валюті USD. Під час створення рахунку розраховується за поточним курсом відносно суми `invoice.amountFiat`. **У момент оплати перезаписується фактично отриманою сумою**, приведеною до USD за курсом на цей момент. Від неї ж перераховується комісія в `invoice.commissionFiatUSD` |
| `invoice.amountFiat` | Оригінальна сума рахунку у фіатній валюті. Не змінюється |
| `invoice.calcAmountFiat` | Розрахована сума у валюті `invoice.currencyFiat` за курсом криптовалюти на момент оплати. Цей параметр може відрізнятися від суми в `invoice.amountFiat` через те, що покупець міг оплатити рахунок не одразу після створення, а через деякий час. За цей час курс криптовалюти відносно `invoice.currencyFiat` міг змінитися в будь-який бік |
| `invoice.currencyFiat` | Валюта фіату |
| `invoice.description` | Опис, заданий під час створення рахунку |
| `invoice.serviceData` | Службові дані, задані під час створення рахунку |
| `invoice.status` | Статус рахунку |
| `payment.id` | ID платежу у форматі UUID |
| `payment.amount` | Сума платежу в криптовалюті |
| `payment.hash` | Хеш транзакції в блокчейні |
| `payment.transactionDatetime` | Дата й час транзакції в блокчейні (UTC) |

## Підпис сповіщення

Кожен запит підписується секретом вебхука. Підпис передається в заголовках `X-Timestamp` і `X-Signature` й дає змогу переконатися, що сповіщення надіслав сервіс, а не сторонній, який дізнався адресу вашого обробника.

Перевіряйте підпис до обробки замовлення. Механіка й готові приклади — у розділі «[Перевірка підпису вебхука](./signature-verification.md)».

## Рекомендації щодо обробки

**Не відхиляйте сповіщення через строк оплати, що минув.** Перевірка на кшталт «рахунок прострочено, отже оплата невалідна» виглядає логічно, але відсікає частину реальних платежів: у повільних мережах транзакція може підтвердитися вже після закінчення строку, а продавець може прив’язати платіж до простроченого рахунку вручну. Факт оплати підтверджується самим сповіщенням.

**Звіряйте суму за оригінальним полем** `invoice.amountFiat`. Це сума рахунку в тому вигляді, у якому її було виставлено, вона не змінюється. Поле `amountFiatUSD` відображає фактично отриману суму й може відрізнятися від виставленої — як через рух курсу, так і через ручну прив’язку платежу.

**Розбирайте суми як числа.** Незначущі нулі зникають: сума 10.00 надійде як 10, для показу форматуйте на своєму боці. Суми менші за 0.0001 надходять в експоненційному записі, наприклад 1.0e-6 — штатний розбір JSON віддасть правильне число, зламається лише ручний розбір рядка.

**Обробляйте сповіщення ідемпотентно.** Те саме сповіщення може надійти повторно — наприклад, якщо ваш скрипт успішно обробив платіж, але повернув код, відмінний від 2xx. Перед видачею товару перевіряйте, чи не було цей `invoice.id` уже оброблено.

**Екрануйте значення під час виведення.** Поля `invoice.description` і `invoice.serviceData` повертаються рівно в тому вигляді, у якому їх передав продавець. Якщо виводите їх у HTML — екрануйте на своєму боці.

## Періодичність доставки

За адресою WH URL сервер має відповісти з HTTP кодом 2xx. Будь-який інший код, таймаут або обрив з’єднання вважаються невдалою доставкою.

Редиректи не виконуються: відповідь 301 або 302 — це невдала доставка, а не перехід за новою адресою. Вказуйте кінцеву адресу обробника.

На з’єднання відводиться 5 секунд, на весь запит — 10 секунд. Якщо обробник не вклався, доставка вважається невдалою.

У разі невдалої доставки сервіс надсилає повторні запити з такою періодичністю:

* Через 5 хвилин після останньої невдалої доставки
* Через 15 хвилин
* Через 30 хвилин
* Через 1 годину
* Через 3 години
* Через 6 годин
* Через 12 годин
* Через 24 години

Подальші спроби доставки сповіщення припиняються.

## Вимкнення WH URL

Іноді WH скрипт інтернет-магазину за коректної обробки платежу віддає HTTP код, відмінний від 2xx. Це призводить до частих повторних періодичних запитів нашим сервером за таймінгами, вказаними в попередньому розділі, що дає зайве навантаження на наш і клієнтський сервер.

Щоб запобігти таким випадкам, у нас працює механізм вимкнення WH URL у проєкті. Щоб цього не сталося, виконайте такі кроки:

1. Змініть програмний код WH URL так, щоб у разі успішної обробки платежу він віддавав код 2xx, зазвичай 200. Перевірте за допомогою будь-якого емулятора, наприклад Postman.
2. Напишіть у техпідтримку для корекції налаштувань.
3. Знову ввімкніть WH URL у налаштуваннях проєкту та збережіть проєкт.
