Розроблення модуля мультивалютності для 1С-Bitrix
У Bitrix є вбудована підтримка валют через модуль currency: таблиця b_currency, курси у b_currency_rate, компонент bitrix:currency.rates. На перший погляд — готове рішення. На практиці виникають питання, які стандартний механізм не вирішує: автоматичне оновлення курсів із ЦБ РФ або ECB, відображення цін у валюті відвідувача з визначенням за IP, фіксація курсу на момент замовлення, керування цінами в різних валютах незалежно (а не через пересчет із базової).
Архітектура модуля
Модуль vendor.multicurrency надбудовується над стандартним currency, не замінюючи його. Базова валюта — рубль, курси зберігаються у стандартній b_currency_rate. Модуль додає:
- Автоматичне оновлення курсів із зовнішніх джерел
- Визначення валюти користувача
- Фіксацію курсу в замовленні
- Незалежні ціни в валютах (не пересчет)
Автоматичне оновлення курсів
class RateUpdater
{
public function updateFromCbRu(): void
{
$xml = simplexml_load_file('https://www.cbr.ru/scripts/XML_daily.asp');
foreach ($xml->Valute as $valute) {
$code = (string)$valute->CharCode;
$rate = (float)str_replace(',', '.', (string)$valute->Value);
$nominal = (int)$valute->Nominal;
// Курс у Bitrix — скільки рублів за 1 одиницю іноземної валюти
$ratePerUnit = $rate / $nominal;
\CCurrencyRates::SetRatesList(SITE_ID, [[
'CURRENCY' => $code,
'RATE' => $ratePerUnit,
'RATE_CNT' => 1,
'DATE_RATE' => date('d.m.Y'),
]]);
}
}
}
Агент запускається кожні 4 години. Джерело курсів (ЦБ РФ, ECB, НБУ, fixer.io) — параметр налаштувань модуля. Підтримується наценка на курс у відсотках (банківський спред).
Визначення валюти користувача
Пріоритет визначення:
- Явний вибір користувачем (cookie
user_currency) - Визначення за IP через MaxMind GeoIP2 або ip-api.com:
RU→ RUB,BY→ BYB/RUB,DE/FR/...→ EUR - Заголовок
Accept-Languageбраузера - Валюта за замовчуванням (із налаштувань модуля)
$currency = CurrencyDetector::detect(
$_COOKIE['user_currency'] ?? null,
$_SERVER['REMOTE_ADDR'],
$_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? ''
);
// Зберігаємо в сесії для поточного запиту
$_SESSION['CURRENT_CURRENCY'] = $currency;
Відображення цін
Компонент-помічник vendor:multicurrency.price приймає ціну в базовій валюті (рублях) та відображає її в поточній валюті користувача:
// Конвертація через стандартний метод Bitrix
$priceInUserCurrency = \CCurrencyRates::ConvertCurrency($priceRub, 'RUB', $userCurrency);
$formatted = \CCurrencyLang::CurrencyFormat($priceInUserCurrency, $userCurrency, true);
// → "€ 149,90"
Перемикач валют — компонент vendor:multicurrency.switcher. При виборі валюти — запис у cookie та AJAX-перерисування блоків із цінами без повного перезавантаження сторінки.
Незалежні ціни в валютах
Для B2B-сценаріїв іноді потрібні ціни, установлені вручну в кожній валюті (не пересчет з рублів, оскільки ціни можуть не відповідати курсу). У цьому випадку ціни зберігаються в додаткових цінових типах Bitrix:
- Цінова тип
BASE(RUB) — стандартна - Цінова тип
EUR_PRICE— ціна в євро, установлюється вручну - Цінова тип
USD_PRICE— ціна в доларах
Модуль додає логіку: якщо для поточної валюти є окремий цінової тип — використовувати його, інакше — конвертувати з базового.
Фіксація курсу в замовленні
Курс валюти на момент замовлення фіксується у b_sale_order.USER_DESCRIPTION (або в окремому HL-блоці):
AddEventHandler('sale', 'OnBeforeSaleOrderAdd', ['\Vendor\Multicurrency\OrderHandler', 'fixRate']);
public static function fixRate(\Bitrix\Main\Event $event): void
{
$order = $event->getParameter('ENTITY');
$currency = $_SESSION['CURRENT_CURRENCY'] ?? 'RUB';
$rate = \CCurrencyRates::GetConvertFactor('RUB', $currency);
$order->setField('CURRENCY', $currency);
// Зберігаємо курс у додатковому полі замовлення
OrderMetaTable::add(['ORDER_ID' => 0, 'CURRENCY' => $currency, 'RATE' => $rate]);
}
Фіксований курс потрібен для правильного відображення суми замовлення в історії та для бухгалтерських документів.
Терміни розроблення
| Етап | Тривалість |
|---|---|
| Автоматичне оновлення курсів, агент | 1 день |
| Визначення валюти користувача (GeoIP) | 1 день |
| Перемикач валют, cookie | 1 день |
| AJAX-перерисування цін | 1 день |
| Незалежні цінові типи за валютами | 1 день |
| Фіксація курсу в замовленні | 1 день |
| Форматування та локалізація | 0,5 дня |
| Тестування | 0,5 дня |
Разом: 7 робочих днів. Підключення додаткових джерел курсів (НБУ, Національний банк Беларусі) — по 0,5 дня на джерело.







