Документация
Host-to-host (H2H): оплата криптовалютой в вашем собственном интерфейсе
Как показать платёж CryptoLike на своём экране: адрес, точная сумма, сеть, QR и таймер из инвойса, выбор монеты через API, подтверждение заказа по вебхуку.
Host-to-host (H2H) — это схема, в которой ваш сервер создаёт платёж через API CryptoLike, а показывает его ваш собственный интерфейс: страницу CryptoLike плательщик не открывает. В каждом ответе с инвойсом есть всё, что нужно экрану оплаты, — адрес, точная сумма, сеть, данные для QR и срок оплаты, а подписанный вебхук сообщает вашему серверу, что платёж подтверждён. Ниже — когда выбирать H2H, как идёт процесс, что обязательно показать плательщику и что делать, если он отправил меньше, больше или слишком поздно.
Когда выбирать H2H, страницу оплаты или виджет
Во всех трёх вариантах один и тот же инвойс, одни и те же статусы и вебхуки. Разница в том, кто рисует экран оплаты.
| Вариант | Кто рисует экран | Когда выбирать | Что нужно сделать |
|---|---|---|---|
| Страница оплаты | CryptoLike, по checkout_url |
Нужен самый короткий путь: редирект и вебхук | Редирект с вашего бэкенда |
| Виджет оплаты | CryptoLike, во фрейме на вашей странице | Покупатель остаётся в вашей корзине, и страница CryptoLike может появиться внутри неё | Ваш origin в списке разрешённых, скрипт и правило CSP |
| H2H | Вы | Мобильное приложение, терминал, бот в мессенджере или корзина, которая целиком должна выглядеть как ваш продукт | Экран оплаты со всеми элементами из списка ниже |
Страница оплаты и виджет уже показывают предупреждение о сети, таймер, живой статус и тексты для недоплаты или истёкшего платежа на английском, русском и испанском. В H2H всё это — ваша работа, поэтому начните со страницы оплаты или виджета, если интерфейс не обязан быть полностью вашим. Виджет описан в руководстве по виджету оплаты.
Как проходит платёж
- Ваш сервер создаёт инвойс —
POST /v1/invoicesс подписью вашего API-ключа и заголовкомIdempotency-Key. Передайтеcoin_id, чтобы сразу зафиксировать монету, или не передавайте — тогда плательщик выберет её в вашем интерфейсе. - Если монета не задана, плательщик выбирает её. Сервер читает
GET /v1/invoices/{id}/coin-options, интерфейс показывает список, сервер фиксирует выбор запросомPOST /v1/invoices/{id}/coin. - Интерфейс показывает платёж из ответа с инвойсом: сеть, адрес,
payer_amount, QR, таймер доttl_expires_atи статус. - Сервер следит за статусом по вебхукам
invoice.*, а счётчик подтверждений берёт изGET /v1/invoices/{id}— не чаще раза в несколько секунд. Ваша страница спрашивает ваш сервер, а не API CryptoLike. - Сервер подтверждает заказ только по проверенному вебхуку
invoice.paid, после чего интерфейс показывает подтверждение.
Секрет API остаётся на вашем сервере. Браузер или приложение получают только то, что решил показать ваш сервер, и запросы не подписывают. Подпись описана в разделе аутентификация.
Создание инвойса
Запрос ниже сразу фиксирует монету — USDT в сети TRON. Без coin_id в ответе поля монеты, address и платёжный блок равны null, пока плательщик не выберет монету.
POST /v1/invoices HTTP/1.1
Host: api.cryptolike.net
Content-Type: application/json
Idempotency-Key: order-10042
X-API-Key: <key_id>
X-Timestamp: <unix seconds>
X-Signature: <HMAC-SHA256 of the request>
{"amount": "49.90", "currency": "USD", "coin_id": "6f1c2a3e-8d4b-4c5a-9e7f-0a1b2c3d4e5f", "order_id": "10042", "description": "Order #10042 — annual plan", "ttl_seconds": 1800, "fee_paid_by": "merchant"}В ответ приходит инвойс (значения — из примера в справочнике API):
{
"id": "4e2bc88c-cb79-4afc-b864-c1ba8e9d50c9",
"status": "new",
"currency": "USD",
"amount": "49.90",
"coin_id": "6f1c2a3e-8d4b-4c5a-9e7f-0a1b2c3d4e5f",
"ticker": "USDT",
"network": "tron",
"address": "TXYZopYRdj2D9XRtbG411XZZ3kM5VW9t7g",
"amount_crypto": "49.90",
"payer_amount": "49.90",
"paid_amount": "0",
"remaining_amount": "49.90",
"overpaid_amount": "0",
"amount_fiat": "49.90",
"fiat_currency": "USD",
"rate_locked": "1.0004",
"rate_locked_at": "2026-09-16T12:00:00Z",
"late_payment": false,
"fee_paid_by": "merchant",
"order_id": "10042",
"description": "Order #10042 — annual plan",
"return_url": null,
"webhook_url": null,
"metadata": null,
"allowed_coin_ids": null,
"checkout_url": "https://cryptolike.net/pay/4e2bc88c-cb79-4afc-b864-c1ba8e9d50c9",
"ttl_expires_at": "2026-09-16T12:30:00Z",
"expired_at": null,
"created_at": "2026-09-16T12:00:00Z",
"updated_at": "2026-09-16T12:00:00Z",
"payment_uri": "tron:TXYZopYRdj2D9XRtbG411XZZ3kM5VW9t7g?amount=49.9&token=TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"qr_payload": "TXYZopYRdj2D9XRtbG411XZZ3kM5VW9t7g",
"confirmations": null,
"required_confirmations": 20
}Поля, которые нужны экрану:
payer_amountиticker— ровно столько плательщик должен отправить. Приfee_paid_by: payerкомиссия платформы уже включена, поэтомуpayer_amountбольше, чемamount_crypto. Показывайтеpayer_amount, а неamountи неamount_crypto. Комиссии — на странице тарифов.network—btc,ltc,ethилиtron. Один тикер бывает в двух сетях (USDT в TRON и в Ethereum), и именно сеть определяет, куда отправлять.address— адрес для оплаты этого инвойса.payment_uri— ссылка, которая открывает кошелёк с адресом и суммой, которую ещё осталось оплатить: BIP-21 в Bitcoin и Litecoin, EIP-681 в Ethereum, ссылкаtron:в TRON.qr_payload— что закодировать в QR: голый адрес во всех сетях, без суммы. Многие плательщики платят с биржи, а форма вывода на бирже принимает только адрес. Если нужен «QR с суммой» для кошельков, предложите его переключателем в Bitcoin и Litecoin и закодируйте тамpayment_uri.ttl_expires_at— срок оплаты. Его задаётttl_seconds— от 60 секунд до 30 дней; без него действует настройка аккаунта (по умолчанию 30 минут). Для цены в USD или другой фиатной валюте курс вrate_lockedдо этого момента не меняется.confirmationsиrequired_confirmations— счётчик подтверждений;confirmationsравенnull, пока ничего не пришло.
Храните каждую сумму той строкой, которую вернул API: не округляйте её и не пропускайте через число с плавающей точкой.
Выбор монеты в вашем интерфейсе
Для инвойса без coin_id список монет и выбор работают через два запроса — это тот же список и та же операция, что на странице оплаты.
GET /v1/invoices/4e2bc88c-cb79-4afc-b864-c1ba8e9d50c9/coin-options{
"coin_options": [
{ "coin_id": "6f1c2a3e-8d4b-4c5a-9e7f-0a1b2c3d4e5f", "ticker": "USDT", "name": "Tether USD", "network": "tron", "network_name": "TRON",
"decimals": 6, "confirmations": 20, "estimated_amount": "49.90", "rate_as_of": "2026-09-16T12:00:03Z",
"estimate_reason": null, "estimate_message": null },
{ "coin_id": "a01d6e2b-3c4f-4a5b-8c7d-9e0f1a2b3c4d", "ticker": "BTC", "name": "Bitcoin", "network": "btc", "network_name": "Bitcoin",
"decimals": 8, "confirmations": 2, "estimated_amount": null, "rate_as_of": null,
"estimate_reason": "rate_stale",
"estimate_message": { "key": "checkout.estimate.rate_stale", "default": "The exchange rate is updating. Choose this currency to see the exact amount." } }
]
}- Рядом с каждым тикером показывайте
network_name, аestimated_amount— со знаком≈: это оценка. Если она равнаnull, покажите вместо неё текст изestimate_message; монету всё равно можно выбрать. - В список попадают только монеты, которые вы предлагаете для инвойсов и которые подходят к валюте инвойса; если у инвойса есть
allowed_coin_ids, список сужается до них. Монеты на обслуживании в него не входят. - Если монета уже выбрана, запрос отвечает
409сdetails.coin_id, а в самом инвойсе уже есть адрес.
Зафиксируйте выбор со своего сервера, с Idempotency-Key:
POST /v1/invoices/4e2bc88c-cb79-4afc-b864-c1ba8e9d50c9/coin HTTP/1.1
Content-Type: application/json
Idempotency-Key: order-10042-coin
{"coin_id": "6f1c2a3e-8d4b-4c5a-9e7f-0a1b2c3d4e5f"}В ответ приходит инвойс с address, payer_amount, payment_uri, qr_payload и ttl_expires_at — в той же форме, что выше. При выборе платёж оценивается заново и курс фиксируется, поэтому показывайте payer_amount из этого ответа, а не оценку. Отказы: 400 с details.field: coin_id — монеты нет среди вариантов; 409 — монета уже выбрана (даже та же самая) или инвойс уже не в статусе new; 503 — курс или новый адрес сейчас недоступны: подождите несколько секунд и повторите тот же запрос. Повтор с тем же Idempotency-Key вернёт первый ответ. Монету можно выбрать один раз; если у плательщика открыта ещё и страница оплаты, она сразу переключится на платёж.
Что обязательно показать на экране оплаты
Все эти элементы есть на странице оплаты CryptoLike; на вашем экране нужен каждый из них.
| Элемент | Поле | Зачем |
|---|---|---|
| Сеть словами, для токена — со стандартом (TRON, TRC20) | network, ticker |
Одинаковые тикеры и форматы адресов есть в нескольких сетях |
| Предупреждение о неправильной сети рядом с адресом | ticker, network |
«Отправляйте на этот адрес только USDT в сети TRON. Средства, отправленные в другой сети, вернуть невозможно.» |
| Адрес с кнопкой копирования | address |
Плательщик вставляет его в кошелёк; средства на адрес с опечаткой вернуть нельзя |
| Точная сумма с кнопкой копирования | payer_amount, ticker |
Перевод меньше суммы становится недоплатой |
| QR-код и сумма рядом с ним | qr_payload |
QR содержит только адрес во всех сетях |
| Ссылка «Открыть в кошельке» | payment_uri |
Одно нажатие на телефоне, где установлен кошелёк |
| Сколько осталось времени | ttl_expires_at |
После срока инвойс истекает, а более поздний перевод считается поздней оплатой |
| Статус и подтверждения, пока платёж ждёт | status, confirmations, required_confirmations |
«Платёж обнаружен, 3 из 20 подтверждений» — плательщик не отправит второй раз |
| Экран результата | status, paid_amount, remaining_amount |
Оплачен, недоплачен с остатком, истёк или отменён — и следующий шаг для каждого случая |
Отсчитывайте таймер по часам вашего сервера, а не устройства плательщика. Когда время вышло, скройте адрес и QR и предложите создать новый платёж. Статусы — new, pending, paid, underpaid, expired и cancelled; почему перевод ждёт, прежде чем засчитаться, объясняет статья о подтверждениях.
Недоплата, переплата и поздняя оплата
- Недоплата. Подтверждённый перевод меньше
payer_amountпереводит инвойс вunderpaidи отправляетinvoice.underpaid; нехватка в пределах допуска недоплаты вашего аккаунта всё равно считаетсяpaid. Инвойс открыт для доплаты на тот же адрес доttl_expires_at: покажитеremaining_amountи обновлённыйpayment_uri— теперь в нём остаток. После срока недоплата окончательная; попросите плательщика связаться с вами. Подробнее — недоплата. - Переплата. Статус
paid, аoverpaid_amountбольше нуля; его несётinvoice.paid, который приходит повторно, когда следующий перевод увеличивает переплату. Вся сумма зачисляется на ваш баланс; разницу урегулируйте с покупателем. - Поздняя оплата. Перевод, подтверждённый после закрытия инвойса (
expired,cancelledили окончательныйunderpaid), всё равно зачисляется на ваш баланс: инвойс получаетlate_payment: true, вам приходитinvoice.late_payment, статус не меняется. Так же бывает, когда перевод к сроку уже обнаружен, но ещё не подтверждён: инвойс истекает, а перевод приходит как поздняя оплата. Решите, выполнить заказ или вернуть деньги. Подробнее — истёкший платёж. - Откат. Если реорганизация сети убирает подтверждённый перевод, вам приходит
invoice.revertedс пересчитанными суммами. Остановите выполнение заказа до новогоinvoice.paid.
Подтверждайте заказ только по вебхуку
Выполняйте заказ, когда ваш сервер получил invoice.paid с верной подписью вебхука, — а не когда плательщик нажал «Я оплатил» и не по статусу, который увидела ваша страница. Доставка — как минимум один раз: сохраняйте event_id, отвечайте 2xx в течение 10 секунд и пропускайте повторы. Вебхуки одинаковы для H2H, страницы оплаты и виджета и не содержат payment_uri, qr_payload и счётчика подтверждений — когда они нужны, читайте GET /v1/invoices/{id}. Типы событий, повторы и тестовый вектор — в справочнике по вебхукам, пошагово — в руководстве как проверять вебхуки платежей.
Перед запуском проведите в тестовой сети по одному платежу на каждый случай: оплачен, недоплачен и потом доплачен, истёк и пришёл с опозданием. Тестовая среда описана в руководстве разработчика.
Вопросы и ответы
Нужен ли виджет для H2H?
Нет. В H2H экран рисует ваш интерфейс по полям инвойса, и в браузер плательщика ничего от CryptoLike не загружается. Виджет — другой вариант: страница оплаты CryptoLike во фрейме внутри вашей корзины.
Можно ли всё-таки отправить плательщика на страницу оплаты?
Да. У каждого инвойса есть checkout_url, и страница оплаты показывает тот же инвойс. Монета, выбранная через API, сразу переключает открытую страницу на платёж, поэтому страницу можно предложить как запасной вариант — например, плательщику, у которого кошелёк на другом устройстве.
Меняются ли вебхуки в H2H?
Нет. События, подпись и повторы те же, что со страницей оплаты. Платёжного блока инвойса — payment_uri, qr_payload, confirmations и required_confirmations — в теле вебхука нет; читайте инвойс через GET /v1/invoices/{id}.
Какую сумму отправляет плательщик, если комиссию платит он?
payer_amount. При fee_paid_by: payer в неё уже входит комиссия платформы, а amount_crypto — то, что получаете вы. Показывайте payer_amount и храните её той строкой, которую вернул API.