Готовое решение «Лоджик: Здоровье» подойдёт для клиник, стоматологий и других медицинских учреждений. Мы создали и запустили ряд успешных проектов в тематике медицины, этот опыт лёг в основу данного решения.
Вы без проблем сможете создать ваш сайт на базе нашего решения. Мы имеем большой опыт работы с готовыми решениями и при разработке старались делать наш продукт удобным.
Все необходимые разделы уже готовы. Вам останется только добавить нужную информацию.
Поможем с установкой и настройкой шаблона, если вам нужна помощь, вы можете написать нам в форму support.logicloud.ru
Сайт имеет всё необходимое для комфортного использования.
Версия для слабовидящих создана в соответствии с требованиями законодательства.
Сайт адаптирован под использование на смартфонах и планшетах.
Удобная форма on-line записи поможет вашим пользователям записаться к нужному специалисту.
На сайте предусмотрены формы обратной связи для приёма обращений от пользователей.
Удобный раздел с услугами позволит разместить информацию максимально комфортно и понятно.
Пользователь может перейти к записи с любой страницы сайта.
Вы сможете создать отдельную страницу для каждого врача и разместить там подробную информацию.
Для получения обратной связи от пользователей в шаблоне предусмотрены разделы «Отзывы» и «Вопрос ответ».
Широкие возможности для доработок. Мы создали решение на базе стандартных компонентов 1С-Битрикс. У вас не возникнет проблем с доработкой решения.
- Форма записи на приём отвечала «400 Bad Request». Обработчик include/making-accept.php искал инфоблок заявок по символьному коду lcld_online_form, тогда как мастер установки создаёт инфоблоки с суффиксом сайта: CIblock::CreateIblock() и CIblock::ImportIblockFromXml() формируют код как '<код>_' . WIZARD_SITE_ID, то есть на рабочем сайте инфоблок называется lcld_online_form_s1. Инфоблок не находился, и запрос отклонялся ещё до создания элемента. Поиск инфоблоков поставки вынесен в метод \Logicloud\Health\Iblock\Resolver::getIdByWizardCode(): сначала проверяется код с суффиксом текущего сайта, затем — код без суффикса (на случай, если инфоблок создавали вручную или переносили с другого сайта). Тот же способ поиска применён к инфоблоку врачей в include/making-form.php.
- В заявке не заполнялся врач. В версии 2.0.0 ключ doctor исключался из разбора POST целиком, поэтому свойство «Врач» (тип «Привязка к элементам») оставалось пустым. Теперь оно заполняется проверенным идентификатором врача — тем самым элементом, который уже найден и подтверждён на принадлежность инфоблоку врачей и активность.
- Уточнён код ответа при ошибке установки. Ненайденный инфоблок заявок — это не ошибка запроса: теперь возвращается 500, а в журнал событий пишется сообщение с искомым кодом и идентификатором сайта. Код 400 остаётся только для запроса без корректного идентификатора врача.
- Файлы include/making-accept.php и include/making-form.php входят в состав сайта, который разворачивает мастер установки, поэтому обновление кладёт их в /bitrix/wizards/, а не в корень сайта. Скопируйте оба файла из /bitrix/wizards/logicloud/health/site/public/ru/include/ в каталог include/ вашего сайта — либо запустите мастер заново, если сайт ещё не наполнен.
- Файл модуля lib/iblock/resolver.php обновляется автоматически, отдельных действий не требует.
- Анонимный вызов произвольных событий ядра (submit.php). Эндпоинт формы выполнял GetModuleEvents("main", $_POST['EVENT_ID'], true) и ExecuteModuleEventEx($arEvent, array($_POST)) — любой посетитель мог анонимно вызвать любой обработчик события модуля main с полностью управляемыми аргументами. Теперь имя события берётся только из подписанных настроек компонента, область поиска обработчиков ограничена модулем logicloud.health, а в обработчик передаётся отфильтрованный по белому списку набор полей, а не весь $_POST.
- Неаутентифицированная запись в произвольный инфоблок (mass assignment, submit.php). IBLOCK_ID, SECTION_ID, ACTIVE, IBLOCK_ITEM_NAME принимались из запроса, а в PROPERTY_VALUES попадали все остальные ключи $_POST. Введена подпись серверных параметров формы (\Logicloud\Health\Security\FormSigner на базе Bitrix\Main\Security\Sign\Signer): браузер возвращает подписанную строку, подменить её нельзя. Инфоблок дополнительно проверяется на принадлежность текущему сайту, свойства принимаются только из списка полей, объявленных в настройках компонента, и только из числа реально существующих свойств инфоблока.
- Проверка капчи только на клиенте. Ранее JS обращался к ajax/captcha.php и, получив «OK», отправлял данные в submit.php — прямой POST капчу не проходил вообще. Проверка токена перенесена на сервер и выполняется в том же хите, в котором обрабатываются данные формы (класс \Logicloud\Health\Security\Captcha).
- Неаутентифицированная загрузка файлов (submit.php). Файлы принимались без ограничений и сохранялись в корень /upload/. Теперь загрузка возможна только в поля типа «Файл», объявленные в настройках компонента, действует белый список расширений (jpg, jpeg, png, gif, webp, bmp, pdf, doc, docx, xls, xlsx, odt, ods, rtf, txt, csv, zip), ограничение размера 10 МБ, проверка is_uploaded_file(); файлы складываются в отдельный каталог /upload/lcld.forms/ и привязываются к модулю.
- Неаутентифицированная запись в произвольный инфоблок (making-accept.php). IBLOCK_ID брался из $_POST['iblockId']. Инфоблок теперь определяется на сервере по символьному коду (lcld_online_form) в рамках текущего сайта, свойства принимаются только из списка свойств этого инфоблока, врач проверяется на принадлежность инфоблоку врачей и на активность. Устранено обращение к explode('-', $key)[1] без проверки наличия элемента, дававшее warning и раскрытие пути в логах.
- Раскрытие данных чужих инфоблоков (making-form.php). По $_POST['doctorId'] можно было получить название и изображение любого элемента любого инфоблока. Выборка ограничена инфоблоком врачей и активными элементами, добавлена обработка отсутствующего элемента.
- Сохранённая XSS в отзывах (news.list/reviews и news.list/mainpage.reviews). Свойства REVIEW и FIO выводились без экранирования, а источником данных была публичная форма. Значение REVIEW пропускается через CBXSanitizer (уровень SECURE_LEVEL_MIDDLE), ФИО и дата экранируются полностью.
- CSRF на странице настроек модуля (options.php). Обработчик $_REQUEST['LCLD_SETTINGS'] сохранял настройки без проверки sessid и без проверки прав. Добавлены check_bitrix_sessid(), bitrix_sessid_post() в форме и проверка права «W» на модуль через $APPLICATION->GetGroupRight().
- Снятие штатной проверки прав (options.php). Константа NOT_CHECK_PERMISSIONS = true больше не объявляется — проверка прав выполняется ядром, а страница дополнительно проверяет права и sessid самостоятельно. У модуля включены групповые права (MODULE_GROUP_RIGHTS).
- CSRF на копии страницы настроек (/bitrix/admin/lcld_template_settings.php). Закрыт теми же проверками — обе страницы теперь используют одну реализацию.
- Небезопасная десериализация данных импорта (services/classes/chighloadblocks.php). Значения с префиксом serialize# передавались в unserialize() без ограничения классов (PHP Object Injection). Добавлен параметр allowed_classes = false и обработка некорректного значения.
- Небезопасная десериализация настроек модуля. Во всех точках (header.php, footer.php, captcha.php, страницы настроек, шаблон формы) вызовы unserialize(Option::Get(...)) заменены на класс \Logicloud\Health\Settings с allowed_classes = false, проверкой типа и статическим кешем.
- Вывод настроек без экранирования. Адрес, телефоны, график работы, ссылки на соцсети, favicon и логотипы в header.php и footer.php экранируются; на внешние ссылки добавлен rel="noopener noreferrer". Поле «Сторонние скрипты» (scripts_text) по-прежнему выводится как HTML — это его назначение, но записать его теперь может только пользователь с правом «W» на модуль и только с валидным sessid.
- Экранирование в шаблоне формы и хлебных крошках. Заголовки, описания, плейсхолдеры, значения и коды полей, ссылки и заголовки цепочки навигации выводятся через htmlspecialcharsbx(), настройки формы передаются в JS через CUtil::PhpToJSObject().
- Валидация форм переведена на Яндекс SmartCaptcha. Токен проверяется на сервере по адресу https://smartcaptcha.cloud.yandex.ru/validate, результат читается из поля status ответа (ok/failed).
- Поля настроек заменены: вместо «Приватный ключ», «Публичный ключ» и «Минимальное значение оценки пользователя» теперь «Клиентский ключ» и «Серверный ключ». Порог оценки убран — у SmartCaptcha ответ бинарный, оценки score в нём нет. Ссылка на консоль для получения ключей ведёт на Yandex Cloud.
- Ключи хранятся в тех же настройках модуля под новыми именами captcha_client_key и captcha_server_key. Неприменимые ключи Google (captcha_public_key, captcha_private_key, captcha_value) удаляются из настроек автоматически при обновлении.
- В шаблоне подключается виджет https://smartcaptcha.cloud.yandex.ru/captcha.js в режиме render=onload. Капча невидимая: виджет отрисовывается в скрытый контейнер формы и запускается при отправке, посетитель видит проверку только в спорных случаях.
- Промежуточный запрос к ajax/captcha.php убран, и это не оптимизация, а требование сервиса: токен SmartCaptcha одноразовый и живёт пять минут, поэтому предварительная проверка «расходовала» бы его и последующая отправка формы всегда завершалась бы ошибкой. Токен уходит сразу в ajax/submit.php вместе с данными формы. Файл ajax/captcha.php оставлен и отвечает кодом 410, чтобы закешированные у посетителей старые версии скриптов получали понятный ответ, а не 404.
- Обработаны ошибки виджета (network-error, javascript-error) и добавлена страховка по таймауту: если посетитель закрыл окно проверки, форма не остаётся в подвешенном состоянии.
- После успешной отправки и после ошибки виджет сбрасывается — повторная отправка формы работает без перезагрузки страницы.
- Ответ сервера с кодом 403 (в том числе непройденная капча) показывается посетителю отдельным сообщением, а не общей «ошибкой сервера».
- Обход каталога на странице настроек шаблона. Поле tmp_name виджета Bitrix\Main\UI\FileInput подставлялось в путь как есть: $_SERVER['DOCUMENT_ROOT'] . '/upload/tmp' . $fileData['tmp_name']. Значение приходит из скрытого поля формы, поэтому пользователь с правом «W» на модуль мог передать tmp_name вида '/../../bitrix/php_interface/dbconn.php' вместе с name='logo.png': CFile::SaveFile проверяет расширение по полю name, а копирует файл по пути из tmp_name. Произвольный файл сервера попадал в web-доступный /upload/ и становился доступен по прямой ссылке, а из-за параметра 'del' => 'Y' ещё и удалялся с исходного места. Теперь путь нормализуется через realpath() и принимается, только если он остался внутри /upload/tmp и указывает на существующий файл; дополнительно действует белый список расширений (jpg, jpeg, png, gif, webp, svg, ico), а отклонённый файл выводит понятное сообщение вместо тихого сохранения.
- Сохранённая XSS в отзывах на детальной странице услуги. Шаблон news.list/services.detail выводил свойства REVIEW и FIO связанных отзывов без экранирования, тогда как в двух других шаблонах отзывов санитайзер уже применялся. Источник данных анонимный — отзывы создаёт публичная форма, поэтому посетитель мог внедрить скрипт, который выполнялся у всех читателей страницы услуги и у администратора при просмотре элемента. Текст отзыва теперь проходит через CBXSanitizer (SECURE_LEVEL_MIDDLE), ФИО и дата экранируются полностью.
- Отражённая XSS в шапке внутренних страниц. headerBufferedContent.php печатал конкатенацией $APPLICATION->GetTitle() и параметры страницы (pageDescription, servicesDesc, minPrice, doctorPrice, doctorMeasure), а значения linkMaking, doctorImg и doctorMakingLink подставлял прямо в атрибуты href и src. Метод GetTitle(), в отличие от ShowTitle(), возвращает заголовок без HTML-кодирования, а шаблон поиска кладёт в заголовок страницы значение параметра запроса q — обращение вида /search/?q=<img src=x onerror=...> выполняло скрипт в браузере посетителя без какой-либо авторизации. Все значения экранируются через htmlspecialcharsbx().
- Бессрочная подпись параметров формы. Подпись закрывала подмену параметров, но не содержала ни области действия, ни срока: снятая однажды со страницы, она оставалась валидной неограниченно долго, и после изменения настроек компонента (например, снятия ACTIVE='Y' для отправки заявок на модерацию) старую конфигурацию можно было продолжать использовать. В подписываемый набор добавлены SITE_ID, FORM_ID и отметка времени; ajax/submit.php принимает подпись только для текущего сайта и не старше суток, с допуском 5 минут на расхождение часов, иначе отвечает 403 SIGNATURE_EXPIRED.
- Убраны короткие открывающие теги <? в языковых файлах шаблона, в include/breadcrumb.php и в install/version.php — при short_open_tag = Off код выводился как текст.
- Устранено переобъявление констант (NO_KEEP_STATISTIC, NOT_CHECK_PERMISSIONS) — в PHP 8.5 переобъявление констант объявлено устаревшим; используется define() с проверкой defined().
- Инициализированы переменные $by/$order, передаваемые по ссылке в CEventMessage::GetList(), CLanguage::GetList(), CSite::GetList() (install/events.php, install/index.php, chighloadblocks.php, cfiles.php, ciblock.php) — ранее выдавалось «Undefined variable».
- Убраны вызовы strlen()/trim() с потенциальным null (wizard.php, cfiles.php) — передача null в строковые функции устарела с PHP 8.1.
- Свойства класса установщика объявлены явно вместо var и динамических свойств (устарели с PHP 8.2).
- Сортировки usort(..., strcmp($a["SORT"], $b["SORT"])) заменены на числовое сравнение с оператором «» и значением по умолчанию — strcmp(null, null) устарел, а лексикографическое сравнение чисел давало неверный порядок (10 перед 2).
- Устранены обращения к несуществующим ключам массивов в шаблонах и result_modifier-ах (?? и isset), count() на потенциальном null — в PHP 8 это TypeError.
- Исправлены вызовы приватных методов класса CHighloadblocks как глобальных функций (__hlImportPrepareField, __getEnumUserFields) — фатальная ошибка при импорте HL-блоков.
- В установщик добавлена проверка минимальной версии PHP с понятным сообщением.
- Устаревшие ветки с прямыми вызовами mysqli_* в services/classes/autoload.php заменены на API ядра.
- PAGE_DESCRIPTION регистрировался в SetResultCacheKeys() только для корневого раздела (doctors.section, prices, news/prices/catalog.section). На всех остальных страницах component_epilog.php читал незарегистрированный ключ, и при попадании в кеш описание раздела пропадало, а в PHP 8 добавлялось предупреждение. Ключ регистрируется безусловно.
- То же исправлено для SERV_DESC, MIN_PRICE и LINK_MAKING в news.list/services.detail: LINK_MAKING теперь всегда попадает в кеш-ключи (раньше задавался только при наличии врачей).
- В news/prices/section.php переменная $sectionIds не инициализировалась: при отсутствии подразделов в endDataCache() уходило неопределённое значение, а после чтения кеша данные не соответствовали структуре.
- Кеш выборки прайса (news/prices/section.php, news/prices/news.php) жил только по времени и не сбрасывался при изменении контента. Добавлена регистрация тега инфоблока (iblock_id_N) через управляемый кеш — выборка обновляется сразу после правки услуг и разделов.
- Время жизни кеша уменьшено с 36 000 000 секунд (более 400 дней) до разумных значений во всех компонентах шаблона и в собственном кеше прайса.
- Выборка разделов глубже второго уровня выполнялась без фильтра по инфоблоку и собирала разделы всех инфоблоков сайта — добавлен IBLOCK_ID.
- Значения, прочитанные из кеша, проверяются на тип перед использованием.
- Файл include.php модуля был пустым — классы из каталога lib/ никогда не подключались. Добавлена регистрация автозагрузки.
- В каталоге lib/ существовали два файла, различающиеся только регистром имени (Main.php и main.php) с разными классами: на Windows и macOS один затирал другой при распаковке дистрибутива. Оставлена одна реализация — lib/main.php, класс \Logicloud\Health\Main.
- При удалении модуля страница настроек оставалась в /bitrix/admin: DeleteDirFiles() вызывался с несуществующим путём install/admin вместо install/assets/admin.
- news.list/services.detail: при отсутствии раздела (неверный PARENT_SECTION или снятая активность) страница падала с ошибкой «Call to a member function GetFields() on null». Аналогично исправлено в news.list/documents, news.list/making.doctors, news.list/services.section.
- news.list/services.detail: сортировка врачей применялась к несуществующему ключу $sections[ID]['DOCTORS'] и фактически не работала.
- news.list/services.detail: расчёт минимальной цены учитывал нулевые и пустые значения и мог дать 0.
- news.list/documents: обращение к $sections[...] до его создания давало предупреждение «Undefined array key», а элементы несуществующих разделов терялись.
- Мастер установки: условие выбора шаблона по умолчанию было взаимоисключающим и всегда сбрасывало шаблон в пустую строку.
- Мастер установки: содержимое css/style.css читалось с диска и вставлялось в страницу внутри цикла по шаблонам — столько раз, сколько найдено шаблонов. Стиль читается один раз и кешируется.
- services/classes/autoload.php: метод IsUtf8() мог вернуть неопределённую переменную и не распознавал кодировки utf8mb4/utf8mb3.
- Форма обратной связи: успешной считалась любая непустая строка ответа. Теперь дополнительно проверяется HTTP-статус 200, эндпоинт возвращает корректные коды 403/405/413/415/500.
- Прайс: подразделы третьего уровня выбирались отдельным запросом на каждый элемент списка (N*M запросов на страницу). Выборка вынесена из цикла.
- news.list/services.detail: данные врачей выбирались по одному элементу на каждую услугу (проблема N+1). Заменено на одну выборку по списку ID.
- Добавлен слой классов модуля с автозагрузкой: \Logicloud\Health\Settings (чтение и запись настроек), \Logicloud\Health\Main (общие утилиты), \Logicloud\Health\Security\FormSigner (подпись параметров форм), \Logicloud\Health\Security\Captcha (серверная проверка reCAPTCHA), \Logicloud\Health\Iblock\Resolver (поиск инфоблоков по коду и белый список свойств).
- Страница настроек шаблона существовала в виде двух разошедшихся копий по 390 строк (options.php и install/assets/admin/lcld_template_settings.php). Реализация вынесена в admin/settings_page.php, обе точки входа сведены к тонким обёрткам.
- Глобальная функция array_filter_recursive() заменена методом \Logicloud\Health\Main::filterRecursive(); старая функция оставлена как обёртка для обратной совместимости и защищена от повторного объявления.
- Компонент logicloud.health:forms переписан: убрано дублирование при разборе параметров полей, добавлены значения по умолчанию, экранирование и единая карта соответствия сообщений об ошибках.
- Шаблон modal формы: два почти одинаковых блока инициализации JS сведены к одному, настройки передаются через CUtil::PhpToJSObject() вместо ручной сборки JSON.
- callback.js: два продублированных почти дословно блока показа ошибок формы сведены в метод _showErrors(), работа с капчей вынесена в _getCaptchaToken() на промисах.
- include/breadcrumb.php переписан на читаемую разметку с микроразметкой schema.org для всех элементов цепочки, включая текущую страницу.
- Убран мёртвый и закомментированный код, приведены к единому стилю отступы, кавычки и объявления типов в затронутых файлах; добавлены комментарии, поясняющие нетривиальные решения.
- Пользовательское событие формы (параметр «Использовать пользовательское событие») теперь ищется среди обработчиков, зарегистрированных на модуль logicloud.health, а не main. Существующие обработчики нужно перерегистрировать: AddEventHandler('logicloud.health', 'ВАШЕ_СОБЫТИЕ', ...).
- Обработчик события получает массив только из полей, объявленных в настройках компонента, вместо всего $_POST.
- Публичный эндпоинт ajax/submit.php принимает только запросы с корректной подписью параметров. Прямые вызовы из стороннего кода, собиравшие POST вручную, перестанут работать.
- После обновления форму защищает капча только при заполненных ключах SmartCaptcha. Ключи Google не переносятся (они неприменимы) и удаляются из настроек. Получите клиентский и серверный ключ в Yandex Cloud SmartCaptcha и укажите их в настройках модуля — до этого формы работают без капчи.
- Эндпоинт ajax/captcha.php больше не выполняет проверку и отвечает кодом 410. Если вы обращались к нему из своего кода, уберите этот вызов.
- Подпись параметров формы действительна сутки и только для того сайта, где была выдана. Если страница с формой отдаётся из долгоживущего кеша (композитный кеш, CDN), убедитесь, что время жизни кеша меньше суток, иначе посетитель получит ответ 403 SIGNATURE_EXPIRED.
- Для страницы настроек модуля требуется право «W» на модуль logicloud.health. После обновления проверьте права групп пользователей.
- Изменения в шаблоне сайта (каталог install/wizards/.../site/templates/logicloud.health) попадают в /bitrix/wizards и применяются при установке мастером. Для уже развёрнутого сайта соответствующие файлы шаблона нужно перенести вручную с учётом ваших правок.
- Исправление мелких ошибок шаблона
- Исправление мелких ошибок шаблона
- Исправление мелких ошибок шаблона
- Исправление мелких ошибок шаблона
- Мелкие доработки шаблонов компонентов
- Мелкие доработки шаблонов компонентов
- Мелкие доработки шаблонов компонентов
Загрузите и установите решение из магазина
Перейдите в список мастеров, найдите «Лоджик: Здоровье» и из меню действий выберите «Установить»
Пройдите все шаги установки
Готово. Наполните сайт актуальной информацией и пользуйтесь
Персональную информацию, указанную на одном из шагов установки, можно отредактировать в разделе «Настройка шаблона» административной панели.
Также будем рады вашим предложениям. Если вы считаете, что шаблону не хватает тех или иных возможностей, опишите нам вашу идею, мы рассмотрим варианты реализации в дальнейших обновлениях.
Для покупки товара в нашем интернет-магазине выберите понравившийся товар и добавьте его в корзину. Далее перейдите в Корзину и нажмите на «Оформить заказ» или «Быстрый заказ».
Если оформляете быстрый заказ: напишите ФИО, телефон и e-mail. Вам перезвонит менеджер и уточнит условия заказа. По результатам разговора вам придет подтверждение оформления товара на почту или через СМС. Теперь останется только ждать доставки и радоваться новой покупке.
Оформление заказа в стандартном режиме выглядит следующим образом. Заполняете полностью форму по последовательным этапам: адрес, способ доставки, оплаты, данные о себе. Советуем в комментарии к заказу написать информацию, которая поможет курьеру вас найти. Нажмите кнопку «Оформить заказ».
Оплачивайте покупки удобным способом. В интернет-магазине доступно 3 варианта оплаты:
- Наличные при самовывозе или доставке курьером. Специалист свяжется с вами в день доставки, чтобы уточнить время и заранее подготовить сдачу с любой купюры. Вы подписываете товаросопроводительные документы, вносите денежные средства, получаете товар и чек.
- Безналичный расчет при самовывозе или оформлении в интернет-магазине: карты МИР. Чтобы оплатить покупку на сайте, система перенаправит вас на сервер платежной системы. Здесь нужно ввести номер карты, срок действия и имя держателя.
- Электронные системы при онлайн-заказе: ЮMoney. Для совершения покупки система перенаправит вас на страницу платежного сервиса. Здесь необходимо заполнить форму по инструкции.
- Безналичная оплата на наш расчетный счет по выставленному счету.
Экономьте время на получении заказа. В интернет-магазине доступно 4 варианта доставки:
- Электронная поставка - все необходимые сведения о лицензии, праве пользования, кодах, ключах и др. высылаются покупателю на его e-mail.
- Курьерская доставка. Когда товар будет отправлен с нашего склада, Вам придет уведомление. В день доставки с Вами заблаговременно свяжется курьер для уточнения времени и деталей доставки. Доставка производится "до двери". Осмотрите упаковку на целостность и соответствие указанной комплектации.
- Постамат. Когда заказ поступит на точку, на Ваш телефон или e-mail придет уникальный код. Заказ нужно оплатить в терминале постамата. Срок хранения — 3 дня.
- Доставка Почтой России. Когда заказ придет в отделение, на Ваш адрес придет извещение о посылке. Перед оплатой Вы можете оценить состояние коробки: вес, целостность. Вскрывать коробку самостоятельно Вы можете только после оплаты заказа. Один заказ может содержать не больше 10 позиций и его стоимость не должна превышать 100 000 р.
Дополнительная информация.
Изучите полный алгоритм продления лицензий на модули 1С-Битрикс: Маркетплейс, включая активацию льготных купонов. Мы детально разбираем все условия: обязательный 30-дневный срок для сохранения максимальной выгоды, пропорциональное ценообразование (12,5%, 25%, 50% от цены модуля) и ограничение по минимальной сумме в 500 рублей. Этот гайд поможет вам эффективно планировать бюджет и гарантировать актуальность вашего проекта.