Розробка функціоналу «назви свою ціну» на 1С-Бітрикс
Механізм PWYW (Pay What You Want) дозволяє покупцю самомуввести суму за товар або послугу — з можливим нижнім порогом. Бітрикс не підтримує це з коробки: ціна в b_catalog_price фіксована, і модуль sale не приймає довільну суму від клієнта. Вся логіка переважує на рівні кошика та форми оформлення замовлення.
Де зберігати налаштування
Для кожного товара, що бере участь у механізмі, потрібні три додаткових параметри:
-
PWYW_ENABLED— флаг активності (Y/N) -
PWYW_MIN_PRICE— мінімальна сума (може бути 0) -
PWYW_SUGGESTED_PRICE— рекомендована сума (відображається за замовчуванням)
Зберігання — властивості інфоблока каталога. Для торговельних пропозицій (SKU) додаються через CIBlockProperty::Add() до IBLOCK_ID торговельних пропозицій. Тип властивостей — N (число) для цін, S для флага.
Альтернатива — HL-блок PwywSettings з полями UF_PRODUCT_ID, UF_MIN_PRICE, UF_SUGGESTED_PRICE, UF_ACTIVE. Підходить, коли потрібно управляти налаштуваннями масово з адміністративного інтерфейсу без редагування кожного товара.
Перехват ціни при додаванні в кошик
Стандартний $basket->addItem() бере ціну з каталога. Потрібно перехопити момент до збереження та підставити ціну від клієнта.
Клієнтська частина: форма на сторінці товара містить поле pwyw_price. При відправці — AJAX на кастомний endpoint.
Серверна обробка:
use Bitrix\Sale\Basket;
use Bitrix\Sale\BasketItem;
use Bitrix\Main\Context;
$request = Context::getCurrent()->getRequest();
$productId = (int)$request->getPost('product_id');
$userPrice = (float)$request->getPost('pwyw_price');
// Перевіряємо мінімальний поріг
$minPrice = getPwywMinPrice($productId); // читає властивість інфоблока
if ($userPrice < $minPrice) {
echo json_encode(['error' => 'Ціна нижче мінімальної']);
die();
}
$basket = Basket::loadItemsForFUser(
\CSaleBasket::GetBasketUserID(),
\Bitrix\Main\Context::getCurrent()->getSite()
);
$item = $basket->createItem('catalog', $productId);
$item->setFields([
'QUANTITY' => 1,
'CURRENCY' => \Bitrix\Currency\CurrencyManager::getBaseCurrency(),
'LID' => SITE_ID,
'PRODUCT_PROVIDER_CLASS' => 'CCatalogProductProvider',
'PRICE' => $userPrice,
'BASE_PRICE' => $userPrice,
'CUSTOM_PRICE' => 'Y', // заборона автоматичного перерахунку
]);
// Зберігаємо введену ціну у властивість кошика
$item->getPropertyCollection()->setProperty([
'NAME' => 'PWYW_PRICE',
'CODE' => 'PWYW_PRICE',
'VALUE' => $userPrice,
'SORT' => 100,
]);
$basket->save();
Поле CUSTOM_PRICE = 'Y' — ключове. Без нього Бітрикс при перерахунку кошика замінить введену ціну каталожною через провайдер CCatalogProductProvider.
Захист від перерахунку
Навіть з CUSTOM_PRICE = 'Y' деякі обработчики можуть скинути ціну. Підписуємся на подію OnSaleBasketItemRefreshData та відновлюємо ціну з властивості кошика:
AddEventHandler('sale', 'OnSaleBasketItemRefreshData', function(&$fields) {
$basketItem = $fields['BASKET_ITEM'];
$props = $basketItem->getPropertyCollection();
$pwywProp = $props->getItemByCode('PWYW_PRICE');
if ($pwywProp && $pwywProp->getValue() > 0) {
$fields['PRICE'] = (float)$pwywProp->getValue();
$fields['BASE_PRICE'] = (float)$pwywProp->getValue();
$fields['CUSTOM_PRICE'] = 'Y';
}
});
Мінімальна ціна та UI-валідація
Мінімальний поріг перевіряється двічі: на клієнті (JavaScript) та на сервері (PHP). Клієнтська перевірка — для UX, серверна — обов'язкова.
На сторінці товара дані мінімальної ціни передаються через data-атрибути або inline-JS:
<div class="pwyw-widget"
data-min-price="{{ $minPrice }}"
data-suggested="{{ $suggestedPrice }}">
<input type="number" name="pwyw_price"
min="{{ $minPrice }}"
value="{{ $suggestedPrice }}"
step="1">
<div class="pwyw-hint">Мінімальна сума: {{ $minPrice }} ₴</div>
</div>
Замість шаблонізатора Бітрикс — значення підставляються в компоненті через $arResult або $arParams.
Відображення в замовленні та особистому кабінеті
В адміністративному замовленні (sale.admin.order.edit) та в листах потрібно показувати, що ціна введена вручну. Переважуємо шаблон компонента bitrix:sale.order.ajax — додаємо вивід властивості PWYW_PRICE з позначкою «ціна вказана покупцем».
У поштових шаблонах типу SALE_NEW_ORDER додаємо блок з виводом властивостей кошика через #BASKET_ITEMS# — властивість PWYW_PRICE вже буде включена в стандартну підстановку.
Аналітика та мінімальні суми
Для аналізу реальної поведінки покупців — які суми вводять, скільки разів вводять нижче мінімуму — логуємо всі спроби в кастомну таблицю b_pwyw_log:
CREATE TABLE b_pwyw_log (
ID INT AUTO_INCREMENT PRIMARY KEY,
PRODUCT_ID INT,
USER_ID INT,
PRICE_ENTERED DECIMAL(10,2),
MIN_PRICE DECIMAL(10,2),
ACCEPTED TINYINT(1),
DATE_ADD DATETIME DEFAULT CURRENT_TIMESTAMP
);
Дані з цієї таблиці допомагають прийняти рішення про корегування мінімального порога.
Строки реалізації
| Варіант | Опис | Строк |
|---|---|---|
| Базовий (одне поле, без обмежень) | Властивості інфоблока + AJAX + обработчик кошика | 3–5 днів |
| З мінімальним порогом та логуванням | + таблиця логів, серверна валідація, UI-підказки | 1 тиждень |
| Повнофункціональний (HL-блок налаштувань, аналітика, підтримка SKU) | Адміністративний інтерфейс + аналітичний звіт | 1.5–2 тижні |







