Как настроить автоматическое изменение типа цены в зависимости от способа оплаты в 1С и Битрикс?
В нашем интернет-магазине требуется реализовать два варианта цен:
- Цена при оплате наличными
- Цена при безналичной оплате картой
Проблема заключается в том, что в 1С расчеты ведутся иначе, чем в Битрикс. Простое добавление наценки 6% с последующим округлением не решает задачу корректно.
Пример:
- Наличная цена: 2499 руб.
- Безналичная цена: 2699 руб. (хотя по расчетам должна быть 2649 руб.), с округлением до сотни и вычитанием 1 рубля.
Основной вопрос: Как настроить систему так, чтобы при выборе способа оплаты безналичным расчетом, цена автоматически бралась из соответствующего типа цен?
Дополнительная информация: В стандартном функционале Битрикс типы цен можно привязать только к группам пользователей, а в нашем случае требуется единая настройка для всех клиентов.
Чтобы система автоматически подставляла безналичную цену, создайте в 1С и в Битрикс два типа цен с одинаковыми внешними кодами (например, CASH и CARD), реализуйте в 1С точную формулу расчёта безналичной цены (учтите порядок операций: округление ↔ наценка), экспортируйте обе цены в Битрикс и переключайте применяемый тип цены на этапе корзины/чекаута — через событие OnGetOptimalPrice или клиентский переключатель. Главное — вычислять и выгружать в 1С ту версию безналичной цены, которая соответствует вашим бизнес‑правилам, чтобы избежать расхождений (например, 2649 vs 2699 руб.).
Содержание
- Настройка типа цены в 1С и Битрикс
- Рассчет безналичной цены в 1С (порядок операций и формулы)
- Выгрузка цен из 1С и сопоставление типов цен Битрикс
- Автоматическое применение типа цены в Битрикс по способу оплаты
- Тестирование, отладка и типичные ошибки
- Примеры кода (1С и Bitrix)
- Источники
- Заключение
Настройка типа цены в 1С и Битрикс
-
Определите бизнес‑правило расчёта. Выясните точно, в каком порядке должны применяться операции: округление до сотни — перед наценкой или после неё; где вычитается 1 рубль. Пример ошибки в вашем кейсе: если наценка применяется до округления, то 2499 * 1.06 = 2648.94 → округление до сотни → 2700 → −1 = 2699; если округлять до сотни сначала: 2500 * 1.06 = 2650 → −1 = 2649.
-
Создайте типы цен в 1С:
- Названия: «Наличная», «Безналичная».
- Установите одинаковые внешние коды (XML_ID) — например
CASHиCARD. Эти коды потом используются при выгрузке в Bitrix.
-
Создайте соответствующие типы цен в Битрикс:
- Админка → Каталог → Типы цен (или /bitrix/admin/cat_group_admin.php).
- Добавьте «Наличная» и «Безналичную» и укажите XML_ID, совпадающие с 1С (
CASH,CARD).
-
Решите, где хранится окончательная цена:
- Рекомендуется вычислять и сохранять итоговую безналичную цену в 1С и выгружать её в отдельный тип цены. Тогда в Битрикс вы будете точно отображать и считать ту цену, которую заложил бухгалтер/менеджмент.
- Если по каким‑то причинам нельзя вычислять в 1С (лицензия, ограничения), тогда реализуйте ту же формулу в Битрикс — но это риск рассинхронизации.
Рассчет безналичной цены в 1С (порядок операций и формулы)
Почему у вас получилось 2699 вместо 2649 — из‑за порядка операций. Приведу две варианта формул и объяснение, как добиться ожидаемого результата.
Входные: base = 2499, маржа = 6% (×1.06), финальное правило: округление до сотни и вычитание 1 рубля (точный порядок нужно согласовать с бизнесом).
Вариант A — округление до сотни ДО наценки (получает 2649):
- base100 = RoundToHundred(base) → 2500
- temp = base100 * 1.06 → 2650.0
- final = RoundToRuble(temp) − 1 → 2649
Вариант B — наценка, затем округление до сотни (получает 2699):
- temp = base * 1.06 → 2648.94
- temp100 = RoundToHundred(temp) → 2700
- final = temp100 − 1 → 2699
Как реализовать в 1С (алгоритм, псевдокод):
Функция RoundToHundred(value, mode)
Если mode = "up" Тогда
Возврат ОкруглитьВВерх(value/100)*100
ИначеЕсли mode = "down" Тогда
Возврат ОкруглитьВниз(value/100)*100
Иначе
Возврат Окр(value/100)*100 // ближайшее
КонецЕсли
КонецФункции
// Вариант A (рекомендуемый, если вы хотите 2649):
base = ТекущаяНаличнаяЦена;
base100 = RoundToHundred(base, "nearest");
cardPrice = Окр(base100 * 1.06, 0) - 1;
Примечания:
- В 1С используйте функции округления вашей конфигурации (Окр, Округлить, Цел/Остаток в зависимости от версии). Если не уверены, попросите программиста 1С реализовать RoundToHundred через целочисленные операции (целая часть / ceil / floor).
- Внесите финальную цену в отдельный тип цен «CARD» и сохраните в регистре цен перед выгрузкой.
Выгрузка цен из 1С и сопоставление типов цен Битрикс
- Экспортируйте оба типа цен (CASH и CARD) из 1С в каталог интернет‑магазина. Для корректной привязки используйте внешний код/XML_ID — этот момент описан в справке по обмену; пример: настройка внешнего кода в 1С и соответствие в Битрикс Как настроить одновременный вывод двух цен?.
- В УТ/Управление торговлей обратите внимание на соглашения и режим выгрузки: в некоторых изданных 1С (например, «Малый бизнес») выгружается только один вид цен; для нескольких типов цен может потребоваться «Бизнес‑»лицензия. Практические примеры настройки описаны в статье про выгрузку цен для УТ11: Настройка выгрузки цен из 1С в интернет‑магазин.
- После обмена проверьте в Битрикс таблицу цен (b_catalog_price) — должны появиться записи с разными CATALOG_GROUP_ID для ваших типов.
Если выгрузка нескольких типов невозможна по лицензии, варианты:
- Реализовать расчет вторичной цены на стороне Битрикс — но убедитесь, что формула и функции округления совпадают.
- Хранить вторую цену в торговом предложении как свойство и выводить её вручную.
Автоматическое применение типа цены в Битрикс по способу оплаты
Есть два рабочих подхода:
- Серверный (автоматическая подстановка цены при пересчёте корзины)
- Идея: при расчёте цены для позиции перехватить выбор типа цены и вернуть цену нужного типа через событие
OnGetOptimalPrice. - Механизм:
- При выборе способа оплаты на фронтенде сохраняйте код способа оплаты в сессии (например,
$_SESSION['SELECTED_PAYMENT_METHOD']='CARD'). - В init.php или в модуле зарегистрируйте обработчик:
AddEventHandler("catalog", "OnGetOptimalPrice", "MyOnGetOptimalPriceHandler");
- В обработчике: если в сессии выбран
CARD, прочитайте цену из priceTypeCARDи верните структуру, ожидаемую модулем каталога (см. пример в блоке “Примеры кода”).
- При выборе способа оплаты на фронтенде сохраняйте код способа оплаты в сессии (например,
- Плюсы: цены на этапе оформления/корзины всегда берутся из того типа, который вы выгрузили; скидки и промоакции корректно применяются.
- Минусы: на страницах каталога/карточке товара статически показывается базовая цена — нужно дополнительно обновлять видимую цену через AJAX при смене метода оплаты.
- Клиентский (показываем оба значения и переключаем отображение)
- Измените шаблон компонента каталога/детальной страницы: извлекайте обе цены (
CASHиCARD) и выводите рядом или как переключатель. - При выборе способа оплаты в чеке через JS изменяйте отображаемую цену и отправляйте запрос на пересчёт корзины.
- Плюсы: визуально сразу видно, какая будет цена при выборе того или иного способа оплаты.
- Минусы: если логика расчёта сложная (налоги, курсы валют, индивидуальные скидки), клиентская подстановка должна учитывать эти факторы или требовать пересчёта на сервере.
Кеширование:
- Учитывайте кеш компонент — если компонент кеширует вывод без учёта сессии, клиент не увидит актуальную цену. Включите динамическую область или обновляйте цену через AJAX.
Практическая заметка: подробнее о механизмах подстановки цен и провайдеров цен — см. примеры и разбор в статье о персональных ценах и событиях: Персональные цены и скидки в 1С‑Битрикс.
Тестирование, отладка и типичные ошибки
План тестов:
- Создайте тестовый товар с ценой 2499.
- В 1С вручную рассчитаете безналичную цену двумя способами (вариант A и B) и сравните.
- Пропустите выгрузку, проверьте в XML/экспорте, что значения для
CASHиCARDсовпадают с ожидаемыми. - Выполните обмен — в Битрикс проверьте записи в b_catalog_price.
- На фронтенде: выберите способ оплаты «наличными» и «карта», убедитесь, что корзина и итог пересчитываются и берут правильную цену.
Частые ошибки:
- Несовпадение внешних кодов (XML_ID) — цены не сопоставляются.
- Неправильный порядок округления — как в вашем примере.
- Лицензионные ограничения 1С — экспортируется только один тип цен.
- Кеширование шаблона каталога мешает увидеть актуальную цену.
- Не пересчитывается корзина при смене способа оплаты (нужно AJAX/перезагрузку или серверную обработку).
Примеры кода (1С и Bitrix)
- Псевдо‑алгоритм расчёта в 1С (логика округления до сотни перед наценкой — даёт 2649):
// Псевдокод (в 1С реализовать через встроенные функции округления) base = Товар.ЦенаНаличными; // 2499 base100 = RoundToHundred(base, "nearest"); // 2500 temp = base100 * 1.06; // 2650 cardPrice = Round(temp, 0) - 1; // 2649 Товар.ЦенаБезнал = cardPrice;
Функцию RoundToHundred реализуйте через целочисленные операции (ceil/floor/round).
- Обработчик OnGetOptimalPrice — пример для Bitrix (поместите в init.php или модуль):
AddEventHandler("catalog", "OnGetOptimalPrice", "UA_OnGetOptimalPriceHandler");
function UA_OnGetOptimalPriceHandler($productID, $quantity, $userGroups, $renew = "N", $siteID = SITE_ID)
{
if (!isset($_SESSION)) { @session_start(); }
$pay = $_SESSION['SELECTED_PAYMENT_METHOD'] ?? null;
if ($pay !== 'CARD') {
return false; // Использовать стандартный механизм
}
// получить ID типа цены по XML_ID = 'CARD'
$rsGroup = CCatalogGroup::GetList([], ['XML_ID' => 'CARD']);
if (!($arGroup = $rsGroup->Fetch())) return false;
$priceTypeId = intval($arGroup['ID']);
if (!$priceTypeId) return false;
$dbPrice = CPrice::GetList([], ['PRODUCT_ID' => $productID, 'CATALOG_GROUP_ID' => $priceTypeId]);
if ($arPrice = $dbPrice->Fetch()) {
$price = floatval($arPrice['PRICE']);
return [
"PRICE" => $arPrice,
"RESULT_PRICE" => [
"BASE_PRICE" => ["PRICE" => $price, "CURRENCY" => $arPrice['CURRENCY']],
"DISCOUNT_PRICE" => 0,
"MIN_PRICE" => ["PRICE" => $price, "CURRENCY" => $arPrice['CURRENCY']]
],
"DISCOUNT_LIST" => []
];
}
return false;
}
- Простой AJAX‑скрипт на фронтенде (при выборе способа оплаты сохранить в сессии и перезагрузить корзину):
// Пример: при смене radio с data-code
document.querySelectorAll('input[name="PAY_SYSTEM_ID"]').forEach(function(el){
el.addEventListener('change', function(){
var pay = this.dataset.code || this.value;
BX.ajax({
url: '/local/ajax/set_payment.php',
method: 'POST',
dataType: 'json',
data: {'pay': pay},
onsuccess: function(){ location.reload(); } // либо обновлять только блок корзины через AJAX
});
});
});
/local/ajax/set_payment.php:
<?php
session_start();
$pay = $_POST['pay'] ?? '';
// валидация $pay: только разрешённые значения
$_SESSION['SELECTED_PAYMENT_METHOD'] = $pay;
echo json_encode(['status' => 'ok']);
Источники
- https://aspro.ru/kb/article/73/
- https://nikaverro.ru/blog/bitrix/nastroyka-vygruzki-tsen-iz-1s-v-bitriks-dlya-ut-11/
- https://www.intervolga.ru/blog/projects/personalnye-tseny-i-skidki-v-internet-magazine-na-1c-bitriks/
Заключение
Коротко: для корректной работы настройка типа цены 1С Битрикс должна включать два синхронизированных типа цен (CASH и CARD), точную реализацию формулы расчёта безналичной цены в 1С (с правильным порядком округления и наценки) и логику подстановки нужного типа цены в Битрикс на этапе корзины/чекаута (OnGetOptimalPrice или клиентский переключатель). Начните с уточнения бизнес‑правила округления (до сотни до наценки или после), реализуйте это в 1С и протестируйте полную цепочку: расчёт → выгрузка → отображение → перерасчёт корзины.