Интеграция Binance Pay v3 в Битрикс: создание платежа, webhook и пополнение баланса пользователя
Интеграция Binance Pay с сайтом на 1С-Битрикс может использоваться не только для оплаты обычных заказов, но и для пополнения внутреннего баланса пользователя. Такой сценарий часто встречается в личных кабинетах, сервисах, маркетплейсах, форумах с платными функциями, B2B-порталах и проектах, где пользователь заранее вносит средства, а потом расходует их внутри сайта.
На первый взгляд задача выглядит просто: пользователь ввел сумму, оплатил через Binance Pay, а сайт увеличил его баланс. Но технически это полноценная платежная интеграция: нужно создать ордер, подписать запрос, сохранить платеж в базе, принять webhook, проверить статус оплаты, защититься от повторной обработки и только после этого обновить пользовательское поле баланса.
Такие задачи относятся к кастомной разработке на PHP и Битрикс. Если нужно подключить оплату, доработать личный кабинет, исправить обработку webhook или связать платежную систему с внутренним балансом, это можно реализовать в рамках услуги доработки Bitrix и PHP-задачи.
Как работает схема пополнения баланса
Общий процесс интеграции Binance Pay v3 можно разделить на несколько этапов:
- Пользователь вводит сумму пополнения на сайте.
- Сервер создает платежный ордер в Binance Pay.
- Binance возвращает данные для оплаты: ссылку, QR-код или deeplink.
- Пользователь оплачивает через приложение или платежную страницу Binance.
- Binance отправляет webhook на сайт.
- Сервер проверяет статус платежа и находит внутреннюю запись заказа.
- Если платеж успешный и ранее не был обработан, баланс пользователя увеличивается.
- Фронтенд через AJAX проверяет статус и закрывает окно оплаты.
Важно: баланс пользователя нельзя обновлять сразу после создания платежа или открытия QR-кода. Деньги нужно зачислять только после подтверждения оплаты через webhook.
Создание платежа через Binance Pay v3
Для создания платежа используется endpoint:
POST /binancepay/openapi/v3/order
Минимальный payload для пополнения баланса может выглядеть так:
{
"merchantTradeNo": "ORDER123456789",
"orderAmount": "10.00",
"currency": "USDT",
"env": {
"terminalType": "WEB"
},
"description": "Balance Top-up",
"goodsDetails": [
{
"goodsType": "01",
"goodsCategory": "D000",
"referenceGoodsId": "balance_topup",
"goodsName": "Balance Top-up"
}
],
"returnUrl": "https://example.com/success",
"cancelUrl": "https://example.com/cancel"
}
В этом запросе важно правильно сформировать merchantTradeNo. Это внутренний номер платежа,
по которому потом можно связать webhook Binance с записью в Битрикс.
Для пополнения баланса лучше использовать уникальный ID операции, а не просто ID пользователя. Например:
BPAY1234567890
Такой номер можно сохранить в Highload-блоке и использовать как ключ для поиска платежа после webhook.
Требования к merchantTradeNo
У Binance Pay есть важные ограничения к полю merchantTradeNo:
- только буквы и цифры;
- без пробелов, дефисов и специальных символов;
- максимальная длина — 32 символа;
- значение должно быть уникальным для платежа.
Если сформировать номер с неподходящими символами или слишком длинной строкой, Binance может отклонить запрос на создание платежа.
Подпись запроса Binance Pay
Для обращения к Binance Pay запрос нужно подписывать. Подпись формируется из timestamp, nonce и JSON-тела запроса.
$signaturePayload = $timestamp . "\n" . $nonce . "\n" . $jsonPayload . "\n";
$signature = strtoupper(hash_hmac('SHA512', $signaturePayload, $secretKey));
Важно, чтобы в подпись попадал именно тот JSON, который уходит в запрос. Если сначала подписать один payload, а потом отправить другой формат JSON, подпись не пройдет.
Заголовки запроса:
Content-Type: application/json
BinancePay-Timestamp: timestamp
BinancePay-Nonce: nonce
BinancePay-Signature: signature
BinancePay-Certificate-SN: API_KEY
На практике ошибки подписи часто возникают из-за неправильного timestamp, лишних переносов, повторной генерации JSON, неверного secret key или использования не того API key.
Что нужно сохранить в Битрикс при создании платежа
После успешного создания ордера в Binance Pay нужно сохранить внутреннюю запись платежа. Для этого удобно использовать Highload-блок.
Минимальный набор полей:
UF_ORDER_ID
UF_USER_ID
UF_AMOUNT
UF_PAID
Но в реальном проекте лучше хранить больше технических данных:
UF_ORDER_ID— внутренний номер платежа, который передается какmerchantTradeNo;UF_USER_ID— ID пользователя Битрикс;UF_AMOUNT— сумма пополнения;UF_CURRENCY— валюта платежа, напримерUSDT;UF_PAID— флаг успешной оплаты;UF_STATUS— технический статус платежа;UF_RESPONSE— ответ Binance при создании платежа;UF_WEBHOOK— последний webhook от Binance;UF_CREATED_AT— дата создания операции;UF_PAID_AT— дата успешной оплаты.
Пример базовой записи:
$entityDataClass::add([
'UF_ORDER_ID' => $orderId,
'UF_USER_ID' => $userId,
'UF_AMOUNT' => $amount,
'UF_PAID' => false
]);
Если на проекте уже есть личный кабинет, внутренняя валюта, история пополнений или платные функции, структуру хранения лучше продумать заранее. Это уже не просто подключение платежной кнопки, а доработка бизнес-логики на Битрикс.
Webhook Binance Pay
После оплаты Binance отправляет уведомление на callback URL сайта. Пример структуры:
{
"bizType": "PAY",
"data": "{...}",
"bizStatus": "PAY_SUCCESS"
}
Важный момент: поле data приходит как строка JSON. Его нужно декодировать отдельно.
$data = json_decode($rawData, true);
$innerData = json_decode($data['data'], true);
Проверка успешного платежа может выглядеть так:
if ($data['bizType'] === 'PAY' && $data['bizStatus'] === 'PAY_SUCCESS') {
// обработка успешной оплаты
}
Но одной проверки статуса недостаточно. В рабочей интеграции нужно дополнительно:
- получить
merchantTradeNoиз вложенногоdata; - найти внутреннюю запись платежа в Highload-блоке;
- проверить, не был ли платеж уже обработан;
- сравнить сумму и валюту;
- сохранить webhook в лог;
- только после этого пополнить баланс пользователя.
Почему важна защита от повторного webhook
Webhook может прийти повторно. Это нормальная ситуация для платежных систем: сервис может отправить уведомление еще раз, если не получил корректный ответ или повторяет доставку события.
Поэтому перед обновлением баланса обязательно нужно проверить флаг UF_PAID.
if ($order['UF_PAID']) {
exit;
}
Без такой проверки пользовательский баланс может быть пополнен дважды по одному и тому же платежу. Для платежных интеграций это критическая ошибка.
Поиск платежа в Highload-блоке
После получения webhook нужно найти внутреннюю запись платежа по merchantTradeNo.
$order = $entityDataClass::getList([
'filter' => [
'UF_ORDER_ID' => $merchantTradeNo
]
])->fetch();
Если запись не найдена, баланс обновлять нельзя. В этом случае нужно залогировать входящий webhook и вернуть технический ответ.
Также полезно проверять, что UF_USER_ID существует, пользователь активен, а сумма платежа совпадает
с ожидаемой суммой в базе.
Обновление баланса пользователя
В простом варианте баланс пользователя может храниться в пользовательском поле, например UF_BALANCE.
После успешного webhook получаем пользователя, прибавляем сумму и сохраняем новое значение.
$rsUser = CUser::GetByID($userId);
$arUser = $rsUser->Fetch();
$newBalance = (float)$arUser['UF_BALANCE'] + (float)$amount;
$user = new CUser();
$user->Update($userId, [
'UF_BALANCE' => $newBalance
]);
После этого платеж нужно отметить как обработанный:
$entityDataClass::update($order['ID'], [
'UF_PAID' => true
]);
В более надежной реализации лучше обновлять не только UF_PAID, но и статус, дату оплаты,
исходный webhook и итоговый баланс после операции.
$entityDataClass::update($order['ID'], [
'UF_PAID' => true,
'UF_STATUS' => 'PAY_SUCCESS',
'UF_WEBHOOK' => $rawData,
'UF_PAID_AT' => new \Bitrix\Main\Type\DateTime()
]);
Что важно учесть при работе с балансом
Пополнение баланса — это финансовая операция внутри сайта. Поэтому лучше не ограничиваться простым увеличением пользовательского поля.
В нормальной архитектуре желательно хранить историю операций:
- сумма пополнения;
- валюта платежа;
- пользователь;
- номер операции;
- статус оплаты;
- ответ Binance;
- дата создания;
- дата оплаты;
- баланс до операции;
- баланс после операции.
Это помогает разбираться в спорных ситуациях: пользователь оплатил, но баланс не обновился; webhook не дошел; платеж пришел повторно; сумма не совпала; администратору нужно проверить историю начислений.
Проверка статуса оплаты через AJAX
После создания платежа пользователь обычно видит модальное окно с QR-кодом или ссылкой на Binance Pay. Чтобы интерфейс понимал, что оплата завершена, можно сделать AJAX-endpoint:
/ajax/check_binance_payment.php
Он получает orderId, проверяет запись в Highload-блоке и возвращает текущий статус.
$order = $entityDataClass::getList([
'filter' => [
'UF_ORDER_ID' => $orderId
]
])->fetch();
echo json_encode([
'status' => $order['UF_PAID'] ? 'paid' : 'pending'
]);
Пример ответа:
{
"status": "paid"
}
Этот endpoint не должен сам обновлять баланс. Его задача — только показать фронтенду актуальное состояние. Обновление баланса должно происходить на сервере после webhook от Binance.
Фронтенд-проверка статуса оплаты
На фронтенде можно периодически отправлять запрос и проверять, был ли платеж обработан.
setInterval(function() {
$.post('/ajax/check_binance_payment.php', { orderId: orderId }, function(res) {
if (res.status === 'paid') {
$('#modal-pay-binance').fadeOut();
}
});
}, 3000);
После получения статуса paid можно закрыть окно оплаты, обновить баланс в интерфейсе,
показать сообщение об успешном пополнении или перезагрузить часть личного кабинета.
Если на сайте медленно обновляется личный кабинет, зависает AJAX или долго открывается платежное окно, стоит отдельно проверить фронтенд и серверную часть. В таких случаях помогает технический аудит производительности сайта.
Отображение данных в попапе оплаты
В модальном окне можно показать сумму, описание платежа, продавца и QR-код для оплаты.
<div id="modal-pay-binance">
<p>Payment Amount: <span id="amount"></span></p>
<p>Merchant: Device Forum LLC</p>
<p>Details: <span id="desc"></span></p>
<div id="qr"></div>
</div>
Данные можно заполнить из ответа Binance:
$('#amount').text(data.totalFee + ' ' + data.currency);
$('#desc').text(data.description);
$('#qr').html('<img src="' + data.qrcodeLink + '" alt="Binance Pay QR">');
Для пользователя важно, чтобы окно оплаты было понятным: какая сумма списывается, в какой валюте, что именно оплачивается и что произойдет после успешного платежа.
Ключевые требования Binance Pay
При интеграции нужно учитывать несколько технических требований:
merchantTradeNo— только буквы и цифры, максимум 32 символа;env.terminalType— для сайта обычно используется значениеWEB;goodsDetails— обязательный массив с описанием товара или услуги;timestamp— передается в миллисекундах;signature— HMAC SHA512 в верхнем регистре;dataв webhook — вложенная JSON-строка, которую нужно декодировать отдельно.
Невнимательность к этим деталям обычно приводит к ошибкам создания платежа, неверной подписи, неработающему webhook или ситуации, когда пользователь оплатил, но баланс не пополнился.
Типовые ошибки при интеграции Binance Pay с Битрикс
Неправильный merchantTradeNo
Если в номере платежа есть дефисы, пробелы, подчеркивания или он длиннее 32 символов, Binance может не принять запрос. Лучше заранее сделать отдельную функцию генерации номера.
Ошибка подписи запроса
Частая причина — подписывается не тот JSON, который отправляется в API. Также нужно проверить timestamp, nonce, secret key и регистр итоговой подписи.
Webhook приходит, но баланс не обновляется
Нужно проверить, правильно ли декодируется вложенное поле data, находится ли платеж по
merchantTradeNo, не стоит ли уже флаг UF_PAID, и нет ли ошибки при обновлении пользователя.
Баланс пополняется повторно
Это происходит, если не проверять, был ли платеж уже обработан. Перед начислением обязательно нужно проверять
UF_PAID или другой флаг идемпотентности.
Фронтенд не закрывает окно оплаты
В этом случае нужно смотреть AJAX-проверку, формат JSON-ответа, обработку res.status и то,
обновляется ли статус платежа в Highload-блоке после webhook.
Такие проблемы часто требуют не просто “поправить одну строку”, а разобраться в цепочке: создание платежа, сохранение операции, webhook, обновление баланса, AJAX и интерфейс пользователя. Это типичный пример исправления сложной PHP-логики в Битрикс.
Что проверить после внедрения
После подключения Binance Pay важно протестировать весь цикл, а не только создание QR-кода.
- Проверить, что платеж создается через Binance Pay v3.
- Убедиться, что
merchantTradeNoсоответствует ограничениям Binance. - Проверить корректность подписи запроса.
- Убедиться, что запись о платеже сохраняется в Highload-блок.
- Проверить, что webhook приходит на сайт.
- Проверить декодирование вложенного поля
data. - Убедиться, что успешный статус
PAY_SUCCESSобрабатывается корректно. - Проверить, что баланс пользователя увеличивается только один раз.
- Проверить, что AJAX возвращает
paidпосле оплаты. - Проверить, что интерфейс личного кабинета показывает новый баланс.
Когда такая интеграция особенно полезна
Binance Pay с пополнением баланса подходит для проектов, где пользователь сначала вносит средства, а потом использует их внутри сайта.
Например:
- личный кабинет с внутренним счетом;
- платный форум или закрытое сообщество;
- сервис цифровых услуг;
- маркетплейс с внутренним балансом;
- B2B-портал с предоплатой;
- сайт с платными действиями или подписками;
- система заявок, где средства списываются по мере использования.
Посмотреть похожие технические задачи по интеграциям, оплатам, личным кабинетам и нестандартной логике можно в разделе примеры работ.
Почему лучше не делать платежную интеграцию “на костылях”
В платежных сценариях любая мелкая ошибка может привести к реальной проблеме: деньги списались, а баланс не обновился; webhook пришел дважды; пользователь увидел оплату, но не получил доступ; администратор не может понять, что произошло.
Поэтому при интеграции Binance Pay важно заранее продумать:
- структуру хранения платежей;
- уникальные номера операций;
- проверку подписи;
- обработку повторных webhook;
- логи запросов и ответов;
- историю начислений;
- проверку суммы и валюты;
- поведение интерфейса после оплаты;
- ручную проверку спорных платежей администратором.
Если проект уже работает и в нем есть старые доработки, нестандартный личный кабинет или своя система баланса, перед внедрением оплаты лучше оценить текущую архитектуру. Подробнее о подходе к таким задачам можно прочитать на странице о студии.
Итог
Интеграция Binance Pay v3 в Битрикс с пополнением баланса строится вокруг полного платежного цикла: пользователь создает пополнение, сервер формирует ордер в Binance, данные операции сохраняются в Highload-блок, webhook подтверждает оплату, после чего баланс пользователя обновляется на сайте.
Самые важные моменты: корректно сформировать merchantTradeNo, правильно подписать запрос,
сохранить платеж до оплаты, обработать вложенный JSON в webhook, защититься от повторного начисления
и не обновлять баланс до подтверждения PAY_SUCCESS.
Если нужно подключить Binance Pay, доработать личный кабинет, реализовать внутренний баланс, исправить webhook или разобраться, почему после оплаты не зачисляются средства, можно обратиться через страницу контактов.