Ваш опыт = наш роадмап!
Расскажите, как мы можем усилить платформы
ISPsystem для вашего бизнеса. Опрос займет 5 минут.
Пройти опрос
Режим фокусировки

Плагины. Общие принципы

В статье используются следующие термины
Перед изучением статьи рекомендуется ознакомиться с документацией разработчиков COREmanager, поскольку часть механизмов наследуется из базового фреймворка.

Плагины позволяют изменять поведение платформы BILLmanager, перехватывать события, расширять интерфейс и добавлять новые функции. В статье описаны принципы работы плагинов, их структура и приведён пример создания плагина-валидатора. Об особенностях написания плагинов см. статью Создание плагина для BILLmanager.

Модификации BILLmanager

 BILLmanager позволяет добавить следующие модификации:

  • модули — крупные и самостоятельные компоненты системы, которые выполняют определённую функцию или набор функций. Например, расширяют функциональность за счёт интеграции со сторонней системой. Модули:
    • обычно имеют свои зависимости и могут включать в себя несколько плагинов;
    • не предназначены для динамического изменения поведения системы в реальном времени;
    • могут требовать изменений в основной архитектуре системы;
    • по функциональности разделяются на:
      • обработчики услуг;
      • методы оплаты;
      • шлюзы сообщений;
      • онлайн-кассы;
      • модули документооборота;
      • модули для координации со сторонними системами — LDAP, Omni, amoCRM и т.д.

Подробнее см. статью Модули. Общие принципы..

  • плагины — обычно более простые программные компоненты, которые добавляют определённую функциональность или изменяют поведение основной системы. Плагины позволяют:
    • интегрировать новые функции без изменения исходного кода;
    • перехватывать внутренние события;
    • добавлять новые элементы интерфейса;
    • выполнять фоновые задачи через триггеры на определённые события;
    • адаптировать систему под конкретные потребности.

Сравнение плагинов и модулей см. в статье Плагины и модули в BILLmanager.

Виды плагинов

Плагины по функциональности разделяются на:

  • плагины, изменяющие поведение платформы;
  • плагины, расширяющие функциональность платформы;
  • плагины, выполняющие фоновые задачи.

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

Плагины, расширяющие функциональность, добавляют:

  • новые элементы — настраиваемые таблицы и формы, необходимые для решения конкретных задач;
  • новые действия и сценарии работы с платформой.

Плагины, которые выполняют фоновые задачи:

  • добавляют триггеры на определённые события в платформе;
  • позволяют запускать в фоне “тяжёлые” задачи, которые не должны влиять на работу с платформой в интерфейсе. Например, выполнение фоновых задач на основе событий.

Подробнее см. статью Фоновые плагины.

Задачи плагина

Плагин регистрирует обработчики через XML-файл в директории /usr/local/mgr5/etc/xml/. Каждый обработчик описывается узлом handler:

<mgrdata>
    <handler name="vmlic.py" type="xml">
        ...
    </handler>
</mgrdata>

Атрибуты узла handler:

Атрибут

Описание

name

Имя файла-обработчика в директории /usr/local/mgr5/addon/. Имя должно совпадать с указанным в узле handler.

type

Способ взаимодействия BILLmanager со скриптом: cgi или xml:

  • type="cgi" — BILLmanager формирует переменные окружения с информацией о запросе и вызывает скрипт. Скрипт возвращает XML-файл в stdout. BILLmanager объединяет полученный XML-файл с основным;
  • type="xml" — BILLmanager формирует переменные окружения и передаёт основной XML-файл в stdin скрипта. Скрипт модифицирует XML-файл и возвращает его в stdout. BILLmanager подменяет основной XML-файл на полученный от скрипта.

protocol

Протокол вызова скрипта:

  • fcgi — вызов через FastCGI;
  • не указан — обычный вызов.

ignore_errors

Если указано значение yes, ошибки обработчика не влияют на работу платформы.

В платформе BILLmanager любое взаимодействие (например, пользовательское нажатие, внутренний вызов платформы или обращение от внешнего сервиса) вызывает функцию Action (действие). К Action привязываются Event (события), которые вызываются до, после или в обоих случаях (и до, и после) с действием в зависимости от настроек.

При регистрации плагина внутри handler используется один из следующих узлов:

  • func — регистрирует Action: скрипт становится обработчиком функции;
  • event — регистрирует Event: скрипт вызывается при наступлении события;
  • task — регистрирует Event: скрипт вызывается независимо от вызвавшего действия.

Чтобы получить список Action, используйте команду:

/usr/local/mgr5/sbin/mgrctl -m billmgr actionlist

Чтобы получить список Event для определённого Action, используйте команду:

/usr/local/mgr5/sbin/mgrctl -m billmgr eventlist action=<имя_действия>

func — Action, расширение форм и интерфейса

Плагин становится обработчиком конкретной функции BILLmanager:

  • формы;
  • списка;
  • кнопки.

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

Пример скрипта
<handler name="vmlic_action.py" type="xml">
    <func name="vmlic.settings"/>
    <func name="vmlic.errors"/>
    <func name="vmlic.errors.retry"/>
</handler>

Атрибуты узла func:

Атрибут

Описание

name

Имя действия (Action), которое обрабатывает скрипт.

postdata

Укажите yes, чтобы передать тело POST-запроса в stdin скрипта. Актуально только для POST-запросов. Например, при сохранении формы sok=ok. Для GET-запросов тело всегда пустое.

Типичные задачи:

  • добавить страницу настроек плагина в административный интерфейс;
  • вывести список объектов, которыми управляет плагин;
  • добавить кнопку действия к существующему списку услуг;
  • валидировать поле формы при заказе (check.<name>).

event — Event, перехватчик действия

Плагин подписывается на Action BILLmanager и вызывается автоматически — до или после его выполнения.

<handler name="vmlic.py" type="xml">
    <event name="dedic.open" before="yes" base="project"/>
    <event name="eventaction.postsetparam" before="yes"/>
    <event name="eventaction.postclose" before="yes"/>
</handler>

Атрибуты узла event:

Атрибут

Описание

name

Имя действия (Action), на который подписывается обработчик.

before

Укажите yes, чтобы вызвать скрипт до выполнения основного действия.

after

Укажите yes, чтобы вызвать скрипт после выполнения основного действия.

proirity

Определяет порядок вызова среди других обработчиков одного события: before — до базового обработчика, after — после. Если base не указан: before — в начало очереди, after — в конец.

Обратите внимание: атрибут пишется как proirity, а не priority — особенность COREmanager, сохранённая для совместимости.

base

Имя базового обработчика, относительно которого определяется порядок через proirity. project — подписаться на Action BILLmanager, а не COREmanager.

postdata

Укажите yes, чтобы передать тело POST-запроса в stdin скрипта. Актуально только для POST-запросов. Например, при сохранении формы sok=ok. Для GET-запросов тело всегда пустое.

Чтобы заблокировать стандартное действие, скрипт с before="yes" должен вернуть <skipaction/> в ответе:

<doc>
	<skipaction/>
</doc>

Если <skipaction/> не возвращён, платформа выполнит стандартное действие в штатном режиме. Обработчики с after="yes" не вызываются, если стандартное действие было заблокировано через <skipaction/>.

Типичные задачи:

  • выполнить действие во внешней системе при открытии, закрытии или изменении услуги;
  • синхронизировать данные между BILLmanager и внешним сервисом;
  • заблокировать стандартное действие платформы и заменить его своим.

task — Event, независимый от породившего действия

Плагин подписывается на Action, но вызывается независимо от него. Основное выполнение не блокируется.

<handler name="vmlic_task.py" type="xml">
	<task name="vmlic.task"/>
</handler>

Атрибуты узла task:

Атрибут

Описание

name

Имя действия (Action), на который подписывается обработчик.

get

Укажите yes, чтобы отслеживать Action без параметров sv_field и sok=ok в запросе.

submit

Укажите yes, чтобы отслеживать Action с параметром sok=ok в запросе.

setvalues

Укажите yes, чтобы отслеживать Action с параметром sv_field в запросе.

sv_field

Список полей через запятую для фильтрации по sv_field. Используется совместно с setvalues.

sessiondata

Укажите yes, чтобы передать в скрипт результат обработки Action в формате XML.

Типичные задачи:

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

Структура плагина

Плагин состоит из: XML-файла с описанием и скрипта (или нескольких скриптов) с логикой обработки.

/usr/local/mgr5/
├── etc/xml/
│   └── billmgr_mod_myplugin.xml   # Регистрация и описание интерфейса.
└── addon/
    └── myplugin.py                # Логика обработки.

XML-файл

XML-файл регистрирует плагин в платформе и описывает элементы интерфейса. Размещается в директории /usr/local/mgr5/etc/xml/. Шаблон имени файла — billmgr_mod_<название>.xml.

Файл содержит корневой узел <mgrdata> с дочерними узлами:

Пример файла

Основные узлы XML-файла:

Узел

Описание

plugin

Регистрирует плагин в платформе. Атрибут name — уникальное имя плагина.

handler

Регистрирует обработчики событий и функций. Подробнее см. раздел Задачи плагина.

metadata

Описывает элемент интерфейса: форму (type="form"), список (type="list") или отчёт (type="report"). Атрибут name — имя функции, которую описывает элемент.

mainmenu

Добавляет пункты в главное меню платформы. Атрибут level — уровень доступа.

lang

Описывает локализацию. Атрибут name — код языка (ru, en).

metadata

Узел metadata описывает формы, списки и отчёты. Атрибуты:

Атрибут

Описание

name

Имя функции, которую описывает элемент.

type

Тип элемента. Возможные значения:

  • form — форма;
  • list — список;
  • report — отчёт.

level

Уровень доступа. Подробнее см. раздел Права доступа к функциям плагина.

lang и messages

Локализация строится из следующих уровней вложенности: lang → messages → msg.

Специальные секции messages с зарезервированными именами:

Имя секции

Описание

plugin

Название и описание плагина в маркетплейсе. Ключи: desc_short_<name>, desc_full_<name>, price_<name>.

msgerror

Тексты ошибок. Ключ: msg_error_<err_type> соответствует err_type в XmlException.

desktop

Названия пунктов меню. Ключ: menu_<func_name>.

<func_name>

Подписи полей формы или столбцов списка. Ключ совпадает с именем поля или столбца.

Подсказки к полям формы задаются ключом с префиксом hint_:

Пример подсказки
<msg name="hint_api_key">Токен можно получить в личном кабинете.</msg>

Подробнее про описание и параметры XML-форм см. в документации COREmanager.

Скрипт

Скрипт содержит логику обработки. Размещается в директории /usr/local/mgr5/addon/. При использовании type="xml":

  1. Платформа передаёт входной XML-файл в stdin скрипта.
  2. Скрипт обрабатывает его и возвращает результат в stdout.
Минимальная структура скрипта на Python с использованием SDK

Параметры запроса доступны через переменные окружения с префиксом PARAM_. SDK содержит методы для работы с окружением:

SDK

Окружение

Описание

session.get_query_param("func")

PARAM_func

Имя вызванной функции.

session.get_query_param("elid")

PARAM_elid

Идентификатор объекта.

session.get_query_param("sok")

PARAM_sok

ok, если форма отправлена.

session.get_input_xml()

stdin

Входной XML-файл.

Ответ скрипта в зависимости от результата работы и типа обработчика:

Ситуация

Что вернуть в stdout

Успешная обработка события

<?xml version="1.0" encoding="UTF-8"?>\n<doc/>

Данные формы

ET.tostring(xml, encoding="unicode")

Ошибка

err.as_xml() из XmlException

Блокировка действия

<doc><skipaction/></doc>

Права доступа к функциям плагина

По умолчанию функции и формы плагина доступны всем пользователям. Чтобы ограничить доступ, используйте атрибут level в элементе <metadata>:

<metadata name="vmlic.settings" type="form" level="admin+">

Доступные значения атрибута level:

Значение

Числовой уровень

Кому доступно

all

от 0

Все пользователи, включая неавторизованных.

public

от 1

Все авторизованные пользователи. Доступ нельзя ограничить через политики прав — функция доступна, даже если в политиках используется значение "Всё запрещено".

registered

от 2

Все авторизованные пользователи.

nobody

= 0

Только неавторизованные пользователи.

user

= 16

Только обычные пользователи.

reseller

= 24

Только реселлеры.

admin

= 29

Только администраторы платформы.

super

= 30

Только администраторы сервера.

Модификаторы:

  • + после имени — указанный уровень и выше. admin+ открывает доступ администраторам платформы (29) и администраторам сервера (30);
  • - после имени — указанный уровень и ниже. reseller- открывает доступ реселлерам (24) и всем с более низким уровнем;
  • несколько значений через запятую объединяются: admin,super+ эквивалентно admin+.

Для административных форм плагина рекомендуется level="admin+".

Значения all, registered и public уже означают "этот уровень и выше". Модификатор + для них избыточен. Для остальных значений без модификатора доступ ограничен указанным уровнем.

Пример плагина-валидатора

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

Постановка задачи

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

Решение

BILLmanager вызывает плагин-валидатор при проверке поля с атрибутом check="checker" и ожидает в ответ либо нормализованное значение, либо ошибку.

Структура проекта

checker/
├── addon/
│   └── checker.py          # Логика валидации.
├── xml/
│   └── billmgr_mod_checker.xml  # Регистрация плагина.
├── requirements.txt        # Зависимости Python.
├── Makefile                # Сборка и установка файлов.
└── install.sh              # Установка зависимостей и плагина.

XML-файл

Файл регистрирует плагин и объявляет локализацию ошибок валидации. Размещается в /usr/local/mgr5/etc/xml/.

Ключи ошибок для валидатора имеют формат desc_ — без стандартного префикса msg_error_ (msg_error_ используется для всплывающих ошибок).

Регистрация валидаторов выполняется автоматически на основе паттерна именования check.*. Поэтому нужно зарегистрировать новый Action (func) с именем, содержащим check. в начале.  Например, check.checker.

Пример XML-файла

Скрипт

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

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

Набор разработчика SDK BILLmanager не содержит готовых абстракций для плагинов, но на основе информации из раздела Структура плагина можно написать следующий код:

Пример кода

Makefile

Makefile отвечает за копирование файлов плагина в нужные директории BILLmanager. Его вызывает install.sh после установки зависимостей. isp.mk — стандартный набор правил сборки ISPsystem. Он определяет переменные DISTDIR, цель install и другие вспомогательные цели. Подключается в конце через include.

XML-файл и изображения загружаются автоматически, если соблюдена нужная структура:

  • XML-файл в папку xml на уровне Makefile;
  • изображения — в dist/skins/common/img/*.

После этого изображения можно использовать, например, в таких формах при имени изображения sad.png:

Пример кода
  <toolbar>
      <toolbtn func="vmlic.errors.retry"   name="retry"   img="sad" type="group"/>
      <toolbtn func="vmlic.errors.resolve" name="resolve" img="sad" type="group"/>
      <toolbtn func="vmlic.errors.delete" name="delete" img="sad" type="group" warning="yes"/>
  </toolbar>
MGR    = billmgr
PLUGIN = checker
BASE  ?= /usr/local/mgr5
SRC    = $(shell pwd)
VENV_PATH = $(SRC)/venv-checker

dist-prepare: $(DISTDIR)/addon/checker.py \

# Копируем скрипт и подменяем shebang на venv-интерпретатор
$(DISTDIR)/addon/checker.py: $(SRC)/addon/checker.py
	@echo "checker: copy main script"
	@mkdir -p $(DISTDIR)/addon/
	cp -f $(SRC)/addon/checker.py $(DISTDIR)/addon/checker.py
	sed -i '1s|^#!.*|#!$(VENV_PATH)/bin/python3|' $(DISTDIR)/addon/checker.py
	chmod 744 $(DISTDIR)/addon/checker.py

install.sh

install.sh — скрипт первичной установки плагина. Запускается вручную от root на сервере. Скрипт:

  1. Устанавливает системные зависимости (python3-venv, make и др.) через пакетный менеджер дистрибутива.
  2. Создаёт изолированное виртуальное окружение Python, чтобы зависимости плагина не конфликтовали с системными пакетами.
  3. Копирует файлы плагина в /usr/local/mgr5/src/checker/ и запускает make install.
Создайте install.sh, чтобы упростить установку на нескольких серверах. Плагин будет работать без этого файла.
Пример содержимого install.sh

Проверка

После установки:

  1. Сбросьте кеш и перезапустите платформу:
    rm -rf /usr/local/mgr5/var/.xmlcache*
    /usr/local/mgr5/sbin/mgrctl -m billmgr exit
  2. Проверьте регистрацию обработчика в журнале /usr/local/mgr5/var/billmgr.log. Установите достаточный уровень логирования платформы:
    action EXTINFO Register action 'check.checker'
  3. Откройте параметры нужного типа продукта → выберите параметр → нажмите Изменить.
  4. В открывшейся форме найдите поле Функция проверки и выберите валидатор. В данном случае check.checker.
Может быть полезно