Как выбрать API интернет-магазина

В модуле sale выбор API зависит не только от данных, но и от действия над ними. Один заказ объединяет корзину, свойства, оплаты, отгрузки, скидки, статусы и историю. Если изменить только одну запись через ORM, связанные объекты могут остаться в несогласованном состоянии.

Для нового кода используйте объектную модель заказа, ORM-классы, менеджеры сервисов и обработчики D7. Классический API нужен для отдельных операций, у которых нет полной замены, и для поддержки существующего проекта.

Перед работой подключите модули:

  • sale — для работы с API интернет-магазина,

  • currency — для сценариев с валютами,

  • catalog — для товаров, цен, остатков, резервирования и складских операций.

Связи объектов и поля ORM-классов описаны в материале Схема работы интернет-магазина и основные объекты.

Как выбрать между объектной моделью, ORM и менеджерами

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

Задача

Метод

Пояснение

Создать или изменить корзину, заказ, оплату либо отгрузку

Объектная модель Bitrix\Sale

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

Получить список, отфильтровать строки или рассчитать агрегаты

ORM-классы Bitrix\Sale\Internals\*Table

Формируют выборку без загрузки полного объекта заказа

Прочитать или изменить отдельную настройку

Профильный ORM-класс или менеджер

Работает с настройками типов плательщиков, свойств, статусов, компаний и других объектов вне жизненного цикла заказа

Выбрать платежную систему, службу доставки, кассу или компанию

Профильный Manager

Возвращает настроенный сервис и учитывает его ограничения

Рассчитать заказ, скидки, доставку или доступность сервиса

Объектная модель и профильный сервис

Расчет зависит от состава заказа, покупателя, сайта, типа плательщика и настроек

Поддержать существующий код или выполнить операцию без полного D7-аналога

Классический API CSale*

Сохраняет совместимость или предоставляет специальную операцию, которой нет на другом уровне API

Объектная модель

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

  • Bitrix\Sale\Basket — корзина,

  • Bitrix\Sale\Order — заказ,

  • Bitrix\Sale\PaymentCollection — коллекция оплат,

  • Bitrix\Sale\ShipmentCollection — коллекция отгрузок.

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

Способ сохранения корзины зависит от ее связи с заказом. Если корзина еще не привязана к заказу, вызовите Basket::save(). Корзину сохраненного заказа отдельно не сохраняйте: вызовите Order::save().

Оба метода возвращают объект Bitrix\Sale\Result. Проверьте его после сохранения: успешное изменение отдельного поля еще не означает, что все данные записаны.

ORM-классы

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

  • Bitrix\Sale\Internals\OrderTable — для заказов,

  • Bitrix\Sale\Internals\BasketTable — для позиций корзины,

  • Bitrix\Sale\Internals\PaymentTable — для оплат,

  • Bitrix\Sale\Internals\ShipmentTable — для отгрузок.

Не изменяйте через эти классы заказ и его коллекции. ORM-запись не выполняет полный жизненный цикл объектной модели и не согласует корзину, оплаты, отгрузки, свойства, скидки и историю.

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

Менеджеры и сервисы

Менеджер выбирает настроенную реализацию и применяет правила подсистемы. Используйте:

  • Bitrix\Sale\Delivery\Services\Manager — для служб доставки,

  • Bitrix\Sale\PaySystem\Manager — для платежных систем,

  • Bitrix\Sale\Cashbox\Manager и Bitrix\Sale\Cashbox\CheckManager — для касс и чеков,

  • Bitrix\Sale\Services\Company\Manager — для компаний,

  • Bitrix\Sale\DiscountCouponsManager — для купонов в расчете корзины или заказа.

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

Классический API

К классическому API относятся классы CSale*. Проверяйте назначение каждого класса отдельно. Одни классы устарели целиком, другие продолжают предоставлять отдельные актуальные операции.

Для нового сценария сначала ищите объектную модель, ORM-класс или менеджер. Обращайтесь к классическому API, если для конкретной операции нет полной замены в D7.

Корзина и заказ

Корзина хранит выбранные товары, а заказ объединяет корзину, свойства, оплаты и отгрузки. Для чтения или изменения одного заказа загрузите объект Bitrix\Sale\Order. Для списка сохраненных полей используйте ORM.

Задача

Метод

Пояснение

Создать пустую корзину

Bitrix\Sale\Basket::create()

Для нового кода не используйте CSaleBasket::Add()

Загрузить корзину покупателя

Basket::loadItemsForFUser() и Bitrix\Sale\Fuser

Методы загружают корзину по идентификатору покупателя без самостоятельного запроса к строкам корзины

Добавить товар каталога

Bitrix\Catalog\Product\Basket::addProductToBasket()

Метод заполняет рассчитанные поля товара через провайдера

Изменить позицию корзины

BasketItem::setField(), затем Basket::save() для самостоятельной корзины или Order::save() для корзины сохраненного заказа

Не обновляйте позицию через BasketTable::update() и не сохраняйте корзину заказа отдельно

Прочитать позиции для отчета

Bitrix\Sale\Internals\BasketTable::getList()

ORM-выборка не требует загружать каждую корзину в цикле

Создать заказ

Bitrix\Sale\Order::create(), коллекции заказа и Order::save()

Для нового кода не используйте CSaleOrder::Add() и прямые записи в таблицы

Загрузить и изменить заказ

Order::load(), методы заказа и его коллекций

Не изменяйте заказ через OrderTable::update()

Отменить или физически удалить заказ

Поле CANCELED и Order::save() для обычного отказа, Order::delete() только для служебного удаления

Не используйте физическое удаление для отмены покупки

Получить список заказов

Bitrix\Sale\Internals\OrderTable::getList()

Не загружайте каждый заказ через Order::load(), если нужны только сохраненные поля

Проверить права на конкретный заказ

Методы CSaleOrder::CanUser*() для нужной операции

Уровень доступа к модулю и статус заказа не заменяют проверку права на конкретную операцию

При изменении заказа соблюдайте последовательность действий:

  1. Проверьте права.

  2. Загрузите объект.

  3. Измените профильную коллекцию.

  4. Пересчитайте зависимые данные.

  5. Сохраните заказ.

Не запускайте save() повторно без разбора ошибок и предупреждений. Повтор без условий из обработчика события может вызвать рекурсию.

Настройки и свойства заказа

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

Задача

Метод

Пояснение

Создать или найти тип плательщика

Bitrix\Sale\Internals\PersonTypeTable, Bitrix\Sale\PersonType

Настройка должна быть связана с нужным сайтом

Создать группу или описание свойства заказа

Bitrix\Sale\Internals\OrderPropsGroupTable, OrderPropsTable

Классы работают с настройкой поля, не со значением в заказе

Заполнить или изменить значение свойства заказа

Order::getPropertyCollection() и объект значения

Изменения сохраняются вместе с заказом

Создать статус и локализованное название

Bitrix\Sale\Internals\StatusTable и StatusLangTable

Тип статуса заказа и отгрузки задавайте явно

Получить разрешенные статусы

Bitrix\Sale\OrderStatus или Bitrix\Sale\DeliveryStatus

Выберите класс по типу объекта

Создать или изменить профиль покупателя

CSaleOrderUserProps::DoSaveUserProfile()

D7-сценария с сопоставлением значений нет

Удалить профиль покупателя

CSaleOrderUserProps::Delete()

Метод удаляет профиль вместе со связанными значениями

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

Оплаты, доставки и кассы

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

Задача

Метод

Пояснение

Создать оплату

Order::getPaymentCollection()->createItem()

Оплата сохраняется в составе заказа

Выбрать доступную платежную систему

Bitrix\Sale\PaySystem\Manager::getListWithRestrictions()

Учитывает ограничения для оплаты и заказа

Получить настроенную платежную систему

PaySystem\Manager::getObjectById()

Возвращает объект сервиса для запуска обработчика

Создать обработчик платежной системы

Наследник PaySystem\ServiceHandler или BaseServiceHandler

Работает в механизме платежных систем D7

Создать отгрузку

Order::getShipmentCollection()->createItem()

Отгрузка сохраняется вместе с позициями и заказом

Выбрать доступную службу доставки

Delivery\Services\Manager::getRestrictedList()

Учитывает ограничения службы для отгрузки

Рассчитать доставку

Объект службы из Delivery\Services\Manager и объект отгрузки

Расчет зависит от состава и адресных данных заказа

Создать обработчик доставки

Наследник Bitrix\Sale\Delivery\Services\Base

Регистрируется как служба доставки нового типа

Работать с транспортной заявкой

Bitrix\Sale\Delivery\Requests\Manager и обработчик доставки

Связывает заявку с отгрузками и внешней службой

Получить доступную кассу

Bitrix\Sale\Cashbox\Manager

Учитывает ограничения кассы, оплаты, отгрузки и компании

Создать или перепечатать чек

Bitrix\Sale\Cashbox\CheckManager

Управляет жизненным циклом чека и результатом печати

Не создавайте оплату или отгрузку прямой записью через PaymentTable и ShipmentTable. Для отчетов эти классы подходят, но для изменения состояния нужны коллекции заказа и профильные методы.

Скидки, купоны и резервирование

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

Задача

Метод

Пояснение

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

Bitrix\Sale\Discount::buildFromBasket(), calculate() и Basket::applyDiscount()

Не вызывайте buildFromBasket() для корзины заказа; сохраненный заказ пересчитывайте через Order::doFinalAction(true)

Пересчитать сохраненный заказ

Order::doFinalAction(true)

Выполняйте после изменений, которые влияют на стоимость

Передать купон в расчет

Bitrix\Sale\DiscountCouponsManager

Принятый код купона еще не подтверждает применение скидки

Создать правило работы с корзиной

CSaleDiscount::Add()

У сценария настройки правила нет полной замены в D7

Зарезервировать или списать товар

Объекты заказа, отгрузки и сервисы Bitrix\Sale\Reservation

Операция связана с количеством в отгрузке и провайдером каталога

Провести складское движение

API складских документов модуля catalog

Заказ и отгрузка не заменяют складской документ

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

Местоположения, покупатели и связанные данные

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

Задача

Метод

Пояснение

Найти местоположение

ORM-классы пространства имен Bitrix\Sale\Location

Используйте код или идентификатор конкретного адресного объекта

Передать адрес в расчет доставки

Коллекция свойств заказа и менеджер доставки

Значение свойства должно соответствовать типу и настройке местоположения

Получить общую сумму налога заказа

Order::getTaxValue()

Возвращает итог для объекта заказа

Прочитать сохраненные строки налогов

CSaleOrderTax

Полного D7-сценария для детализации нет

Связать корзину с покупателем

Bitrix\Sale\Fuser

Идентификатор покупателя корзины отличается от идентификатора пользователя

Получить показатели покупателя

Bitrix\Sale\BuyerStatistic

Возвращает сохраненную статистику по пользователю, сайту и валюте

Прочитать или изменить внутренний счет

CSaleUserAccount для баланса, Bitrix\Sale\Internals\UserTransactTable для чтения журнала

У D7 нет класса для безопасного изменения баланса. Передавайте в UpdateAccount() изменение суммы, а не новый итог

Статусы, события и история

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

Задача

Метод

Пояснение

Изменить статус заказа

OrderStatus, проверка CSaleOrder::CanUserChangeOrderStatus() и объект Order

Матрица статусов не заменяет проверку доступа к конкретному заказу

Изменить статус отгрузки

DeliveryStatus и объект Shipment

Не смешивайте статус отгрузки с признаками разрешения и списания

Подписаться на жизненный цикл заказа

Bitrix\Main\EventManager и события OnSale*

Выберите событие по моменту: до изменения, до сохранения или после полного сохранения

Прочитать журнал изменений

CSaleOrderChange

Класс Bitrix\Sale\OrderHistory формирует историю, но чтение журнала выполняет классический API

Отправить штатное уведомление

Настройки почтовых событий и жизненный цикл заказа

Не дублируйте штатное письмо собственным обработчиком

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

Отчеты, архив и интеграции

Эти сценарии чаще читают много заказов, поэтому полная загрузка объектной модели нужна не всегда.

Задача

Метод

Пояснение

Построить список или агрегат

OrderTable, BasketTable, PaymentTable, ShipmentTable

ORM-выборка подходит только для чтения

Прочитать архивный заказ или восстановить архивный объект в памяти

Bitrix\Sale\Archive\Manager

Метод returnArchivedOrder() возвращает объект только для чтения; не сохраняйте его как активный заказ

Подготовить печатную форму

Bitrix\Sale\Order, связанные коллекции и PHP-шаблон

ORM подходит для предварительного поиска, но не заменяет объект заказа с полным набором данных формы

Настроить штатный обмен с 1С

Компонент bitrix:sale.export.1c и настройки обмена

Не копируйте внутреннюю реализацию компонента в собственный модуль

Реализовать собственную интеграцию

OrderTable для пакетного отбора идентификаторов и простых сохраненных полей; Order для полного сообщения и изменений

Загружайте объект заказа непосредственно перед чтением связанных коллекций или записью; храните внешний идентификатор и состояние обмена

Оформить заказ в публичной части

Компонент bitrix:sale.order.ajax для типовой формы, объектная модель для собственной бизнес-логики

Не меняйте внутренние шаги компонента прямой записью в таблицы

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

Сводная таблица классического API

К классическому API относятся классы CSale*. Для многих задач нового кода есть подход D7, но отдельные операции по-прежнему выполняют через классический API. Таблица помогает выбрать актуальный подход для конкретной задачи.

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

Задача

Классический API

Актуальный подход

Работать с корзиной

CSaleBasket

Bitrix\Sale\Basket, BasketItem, Fuser, Bitrix\Catalog\Product\Basket

Создать или изменить заказ

CSaleOrder

Bitrix\Sale\Order и коллекции заказа; методы CSaleOrder::CanUser*() остаются для проверки прав

Настроить платежную систему

CSalePaySystem, CSalePaySystemAction

Bitrix\Sale\PaySystem\Manager, Service, ServiceHandler

Настроить службу доставки

CSaleDelivery, CSaleDeliveryHandler

Bitrix\Sale\Delivery\Services\Manager и наследник Services\Base

Создать статус или проверить переход

CSaleStatus

Bitrix\Sale\Internals\StatusTable для настройки, OrderStatus и DeliveryStatus для разрешенных переходов

Создать или найти тип плательщика

CSalePersonType

Bitrix\Sale\Internals\PersonTypeTable и Bitrix\Sale\PersonType; тип плательщика нужно связать с сайтом

Настроить свойства заказа

CSaleOrderProps

OrderPropsTable для настроек и коллекция свойств объекта заказа для значений

Рассчитать или настроить правило корзины

CSaleDiscount

Bitrix\Sale\Discount и DiscountCouponsManager для расчета; для создания и чтения настроек правила полный D7-сценарий отсутствует

Создать, изменить или удалить профиль

CSaleOrderUserProps

ORM-классы профилей для чтения; DoSaveUserProfile() и Delete() сохраняют целостность связанных значений

Получить налог заказа

CSaleOrderTax

Order::getTaxValue() возвращает общую сумму; строки сохраненного налога читает классический API

Прочитать журнал изменений

CSaleOrderChange

Полной замены для чтения журнала нет; события D7 используют для реакции на новые изменения

Настроить обмен с 1С

CSaleExport, CSaleOrderLoader

Штатный компонент обмена или собственная интеграция на Order; классические классы остаются частью поддерживаемого штатного обмена

Типичные ошибки выбора API

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

Выбирайте API по задаче:

  • объектная модель выполняет жизненный цикл покупки,

  • ORM читает данные массово,

  • менеджер выбирает настроенный сервис,

  • классический API выполняет операции без полной замены в D7.

После операции проверяйте результат:

  • после записи — объект Result,

  • расчета — итоговые значения и состояния,

  • пакетного чтения — полноту активных и архивных данных.

Ошибка

Почему возникает проблема

Как делать

Изменять заказ через OrderTable::update()

Не согласуются коллекции, расчеты, события и история

Загрузить Order, изменить профильный объект и вызвать save()

Создавать оплату или отгрузку отдельной ORM-записью

Объект не включается корректно в коллекцию заказа

Создать элемент через коллекцию загруженного заказа

Загружать каждый заказ через Order::load() для простого списка

Полная объектная модель создает лишнюю нагрузку

Выбрать нужные поля одним ORM-запросом

Менять справочник только через объект заказа

Настройка существует независимо от заказа

Использовать профильный ORM-класс или менеджер

Выбирать сервис только методом getObjectById()

Идентификатор не подтверждает доступность для текущего заказа

Сначала получить список с ограничениями, затем загрузить выбранный сервис

Считать успешное добавление купона подтверждением скидки

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

Пересчитать объект и проверить статус купона

Проверять только статус перед изменением заказа

Статус не подтверждает права на сайт и конкретную операцию

Вызвать профильный метод проверки прав для заказа

Смешивать активные и архивные заказы в одном источнике

После архивирования заказ исчезает из активных ORM-таблиц

Прочитать активные и архивные данные отдельно и объединить по явному правилу

Повторять save() при любой ошибке

Причина может сохраниться, а обработчики запустятся повторно

Разобрать результат, загрузить актуальное состояние и решить, допустим ли повтор

Переписать классический вызов без проверки границы замены

У метода может не быть полного D7-аналога

Сверить конкретную операцию со сводной таблицей и профильной статьей