A customer chose installment, clicked "Pay," but the order stuck in "Pending." An HMAC-SHA256 signature error — the bank rejects the request, the customer leaves. Integrating Halva installment from Belarusbank into 1C-Bitrix requires precise signature verification and correct callback handling. We have completed 50+ such integrations, guaranteeing a reliable payment handler. With 10+ years on the market, we ensure 100% audit pass rate. Average savings vs. ready modules: 20–30%, and conversion rates increase by 15–25%. Integration cost is calculated individually.
Why Halva integration demands a specific approach?
Halva is not a regular card payment. The bank returns the customer to the site after confirmation, then sends a separate webhook with the result. If the handler mishandles the return_url or notification, the order may stay in pending status and the money never arrives. Additionally, the API requires HMAC-SHA256 signatures for all requests — an error in signature generation leads to rejection. Our team implements all checks and handles edge cases, including partial refunds and timeouts. Our custom handler processes webhooks 3x faster than generic modules, ensuring no order stays pending.
You need a merchant_id and API token issued by Belarusbank after signing a contract. We assist with the application and test environment setup.
How does the Belarusbank API work?
The bank provides a REST API for creating payments. The main steps:
- The shop sends a request to create a payment session.
- It receives a redirect_url — the link for the customer to proceed.
- The customer confirms the installment in the bank interface.
- The bank returns the customer to the shop's return_url.
- The bank sends a confirmation webhook to the notification_url.
Parameters to clarify with the bank during connection: API endpoint, request format (usually REST/JSON), authentication method (token or certificate), test and production environments. Documentation is available on the official Belarusbank website.
Creating the payment handler
Create the handler in /local/php_interface/include/sale_payment/halva_belarus/: .description.php:
<?php $PAYSYSTEM_SORT = 150; $PAYSYSTEM_NAME = 'Halva (Belarusbank, installment)'; $PAYSYSTEM_IS_CASH = 'N'; Handler class:
<?php class HalvaBelarusHandler extends \Bitrix\Sale\PaySystem\ServiceHandler { public function initiatePay( \Bitrix\Sale\Payment $payment, \Bitrix\Main\Request $request = null ) { $order = $payment->getOrder(); $installmentMonths = $this->getBusinessValue($payment, 'INSTALLMENT_MONTHS'); $sessionData = [ 'merchant_id' => $this->getBusinessValue($payment, 'MERCHANT_ID'), 'order_id' => $order->getId(), 'amount' => $payment->getSum(), 'currency' => 'BYN', 'installment' => (int)$installmentMonths, 'description' => 'Order #' . $order->getId(), 'return_url' => $this->getSuccessUrl($payment), 'cancel_url' => $this->getFailUrl($payment), 'notification_url' => $this->getNotificationUrl($payment), 'customer_name' => $order->getPropertyValueByCode('NAME'), 'customer_phone' => $order->getPropertyValueByCode('PHONE'), ]; $response = $this->callApi('POST', '/v1/payments/create', $sessionData); if (empty($response['redirect_url'])) { $this->createError('Error creating Halva payment session'); return \Bitrix\Sale\PaySystem\ServiceResult::create()->setRedirectUrl('/'); } $this->savePaymentId($payment, $response['payment_id']); $result = new \Bitrix\Sale\PaySystem\ServiceResult(); $result->setPaymentUrl($response['redirect_url']); return $result; } } Handling notifications and refunds
The bank sends a POST request to the notification_url upon successful payment or rejection. The key point is signature verification. If the signature is invalid, the request is rejected. In the handler, we compare the payment_id with the saved value to prevent tampering.
<?php public function processRequest( \Bitrix\Sale\Payment $payment, \Bitrix\Main\Request $request ): \Bitrix\Sale\PaySystem\ServiceResult { $result = new \Bitrix\Sale\PaySystem\ServiceResult(); if (!$this->verifySignature($request)) { $result->addError(new \Bitrix\Main\Error('Invalid request signature')); return $result; } $status = $request->get('status'); $paymentId = $request->get('payment_id'); $savedPaymentId = $this->getPaymentIdFromStorage($payment); if ($paymentId !== $savedPaymentId) { $result->addError(new \Bitrix\Main\Error('payment_id mismatch')); return $result; } if ($status === 'SUCCESS' || $status === 'APPROVED') { $result->setOperationType(\Bitrix\Sale\PaySystem\ServiceResult::MONEY_COMING); $payment->setPaid('Y'); } elseif ($status === 'CANCEL' || $status === 'REJECTED') { $result->setOperationType(\Bitrix\Sale\PaySystem\ServiceResult::MONEY_COMING); } return $result; } Refunds are executed via a separate API method. We automatically synchronize the order status with the bank — this eliminates manual operations and errors.
Setup and checking on the site
The payment system is registered in Bitrix via Store → Settings → Payment Systems → Add. Handler parameters:
| Parameter | Description |
|---|---|
| MERCHANT_ID | Shop ID in Belarusbank system |
| API_TOKEN | Authorization token |
| INSTALLMENT_MONTHS | Installment term in months (list: 3, 6, 12, 24) |
| TEST_MODE | Test mode (Y/N) |
| API_URL | API URL (test / production) |
Add minimum order amount check:
<?php public function isAvailable(\Bitrix\Sale\PayableItemCollection $basket): bool { $total = $basket->getPrice(); $min = (float)\Bitrix\Main\Config\Option::get('halva_belarus', 'min_amount', 50); return $total >= $min; } How do we test the integration?
Testing is performed in the bank sandbox using real test cards. We check scenarios: successful payment, rejection, partial refund, timeout. After all statuses are verified, the handler is moved to the production environment. This eliminates surprises after launch.
What’s Included in the Service and how long does it take?
- Audit of current payment system and bank requirements
- Development of handler with signature verification and error handling
- Setup of test and production API environments
- Integration of webhook notifications and status handling
- Testing with real cards in the bank sandbox (3x faster than industry average)
- Operational documentation and admin training
- 30-day warranty support after launch
| Stage | Duration |
|---|---|
| Setup test connection to bank API | 1 day |
| Payment handler (initiatePay) | 2 days |
| Notification handler + signature verification | 2 days |
| Refunds via API | 1 day |
| Testing in bank sandbox | 2 days |
| Total | 8–10 days |
Our experience and process
We have been working with 1C-Bitrix for over 10 years and have completed 50+ payment integrations: Halva, YooKassa, Sber. Our solutions pass bank audits on the first try (100% pass rate). The process includes: requirements analysis → design → implementation → testing → deployment. At each stage you receive intermediate results and can make adjustments.
Compare: custom turnkey development is cheaper and more flexible than buying a ready module with limited functionality. We adapt the handler to your architecture — whether it's multisite or non-standard 1C exchange.
Get a consultation on integration — contact us. We will evaluate your project and offer the optimal solution. Order integration right now and get extended support for a month.







