Integration of 1C-Bitrix with the Robokassa payment 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

Integration of 1C-Bitrix with Robokassa Payment System

Robokassa is a payment aggregator: accepts cards, YuMoney, QIWI, cash via terminals. Convenient when you need to provide maximum payment methods. Bitrix has a ready Robokassa module in the Marketplace, but custom implementation with parameter control and logic is often needed.

How It Works

  1. Bitrix forms a signed link to Robokassa form
  2. Customer pays (card, wallet, cash)
  3. Robokassa sends POST notification to store's ResultURL
  4. Store verifies signature, confirms payment
  5. Robokassa redirects customer to SuccessURL or FailURL

Parameters and Signature Formation

Basic request parameters to Robokassa:

Parameter Value Description
MerchantLogin from account Store login
OutSum amount Payment amount
InvId orderId Order number
Description text Description (up to 100 characters)
SignatureValue MD5/SHA256 Signature
IsTest 1 Test mode
Encoding utf-8 Encoding

Signature is formed as MD5 or SHA256 (depends on store settings in Robokassa account):

// MD5 signature
$signature = md5("{$merchantLogin}:{$outSum}:{$invId}:{$password1}");

// SHA256 (recommended)
$signature = hash('sha256', "{$merchantLogin}:{$outSum}:{$invId}:{$password1}");

// Payment form URL
$payUrl = 'https://auth.robokassa.ru/Merchant/Index.aspx?'
    . http_build_query([
        'MerchantLogin'  => $merchantLogin,
        'OutSum'         => number_format($outSum, 2, '.', ''),
        'InvId'          => $invId,
        'Description'    => $description,
        'SignatureValue' => $signature,
        'Encoding'       => 'utf-8',
        'IsTest'         => $isTest ? 1 : 0,
    ]);

Processing ResultURL

Robokassa sends POST with parameters to ResultURL. Signature verification is mandatory — uses Password2 (different from Password1):

$outSum    = $_POST['OutSum'];
$invId     = $_POST['InvId'];
$received  = strtolower($_POST['SignatureValue']);
$password2 = $this->getBusinessValue($payment, 'ROBOKASSA_PASSWORD2');

$expected = strtolower(hash('sha256', "{$outSum}:{$invId}:{$password2}"));

if ($received !== $expected) {
    echo 'bad sign';
    exit;
}

// Signature is correct — confirm payment
$order = \Bitrix\Sale\Order::loadByAccountNumber($invId);
// ... setPaid('Y'), save()

echo "OK{$invId}";  // Robokassa expects exactly this response

Critical: response to ResultURL must be exactly OK{InvId}. If Robokassa doesn't receive this response — considers notification unsent and retries (up to 8 times).

Additional Parameters (Shp_*)

Robokassa supports custom parameters with Shp_ prefix. They are included in signature and returned in ResultURL. Use to pass order identifier to Bitrix if InvId is occupied or additional data needed:

$signature = hash('sha256',
    "{$merchantLogin}:{$outSum}:{$invId}:{$password1}:Shp_item={$itemId}&Shp_user={$userId}"
);
// Shp_ parameters are included in signature in alphabetical key order

Fiscalization

Robokassa supports FZ-54 via Receipt parameter in base64-encoded JSON:

$receipt = [
    'sno' => 'osn',  // tax system
    'items' => array_map(function($basketItem) {
        return [
            'name'     => $basketItem->getField('NAME'),
            'quantity' => $basketItem->getQuantity(),
            'sum'      => $basketItem->getPrice() * $basketItem->getQuantity(),
            'payment_method'  => 'full_prepayment',
            'payment_object'  => 'commodity',
            'tax'      => 'vat20',
        ];
    }, iterator_to_array($order->getBasket())),
];

$receiptEncoded = base64_encode(json_encode($receipt, JSON_UNESCAPED_UNICODE));

Development Timeline

Task Duration
Handler: link generation + ResultURL 1–2 days
Additional Shp_* parameters 0.5 day
Fiscalization +1–2 days
Full cycle testing 0.5 day