Integration of 1C-Bitrix with Alfa-Bank Belarus's online acquiring system

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1173
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    745
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

1C-Bitrix Integration with Alfa-Bank Internet Acquiring (Belarus)

Alfa-Bank Belarus is one of the most technologically advanced banks in the Belarusian market, providing internet acquiring through its own payment gateway. Unlike Russian Alfa-Bank, the Belarusian subsidiary uses a different API — based on the OpenWay protocol — which means separate documentation and a separate onboarding process.

Gateway Technology Stack

Alfa-Bank Belarus uses a payment gateway built on OpenWay processing (ecom.alfa-bank.by). The workflow is a standard redirect flow:

  1. The store sends an order registration request → receives formUrl and orderId
  2. The buyer is redirected to formUrl
  3. After payment — redirect to returnUrl + notification to callbackUrl
  4. The store verifies the status via getOrderStatus

The API accepts requests via HTTPS; authentication uses userName/password as request parameters (basic parameters, not a header). The format is form-urlencoded or JSON depending on the endpoint.

Order Registration

class AlfaBankBelarusGateway
{
    private const API_URL = 'https://ecom.alfa-bank.by/payment/rest/';
    private string $userName;
    private string $password;

    public function registerOrder(array $orderData): array
    {
        $params = [
            'userName'    => $this->userName,
            'password'    => $this->password,
            'orderNumber' => $orderData['number'],
            'amount'      => (int)($orderData['amount'] * 100), // kopecks
            'currency'    => 933,  // BYN per ISO 4217
            'returnUrl'   => $orderData['returnUrl'],
            'failUrl'     => $orderData['failUrl'],
            'description' => 'Order #' . $orderData['number'],
            'language'    => 'ru',
            'pageView'    => 'DESKTOP', // or MOBILE
        ];

        $response = $this->request('register.do', $params);

        if (!empty($response['errorCode']) && $response['errorCode'] !== '0') {
            throw new \RuntimeException(
                'Registration error: ' . ($response['errorMessage'] ?? 'unknown error')
            );
        }

        return $response; // contains orderId and formUrl
    }

    private function request(string $method, array $params): array
    {
        $ch = curl_init(self::API_URL . $method);
        curl_setopt_array($ch, [
            CURLOPT_POST           => true,
            CURLOPT_POSTFIELDS     => http_build_query($params),
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_SSL_VERIFYPEER => true,
            CURLOPT_TIMEOUT        => 30,
        ]);
        $result = curl_exec($ch);
        curl_close($ch);
        return json_decode($result, true);
    }
}

Order Status Check

public function getOrderStatus(string $orderId): array
{
    return $this->request('getOrderStatus.do', [
        'userName' => $this->userName,
        'password' => $this->password,
        'orderId'  => $orderId,
        'language' => 'ru',
    ]);
}

Status codes are similar to other gateways based on comparable processing systems:

Code Meaning Action
0 Registered Wait
1 Pre-authorized Two-stage — wait
2 Paid Confirm in Bitrix
3 Cancelled Notify the buyer
4 Refunded Update status
6 Rejected Suggest retry

Integration with the Bitrix Payment System

// /local/php_interface/include/sale_payment/alfabank_by/handler.php
class AlfaBankByHandler extends \Bitrix\Sale\PaySystem\ServiceHandler
{
    public function initiatePay(
        \Bitrix\Sale\Payment $payment,
        \Bitrix\Main\Request $request
    ): \Bitrix\Sale\PaySystem\ServiceResult {

        $result = new \Bitrix\Sale\PaySystem\ServiceResult();
        $order  = $payment->getOrder();

        $gateway = new AlfaBankBelarusGateway(
            $this->getBusinessValue($payment, 'ALFABANK_BY_USER'),
            $this->getBusinessValue($payment, 'ALFABANK_BY_PASSWORD')
        );

        try {
            $response = $gateway->registerOrder([
                'number'    => 'BX' . $order->getId(),
                'amount'    => $payment->getSum(),
                'returnUrl' => $this->getSuccessUrl($payment),
                'failUrl'   => $this->getFailUrl($payment),
            ]);

            // Save the bank's orderId for subsequent verification
            $payment->setField('PS_INVOICE_ID', $response['orderId']);
            $payment->save();

            $result->setPaymentUrl($response['formUrl']);
        } catch (\Exception $e) {
            $result->addError(new \Bitrix\Main\Error($e->getMessage()));
        }

        return $result;
    }
}

Handling Callback Notifications

Alfa-Bank Belarus sends a GET request to callbackUrl (or POST, depending on the contract settings). Parameters include mdOrder (bank's orderId) and orderNumber (store's order number).

Important: do not update the status based solely on callback parameters. Always call getOrderStatus.do for verification:

public function processRequest(
    \Bitrix\Sale\Payment $payment,
    \Bitrix\Main\Request $request
): \Bitrix\Sale\PaySystem\ServiceResult {

    $result = new \Bitrix\Sale\PaySystem\ServiceResult();
    $orderId = $request->get('mdOrder') ?: $payment->getField('PS_INVOICE_ID');

    $gateway = new AlfaBankBelarusGateway(/* credentials */);
    $status = $gateway->getOrderStatus($orderId);

    if (($status['OrderStatus'] ?? -1) === 2) {
        $payment->setPaid('Y');
        $payment->save();
        $result->setOperationType(\Bitrix\Sale\PaySystem\ServiceResult::MONEY_COMING);
    }

    return $result;
}

Currency and Amounts

  • Currency BYN — ISO code 933
  • Amount in Belarusian kopecks (integer)
  • If the site uses a different currency — convert before creating the payment on the store side

Testing

Alfa-Bank Belarus provides a test environment (ecom-test.alfa-bank.by). Test credentials are issued individually during onboarding. Minimum test scenario: successful payment → callback → status 2 → record in Bitrix → repeated payment with the same orderNumber must return an "order already paid" error.

Timeline

Task Duration
Handler development 2–3 days
Testing 1 day
Live connection and acceptance 1 day