Приём криптоплатежей Finem
Finem принимает оплату в USDT (TRC-20, сеть TRON) по инвойсовой модели: вы создаёте инвойс через API, показываете покупателю ссылку на страницу оплаты, Finem отслеживает поступление в блокчейне и уведомляет вас вебхуком.
Как это работает
- Ваш сервер создаёт инвойс —
POST /api/invoice— и получаетpaymentUrl. - Покупатель переходит по
paymentUrl: видит сумму в USDT, QR-код и адрес кошелька, отправляет перевод. - Finem видит транзакцию в сети (статус
Confirming), дожидается подтверждения и закрывает инвойс (Success). - На каждую смену статуса вам уходит вебхук на
urlCallback.
Аутентификация
Все запросы мерчанта подписываются заголовком X-API-KEY — ключ выдаётся вместе с
аккаунтом и виден в панели (Settings). Ключ секретный: не публикуйте его в клиентском коде и репозиториях.
X-API-KEY: ваш-ключ-мерчанта
Создание инвойса
| Поле | Тип | Описание |
|---|---|---|
amount обязательное | number | Сумма в валюте currency. Больше нуля. |
currency обязательное | string | Код валюты: фиат (RUB, KZT, …) или USDT.
Фиат конвертируется в USDT по курсу на момент создания, курс фиксируется в инвойсе. |
orderId обязательное | string | Идентификатор заказа в вашей системе. Ключ идемпотентности: повторный запрос
с тем же orderId вернёт уже созданный инвойс, а не новый. |
lifetime | int | Срок жизни инвойса в секундах, 300–43200. По умолчанию 1800 (30 минут). |
urlCallback | string | URL для вебхуков по этому инвойсу. Если не задан — берётся callback-адрес мерчанта из профиля. |
urlSuccess | string | Кнопка «Вернуться в магазин» на странице оплаты после успешной оплаты. |
urlReturn | string | Кнопка возврата при отмене или недоплате. |
curl -X POST {baseUrl}/api/invoice \
-H "X-API-KEY: <ключ>" -H "Content-Type: application/json" \
-d '{
"amount": 1000,
"currency": "RUB",
"orderId": "shop-order-482",
"urlCallback": "https://shop.example/finem/hook",
"urlSuccess": "https://shop.example/thanks"
}'
Ответ:
{
"orderId": 42,
"merchantOrderId": "shop-order-482",
"paymentUrl": "{baseUrl}/pay.html?pt=WtzAkHHVPP-RMV3lhpcazQ...",
"walletAddress": "T...",
"network": "TRC20",
"amountUsdt": 10.53,
"amountFiat": 1000,
"currency": "RUB",
"rate": 95,
"status": "Pending",
"expiresAt": "2026-07-05T12:00:00Z"
}
paymentUrl — ссылка для покупателя. amountUsdt — сумма, которую он должен
отправить (страница оплаты показывает её сама).
Статус инвойса
Публичный эндпоинт (без ключа): pt — токен из paymentUrl. Его же опрашивает
страница оплаты. Удобен, чтобы сверить статус при получении вебхука.
{
"orderId": 42,
"status": "Success",
"walletAddress": "T...",
"network": "TRC20",
"amountUsdt": 10.53,
"amountFiat": 1000,
"receivedUsdt": 12.0,
"paidOver": true,
"currency": "RUB",
"expiresAt": "2026-07-05T12:00:00Z",
"uiPollSeconds": 5,
"urlSuccess": "https://shop.example/thanks",
"urlReturn": null
}
Статусы и жизненный цикл
Основной путь: Pending → Confirming → Success. Терминальные статусы:
Success, WrongAmount, Expired, Canceled.
| Статус | Значение |
|---|---|
| Pending | Инвойс создан, ждём поступление в блокчейне. |
| Confirming | Транзакция видна в сети, ждём подтверждения. Деньги ещё не зачислены. Обычно длится меньше минуты. |
| Success | Оплачено и подтверждено сетью. receivedUsdt — фактически полученная сумма;
при переплате в пределах допуска paidOver = true, зачисляется всё полученное. |
| WrongAmount | Недоплата сверх допуска. Терминальный: инвойс закрыт, средства ожидают ручного разбора оператором. Покупатель видит «получена неполная сумма». |
| Expired | Не оплачен в течение lifetime. |
| Canceled | Отменён вручную оператором. |
Confirming), инвойс всё равно закроется в
Success.Допуски сумм
Сумма перевода сверяется с суммой инвойса. Значения по умолчанию (настраиваются на стороне Finem):
| Ситуация | Правило по умолчанию | Результат |
|---|---|---|
| Недоплата «на комиссию» | не больше 5 USDT и не больше 20% от суммы | Success, зачисляется фактическая сумма |
| Переплата | не больше 5 USDT | Success, paidOver = true, зачисляется всё полученное |
| Недоплата сверх допуска | получено ≥ 50% суммы | WrongAmount, средства на ручном разборе |
| Прочее (слишком мало / слишком много) | — | Инвойс остаётся активным, перевод уходит в очередь ручного разбора |
Страница оплаты
paymentUrl ведёт на хостед-страницу Finem: сумма в USDT, QR-код (генерируется локально,
адреса не передаются третьим сторонам), адрес кошелька с кнопкой копирования и таймер. Страница сама
обновляет состояние: «платёж обнаружен, ждём подтверждения», «оплачено», «получена неполная сумма»,
«время истекло». Кнопки возврата берутся из urlSuccess / urlReturn.
POS-терминал
Альтернатива серверному API — публичная страница приёма оплаты без интеграции. Включается в панели
мерчанта (Settings → «POS-терминал») и выдаёт постоянную ссылку с публичным токеном PosToken:
он позволяет только создавать инвойсы в вашу пользу, доступа к данным или балансу не даёт.
Обычная ссылка
Покупатель сам вводит сумму и валюту, видит конвертацию в USDT и таймер актуальности курса (2 минуты),
затем нажимает «Перейти к оплате» — инвойс создаётся тем же способом, что и через
POST /api/invoice, и покупатель попадает на обычную страницу оплаты.
Ссылка с фиксированной суммой
Чтобы покупателю не приходилось вводить сумму — например, для ссылки на конкретный товар или
готовый счёт — добавьте в ту же ссылку параметры amount и currency:
| Параметр | Описание |
|---|---|
amount | Сумма в указанной валюте. Больше нуля. |
currency | Код валюты — тот же список, что и при создании инвойса через API. |
Поля суммы и валюты становятся нередактируемыми и уже заполнены переданными значениями, но форма, котировка в USDT и кнопка «Перейти к оплате» остаются видимыми — покупатель подтверждает переход сам. Такую ссылку можно собрать и прямо в панели мерчанта (Settings → «Ссылка с фиксированной суммой»).
PosToken отзывается и перегенерируется мгновенно (кнопки
«Перегенерировать» / «Выключить» в Settings) — старые ссылки терминала после этого перестают работать.Вебхуки: формат и доставка
При каждой смене статуса Finem отправляет POST с JSON на urlCallback
инвойса (или callback-адрес мерчанта, если у инвойса свой не задан):
{
"orderId": 42,
"merchantOrderId": "shop-order-482",
"status": "Success",
"amountUsdt": 10.53,
"receivedUsdt": 10.53,
"paidOver": false,
"currency": "RUB",
"txHash": "9df31a..."
}
Правила доставки:
- Успехом считается любой HTTP-ответ 2xx. Таймаут — 10 секунд.
- При неудаче — повторы с экспоненциальной задержкой (30 с → 1 м → 2 м → … до 1 часа), максимум 10 попыток.
- Гарантия — at-least-once: обработчик должен быть готов к дублям.
Ключ идемпотентности — пара
orderId + status.
GET /api/invoice/status и не доверять только телу
уведомления.Переотправка вебхука
Ставит в очередь вебхук с текущим статусом инвойса — например, если ваш обработчик был
недоступен дольше окна ретраев. Требует X-API-KEY.
{ "orderId": "shop-order-482" } // ваш orderId из создания инвойса
Ответ 202 — поставлено в очередь; 400 — у инвойса нет callback-адреса;
404 — инвойс не найден.
Тестовый вебхук
Для отладки обработчика: синхронно шлёт payload той же формы, что и боевой, с полем
"test": true, и сразу возвращает результат. В очередь не пишется, ретраев нет.
Требует X-API-KEY.
// запрос
{ "url": "https://shop.example/finem/hook", "status": "WrongAmount" }
// url необязателен (возьмётся callback мерчанта), status по умолчанию Success
// ответ
{ "delivered": true, "httpStatus": 200, "url": "https://shop.example/finem/hook" }
Ошибки
| Код | Тело | Причина |
|---|---|---|
401 | текст | Нет заголовка X-API-KEY или ключ неверный/неактивный. |
400 | {"error":"invalid"} | Сумма ≤ 0 или пустой orderId. |
400 | {"error":"bad_currency"} | Валюта не поддерживается / нет курса. |
409 | {"error":"no_available_wallets"} |
Нет свободного кошелька под эту сумму — повторите позже или измените сумму на несколько USDT. |
404 | — | Инвойс не найден (статус/переотправка). |
Валюты и сеть
Приём — только USDT TRC-20 (сеть TRON). Валюта инвойса: USDT либо фиат —
RUB, KZT, UZS, TJS, KGS,
VND, PHP, GEL, IDR, MDL,
THB (список расширяется). Курс фиксируется на момент создания инвойса и возвращается
в поле rate.
Finem · документация API v1 · вопросы — вашему менеджеру