Введение и базовые концепции

Модуль Интернет-магазин sale отвечает за процесс покупки: от корзины до оформленного заказа. В заказе он связывает товары с покупателем, оплатой, доставкой, скидками и документами.

Типовой сценарий заказа состоит из нескольких шагов:

  1. Покупатель выбирает товар или торговое предложение из каталога.

  2. Товар попадает в корзину.

  3. На основе корзины создается заказ.

  4. К заказу добавляют свойства, оплату и отгрузку.

  5. Интернет-магазин применяет правила работы с корзиной и купоны.

  6. После оформления заказа интернет-магазин меняет статусы заказа и формирует документы.

Связь с торговым каталогом

Модуль Торговый каталог хранит данные для продажи товара: тип товара, цены, остатки, доступность, НДС, единицы измерения и торговые предложения. Модуль Интернет-магазин берет эти данные при добавлении позиции в корзину и при расчете заказа.

Товар или торговое предложение -> Корзина -> Заказ

Если у товара есть торговые предложения, в корзину добавляют конкретное предложение. Родительская карточка хранит общее описание товара, а предложение хранит выбранный вариант: размер, цвет, комплектацию, цену и остаток.

Подробнее о товарах в разделе Торговый каталог.

Основные термины

Корзина — набор товаров и услуг, которые покупатель выбрал до оформления заказа. С корзиной работает класс Bitrix\Sale\Basket.

Позиция корзины — один товар, торговое предложение или услуга в корзине. Позиция хранит количество, цену, валюту, название, поставщика товара и служебные данные для расчета.

Покупатель — пользователь, к которому привязана корзина и для которого создается заказ. Класс Bitrix\Sale\Fuser связывает корзину с идентификатором покупателя.

Заказ — оформленная продажа. Заказ объединяет корзину, покупателя, сайт, тип плательщика, свойства, оплаты, отгрузки, скидки, статусы и историю изменений. С заказом работает класс Bitrix\Sale\Order.

Тип плательщика — настройка, которая определяет доступные свойства заказа, платежные системы и службы доставки. Например, можно настроить разные способы оформления заказа для физического и юридического лица.

Свойства заказа — данные, которые покупатель или интеграция передают при оформлении заказа: имя, телефон, адрес, ИНН, комментарий и другие поля.

Оплата — часть заказа, которая фиксирует сумму к оплате, платежную систему и состояние оплаты. С оплатой работает класс Bitrix\Sale\Payment.

Платежная система — обработчик оплаты. Платежная система создает платежную ссылку, перенаправляет покупателя на страницу оплаты или принимает ответ от платежного сервиса.

Отгрузка — часть заказа, которая фиксирует доставляемые позиции, службу доставки, стоимость доставки и состояние отгрузки. С отгрузкой работает класс Bitrix\Sale\Shipment.

Служба доставки — обработчик доставки. Служба доставки рассчитывает стоимость и срок, хранит настройки обработчика и участвует в создании отгрузки.

Статус — состояние заказа или отгрузки. Например, заказ может быть новым, выполненным или отмененным. Состояние оплаты хранится в полях оплаты, например в поле PAID.

Правило работы с корзиной — правило скидки или другого изменения условий покупки. Расчетом скидок и правил занимается Bitrix\Sale\Discount.

Купон — код, который покупатель вводит для применения правила работы с корзиной.

Касса — обработчик онлайн-кассы. Касса получает данные заказа, оплаты или отгрузки и формирует фискальные документы в зависимости от типа операции.

Чек — фискальный документ, который отражает оплату, возврат или другой кассовый сценарий.

Местоположение — справочник стран, регионов, городов и других адресных объектов. Свойства заказа, службы доставки и ограничения используют местоположения для адресов и условий оформления заказа.

Настройки в интерфейсе продукта

Настройки модуля находятся в разделе Настройки > Настройки продукта > Настройки модулей > Интернет-магазин. На странице доступны группы настроек:

  • служебные параметры магазина: e-mail отдела продаж, хранение корзины, блокировка и отображение заказов, валюта, округление и сайты-магазины,

  • параметры корзины, cookies и идентификатора пользователя магазина,

  • настройки скидок, налога для доставки, просмотренных и сопутствующих товаров,

  • пути к пользовательским обработчикам платежных систем и служб доставки,

  • параметры веса, адрес магазина и виджет местоположений,

  • права на заказы и уровень доступа к модулю,

  • автоматизация статусов заказа и отгрузки, архивирование и шаблон нумерации заказов,

  • настройки чеков, страниц результата оплаты, подписок на товары, напоминаний и истории изменения заказов.

Основные справочники магазина настраивают на отдельных страницах административного интерфейса:

  • типы плательщиков, свойства заказа, статусы, платежные системы, службы доставки, кассы и местоположения — в разделе Магазин,

  • товары, торговые предложения, цены и остатки — в разделе Контент и настройках модуля Торговый каталог.

Если заказ создается из кода, заранее подготовьте настройки, которые понадобятся в сценарии: тип плательщика, свойства заказа, платежную систему, службу доставки, валюту и товары каталога. Код использует эти настройки по идентификаторам и символьным кодам, поэтому они должны существовать до запуска сценария.

Компоненты магазина

Для вывода корзины и формы оформления заказа на сайте используйте компоненты. Компоненты подходят для типовых публичных сценариев: корзины, формы оформления заказа, списка заказов покупателя, страницы оплаты и персональных разделов.

Компонент получает данные корзины и заказа, учитывает параметры показа и передает результат в шаблон. Если нужно изменить бизнес-логику оформления, используйте объектную модель модуля sale, а компонент оставьте для вывода формы и работы с интерфейсом.

Подробнее о работе компонентов читайте в статье Компоненты.

Базовый порядок работы

Работа с объектной моделью модуля sale в большинстве сценариев начинается с корзины.

  1. Создайте или загрузите корзину для сайта и покупателя.

  2. Добавьте в корзину товары, торговые предложения или услуги.

  3. Создайте заказ и передайте в него корзину.

  4. Укажите сайт, валюту, покупателя и тип плательщика.

  5. Заполните свойства заказа.

  6. Создайте отгрузку через коллекцию заказа, выберите службу доставки и рассчитайте ее стоимость.

  7. Создайте оплату с текущей суммой заказа и выберите доступную платежную систему.

  8. Выполните финальный расчет, обновите сумму оплаты и повторно проверьте доступность выбранных сервисов.

  9. Сохраните заказ и обработайте результат.

Оплата и отгрузка относятся к заказу. Не создавайте их отдельно от заказа, если вы оформляете покупку через объектную модель. Если при первом сохранении оплата или пользовательская отгрузка не нужны, пропустите соответствующий шаг и добавьте объект позже через коллекцию загруженного заказа.

API модуля

Перед использованием API подключите модуль sale. Если сценарий работает с товарами каталога, подключите модуль catalog.

if (!\Bitrix\Main\Loader::includeModule('sale'))
{
    throw new \RuntimeException('Не удалось подключить модуль sale');
}

if (!\Bitrix\Main\Loader::includeModule('catalog'))
{
    throw new \RuntimeException('Не удалось подключить модуль catalog');
}

В модуле Интернет-магазин для разных задач используют разные группы API. Выбор зависит от сценария.

  • Объектная модель подходит для оформления заказа и изменения его частей. Используйте классы Basket, Order, Payment и Shipment, чтобы создать корзину, заказ, оплату и отгрузку с проверками и событиями модуля.

  • ORM-классы *Table используйте для чтения справочников: типов плательщиков, свойств заказа, статусов, платежных систем, служб доставки, местоположений и других записей.

  • Сервисы и менеджеры используйте, когда нужно получить настроенную платежную систему, службу доставки, кассу или ограничение.

  • Классический API используйте там, где для сценария нет полной замены на D7 или код уже написан на классическом API.

Основные объекты для первого сценария:

Объект

Роль в сценарии

Bitrix\Sale\Basket

Хранит позиции до создания заказа и передает их в заказ

Bitrix\Sale\Fuser

Определяет покупателя, к которому привязана корзина

Bitrix\Sale\Order

Объединяет корзину, свойства, оплаты, отгрузки, скидки, статусы и историю продажи

Bitrix\Sale\Payment

Хранит сумму, платежную систему и состояние оплаты внутри заказа

Bitrix\Sale\Shipment

Хранит доставляемые позиции, службу доставки, стоимость и состояние отгрузки внутри заказа

Bitrix\Sale\Discount

Рассчитывает правила работы с корзиной, скидки и купоны для корзины или заказа

Пример. Создадим заказ с одним товаром из каталога, заполним свойство заказа, добавим отгрузку и оплату, затем сохраним заказ.

// Перед запуском примера подготовьте:
// $productId — идентификатор товара или торгового предложения
// $userId — идентификатор покупателя
// $personTypeId — идентификатор типа плательщика
// $propertyCode — символьный код свойства заказа
// $propertyValue — значение свойства заказа
// $paySystemId — идентификатор платежной системы
// $deliveryId — идентификатор службы доставки

if (!\Bitrix\Main\Loader::includeModule('sale'))
{
    throw new \RuntimeException('Не удалось подключить модуль sale');
}

if (!\Bitrix\Main\Loader::includeModule('catalog'))
{
    throw new \RuntimeException('Не удалось подключить модуль catalog');
}

$siteId = SITE_ID;
$currency = 'RUB';

// Создать корзину для сайта
$basket = \Bitrix\Sale\Basket::create($siteId);

// Добавить товар каталога в корзину
$basketResult = \Bitrix\Catalog\Product\Basket::addProductToBasket($basket, [
    'PRODUCT_ID' => $productId,
    'QUANTITY' => 1,
], [
    'SITE_ID' => $siteId,
    'USER_ID' => $userId,
]);

if (!$basketResult->isSuccess())
{
    throw new \RuntimeException(implode('; ', $basketResult->getErrorMessages()));
}

// Создать заказ покупателя
$order = \Bitrix\Sale\Order::create($siteId, $userId, $currency);
$personTypeResult = $order->setPersonTypeId($personTypeId);

if (!$personTypeResult->isSuccess())
{
    throw new \RuntimeException(implode('; ', $personTypeResult->getErrorMessages()));
}

$basketSetResult = $order->setBasket($basket);

if (!$basketSetResult->isSuccess())
{
    throw new \RuntimeException(implode('; ', $basketSetResult->getErrorMessages()));
}

// Заполнить свойство заказа по символьному коду
$propertyCollection = $order->getPropertyCollection();
$property = $propertyCollection->getItemByOrderPropertyCode($propertyCode);

if (!$property)
{
    throw new \RuntimeException('Свойство заказа не найдено');
}

$propertyResult = $property->setValue($propertyValue);

if (!$propertyResult->isSuccess())
{
    throw new \RuntimeException(implode('; ', $propertyResult->getErrorMessages()));
}

// Добавить отгрузку и ее позиции
$shipmentCollection = $order->getShipmentCollection();
$shipment = $shipmentCollection->createItem();
$shipmentItemCollection = $shipment->getShipmentItemCollection();

foreach ($basket as $item)
{
    $shipmentItem = $shipmentItemCollection->createItem($item);
    if (!$shipmentItem)
    {
        throw new \RuntimeException('Не удалось создать позицию отгрузки');
    }

    $shipmentItemResult = $shipmentItem->setQuantity($item->getQuantity());

    if (!$shipmentItemResult->isSuccess())
    {
        throw new \RuntimeException(implode('; ', $shipmentItemResult->getErrorMessages()));
    }
}

// Выбрать доступную службу доставки
$availableDeliveries = \Bitrix\Sale\Delivery\Services\Manager::getRestrictedObjectsList(
    $shipment
);
$delivery = $availableDeliveries[$deliveryId] ?? null;

if (!$delivery)
{
    throw new \RuntimeException('Служба доставки недоступна для заказа');
}

$shipment->setDeliveryService($delivery);

$deliveryResult = $shipmentCollection->calculateDelivery();

if (!$deliveryResult->isSuccess())
{
    throw new \RuntimeException(implode('; ', $deliveryResult->getErrorMessages()));
}

// Добавить оплату и выбрать доступную платежную систему
$paymentCollection = $order->getPaymentCollection();
$payment = $paymentCollection->createItem();
$paymentResult = $payment->setFields([
    'SUM' => $order->getPrice(),
    'CURRENCY' => $currency,
]);

if (!$paymentResult->isSuccess())
{
    throw new \RuntimeException(implode('; ', $paymentResult->getErrorMessages()));
}

$availablePaySystems = \Bitrix\Sale\PaySystem\Manager::getListWithRestrictions(
    $payment,
    \Bitrix\Sale\Services\Base\RestrictionManager::MODE_CLIENT
);

if (!isset($availablePaySystems[$paySystemId]))
{
    throw new \RuntimeException('Платежная система недоступна для заказа');
}

$paySystem = \Bitrix\Sale\PaySystem\Manager::getObjectById($paySystemId);

if (!$paySystem)
{
    throw new \RuntimeException('Платежная система не найдена');
}

$payment->setPaySystemService($paySystem);

// Рассчитать заказ после выбора доставки и платежной системы
$calculateResult = $order->doFinalAction(true);

if (!$calculateResult->isSuccess())
{
    throw new \RuntimeException(implode('; ', $calculateResult->getErrorMessages()));
}

$paymentResult = $payment->setField('SUM', $order->getPrice());

if (!$paymentResult->isSuccess())
{
    throw new \RuntimeException(implode('; ', $paymentResult->getErrorMessages()));
}

// Повторно проверить сервисы после финального расчета
$availableDeliveries = \Bitrix\Sale\Delivery\Services\Manager::getRestrictedObjectsList(
    $shipment
);

if (!isset($availableDeliveries[$deliveryId]))
{
    throw new \RuntimeException('Служба доставки недоступна после расчета заказа');
}

$availablePaySystems = \Bitrix\Sale\PaySystem\Manager::getListWithRestrictions(
    $payment,
    \Bitrix\Sale\Services\Base\RestrictionManager::MODE_CLIENT
);

if (!isset($availablePaySystems[$paySystemId]))
{
    throw new \RuntimeException('Платежная система недоступна после расчета заказа');
}

// Сохранить заказ и проверить результат
$result = $order->save();

if (!$result->isSuccess())
{
    throw new \RuntimeException(implode('; ', $result->getErrorMessages()));
}

После успешного выполнения примера метод save() сохранит заказ. Корзина станет частью заказа. Отгрузка будет содержать доставляемые позиции, а оплата — платежную систему и рассчитанную сумму заказа.

В примере показан базовый порядок работы с объектной моделью. В рабочем сценарии учитывайте:

  • что товар или торговое предложение должны быть активны и доступны для покупки,

  • обязательные свойства заказа нужно заполнить до сохранения,

  • платежная система и служба доставки должны быть доступны для выбранного сайта, типа плательщика и условий заказа,

  • нужно проверить права пользователя, от имени которого выполняется код.

Связанные материалы

Основной сценарий работы с заказом в материалах:

  1. Схема работы интернет-магазина и основные объекты — разберитесь, как связаны корзина, заказ, свойства, оплаты и отгрузки.

  2. Как выбрать API интернет-магазина — выберите объектную модель, ORM, менеджер сервиса или классический API для своей задачи.

  3. Базовые настройки интернет-магазина — подготовьте сайт, валюту, тип плательщика и настройки, которые нужны вашему сценарию.

  4. Работа с корзиной — создайте или загрузите корзину и подготовьте позиции.

  5. Оформление заказа и публичные сценарии — используйте стандартную публичную форму оформления.

  6. Создание заказа — соберите заказ в серверном, фоновом или интеграционном сценарии.

Если товары, цены и остатки еще не настроены, прочитайте Введение и базовые концепции торгового каталога.

После создания заказа переходите к профильной задаче: