BILLmanager 6
en En
es Es

Plugins. General principles

The article uses the following terms
Before reading this article, it is recommended to review the developer documentation for COREmanager, because part of the mechanisms is inherited from the base framework.

Plugins allow you to change BILLmanager platform behavior, intercept events, extend the interface, and add new functions. The article describes how plugins work, their structure, and gives an example of creating a validation plugin. For plugin development details, see the article Creating modules.

BILLmanager modifications

 BILLmanager allows you to add the following modifications:

  • modules — large and self-contained system components that perform a specific function or set of functions. For example, they extend functionality through integration with a third-party system. Modules:
    • usually have their own dependencies and can include several plugins;
    • are not intended to dynamically change system behavior in real time;
    • may require changes to the core system architecture;
    • by functionality are divided into:
      • service handlers;
      • payment methods;
      • message gateways;
      • online cash registers;
      • document workflow modules;
      • modules for coordination with third-party systems — LDAP, Omni, amoCRM, etc.

See more in the article Modules. General principles.

  • plugins — usually simpler software components that add specific functionality or change the behavior of the main system. Plugins allow you to:
    • integrate new features without changing the source code;
    • intercept internal events;
    • add new interface elements;
    • run background tasks through triggers on specific events;
    • adapt the system to specific needs.

See the comparison of plugins and modules in the article Background plugins.

Types of plugins

Plugins are divided by functionality into:

  • plugins that change platform behavior;
  • plugins that extend platform functionality;
  • plugins that run background tasks.

Plugins that change behavior let you intercept internal events and modify them. For example, add extra fields to the client card and fill them with the required values. Or add new logic for existing actions. See more in the COREmanager documentation article Changing system behavior through event handlers.

Plugins that extend functionality add:

  • new elements — configurable tables and forms needed to solve specific tasks;
  • newe actions and platform workflows.

Plugins that run background tasks:

  • add triggers for specific events in the platform;
  • allow heavy tasks to run in the background, so they do not affect working with the platform in the interface. For example, running background tasks based on events.

See more in the article Background plugins.

Plugin tasks

The plugin registers handlers through an XML file in the /usr/local/mgr5/etc/xml/ directory. Each handler is described by the handler node:

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

Attributes of the handler node:

Attribute

Description

name

Handler file name in the /usr/local/mgr5/addon/ directory. The name must match the one specified in the handler node.

type

How BILLmanager interacts with the script: cgi or xml:

  • type="cgi" — BILLmanager builds environment variables with request information and calls the script. The script returns an XML file in stdout. BILLmanager merges the received XML file with the main one;
  • type="xml" — BILLmanager builds environment variables and passes the main XML file to the script's stdin. The script modifies the XML file and returns it to stdout. BILLmanager replaces the main XML file with the one received from the script.

protocol

Script call protocol::

  • fcgi — call through FastCGI;
  • not specified — regular call.

ignore_errors

If yes is specified, handler errors do not affect platform operation.

In the BILLmanager platform, any interaction (for example, a user click, an internal platform call, or a request from an external service) invokes the Action function (action). Events are bound to the Action and are called before, after, or in both cases (both before and after), depending on the settings.

When registering a plugin, one of the following nodes is used inside handler:

  • func — registers an Action: the script becomes the handler for the function;
  • event — registers an Event: the script is called when the event occurs;
  • task — registers an Event: the script is called regardless of the action that triggered it.

To get the list of Action, use the command:

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

To get the list of Event for a specific Action, use the command:

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

func — Action, form and interface extension

The plugin becomes the handler for a specific BILLmanager function:

  • forms;
  • lists;
  • buttons.

BILLmanager calls the script when the user opens a form or clicks a button.

Example script
<handler name="vmlic_action.py" type="xml">
    <func name="vmlic.settings"/>
    <func name="vmlic.errors"/>
    <func name="vmlic.errors.retry"/>
</handler>

Attributes of the func node:

Attribute

Description

name

Name of the Action handled by the script.

postdata

Specify yes to pass the POST request body to the script's stdin. Relevant only for POST requests. For example, when saving a form sok=ok. For GET requests, the body is always empty.

Typical tasks:

  • add a plugin settings page to the admin interface;
  • display a list of objects managed by the plugin;
  • add an action button to an existing service list;
  • validate a form field when ordering (check.<name>).

event — Event, action interceptor

The plugin subscribes to a BILLmanager Action and is called automatically — before or after it is executed.

<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>

Attributes of the event node:

Attribute

Description

name

Name of the Action the handler subscribes to.

before

Specify yes to call the script before the main action is executed.

after

Specify yes to call the script after the main action is executed.

proirity

Defines the call order among other handlers for the same event: before — before the base handler, after — after it. If base is not specified: before — to the front of the queue, after — to the end.

Note: the attribute is spelled proirity, not priority — this is a COREmanager feature kept for compatibility.

base

Name of the base handler whose order is determined by proirity. project — subscribe to the BILLmanager Action, not COREmanager.

postdata

Specify yes to pass the POST request body to the script's stdin. Relevant only for POST requests. For example, when saving a form sok=ok. For GET requests, the body is always empty.

To block the standard action, the script with before="yes" must return <skipaction/> in the response:

<doc>
	<skipaction/>
</doc>

If <skipaction/> is not returned, the platform will perform the standard action in the usual way. Handlers with after="yes" are not called if the standard action was blocked through <skipaction/>.

Typical tasks:

  • perform an action in an external system when a service is opened, closed, or changed;
  • synchronize data between BILLmanager and an external service;
  • block the standard platform action and replace it with your own.

task — Event, independent of the triggering action

The plugin subscribes to an Action, but is called independently of it. The main execution is not blocked.

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

Attributes of the task node:

Attribute

Description

name

Name of the Action the handler subscribes to.

get

Specify yes to track the Action without sv_field and sok=ok parameters in the request.

submit

Specify yes to track the Action with the sok=ok parameter in the request.

setvalues

Specify yes to track the Action with the sv_field parameter in the request.

sv_field

Comma-separated list of fields for filtering by sv_field. Used together with setvalues.

sessiondata

Specify yes to pass the result of Action processing to the script in XML format.

Typical tasks:

  • periodically check the status of objects in an external system;
  • send accumulated data in batches;
  • perform cleanup or synchronization on a schedule.

Plugin structure

The plugin consists of: an XML file with a description and a script (or several scripts) with processing logic.

/usr/local/mgr5/
├── etc/xml/
│   └── billmgr_mod_myplugin.xml   # Registration and interface description.
└── addon/
    └── myplugin.py                # Processing logic.

XML file

The XML file registers the plugin in the platform and describes interface elements. It is placed in the /usr/local/mgr5/etc/xml/. The file name pattern is billmgr_mod_<name>.xml.

The file contains the root node <mgrdata> with child nodes:

File example

Main XML file nodes:

Node

Description

plugin

Registers the plugin in the platform. The name attribute is the unique plugin name.

handler

Registers event and function handlers. See more in the section Plugin tasks.

metadata

Describes the interface element: form (type="form"), list (type="list"), or report (type="report"). The name attribute is the name of the function described by the element.

mainmenu

Adds items to the platform main menu. The level attribute is the access level.

lang

Describes localization. The name attribute is the language code (ru, en).

metadata

The metadata node describes forms, lists, and reports. Attributes:

Attribute

Description

name

Name of the function described by the element.

type

Element type. Possible values:

  • form — form;
  • list — list;
  • report — report.

level

Access level. See more in the section Function access rights in the plugin.

lang and messages

Localization is built from the following nesting levels: lang → messages → msg.

Special messages sections with reserved names:

Section name

Description

plugin

Plugin name and description in the marketplace. Keys: desc_short_<name>, desc_full_<name>, price_<name>.

msgerror

Error texts. The key msg_error_<err_type> corresponds to err_type in XmlException.

desktop

Menu item names. Key: menu_<func_name>.

<func_name>

Labels for form fields or list columns. The key matches the field or column name.

Hints for form fields are set by the key prefix hint_:

Hint example
<msg name="hint_api_key">The token can be obtained in the client area.</msg>

For more information about XML form description and parameters, see the COREmanager documentation.

Script

The script contains processing logic. It is placed in the /usr/local/mgr5/addon/ directory. When using type="xml":

  1. The platform passes the input XML file to the script's stdin.
  2. The script processes it and returns the result to stdout.
Minimal Python script structure using the SDK

Request parameters are available through environment variables with the PARAM_ prefix. The SDK includes methods for working with the environment:

SDK

Environment

Description

session.get_query_param("func")

PARAM_func

Name of the called function.

session.get_query_param("elid")

PARAM_elid

Object ID.

session.get_query_param("sok")

PARAM_sok

ok if the form was submitted.

session.get_input_xml()

stdin

Input XML file.

Script response depending on the result and handler type:

Situation

What to return in stdout

Successful event processing

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

Form data

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

Error

err.as_xml() from XmlException

Action blocking

<doc><skipaction/></doc>

Function access rights in the plugin

By default, plugin functions and forms are available to all users. To restrict access, use the level attribute in the <metadata> element:

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

Available values of the level attribute:

Value

Numeric level

Who can access

all

from 0

All users, including unauthenticated users.

public

from 1

All authenticated users. Access cannot be restricted through permission policies — the function is available even if the policies use the value "Everything is forbidden".

registered

from 2

All authenticated users.

nobody

= 0

Only unauthenticated users.

user

= 16

Only regular users.

reseller

= 24

Only resellers.

admin

= 29

Only platform administrators.

super

= 30

Only server administrators.

Modifiers:

  • + after the name — the specified level and higher. admin+ grants access to platform administrators (29) and server administrators (30);
  • - after the name — the specified level and lower. reseller- grants access to resellers (24) and everyone with a lower level;
  • multiple values separated by commas are combined: admin,super+ is equivalent to admin+.

For administrative plugin forms, level="admin+" is recommended.

The values all, registered, and public already mean "this level and higher". The + modifier for them is redundant. For the other values, without a modifier, access is limited to the specified level.

Example of a validation plugin

This section provides an example of creating a plugin that checks whether the domain name entered by the user when ordering a service is valid.

Task statement

When ordering a service, the user enters a domain name in the plugin field. You need to validate the entered value before the order is placed. The standard validator domain.check is not suitable, because it works only with standard product types.

Solution

BILLmanager calls the validation plugin when checking a field with the check="checker" attribute and expects either a normalized value or an error in response.

Project structure

checker/
├── addon/
│   └── checker.py          # Validation logic.
├── xml/
│   └── billmgr_mod_checker.xml  # Plugin registration.
├── requirements.txt        # Python dependencies.
├── Makefile                # Build and install files.
└── install.sh              # Install dependencies and plugin.

XML file

The file registers the plugin and declares localization for validation errors. It is placed in /usr/local/mgr5/etc/xml/.

The validator error keys use the desc_ format — without the standard msg_error_ prefix (msg_error_ is used for pop-up errors).

Validators are registered automatically based on the naming pattern check.*. Therefore, you need to register a new Action (func) with a name that starts with check.. For example, check.checker.

XML file example

Script

When developing in Python, we recommend running all code in a virtual environment. Examples are shown in the code below and in the Makefile section — these are different ways to provide isolation in a virtual environment.

The code below is an example solution to the task, not a ready-made solution.

The BILLmanager SDK developer kit does not include ready-made abstractions for plugins, but based on the information in the Plugin structure section, you can write the following code:

Code example

Makefile

Makefile is responsible for copying the plugin files to the required BILLmanager directories. It is called by install.sh after the dependencies are installed. isp.mk is the standard ISPsystem build rule set. It defines the DISTDIR variable, the install target, and other helper targets. It is included at the end through include.

The XML file and images are uploaded automatically if the required structure is followed:

  • XML file into the xml folder at the Makefile level;
  • images — into dist/skins/common/img/*.

After that, images can be used, for example, in such forms when the image name is sad.png:

Code example
  <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 \

# Copy the script and replace shebang with the venv interpreter
$(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 — initial installation script for the plugin. It is run manually as root on the server. The script:

  1. Installs system dependencies (python3-venv, make, etc.) through the distribution package manager.
  2. Creates an isolated Python virtual environment so the plugin dependencies do not conflict with the system packages.
  3. Copies the plugin files to /usr/local/mgr5/src/checker/ and runs make install.
Create install.sh to simplify installation on multiple servers. The plugin will work without this file.
Example of install.sh content

Verification

After installation:

  1. Clear the cache and restart the platform:
    rm -rf /usr/local/mgr5/var/.xmlcache*
    /usr/local/mgr5/sbin/mgrctl -m billmgr exit
  2. Check the handler registration in the /usr/local/mgr5/var/billmgr.log log. Set a sufficient platform logging level:
    action EXTINFO Register action 'check.checker'
  3. Open the parameters of the required product type → select the parameter → click Edit.
  4. In the form that opens, find the Validation function field and select the validator. In this case, check.checker.
Useful tips