Оглавление
Стандартный набор ограничений платёжной системы
Из коробки 1С Битрикс «Управление сайтом» предоставляет следующий набор ограничений:- По цене
- % от стоимости заказа
- По Валюте
- По службе доставки
- По сайтам
- По категориям товара
- По конкретным товарам
Собственный класс ограничений
Давайте представим что ваш интернет магазин помимо основной продукции которая всегда есть в наличии, торгует также товарами под заказ. Т.е. наличие, цену и сроки поставки таких товаров менеджер может узнать отдельно, после оформления заказ на сайте, а дальше согласовать с клиентом итоговую стоимость заказа и выполнить отгрузку.Однако, на сайте доступна онлайн оплата заказа. Естественно принимать оплату онлайн на заказы, с такими товарами нельзя, т.к. приняв оплату, магазин по сути обязуется продать клиенту эти товары по заявленным (и скорее всего не актуальным) ценам. Следовательно, нам нужно внедрить пользовательское ограничение, которое будет проверять корзину на наличие таких товаров.
Чтобы отличать такие товары, создадим в инфоблоке торговых предложений (если у вас каталог с товарами и предложениями) свойство POD_ZAKAZ типа список, с единственным значением "Да".
Теперь у вас есть возможность отмечать торговые предложения специальным флагом. Перейдём к созданию ограничения.
Первым делом нам нужно наследоваться от класса
Base\Restriction
и задать 3 основных метода getClassTitle()
, getClassDescription()
для получения названия и описания ограничения и основной метод проверки основного условия check()
., результат которого и будет учитываться компонентом sale.order.ajax при формировании списка доступных платёжных систем.
<?php
namespace Lib\Restrictions;
use Bitrix\Sale\Internals\Entity;
use Bitrix\Sale\Order;
use Bitrix\Sale\Payment;
use Bitrix\Sale\PaymentCollection;
use Bitrix\Sale\Services\Base;
/**
* Ограничение платёжных систем, при наличию в корзине товаров «под заказ»
*/
class OnOrderProductsInBasket extends Base\Restriction {
/**
* Метод проверки основного условия
* @param $courierUnavailable
* @param array $restrictionParams
* @param $deliveryId
* @return void
*/
public static function check($checkOnOrderItems, array $restrictionParams, $serviceId = 0)
{
if(empty($restrictionParams)){
return true;
}
if($restrictionParams['ONORDERPRODUCTS_UNAVAILABLE'] == 'Y' && $checkOnOrderItems == true){
$result = false;
}
if($restrictionParams['ONORDERPRODUCTS_UNAVAILABLE'] == 'Y' && $checkOnOrderItems == false){
$result = true;
}
if($restrictionParams['ONORDERPRODUCTS_UNAVAILABLE'] == 'N' && $checkOnOrderItems == true){
$result = false;
}
return $result;
}
/**
* Название ограничения
* @return mixed
*/
public static function getClassTitle()
{
return 'по наличию товаров «под заказ» в корзине';
}
/**
* Описание ограничения
* @return mixed
*/
public static function getClassDescription()
{
return 'Ограничение по наличию заказных позиций в корзине.';
}
protected static function extractParams(Entity $entity)
{
if ($entity instanceof Payment) {
/** @var PaymentCollection $collection */
$collection = $entity->getCollection();
/** @var Order $order */
$order = $collection->getOrder();
/** И вот тут проверяем, есть ли в заказе заказная позиция */
$basket = $order->getBasket();
if($basket){
return self::checkOnOrderItems($basket);
}
} else {
return -1;
}
return 0;
}
/**
* Параметры для создания формы ограничения в админке (типа, дефолтных значений и т.д.)
* @param $entityId
* @return array[]
*/
public static function getParamsStructure($entityId = 0)
{
return [
"ONORDERPRODUCTS_UNAVAILABLE" => [
"TYPE" => "Y/N",
"DEFAULT" => "Y",
'MIN' => 0,
"LABEL" => 'Доступно только для заказов, в которых нет товаров, привозимых под заказ'
],
];
}
/**
* Проверяем, есть ли в заказе товары под заказ (которые не лежат на складе Чистовье)
* @param \Sale\Basket $basket
* @return void
*/
public static function checkOnOrderItems(Bitrix\Sale\Basket $basket)
{
$isOnOrderItems = false;
//Получим массив ID товаров с меткой "Под заказ"
$arOnOrderProductsId = self::getOnOrderedProductsId();
//Получим товары корзины пользователя
$products = $basket->getBasketItems();
//И проверим, есть ли в корзине товары из списка "Под заказ"
foreach ($products as $itemIndex => $product) {
$offerId = $product->getProductId();
if(in_array($offerId, $arOnOrderProductsId)){
//Если такие товары найдены, меняем флаг наличия товаров под заказ на true
$isOnOrderItems = true;
}
}
return $isOnOrderItems;
}
/**
* Получить список товаров с меткой "Под заказ"
* @return array
*/
public static function getOnOrderedProductsId()
{
$productsForOrdered = [];
$arSelect = ['ID'];
$arFilter = ['IBLOCK_ID'=>IB_CATALOG_SKU, '!PROPERTY_POD_ZAKAZ'=>false];
$res = \CIBlockElement::GetList(['ID'=>'ASC'], $arFilter, false, false, $arSelect);
while($ob = $res->GetNextElement())
{
$arFields = $ob->GetFields();
$productsForOrdered[] = $arFields['ID'];
}
return $productsForOrdered;
}
}
Вспомогательные методы getOnOrderedProductsId()
возвращает массив товаров с флагом «Под заказ», а метод checkOnOrderItems()
проверяет корзину заказа на наличие товаров из списка, что вернёт первый метод.Подключение и использование
Классы ограничений у меня лежат в папке
/local/Lib/Restrictions/
пространство имён задано как Lib\Restrictions
. Следовательно для «автозагрузки» классов в стиле 1С Битрикс, нам потребуется вызвать Loader::registerAutoLoadClasses()
, можно прямо в /local/php_interface/init.php
, хотя у меня это отдельный файл /local/php_interface/autoload.php
:
use Bitrix\Main\Loader;
//Автозагрузка наших классов
Loader::registerAutoLoadClasses(null, [
'Lib\Restrictions\OnOrderProductsInBasket' => APP_CLASS_FOLDER . 'Restrictions/OnOrderProductsInBasket.php',
]);
Константа
APP_CLASS_FOLDER
указывает на папку со всеми пользовательскими классами.Чтобы ваше ограничение стало доступно в админке, необходимо повесить обработчик на событие инициализации списка ограничений службы доставки
onSaleDeliveryRestrictionsClassNamesBuildList
.Для этого нужно создать функцию возвращающую объект
\Bitrix\Main\EventResult()
с набором классов ограничений для платёжных систем.
/**
* Подключаем кастомные классы ограничения платёжных систем
* @return EventResult
*/
function customPaySystemRestrictionAdd(){
return new \Bitrix\Main\EventResult(
\Bitrix\Main\EventResult::SUCCESS,
[
'Lib\Restrictions\OnOrderProductsInBasket' => APP_CLASS_FOLDER . 'Restrictions/OnOrderProductsInBasket.php',
]
);
}
И остаётся повесить её вызов на событие.
use Bitrix\Main;
$eventManager = Main\EventManager::getInstance();
//Кастомные ограничения платёжных систем
$eventManager->addEventHandler(
'sale',
'onSalePaySystemRestrictionsClassNamesBuildList', //Событие создания списка ограничений платёжных систем
'customPaySystemRestrictionAdd'
);
Теперь, вы можете воспользоваться вашим ограничением. Перейдём в админку, раздел Магазин -> Настройки -> Платёжные системы, выберем интересующую нас службу доставки. У меня это «Банковские карты», перейдём во вкладку «Ограничения» и добавим наше ограничение:
Отметим флаг в настройках ограничения и сохраним.
Теперь выбранная платёжная система не будет доступна, если в корзине есть товар с флагом «Под заказ». Добавим обычные товары в корзину:
Как видите оплата банковской картой доступна. Добавим товар у торговых предложений которого отмечен флаг «Под заказ» (напомню что это обычное пользовательское свойство ифоблока типа «список»)
Добавим его в корзину.
Как видите ограничение отработало корректно и платёжная система «Банковские карты» более недоступна. Используя подобные ограничение вы можете очень тонко настраивать условия доступности платёжных систем.
Желаю удачи!