Integration of 1C-Bitrix with Priorbank's online acquiring system (Belarus)

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

1C-Bitrix Integration with Priorbank Internet Acquiring (Belarus)

Priorbank is one of the largest Belarusian banks and a subsidiary of Raiffeisen Bank International. For Belarusian online stores on Bitrix, it is one of the primary acquiring options: good conversion rates, support for VISA/Mastercard/Belkart cards, and the option to enable instalment payments via "Halva". Priorbank's payment gateway is technically based on Computop Paygate, which is important to keep in mind during integration development.

Gateway Technical Architecture

Priorbank uses Computop Paygate (paygate.computop.com). Key characteristics:

  • Parameters are transmitted in encrypted form — Blowfish (ECB) + Base64, plus HMAC-MD5 for verification
  • Payment form — redirect to the Computop page, not hosted fields
  • Notifications — synchronous via URLNotify (POST on status change) and parameters in URLSuccess/URLFailure

This fundamentally differs from conventional JSON REST APIs: all parameters are encrypted, and an error in the encryption algorithm produces an empty response with no meaningful error message.

Parameter Encryption Algorithm

class ComputopCipher
{
    private string $blowfishKey;
    private string $merchantId;
    private string $hmacKey;

    public function __construct(string $merchantId, string $blowfishKey, string $hmacKey)
    {
        $this->merchantId = $merchantId;
        $this->blowfishKey = $blowfishKey;
        $this->hmacKey = $hmacKey;
    }

    public function encrypt(array $params): string
    {
        $queryString = http_build_query($params);
        $len = strlen($queryString);

        // Pad to a multiple of 8 bytes (Blowfish ECB requirement)
        $pad = (8 - ($len % 8)) % 8;
        $queryString = str_pad($queryString, $len + $pad, "\0");

        $encrypted = openssl_encrypt(
            $queryString,
            'BF-ECB',
            $this->blowfishKey,
            OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING
        );

        return base64_encode($encrypted);
    }

    public function decrypt(string $data): array
    {
        $decrypted = openssl_decrypt(
            base64_decode($data),
            'BF-ECB',
            $this->blowfishKey,
            OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING
        );
        parse_str(rtrim($decrypted, "\0"), $result);
        return $result;
    }

    public function getHmac(array $params): string
    {
        $data = implode('*', [
            $params['PayID'] ?? '',
            $params['TransID'] ?? '',
            $this->merchantId,
            $params['Amount'] ?? '',
            $params['Currency'] ?? '',
        ]);
        return hash_hmac('md5', $data, $this->hmacKey);
    }
}

Building the Payment Form

$cipher = new ComputopCipher($merchantId, $blowfishKey, $hmacKey);

$params = [
    'MerchantID' => $merchantId,
    'TransID'    => 'ORDER_' . $orderId . '_' . time(),
    'Amount'     => (int)($orderAmount * 100),  // in kopecks
    'Currency'   => 'BYN',
    'OrderDesc'  => 'Order #' . $orderId,
    'URLSuccess' => 'https://myshop.by/checkout/success/?order=' . $orderId,
    'URLFailure' => 'https://myshop.by/checkout/fail/?order=' . $orderId,
    'URLNotify'  => 'https://myshop.by/bitrix/tools/sale_ps_result.php',
    'Language'   => 'ru',
    'MAC'        => $cipher->getHmac(['TransID' => 'ORDER_'.$orderId.'_'.time(), 'Amount' => (int)($orderAmount*100), 'Currency' => 'BYN']),
];

$encryptedData = $cipher->encrypt($params);
$len = strlen(http_build_query($params));

HTML form for redirect:

<form method="POST" action="https://paygate.computop.com/pay/">
    <input type="hidden" name="MerchantID" value="<?= $merchantId ?>">
    <input type="hidden" name="Len" value="<?= $len ?>">
    <input type="hidden" name="Data" value="<?= htmlspecialchars($encryptedData) ?>">
    <button type="submit">Pay</button>
</form>

Processing Notifications

Computop sends a POST to URLNotify with encrypted Data and Len:

// In the handler /bitrix/tools/sale_ps_result.php
$encryptedData = $_POST['Data'] ?? '';
$len = (int)($_POST['Len'] ?? 0);

$decrypted = $cipher->decrypt($encryptedData);
parse_str(substr(http_build_query($decrypted), 0, $len), $params);

// Always verify the MAC
$expectedMac = $cipher->getHmac($params);
if (!hash_equals($expectedMac, $params['MAC'] ?? '')) {
    http_response_code(403);
    exit('Invalid MAC');
}

// Success codes
if (($params['Code'] ?? '') === '00000000') {
    $payment->setPaid('Y');
    $payment->setField('PS_STATUS_CODE', $params['Code']);
    $payment->setField('PS_STATUS_MESSAGE', $params['Description'] ?? '');
    $payment->save();
}

Main Computop/Priorbank response codes:

Code Meaning
00000000 Successful payment
00000099 Transaction pending
00000190 Authorization error
00000902 Gateway error

Test Environment

Priorbank provides a test MerchantID and test BlowfishKey. Computop test cards:

  • VISA: 4200000000000000 — successful payment
  • Mastercard: 5500000000000004 — successful payment
  • Any card with Expiry = 1200 — declined

An important testing note: URLNotify must be accessible from Computop servers — localhost will not work. For local development use ngrok or a temporary public URL.

Belarus-Specific Notes

  • Payment currency — BYN (Belarusian ruble), ISO code 974
  • Amount is transmitted in Belarusian kopecks (1 ruble = 100 kopecks)
  • Processing Belkart cards requires a separate connection via the Belkart protocol — different from Computop
  • Bank operational day — business days; settlements on the next banking day

Timeline

Configuration Duration
Payment system handler development 2–3 days
Testing in the test environment 1 day
Live environment connection and verification 1 day
1C integration (if required) 2–3 additional days