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 |







