Integration of 1C-Bitrix with the YUKassa 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
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1175
  • 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
    747
  • 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 the YooKassa Payment System

YooKassa (formerly Yandex.Kassa) is one of the most widely used payment aggregators in Russian e-commerce. Behind the apparent simplicity of "install a module from the marketplace" lie several technical nuances: handling notifications, fiscal receipts under Federal Law 54-FZ, refund processing, and selecting the correct payment confirmation mode. Let's go through everything in order.

How YooKassa Works Technically

YooKassa provides a REST API (api.yookassa.ru/v3/). The classic payment flow:

  1. The store sends POST /payments with the amount, currency, and confirmation.type=redirect — YooKassa returns payment.id and confirmation.confirmation_url
  2. The buyer is redirected to the YooKassa payment page
  3. After payment, YooKassa sends a webhook notification to the store's return_url and a POST to the configured notification URL
  4. The store calls GET /payments/{id} for a final status check

Authentication — HTTP Basic: shopId:secretKey or an OAuth token.

Supported payment methods: bank cards, SBP, YooMoney, SberPay, Tinkoff, QIWI (with limitations), cash via terminals. The method is passed in payment_method_type or selected by the buyer on the YooKassa form.

Integration Options in 1C-Bitrix

Official module. YooKassa provides an official Bitrix module, available for free via the Marketplace (yoomoney.cms.bitrix) and on GitHub. Installed via /bitrix/admin/update_system.php, configured under Shop → Settings → Payment Systems. The module uses the official PHP library yoomoney/yookassa-sdk-php.

Custom handler is required when: non-standard order status logic is needed, the project does not use the standard sale module, or custom fiscalization is required. Placed in /local/php_interface/include/sale_payment/yookassa_custom/.

Key Request Parameters

// Minimal payment creation request via SDK
use YooKassa\Client;

$client = new Client();
$client->setAuth($shopId, $secretKey);

$payment = $client->createPayment([
    'amount' => [
        'value'    => number_format($order->getPrice(), 2, '.', ''),
        'currency' => 'RUB',
    ],
    'confirmation' => [
        'type'       => 'redirect',
        'return_url' => 'https://shop.ru/personal/order/detail/' . $order->getId() . '/',
    ],
    'capture'     => true,  // false for two-stage payments
    'description' => 'Order #' . $order->getAccountNumber(),
    'metadata'    => ['bitrix_order_id' => $order->getId()],
    'receipt'     => $receiptData,  // required when a fiscal register is connected
], uniqid('', true)); // idempotency key

capture: true — single-stage payment, funds are charged immediately. capture: false — two-stage: YooKassa holds the amount, the store calls POST /payments/{id}/capture upon shipment.

Idempotency key (third parameter) — mandatory. Without it, a repeated request on a network error will create a duplicate payment.

Fiscalization (Federal Law 54-FZ)

If receipt transmission is enabled in the YooKassa contract, the receipt object in the request becomes mandatory. Without it the transaction will be rejected. Structure:

$receiptData = [
    'customer' => [
        'email' => $buyer->getEmail(),
        'phone' => $buyer->getPersonalPhone(),  // at least one of the two
    ],
    'items' => [],
];

foreach ($basket->getOrderableItems() as $item) {
    $receiptData['items'][] = [
        'description'     => $item->getField('NAME'),
        'quantity'        => $item->getQuantity(),
        'amount'          => [
            'value'    => number_format($item->getPrice(), 2, '.', ''),
            'currency' => 'RUB',
        ],
        'vat_code'        => 1,  // 1=no VAT, 2=0%, 3=10%, 4=20%
        'payment_subject' => 'commodity',   // item type indicator
        'payment_mode'    => 'full_payment', // payment method indicator
    ];
}

// Don't forget delivery as a separate line item
if ($delivery->getPrice() > 0) {
    $receiptData['items'][] = [
        'description'     => 'Delivery',
        'quantity'        => 1,
        'amount'          => ['value' => number_format($delivery->getPrice(), 2, '.', ''), 'currency' => 'RUB'],
        'vat_code'        => 1,
        'payment_subject' => 'service',
        'payment_mode'    => 'full_payment',
    ];
}

The total of all line items in the receipt must exactly match the payment amount — YooKassa validates this and rejects any discrepancy.

Handling Webhook Notifications

YooKassa sends a POST to the configured URL on every payment status change. The standard handler URL in Bitrix: /bitrix/tools/sale_ps_result.php.

Critical points when processing:

// 1. Verify the source IP address (YooKassa publishes its IP list)
$allowedIPs = ['185.71.76.0/27', '185.71.77.0/27', '77.75.153.0/25', '77.75.156.11', '77.75.156.35'];

// 2. Read the request body
$body = file_get_contents('php://input');
$notification = json_decode($body, true);

// 3. Verify via API (do not trust webhook data directly)
$payment = $client->getPaymentInfo($notification['object']['id']);

// 4. Handle only terminal statuses
switch ($payment->getStatus()) {
    case 'succeeded':
        $bitrixPayment->setPaid('Y');
        $bitrixPayment->save();
        break;
    case 'canceled':
        // Log the cancellation reason from $payment->getCancellationDetails()
        break;
}

YooKassa payment status table:

Status Meaning Action
pending Awaiting buyer action Do nothing
waiting_for_capture Awaiting store confirmation Call capture or cancel
succeeded Paid Confirm in Bitrix
canceled Cancelled Analyze cancellation_details

Refunds

YooKassa supports partial and full refunds via POST /refunds:

$refund = $client->createRefund([
    'payment_id' => $externalPaymentId,
    'amount'     => ['value' => $refundAmount, 'currency' => 'RUB'],
    'description' => 'Refund for order #' . $orderNumber,
    'receipt'    => $refundReceiptData,  // required when fiscal register is connected
], uniqid('', true));

When a fiscal register is connected, a refund without a receipt is rejected. The refund receipt mirrors the line items of the original receipt with type refund.

Testing

YooKassa provides a test environment with the same endpoints. In test mode (shopId=test_...) payments proceed with test cards:

  • 5555555555554477 — successful payment
  • 5555555555554444 — decline

Be sure to test: successful payment, cancellation, webhook with a delay (buyer closed the browser before redirect), and partial refund.

Timeline

Configuration Duration
Ready-made module, no fiscal register 1–2 days
Ready-made module + 54-FZ fiscal 2–4 days
Custom handler + fiscal register + two-stage payments 5–8 days