Главная
/H2H-интеграция (White Label)
Копировать страницу
Эта инструкция описывает приём криптоплатежей через прямое серверное взаимодействие (server-to-server) с API Heleket. В отличие от интеграции через готовую платёжную страницу, при H2H ваш бэкенд сам создаёт инвойс, получает реквизиты для оплаты и обрабатывает уведомления о статусе платежа. Платёжную форму при этом вы можете отрисовывать на своей стороне или использовать ссылку url из ответа API.
Для приёма платежей вам потребуются два значения из личного кабинета:
| Значение | Где взять |
|---|---|
| Merchant ID | UUID мерчанта. Раздел Бизнес → Мерчанты → Настройки мерчанта. |
| API-ключ платежей | Генерируется в настройках мерчанта после прохождения модерации. |
Ключ выплат — отдельный, выпускается в Настройки → API личного кабинета и требует подключённой 2FA. Для приёма платежей он не нужен.
Базовый endpoint всех запросов:
Все запросы отправляются методом POST в формате JSON и должны быть подписаны.
Каждый запрос аутентифицируется двумя HTTP-заголовками:
| Заголовок | Значение |
|---|---|
| merchant | Ваш Merchant ID (UUID). |
| sign | Подпись тела запроса. |
| Content-Type | application/json |
Алгоритм подписи: MD5 от строки, состоящей из base64-кодированного JSON-тела запроса, склеенного с вашим API-ключом.
$body = json_encode($data);
$sign = md5(base64_encode($body) . $API_KEY);КопироватьЕсли тело запроса пустое (запрос без параметров), подпись считается от пустой строки:
$sign = md5(base64_encode('') . $API_KEY);КопироватьВажно про экранирование слешей. PHP по умолчанию экранирует / в JSON (\/), а многие другие языки — нет. Подпись считается от той же строки, что отправляется в теле, поэтому строка для подписи и тело запроса должны быть байт в байт идентичны. В не-PHP стеках экранируйте слеши вручную, иначе подпись не сойдётся (та же проблема возникает при проверке вебхуков, см. раздел 5).
curl https://api.heleket.com/v1/payment \
-X POST \
-H 'merchant: 8b03432e-385b-4670-8d06-064591096795' \
-H 'sign: fe99035f86fa436181717b302b95bacff1' \
-H 'Content-Type: application/json' \
-d '{"amount":"15","currency":"USD","order_id":"1"}'КопироватьНе полагайтесь только на вебхук: всегда держите fallback через /v1/payment/info (раздел 6) на случай, если callback не дошёл.
Endpoint:
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
| amount | string | да | Сумма к оплате. Дробная часть через точку, напр. 10.28. |
| currency | string | да | Код валюты инвойса (фиат или крипта), напр. USD, USDT, BTC. |
| order_id | string | да | Ваш идентификатор заказа. Только буквы, цифры, _ и -. Должен быть уникальным. |
| network | string | нет | Код блокчейн-сети, напр. tron, bsc, eth. |
| to_currency | string | нет | Целевая крипта для пересчёта суммы (всегда код криптовалюты, не фиат). |
| url_callback | string | нет | URL, на который Heleket шлёт вебхуки со статусом. Обязателен для H2H по факту. |
| url_return | string | нет | Куда вернуть клиента из платёжной формы до оплаты. |
| url_success | string | нет | Куда вернуть клиента после успешной оплаты. |
| lifetime | integer | нет | Срок жизни инвойса в секундах (300–43200, по умолчанию 3600). |
| subtract | integer | нет | Какой % комиссии переложить на клиента (0–100). |
| accuracy_payment_percent | numeric | нет | Допустимая недоплата в % (0–5): инвойс закроется как оплаченный при недоплате в пределах. |
| is_payment_multiple | boolean | нет | Разрешить дооплату остатка. По умолчанию true. |
| additional_data | string | нет | Произвольная строка для вас (клиенту не видна), до 255 символов. |
| currencies | array | нет | Белый список валют/сетей для оплаты. |
| except_currencies | array | нет | Чёрный список валют/сетей. |
| discount_percent | integer | нет | Скидка (положит.) или наценка (отрицат.), от -99 до 100. |
| is_refresh | boolean | нет | Обновить просроченный инвойс по тому же order_id (новый адрес и срок). |
Про order_id: если инвойс с таким order_id уже существует, новый создан не будет — вернутся реквизиты существующего. Это удобно для идемпотентности: повторный запрос по тому же заказу безопасен.
Когда сразу приходит адрес кошелька. Поле address заполняется в момент создания только если валюта оплаты однозначно определена: задана крипта + сеть (to_currency + network), либо у криптовалюты единственная сеть (напр. BTC). Иначе клиент выбирает валюту/сеть на платёжной странице, и address появится позже.
Минимальный инвойс на 15 USD (клиент сам выберет крипту и сеть):
{ "amount": "15", "currency": "USD", "order_id": "1" }КопироватьИнвойс на 20 USDT в сети TRON — адрес будет сразу:
{ "amount": "20", "currency": "USDT", "order_id": "1", "network": "tron" }КопироватьИнвойс на 25 USD, оплата только в USDT в любой сети:
{ "amount": "25", "currency": "USD", "order_id": "1", "to_currency": "USDT" }Копировать{
1 "state": 0,
2 "result": {
3 "uuid": "1ec87133-b22d-4643-988f-cac29a6ac85d",
4 "order_id": "3",
5 "amount": "20000.00",
6 "payment_amount": null,
7 "payer_amount": "254.92",
8 "payer_currency": "USDT",
9 "currency": "RUB",
10 "merchant_amount": "249.82816502",
11 "network": "bsc",
12 "address": "0x2b...",
13 "txid": null,
14 "payment_status": "check",
15 "url": "https://pay.heleket.com/pay/1ec87133-b22d-4643-988f-cac29a6ac85d",
16 "expired_at": 1753202502,
17 "is_final": false,
18 "commission": "5.09853397",
19 "address_qr_code": "data:image/png;base64 ..."
20 }
21}Копировать| Поле | Назначение |
|---|---|
| uuid | UUID инвойса в Heleket. Сохраните рядом с заказом. |
| address | Адрес кошелька для оплаты (может быть null, пока валюта не выбрана). |
| payer_amount | Сумма к оплате в payer_currency (с учётом скидки/наценки). |
| payer_currency | Валюта оплаты. null — клиент ещё не выбрал. |
| merchant_amount | Сколько зачислится на ваш баланс за вычетом комиссий. |
| payment_status | Текущий статус (см. раздел 7). |
| url | Ссылка на платёжную страницу Heleket (если не рисуете форму сами). |
| address_qr_code | QR-код адреса в base64 — можно показать клиенту напрямую. |
| expired_at | Unix-таймстамп истечения инвойса. |
| is_final | true — инвойс закрыт (оплачен или просрочен), оплатить уже нельзя. |
state: 0 означает успех. При ошибках валидации state: 1 (раздел 8).
При каждой смене статуса инвойса Heleket отправляет POST на ваш url_callback.
| Поле | Описание |
|---|---|
| type | Тип: payment или wallet. |
| uuid | UUID платежа. |
| order_id | Ваш идентификатор заказа — по нему находите заказ. |
| amount | Сумма инвойса. |
| payment_amount | Сколько фактически заплатил клиент. |
| payment_amount_usd | Фактически уплачено в USD. |
| merchant_amount | Зачислено на баланс за вычетом комиссии. |
| commission | Комиссия Heleket. |
| is_final | Закрыт ли инвойс окончательно. |
| status | Статус платежа (см. раздел 7). |
| from | Адрес кошелька плательщика. |
| network | Сеть платежа. |
| currency | Валюта инвойса. |
| payer_currency | Валюта, которой реально оплатили. |
| txid | Хэш транзакции в блокчейне (может отсутствовать при p2p/ручном закрытии). |
| sign | Подпись вебхука для проверки. |
{
1 "type": "payment",
2 "uuid": "62f88b36-a9d5-4fa6-aa26-e040c3dbf26d",
3 "order_id": "97a75bf8eda5cca41ba9d2e104840fcd",
4 "amount": "3.00000000",
5 "payment_amount": "3.00000000",
6 "merchant_amount": "2.94000000",
7 "commission": "0.06000000",
8 "is_final": true,
9 "status": "paid",
10 "from": "THgEWubVc8tPKXLJ4VZ5zbiiAK7AgqSeGH",
11 "network": "tron",
12 "currency": "TRX",
13 "payer_currency": "TRX",
14 "txid": "6f0d9c8374db57cac0d806251473de754f361c83a03cd805f74aa9da3193486b",
15 "sign": "a76c0d77f3e8e1a419b138af04ab600a"
16}КопироватьПоскольку по вебхуку вы выдаёте товар или пополняете баланс пользователя, нужно убедиться, что запрос пришёл именно от Heleket. Проверяйте обоими способами:
// 1. Считываем сырое тело запроса
1$data = json_decode(file_get_contents('php://input'), true);
2
3// 2. Достаём и убираем подпись из массива
4$sign = $data['sign'];
5unset($data['sign']);
6
7// 3. Считаем хэш от тела (без sign) + ваш API-ключ платежей
8$hash = md5(base64_encode(json_encode($data, JSON_UNESCAPED_UNICODE)) . $apiPaymentKey);
9
10// 4. Сверяем
11if (!hash_equals($hash, $sign)) {
12 // подпись неверна — отклонить
13 http_response_code(400);
14 exit;
15}КопироватьТа же проблема со слешами, что и в разделе 2: при кодировании JSON вне PHP экранируйте / вручную (JSON.stringify(data).replace(/\//g, "\\/") в JS), иначе подпись не совпадёт.
Endpoint:
Передайте uuid или order_id (если передать оба — приоритет у order_id).
curl https://api.heleket.com/v1/payment/info \
-X POST \
-H 'merchant: 8b03432e-385b-4670-8d06-064591096795' \
-H 'sign: <подпись тела>' \
-H 'Content-Type: application/json' \
-d '{"order_id":"1"}'КопироватьОтвет — тот же объект платежа, что и при создании, с актуальным payment_status и is_final. Используйте этот метод как периодическую сверку для «зависших» заказов, а не как основной механизм (вебхуки быстрее и дешевле по запросам).
| Статус | Финальный | Значение |
|---|---|---|
| check | нет | Ожидание появления транзакции в блокчейне. |
| process | нет | Платёж обрабатывается. |
| confirm_check | нет | Транзакция видна, ждём нужное число подтверждений сети. |
| wrong_amount_waiting | нет | Недоплата с возможностью доплатить остаток. |
| paid | да | Оплачено ровно на нужную сумму. Выдавайте товар. |
| paid_over | да | Оплачено больше, чем требовалось. Выдавайте товар. |
| wrong_amount | да | Клиент заплатил меньше, чем требовалось. |
| fail | да | Ошибка при оплате. |
| cancel | да | Платёж отменён, клиент не оплатил. |
| system_fail | да | Системная ошибка. |
| locked | да | Средства заблокированы по программе AML. |
| refund_process | нет | Возврат обрабатывается. |
| refund_paid | да | Возврат выполнен. |
| refund_fail | да | Ошибка при возврате. |
Считайте платёж успешным при paid и paid_over. Для статусов вебхука дополнительно встречается confirm_check как промежуточный «почти готово».
Ошибки валидации — HTTP 422, state: 1:
{ "state": 1, "errors": { "amount": ["validation.required"] } }КопироватьЧастые сообщения (state: 1, поле message):
| Сообщение | Причина |
|---|---|
| The network was not found | Передан неподдерживаемый код сети. |
| The currency was not found | Неподдерживаемый код в currency. |
| Not found service to_currency | Нет сервиса под валюту to_currency. |
| Minimum amount 0.5 USDT | Сумма меньше минимума для валюты. |
| Maximum amount 10000000 USDT | Сумма больше максимума для валюты. |
| Wallet not found | Нет активного торгового кошелька под валюту платежа. |
| You are forbidden | Платежи заблокированы — обратитесь в поддержку. |
| Gateway error / Server error | Технические работы, платёж временно недоступен. |
Внутренняя ошибка — HTTP 500:
{ "message": "Server error, #1", "code": 500, "error": null }КопироватьНа стороне клиента трактуйте Gateway error / Server error / 500 как временные и применяйте повтор с экспоненциальной задержкой.
Справочник кодов валют и сетей, методы возвратов, статические кошельки и выплаты — в соответствующих разделах документации Heleket.