Вебхуки
Вебхук — це HTTP-запит, який Invoise надсилає на ваш сервер, коли змінюється платіж. Можна почати з перевірок статусу через GET і додати вебхуки, коли знадобляться автоматичні оновлення.
1. Зареєструйте свій ендпоінт
Section titled “1. Зареєструйте свій ендпоінт”curl -X POST 'https://platform.invoise.me/api/v1/shops/{shop_id}/webhooks' \ -H 'Authorization: Bearer ivk_...' \ -H 'Idempotency-Key: <saved-unique-key>' \ -H 'Content-Type: application/json' \ -d '{"url":"https://example.com/invoise","filters":["transfer","invoice","payout"]}'Використовуйте власну публічну HTTPS-адресу. Локальні та приватні адреси відхиляються. Збережіть secret, повернутий під час створення ендпоінту: він потрібен для перевірки запитів.
У магазину може бути до 10 ендпоінтів. URL ендпоінту можна змінити, тож використовуйте наявний замість додавання нового. Див. Ліміти.
2. Оберіть потрібні події
Section titled “2. Оберіть потрібні події”| Подія | Значення |
|---|---|
transfer.observed |
Переказ помічено; він ще не підтверджений. |
transfer.confirmed |
Вхідний переказ має достатньо підтверджень. Це може бути лише частковий платіж за рахунком. |
transfer.reverted |
Попередню подію переказу відкотили. |
invoice.closed |
Рахунок закрився в мережі. |
invoice.cancelled |
Сторінку оплати скасовано або в рахунку минув термін; це не повернення коштів. |
payout.sent |
Виплату розіслано в мережу або помічено її вихідний переказ. |
payout.confirmed |
Доступний повний облік розрахунку. |
payout.reverted |
Попереднє підтвердження виплати відкотили. |
payout.failed |
Остаточна невдача виплати потребує втручання. |
Для invoice.cancelled data.reason пояснює причину: expired, коли скінчився термін дії рахунку, merchant_blocked, коли персонал Invoise заблокував мерчанта. Скасування мерчантом не має reason.
Підписуйтеся за групами: transfer, invoice, payout. Вхідні перекази та вихідні виплати — різні події. Тимчасова затримка RPC чи газу — це не payout.failed.
gas.wait і sweep.failed приймаються як фільтри, але Invoise не надсилає їх на ваш ендпоінт. Це внутрішні сигнали: gas.wait означає, що виплата очікує кошти на мережеву комісію й продовжується сама; sweep.failed означає, що спроба перемістити кошти вашому отримувачу не вдалася. Для жодного з них дія не потрібна. Виплата, яка не може завершитися, доходить до вас як payout.failed.
У магазині-пісочниці можна симулювати обидва через POST /shops/{shop_id}/sandbox/simulate, щоб перевірити, що затримана виплата не ламає ваш процес. Вони змінюють лише стан виплати й не надсилають вебхук.
3. Перевірте перед обробкою
Section titled “3. Перевірте перед обробкою”Invoise-Signature має форму t=<timestamp>,v1=<hex>. Підпис — це HMAC-SHA256 від timestamp + "." + raw_body, з використанням вашого секрету вебхука.
Наступний приклад на Node.js також відхиляє часові мітки, що відрізняються від годинника сервера більш ніж на п’ять хвилин. Тримайте цей годинник синхронізованим і свідомо обирайте свій допуск.
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verify(rawBody, header, secret) { const match = /^t=(\d+),v1=([a-f0-9]{64})$/.exec(header ?? ''); if (!match) return false; const [, timestamp, signature] = match; const age = Math.abs(Date.now() / 1000 - Number(timestamp)); if (!Number.isFinite(age) || age > 300) return false; const expected = createHmac('sha256', secret) .update(timestamp + '.') .update(rawBody) .digest(); return timingSafeEqual(Buffer.from(signature, 'hex'), expected);}Передавайте оригінальні байти запиту як rawBody. Не розбирайте JSON і не перетворюйте його назад у рядок перед перевіркою підпису. Відхиляйте неправильні підписи до збереження чи дії за їхнім вмістом.
4. Обробляйте один раз
Section titled “4. Обробляйте один раз”Скорочений вміст виглядає так:
{ "id": "<event-id>", "type": "transfer.confirmed", "created_at": "2026-09-19T10:00:00Z", "data": { "issuance_id": "<issuance-id>", "shop_id": "<shop-id>", "external_id": "order-123", "type": "invoice", "invoice_cancelled": false }}| Випадок | Обробка |
|---|---|
| Дублікати | Усувайте дублікати за Invoise-Event-ID, який збігається з id конверта. Зберігайте ID і бізнес-оновлення атомарно. |
| Прийняття події | Зберігайте прийняті події надійно, повертайте 2xx одразу, а чергу обробляйте потім. |
| Повтори й відтворення | Повтори й ручні відтворення повторюють той самий ID події. Invoise-Attempt-ID змінюється і не є ключем усунення дублікатів. |
| Порядок подій | Події можуть надходити не по порядку. Використовуйте їхній вміст і за потреби звіряйте з поточним статусом. |
Для відкатів chain_event.reference_event_id вказує на попередню подію мережі. Дані виплати містять стабільний payout_id, хеш транзакції, суми та деталі комісії; невідомі суми — null. Список ID вхідних переказів у них обмежено 100 записами, з позначкою усічення.
Старіші збережені події можуть використовувати project_id; спершу читайте shop_id, а за потреби повертайтеся до нього. Відтворення зберігають оригінальні байти.
Перегляд невдалої доставки
Section titled “Перегляд невдалої доставки”Список: GET /api/v1/shops/{shop_id}/deliveries. Повторіть доставку через POST /api/v1/shops/{shop_id}/deliveries/{id}/replay зі збереженим ключем ідемпотентності. Повтор не створює нову бізнес-подію.