Setting up installment payments in 1C-Bitrix

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

Instalment Checkout Setup for 1C-Bitrix

Instalment is a specific payment method that requires more data from the buyer than a standard checkout. For card payment it is enough to click a button and enter a CVV. For instalment, additional details are required: passport data, a phone number for SMS verification, and sometimes a second document. The goal of the instalment checkout setup is to build the correct flow: show instalment at the right moment, avoid overloading the form with unnecessary fields, and correctly pass data to the bank.

When to Show Instalment

Instalment has a minimum order amount (typically 50–300 BYN/RUB). The "Pay in Instalments" button should only be shown when the basket total meets the conditions. This is handled in the isAvailable method of the payment system handler.

On the frontend — dynamic show/hide of buttons when the basket changes:

document.addEventListener('basket:updated', function(e) {
    const total = e.detail.price;
    const minInstallment = window.INSTALLMENT_MIN_AMOUNT || 50;

    document.querySelectorAll('.installment-pay-btn').forEach(btn => {
        btn.style.display = total >= minInstallment ? 'inline-flex' : 'none';
    });

    if (total >= minInstallment) {
        document.getElementById('installment-monthly')
            .textContent = 'from ' + Math.ceil(total / 12) + '/mo.';
    }
});

Instalment Checkout Flow

The standard 1C-Bitrix checkout (bitrix:sale.order.ajax) needs to be adapted for instalment. Two approaches:

Approach 1: Unified checkout with conditional fields. All fields are present in the order form, but additional ones (for instalment) are only shown when the corresponding payment method is selected:

BX.bind(document.getElementById('pay-system-select'), 'change', function() {
    const isInstallment = this.value === 'installment';
    document.getElementById('installment-fields-block').style.display =
        isInstallment ? 'block' : 'none';
    // Set required for instalment fields
    document.querySelectorAll('.installment-required').forEach(el => {
        el.required = isInstallment;
    });
});

Approach 2: Separate confirmation page. The buyer completes the order as normal, then on the payment page sees buttons: "Pay by card" and "Pay in instalments". Clicking the instalment button redirects to the bank's page.

Approach 2 is simpler to implement and disrupts the user experience less. It is the most commonly used approach when integrating with Belarusian instalment services (Halva, Cherepakha, Magnit, Karta Pokupok).

Additional Order Properties for Instalment

To pass data to the bank, we create order properties via the sale module:

// Programmatically add order properties for instalment
$propsToAdd = [
    'INSTALLMENT_TERM'       => ['NAME' => 'Instalment term (months)', 'TYPE' => 'NUMBER'],
    'INSTALLMENT_PROVIDER'   => ['NAME' => 'Instalment provider', 'TYPE' => 'STRING'],
    'INSTALLMENT_APP_ID'     => ['NAME' => 'Bank application ID', 'TYPE' => 'STRING'],
    'INSTALLMENT_STATUS'     => ['NAME' => 'Instalment status', 'TYPE' => 'STRING'],
];

foreach ($propsToAdd as $code => $params) {
    $prop = new \CSaleOrderProps();
    $prop->Add([
        'PERSON_TYPE_ID' => 1,
        'NAME'           => $params['NAME'],
        'TYPE'           => $params['TYPE'],
        'CODE'           => $code,
        'ACTIVE'         => 'Y',
        'USER_PROPS'     => 'N',
        'IS_LOCATION'    => 'N',
        'IS_EMAIL'       => 'N',
        'IS_NAME'        => 'N',
        'IS_PHONE'       => 'N',
        'SORT'           => 500,
    ]);
}

When creating an instalment order we populate INSTALLMENT_TERM and INSTALLMENT_PROVIDER. When the bank's decision is received — INSTALLMENT_APP_ID and INSTALLMENT_STATUS.

Instalment Term Selection in the Cart

Before redirecting to instalment payment, we show the buyer a term selection:

// Instalment term selection component
$availableTerms = [
    ['months' => 6,  'monthly' => ceil($orderTotal / 6)],
    ['months' => 12, 'monthly' => ceil($orderTotal / 12)],
    ['months' => 24, 'monthly' => ceil($orderTotal / 24)],
];
<div class="installment-terms">
    <?php foreach ($availableTerms as $term): ?>
    <label class="term-option">
        <input type="radio" name="installment_months" value="<?= $term['months'] ?>">
        <span class="term-label">
            <strong><?= $term['months'] ?> months</strong>
            <span><?= $term['monthly'] ?> /mo.</span>
        </span>
    </label>
    <?php endforeach; ?>
</div>

The selected term is stored in the session and passed to the payment system handler via getBusinessValue.

Successful Completion Page

After returning from the bank's site (success_url) we show a dedicated page "Instalment Application Submitted":

  • If the bank approved instantly — "Instalment approved, order confirmed"
  • If review will take time — "Application under review. You will receive an SMS with the decision"
  • If declined — "Application declined. You can choose another payment method" with a "Pay by card" button

The status is determined from the GET parameter returned by the bank, or from our database (bl_mtbank_orders.status, bl_bnovo_reservations, depending on the provider).

Logging and Monitoring

All instalment attempts are written to the bl_installment_log log:

CREATE TABLE bl_installment_log (
    id          SERIAL PRIMARY KEY,
    order_id    INT NOT NULL,
    provider    VARCHAR(32) NOT NULL,   -- 'halva', 'karta_pokupok', 'cherepaha', 'magnit'
    amount      NUMERIC(12,2),
    term_months SMALLINT,
    status      VARCHAR(30),
    bank_app_id VARCHAR(128),
    created_at  TIMESTAMP DEFAULT NOW(),
    updated_at  TIMESTAMP DEFAULT NOW()
);

This provides statistics: conversion by provider, average instalment term, proportion of applications by amount.

Timeline

Phase Duration
Order properties and payment system configuration 1 day
Dynamic instalment button display in cart 1 day
Instalment term selection page 1 day
Success/fail pages with correct statuses 1 day
Logging and conversion report 1 day
Full flow testing 1–2 days
Total 6–8 days