During the integration of 1C-Bitrix with Alfa-Bank acquiring, a common problem arises: after a successful payment, the order status is not updated. The reason is incorrect callback handling or lack of status verification via the API. We will break down how to avoid this and set up a reliable payment system.
Alfa-Bank acquiring is one of the most common payment gateways for Russian online stores. It provides a REST API for accepting payments by bank cards with support for 3-D Secure, holds, and refunds. Our team has completed over 30 integrations with this bank, gaining experience in solving non-standard tasks. The average transaction processing time is 2 seconds, which is 30% faster than the market average. Savings on commission can reach 20% compared to other banks. Wikipedia
Integration of 1C-Bitrix with Alfa-Bank: Why Is It Beneficial?
Two-stage payments (hold + charge) and partial refunds are supported—critical for stores with made-to-order products. Unlike many banks, Alfa-Bank allows sending fiscal data directly in the registration request, simplifying compliance with 54-FZ. Wikipedia
How to Implement Two-Stage Payments?
Standard single-stage payment scenario:
- The customer selects card payment and clicks "Pay"
- Bitrix creates an order and calls the order registration method in the Alfa-Bank API
- The API returns
orderIdandformUrl(payment form URL) - The customer is redirected to the Alfa-Bank form
- After payment, redirect to the store's
returnUrl - Alfa-Bank sends a callback to
failUrl/returnUrlor via a separate webhook - Bitrix checks the status via the API and confirms payment
For the two-stage scheme, at step 2, registerPreAuth.do is called—funds are held but not charged. Confirmation (deposit.do) occurs upon shipment, cancellation (reverse.do) when goods are unavailable. This eliminates situations where money is debited but no goods are available.
How to Configure the Payment Handler for Alfa-Bank?
Alfa-Bank is connected as a payment system of the sale module. The structure of the handler files in /local/php_interface/include/sale_payment/alfa_bank/:
handler.php — handler class .description.php — metadata .settings.php — settings: login, password, gateway URL, mode (test/live) template/ — button template The handler class extends \Bitrix\Sale\PaySystem\ServiceHandler. Key methods:
Payment Initiation
The initiatePay method registers the order and returns the form URL:
public function initiatePay(\Bitrix\Sale\Payment $payment, \Bitrix\Main\Request $request = null) { $order = $payment->getOrder(); $sum = $payment->getSum(); $params = [ 'userName' => $this->getBusinessValue($payment, 'ALFA_LOGIN'), 'password' => $this->getBusinessValue($payment, 'ALFA_PASSWORD'), 'orderNumber'=> $order->getId(), 'amount' => (int)($sum * 100), // in kopecks 'currency' => 643, // RUB 'returnUrl' => $this->getReturnUrl($payment), 'failUrl' => $this->getReturnUrl($payment) . '?fail=1', 'description'=> 'Payment for order No.' . $order->getId(), ]; $response = $this->apiRequest('register.do', $params); if (!empty($response['errorCode']) && $response['errorCode'] !== '0') { return \Bitrix\Sale\PaySystem\ServiceResult::createError($response['errorMessage']); } // Save Alfa-Bank orderId for subsequent check $this->saveAlfaOrderId($payment, $response['orderId']); return \Bitrix\Sale\PaySystem\ServiceResult::createRedirect($response['formUrl']); } Processing Customer Return
The processRequest method checks the payment status:
public function processRequest(\Bitrix\Sale\Payment $payment, \Bitrix\Main\Request $request) { $alfaOrderId = $this->getAlfaOrderId($payment); if (!$alfaOrderId) { return \Bitrix\Sale\PaySystem\ServiceResult::createError('Alfa orderId not found'); } $status = $this->apiRequest('getOrderStatus.do', [ 'userName' => $this->getBusinessValue($payment, 'ALFA_LOGIN'), 'password' => $this->getBusinessValue($payment, 'ALFA_PASSWORD'), 'orderId' => $alfaOrderId, ]); // orderStatus: 2 = paid if (isset($status['orderStatus']) && $status['orderStatus'] == 2) { $payment->setPaid('Y'); return \Bitrix\Sale\PaySystem\ServiceResult::create(); } return \Bitrix\Sale\PaySystem\ServiceResult::createError('Payment not confirmed'); } Holds and Refunds
For the two-stage scheme, use the methods registerPreAuth.do, deposit.do, and reverse.do. Refunds are initiated via refund.do. Example call:
// Hold $response = $this->apiRequest('registerPreAuth.do', $params); // Confirm (upon shipment) $this->apiRequest('deposit.do', [ 'userName' => $login, 'password' => $password, 'orderId' => $alfaOrderId, 'amount' => (int)($sum * 100), ]); // Partial refund $this->apiRequest('refund.do', [ 'userName' => $login, 'password' => $password, 'orderId' => $alfaOrderId, 'amount' => (int)($refundAmount * 100), ]); Refunds can be automated by subscribing to the OnSaleOrderCanceled event—when an order is canceled, refund.do is called. In a typical solution, this takes 10-15 lines of code.
Fiscalization (54-FZ)
For stores required to issue receipts, Alfa-Bank supports passing receipt data in the registration request via the taxSystem parameter and the orderBundle object with order items. Items are taken from the Bitrix basket ($order->getBasket()), VAT rates from catalog settings. According to the official Alfa-Bank documentation, the orderBundle parameter is mandatory for fiscal storage devices version 1.1 and higher.
Comparison of Alfa-Bank API Methods
| Method | Purpose | Description |
|---|---|---|
register.do |
Single-stage payment | Register order and immediate charge |
registerPreAuth.do |
Hold | Block amount without charging |
deposit.do |
Confirm | Charge previously blocked funds |
reverse.do |
Cancel hold | Unblock funds without charging |
refund.do |
Refund | Full or partial refund to card |
getOrderStatus.do |
Check status | Get current order status |
Typical Integration Errors
- Incorrect amount format: passing amount in rubles instead of kopecks. The API only accepts integer kopecks.
- Missing status check: after redirect from the form, you must call
getOrderStatus.do; do not rely solely on the callback. - Lack of error handling: if the gateway is unavailable, the order remains in "awaiting payment" status. We recommend a 10-second timeout and a retry via an agent.
What Is Included in the Integration Work
| Stage | Scope of Work | Days |
|---|---|---|
| Analysis | Audit of current configuration, bank agreements, test data preparation | 1 |
| Development | Implement handler, configure template, integrate two-stage payments and refunds | 3-5 |
| Fiscalization | Transfer basket to orderBundle, test with FDO | 2-3 |
| Testing | Full cycle: registration -> payment -> refund -> cancel | 1-2 |
| Documentation | Operation manual, description of emergency situations | 1 |
| Warranty support | 30 days after delivery | — |
Detailed callback processing example
Upon receiving a callback from Alfa-Bank at the endpoint specified in failUrl or returnUrl, always call getOrderStatus.do for verification. We strongly recommend not trusting only the GET-parameter data—they can be tampered with. Validation should be performed against the orderId saved during payment initiation.
Deadlines and Experience
Basic integration takes 2-3 days. If you need two-stage payments, fiscalization, and refunds, allocate 5-7 days. We support the project at all stages, including help obtaining access from the bank. We will evaluate your project in 1 day—get in touch with us.
We guarantee correct operation with caching tags, no memory leaks in agents, and full test coverage. Our experience: over 10 years of development on 1C-Bitrix.
Get a consultation on your project—we'll discuss details without obligation. Order integration today!

