Разработка модуля мультивалютности 1С-Битрикс
В Битрикс есть встроенная поддержка валют через модуль 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;
// Курс в Битрикс — сколько рублей за 1 единицу иностранной валюты
$ratePerUnit = $rate / $nominal;
\CCurrencyRates::SetRatesList(SITE_ID, [[
'CURRENCY' => $code,
'RATE' => $ratePerUnit,
'RATE_CNT' => 1,
'DATE_RATE' => date('d.m.Y'),
]]);
}
}
}
Агент запускается раз в 4 часа. Источник курсов (ЦБ РФ, ECB, NBU, 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 принимает цену в базовой валюте (рублях) и отображает в текущей валюте пользователя:
// Конвертация через стандартный метод Битрикс
$priceInUserCurrency = \CCurrencyRates::ConvertCurrency($priceRub, 'RUB', $userCurrency);
$formatted = \CCurrencyLang::CurrencyFormat($priceInUserCurrency, $userCurrency, true);
// → "€ 149,90"
Переключатель валют — компонент vendor:multicurrency.switcher. При выборе валюты — запись в cookie и AJAX-перерисовка блоков с ценами без полной перезагрузки страницы.
Независимые цены в валютах
Для B2B-сценариев иногда нужны цены, установленные вручную в каждой валюте (не пересчёт из рублей, т.к. цены могут не соответствовать курсу). В этом случае цены хранятся в дополнительных ценовых типах Битрикс:
- Ценовой тип
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 рабочих дней. Подключение дополнительных источников курсов (NBU, НБ Беларуси) — по 0.5 дня на источник.







