Вы написали удобную доработку под один проект и понимаете, что она пригодится десяткам клиентов. Естественное желание — оформить её как тиражный модуль для Маркетплейса 1С-Битрикс: чтобы ставился в пару кликов, обновлялся сам и продавался с витрины. Но между «работающим кодом на проде» и «решением, которое приняли в Маркетплейс», лежит целый пласт требований — структура каталога, корректный установщик, версионирование, лицензирование и десятки правил вендора, о которые спотыкаются на первой же модерации.
В этой статье — практический маршрут от локальной доработки до опубликованного модуля: как разложить файлы, что обязано быть в классе установки, как устроены обновления через систему SiteUpdate, как защитить платное решение лицензией и что проверяет вендор. Материал основан на нашей практике разработки на 1С-Битрикс — без общих слов, с опорой на реальную структуру модуля.
Коротко
- Модуль Маркетплейса — это стандартная структура в
/bitrix/modules/partner.name/с полным установщиком. - Класс установки обязан чисто ставить и удалять файлы, таблицы, события, агенты и права.
- Версии описываются в
install/version.php, обновления разъезжаются черезSiteUpdate. - Платный модуль защищается лицензией по домену и ключу; при её отсутствии функциональность деградирует мягко.
- Перед отправкой прогоните решение по чек-листу вендора: «грязное» удаление и прямые SQL — главные причины отказа.
Что такое модуль Маркетплейса и зачем его собирать
Модуль в 1С-Битрикс — это самостоятельная единица функциональности с собственным пространством имён, своими таблицами, событиями, правами доступа и точкой входа. Ядро само состоит из модулей (main, iblock, catalog, sale и десятки других), и ваш продукт встраивается в ту же систему на равных правах. Маркетплейс — это витрина и инфраструктура доставки таких модулей: каталог решений, механизм установки, лицензирование и автоматические обновления.
Ключевая разница между «модулем для себя» и «модулем для Маркетплейса» не в коде функциональности, а в дисциплине упаковки. Локальную доработку вы пишете под конкретную редакцию, конкретную версию ядра и известное окружение. Тиражный модуль поедет на сотни сайтов, про которые вы ничего не знаете: другая редакция, другой набор установленных модулей, другой хостинг, другая версия PHP. Поэтому от маркетплейсного модуля требуется предсказуемая установка, аккуратное удаление и совместимость в широком диапазоне окружений.
Собирать полноценный модуль стоит, когда у решения появляется тираж: одну и ту же логику вы разворачиваете более чем на одном-двух проектах. В этот момент копировать файлы вручную становится дорого и рискованно, а модуль даёт вам единый установщик, версионирование и канал обновлений. Если же вы делаете уникальную доработку под один магазин, зачастую разумнее оформить её как локальное решение — например, через события и обработчики в отдельном служебном модуле проекта, не выходя на Маркетплейс.
Структура каталога модуля
Модуль живёт в каталоге /bitrix/modules/<идентификатор>/ и имеет строго заданную структуру служебных файлов. Минимально работоспособный и пригодный к публикации модуль состоит из следующих частей.
include.php— точка входа: подключается при вызовеLoader::includeModule()и регистрирует автозагрузку классов модуля.install/index.php— класс установки (наследникCModule) с методамиDoInstall/DoUninstallи установкой/удалением файлов, БД, событий, агентов и прав.install/version.php— текущая версия модуля и дата: константыVERSIONиVERSION_DATE.install/db/— SQL-скрипты установки и удаления таблиц под разные СУБД (в подкаталогах по типу базы).install/components/,install/js/,install/admin/— файлы, которые копируются в публичную часть при установке (компоненты, скрипты, админ-страницы).lib/— классы модуля в неймспейсе, подключаемые автозагрузчиком (сущности ORM, сервисы, хелперы).lang/— языковые файлы для локализации сообщений и интерфейса на русском и других языках.options.php— страница настроек модуля в админке (вкладка «Настройки модулей»).- Описание и метаданные — файлы описания решения (
.description.phpи подобные), которые видит покупатель на витрине.
Важно различать два «слоя» файлов. Всё, что лежит в корне модуля (include.php, lib/, lang/), остаётся в каталоге модуля и работает оттуда. А содержимое install/components/, install/js/, install/admin/ — это шаблонные копии, которые метод установки переносит в публичные каталоги системы (/bitrix/components/, /bitrix/js/, /bitrix/admin/). Соответственно при удалении модуля их нужно так же аккуратно убрать.
Идентификатор, неймспейсы и партнёрский префикс
Идентификатор модуля — это имя его каталога и одновременно ключ, по которому его подключают. Для решений Маркетплейса идентификатор строится по схеме partner.modulename, где partner — уникальный префикс вашей компании, зарегистрированный в партнёрской программе. Такой префикс гарантирует, что модули разных вендоров не столкнутся именами на одном сайте.
От идентификатора зависит сразу несколько вещей: имя каталога модуля, имя каталога установленных компонентов (/bitrix/components/partner.modulename/), пространство имён PHP-классов и ключи языковых сообщений. Хорошая практика — с самого начала выбрать неймспейс, повторяющий идентификатор: например, классы модуля partner.catalogtools живут в неймспейсе Partner\CatalogTools. Это делает автозагрузку прозрачной и снимает риск конфликтов.
Не используйте зарезервированные префиксы вендора и «системные» имена ядра. Модуль с идентификатором вроде catalog или sale невозможно установить — эти имена заняты ядром. Префикс должен быть вашим и стабильным: менять его между версиями нельзя, потому что для системы обновлений это будет совсем другой модуль.
include.php и точка входа модуля
Файл include.php подключается каждый раз, когда любой участок кода вызывает \Bitrix\Main\Loader::includeModule('partner.modulename'). Его задача — минимальна и критична: зарегистрировать автозагрузку классов модуля и, при необходимости, объявить константы и подключить процедурные помощники для обратной совместимости.
Современный подход — не тянуть в include.php тяжёлую логику, а ограничиться регистрацией неймспейса в автозагрузчике ядра. Тогда классы из каталога lib/ подгружаются лениво, только когда действительно нужны. Это ускоряет старт и не нагружает страницы, где модуль не используется.
- Регистрация автозагрузки. Свяжите неймспейс модуля с каталогом
lib/черезLoader::registerAutoLoadClasses()или PSR-совместимую карту, чтобы классы находились по имени. - Константы окружения. Объявите служебные константы (идентификатор модуля, версия API), если они нужны коду в разных местах.
- Процедурные обёртки. При необходимости подключите файлы с функциями-хелперами для старого кода, который ещё не переведён на классы.
- Никаких побочных эффектов. Не выполняйте в
include.phpзапросов к базе, регистрации событий или проверок лицензии «на каждом хите» — это замедлит весь сайт.
Помните: include.php — это горячий путь. Он выполняется на каждой странице, где модуль подключают. Всё, что можно отложить до реального вызова метода, должно быть отложено.
Класс установки: install/index.php
Сердце любого маркетплейсного модуля — класс установки в файле install/index.php. Он наследует CModule, объявляет свойства модуля (идентификатор, название, версию, автора) и реализует методы, которые вызывает мастер установки в админке. По этому классу вендор в первую очередь и оценивает качество упаковки.
Свойства класса берутся из version.php: конструктор считывает файл версии и заполняет MODULE_VERSION и MODULE_VERSION_DATE. Название, описание, имя партнёра и ссылку на сайт вы задаёте прямо в конструкторе, обычно через языковые сообщения, чтобы модуль был локализуемым.
Обязательный набор методов класса установки удобно разложить по зонам ответственности — так код читаемее и его проще проверять:
| Метод | Отвечает за | Парный метод удаления |
|---|---|---|
| DoInstall | Сценарий мастера установки в админке | DoUninstall |
| InstallFiles | Копирование компонентов, JS, админ-страниц в публичную часть | UnInstallFiles |
| InstallDB | Создание таблиц, регистрацию модуля, права | UnInstallDB |
| InstallEvents | Регистрацию обработчиков событий ядра | UnInstallEvents |
| InstallAgents / InstallTasks | Агенты по расписанию и операции прав доступа | UnInstallAgents / UnInstallTasks |
Метод DoInstall обычно проверяет совместимость (версию ядра и наличие нужных модулей-зависимостей), затем последовательно вызывает установку БД, файлов и событий, регистрирует модуль через RegisterModule() и показывает финальный шаг мастера. DoUninstall делает обратное — предлагает сохранить или удалить данные, снимает регистрацию модуля через UnRegisterModule() и вызывает парные методы удаления.
catalog, а его нет, установщик должен вежливо сообщить об этом и не оставить систему в наполовину установленном состоянии.
Жизненный цикл установки и удаления
Полезно держать в голове полный цикл модуля — от постановки до полного удаления, — потому что именно на «краях» этого цикла возникает большинство проблем модерации. Установка и удаление должны быть симметричны: всё, что модуль создал при установке, он обязан убрать при удалении.
- Проверка совместимости. Установщик убеждается, что версия ядра и набор модулей позволяют работать, иначе прерывается с понятным сообщением.
- Установка базы данных. Выполняются SQL-скрипты из
install/db/, создаются таблицы, регистрируется модуль, назначаются права доступа. - Копирование файлов. Компоненты, скрипты и админ-страницы переносятся из
install/в публичные каталоги системы. - Регистрация событий и агентов. Обработчики событий ядра и агенты по расписанию прописываются в системные таблицы.
- Активная работа. Модуль подключается через
Loader::includeModule(), обслуживает свою логику, обновляется поверх себя новыми версиями. - Удаление. Пользователь запускает деинсталляцию: снимаются события и агенты, удаляются файлы, по желанию — таблицы и данные, снимается регистрация модуля.
Отдельно про удаление данных. Хорошая практика — на шаге DoUninstall спросить у администратора, удалять ли таблицы с данными. Кто-то переустанавливает модуль и хочет сохранить накопленное; кто-то уходит навсегда и хочет чистую систему. Оба сценария должны отрабатывать корректно, без осиротевших таблиц, записей в системных списках событий и «висящих» прав доступа.
version.php и обновления через SiteUpdate
Версионирование — обязательная часть маркетплейсного модуля. Файл install/version.php возвращает массив с двумя ключами: VERSION (строка вида 1.2.3) и VERSION_DATE (дата сборки). По этим значениям система понимает, какая версия установлена, а какая доступна к обновлению.
Обновления доставляются через штатный механизм 1С-Битрикс — модуль «Обновление системы», в обиходе SiteUpdate. Вы выкладываете пакет новой версии в партнёрском кабинете, а сайты с установленным модулем видят обновление в разделе обновлений и накатывают его. Пакет применяется поверх текущей установки: старые файлы заменяются новыми, а специальные скрипты обновления донастраивают базу.
Придерживайтесь семантики версий, чтобы и вам, и покупателям было понятно, что меняется:
| Разряд версии | Когда увеличивать | Пример |
|---|---|---|
| Мажорный (X.0.0) | Несовместимые изменения, смена структуры данных | 1.9.4 → 2.0.0 |
| Минорный (0.X.0) | Новая функциональность без слома совместимости | 2.0.0 → 2.1.0 |
| Патч (0.0.X) | Исправления ошибок, мелкие правки | 2.1.0 → 2.1.1 |
Одно железное правило: версия только растёт. Понижение не поддерживается, откатить обновление у покупателя штатно нельзя. Поэтому каждая выпущенная версия должна быть проверена так, будто отката не существует, — потому что его и нет.
VERSION_DATE — не косметика. Система обновлений сравнивает версии и даты, и рассинхрон между реальной сборкой и объявленной датой приводит к тому, что обновление либо не предлагается, либо предлагается некорректно.
Миграции данных между версиями
Самая тонкая часть обновлений — миграции. Когда новая версия меняет структуру таблиц или формат данных, обновление должно не просто заменить файлы, но и привести уже существующие данные к новому виду. И сделать это на сайтах, которые могут обновляться с очень разных стартовых версий.
Ключевой принцип миграций — идемпотентность. Скрипт обновления должен корректно отрабатывать, даже если его запустят повторно или если часть изменений уже применена. Проверяйте наличие колонки перед её добавлением, существование таблицы перед созданием, значение флага перед миграцией. Тогда обновление устойчиво к сбоям и повторным запускам.
- Не удаляйте данные молча. Если версия убирает поле, сначала перенесите ценные данные, а не отбрасывайте их вместе со структурой.
- Пишите миграции «вперёд». Каждый шаг обновления рассчитан на переход с предыдущей версии; учитывайте, что кто-то прыгает через несколько релизов сразу.
- Проверяйте перед изменением. Любое действие со схемой предваряйте проверкой её текущего состояния, чтобы повторный запуск не ломал базу.
- Работайте через API ядра. Для операций со схемой и данными используйте средства ORM и API, а не прямые несовместимые с разными СУБД SQL-конструкции.
- Тестируйте на «грязных» данных. Проверяйте обновление не на чистой установке, а на базе с реальным объёмом и историческими артефактами.
Практический приём: держите в модуле служебную таблицу или опцию с номером применённой схемы данных. Тогда скрипт обновления видит, до какого шага база уже доведена, и выполняет только недостающие миграции. Это надёжнее, чем полагаться на номер версии файлов, особенно когда обновления накатывают через несколько релизов.
Лицензирование и защита тиражирования
Платное решение нужно защитить, иначе один купленный экземпляр разъедется по всем проектам покупателя и дальше. В экосистеме Маркетплейса лицензирование строится вокруг привязки к домену и лицензионному ключу 1С-Битрикс покупателя: модуль проверяет, что работает на разрешённом сайте с действующей лицензией.
Механику проверки вендор оставляет на вас, но общая схема устоялась. Модуль периодически обращается к вашему серверу активаций, передаёт домен и идентификатор ключа, получает статус лицензии и кэширует его на разумный срок. Прямой запрос «на каждом хите» недопустим — он замедлит сайт и создаст зависимость от доступности вашего сервера.
- Кэшируйте результат. Держите статус лицензии в кэше на часы или сутки, а не спрашивайте сервер на каждой странице.
- Деградируйте мягко. Нет лицензии или истекла — ограничьте функциональность и покажите понятное сообщение в админке, но не роняйте сайт и не блокируйте витрину.
- Переживайте недоступность сервера. Если ваш сервер активаций временно недоступен, модуль должен работать по последнему валидному статусу, а не отключаться.
- Не собирайте лишнего. Передавайте на сервер только то, что нужно для проверки лицензии; не выгружайте данные покупателя без явного согласия.
Важно найти баланс между защитой и удобством. Слишком агрессивная проверка (жёсткие блокировки, частые обращения, зависимость от сети) бьёт по добросовестным покупателям и вызывает поток обращений в поддержку. Разумная защита незаметна для честного пользователя и лишь усложняет неправомерное тиражирование.
Требования вендора и подготовка к модерации
Прежде чем модуль попадёт на витрину, его проверяет вендор — компания 1С-Битрикс. Проверка формальная и предметная: смотрят структуру, установку, удаление, безопасность, оформление. Большинство отказов на первой итерации — не из-за качества функциональности, а из-за нарушений «правил упаковки». Разберём типовые требования.
- Чистая установка и удаление. После деинсталляции в системе не должно оставаться таблиц, файлов, событий, агентов и прав модуля. Это требование номер один.
- Работа через API ядра. Прямые SQL-запросы в обход API, особенно к системным таблицам, — частая причина отказа. Используйте ORM и штатные классы.
- Объявленные зависимости. Если модуль требует
catalog,saleили другой модуль, это должно проверяться при установке, а не падать в рантайме. - Права доступа. Модуль обязан объявлять свои уровни прав и уважать их; нельзя давать всем пользователям доступ к админ-функциям.
- Локализация. Все видимые строки — через языковые файлы, минимум русская локализация, без хардкода текста в коде.
- Описание и оформление. Понятное описание решения, корректные метаданные, отсутствие «мусорных» и отладочных файлов в поставке.
- Безопасность. Экранирование вывода, проверка прав на действиях, защита от инъекций и CSRF на административных формах.
Практический совет: перед отправкой поставьте модуль на чистую систему нужной редакции, пройдите весь цикл установки и удаления и проверьте базу и файловую систему на остатки. Отдельно устанавливайте модуль как обычный компонент — например, вынесенный из установщика шаблон компонента должен корректно копироваться в публичную часть и удаляться вместе с модулем.
Как это выглядит в админке 1С-Битрикс
Установленные и доступные решения Маркетплейса управляются из раздела «Marketplace» в административной части. Там же виден установленный модуль, его версия и доступные обновления. Схематично карточка установленного модуля с мастером установки выглядит так:
На стороне кода мастеру соответствуют методы класса установки. Когда администратор жмёт «Установить», ядро вызывает DoInstall; когда «Удалить» — DoUninstall. Между шагами мастер может показывать промежуточные экраны (например, вопрос об удалении данных), которые вы формируете внутри этих методов. Настройки модуля после установки открываются на странице options.php в разделе «Настройки — Настройки продукта — Настройки модулей».
Публикация в партнёрском кабинете
Когда модуль готов и проверен локально, его загружают в партнёрский кабинет как решение Маркетплейса. Процесс проходит несколько понятных стадий, и полезно понимать их заранее, чтобы не удивляться срокам.
- Регистрация решения. Заводите карточку продукта: название, категория, описание, скриншоты, цена или бесплатная модель распространения.
- Загрузка дистрибутива. Пакуете модуль в дистрибутив нужного формата и заливаете его в кабинет; версия берётся из
version.php. - Отправка на модерацию. Вендор проверяет структуру, установку, удаление, безопасность и оформление по своему регламенту.
- Доработка по замечаниям. Если есть замечания, вы исправляете и отправляете повторно; первая итерация редко проходит без правок.
- Публикация. После одобрения решение появляется на витрине и становится доступно к установке и покупке.
- Выпуск обновлений. Новые версии загружаете так же; они разъезжаются по установленным сайтам через SiteUpdate.
Заложите время на модерацию и как минимум одну итерацию правок в план релиза. Планировать «выпустим и сразу начнём продавать в тот же день» — оптимистично: проверка занимает время, а замечания по упаковке почти всегда находятся на первом заходе.
Безопасность и совместимость
Тиражный модуль работает на чужих сайтах, поэтому цена ошибки в безопасности умножается на число установок. Уязвимость в вашем коде — это уязвимость на всех проектах, где модуль стоит. Отсюда повышенные требования к базовой гигиене.
- Экранируйте вывод. Любые данные, попадающие в HTML, пропускайте через экранирование; это защищает от XSS в админ- и публичной части.
- Проверяйте права. Каждое административное действие предваряйте проверкой прав пользователя и защитой формы токеном (CSRF).
- Не доверяйте вводу. Валидируйте и типизируйте параметры запроса; для работы с базой используйте параметризованные средства ORM, а не склейку строк.
- Совместимость по PHP. Проверьте модуль на поддерживаемом диапазоне версий PHP; не используйте синтаксис, недоступный на минимально совместимой версии.
- Совместимость по редакциям. Явно объявляйте, каким редакциям и модулям нужен ваш продукт, и корректно ведите себя там, где зависимости нет.
Совместимость — это не только «запустится или нет», но и предсказуемость на обновлениях ядра. Пишите код против публичного API 1С-Битрикс, а не против внутренних деталей реализации: приватные методы и недокументированные структуры могут измениться в любой версии платформы и молча сломать ваш модуль на сайтах покупателей.
Частые ошибки
- «Грязное» удаление: после деинсталляции остаются таблицы, файлы, зарегистрированные события или агенты — самая частая причина отказа модерации.
- Прямые SQL-запросы к системным таблицам вместо API ядра — ломается на обновлениях платформы и не проходит проверку.
- Необъявленные зависимости: модуль тихо требует
catalogилиsaleи падает фаталом там, где их нет. - Тяжёлая логика в
include.php: проверки лицензии и запросы к базе на каждом хите замедляют весь сайт. - Неидемпотентные миграции: повторный запуск обновления ломает базу, потому что нет проверок текущего состояния схемы.
- Жёсткая проверка лицензии: сбой сети вашего сервера активаций роняет витрины покупателей вместо мягкой деградации.
- Хардкод путей, текста и настроек вместо констант, языковых файлов и страницы
options.php. - Смена идентификатора или префикса между версиями: для системы обновлений это новый продукт, установленная база теряется.
Чек-лист внедрения
Сведём всё в практический список, по которому удобно принимать готовность модуля перед отправкой на модерацию:
- Структура на месте. Есть
include.php,install/index.php,install/version.php, каталогиlib/,lang/и файлы описания. - Идентификатор зафиксирован. Префикс партнёра и неймспейс выбраны, стабильны и совпадают между каталогом, классами и языковыми ключами.
- Установка симметрична удалению. Все
Install*имеют парныеUnInstall*; после удаления система чистая. - Совместимость проверяется. Установщик проверяет версию ядра и зависимости, не оставляя систему в полуустановленном состоянии.
- Версионирование корректно.
VERSIONиVERSION_DATEзаполнены, семантика версий соблюдена, версия только растёт. - Миграции идемпотентны. Обновления проверяют состояние схемы, безопасны к повторному запуску и к прыжкам через релизы.
- Лицензирование мягкое. Статус кэшируется, при недоступности сервера модуль работает, при отсутствии лицензии деградирует без падения.
- Безопасность и локализация. Вывод экранирован, права проверяются, тексты в языковых файлах, отладочный мусор убран.
Вывод
Модуль для Маркетплейса 1С-Битрикс — это не столько про уникальную функциональность, сколько про дисциплину упаковки: строгая структура каталога, установщик, который чисто ставит и удаляет всё за собой, аккуратное версионирование с идемпотентными миграциями и мягкое лицензирование. Соберите эти основы правильно — и модуль пройдёт модерацию, будет спокойно обновляться на сотнях чужих сайтов и станет для вас каналом продаж, а не источником обращений в поддержку. Если нужно спроектировать и собрать такое решение под ключ, мы помогаем на всех этапах — от архитектуры до публикации.