
Мы возвращаемся на Хабр после долгого отсутствия. И сегодня хотим рассказать как быстро и просто создать свой дополнительный модуль для BILLmanager'a. Эта задача существенно упростилась, потому что теперь доступен исходный код уже реализованных нами плагинов.
Возможность получения дополнительного модуля для BILLmanager существовала и ранее, причём несколькими способами.
Первый вариант — заказать модуль у нас, в ISPsystem. Получившийся продукт будет поддерживаться во всех последующих версиях BILLmanager, а также будет доступен для подключения другим пользователям. Однако порой наш плотный roadmap может надолго отсрочить релиз желаемого плагина.
Второй вариант — обратиться к нашим технологическим партнёрам, но в этом случае вопрос с поддержкой продукта нужно будет решать с партнёрами дополнительно.
И, наконец, третий вариант — написать модуль самостоятельно. Начиная с версии 5.58 вам больше не потребуется внушительный опыт программирования, т.к. теперь набор разработчика BILLmanager включает в себя примеры исходного кода 8 существующих плагинов, а именно:
- cpanel – обеспечивает интеграцию с одноимённой панелью управления;
- epp – универсальный обработчик для взаимодействия с поддерживающими протокол EPP регистраторами доменных имён;
- webnames – взаимодействует с этим доменным регистратором;
- thesslstore – модуль для покупки SSL-сертификатов;
- paypal – плагин для приёма платежей через данную платёжную систему;
- privatbank – для взаимодействия с биллингом банка;
- remotemail – почтовый шлюз;
- smsc – СМС-шлюз для компании СМС-центр;
Для получения пакета с примерами требуется установить BILLmanager (инструкция как это сделать находится здесь). В процессе инсталляции выберите желаемую версию продукта (Standard, Advanced или Corporate), а затем установите пакет billmanager-[выбранный_вариант]-devel (например, yum install billmanager-corporate-devel).
После установки пакета devel примеры будут находиться здесь:
/usr/local/mgr5/src/examples
Вооружившись образцами и имеющейся документацией, можно разработать модуль практически для любой платёжной системы, доменного регистратора, СМС-шлюза и т.д.
Рассмотрим процесс написания СМС-шлюза для взаимодействия с сотовым оператором Q-telecom; исходники — под катами чуть ниже.
При переделке модуля использовалось описание API Q-telecom; оно лежит здесь.
Из документации к API видно, что взаимодействие выполняется по протоколу http, так же как и в СМС-шлюзе из примеров. Воспользуемся этим.
Создадим копию директории /usr/local/mgr5/src/examples/smsc и назовём её gwqtc.
Внутри лежит 3 файла: xml отвечает за то, как плагин выглядит в BILLmanager; cpp описывает backend; в makefile лежат инструкции для компилятора как собрать всю эту прелесть в бинарник.
Начнём с самого сложного, — с переделки gwsmsc.cpp. Переименуем его в gwqtc.cpp, затем откроем файл в текстовом редакторе. Меняем в отвечающем за создание post-запроса куске кода названия переменных на описанные ребятами из Q-telecom. Добавляем параметр gzip=none, чтобы в случае сбоев текст ошибки приходил читаемым. Те строки, которые QTC не поймёт — удаляем.
Где и что поменяли

Затем в файле ищем и меняем “smsc” на “qtc” (в итоге изменения будут в двух строках). Всё, файл gwqtc.cpp готов. Самое сложное мы сделали.
Займёмся xml: меняем его имя на billmgr_mod_gwqtc; внутри “SMS-center” перепиcываем на “Q-telecom”, а “smsc” на “qtc”. С внешним видом закончили.
В makefile всё совсем просто: всюду меняем “smsc” на “qtc”.
Теперь скомпилируем и установим модуль командой make install, не забыв перед этим установить пакет gcc-c++, если его в системе нет.
После всех этих действий в BILLmanager, в меню “Интеграция” → “Модули сообщений” → “Создать” вы увидите новый модуль, Q-telecom.
Как это выглядит в BILLmanager

Осталось внести полученные при заключении договора с Q-telecom настройки — и можно пользоваться!
Вот обещанные исходники в конечном их виде.
gwqtc.cpp
#include <gate/gatemodule.h> #include <defines.h> #include <mgr/mgrlog.h> #include <mgr/mgrrpc.h> #include <sstream> #define BINARY_NAME "gwqtc" MODULE("notify"); namespace gate { class QTC : public Module { public: QTC() : Module(BINARY_NAME) { } virtual mgr_xml::Xml Features() const { mgr_xml::Xml out; mgr_xml::XmlNode features = out.GetRoot().AppendChild("features"); features.AppendChild("feature").SetProp("name", GATE_CMD_OUTGOING); out.GetRoot().AppendChild("notify_module", "ntsms"); return out; } virtual mgr_xml::Xml Ingoing(mgr_xml::Xml& msg) const { mgr_xml::Xml out; return out; } virtual void Outgoing(mgr_xml::Xml& msg) const { string message = msg.GetRoot().FindNode("message"); string project_id = msg.GetRoot().FindNode("project").FindNode("id"); string phone = msg.GetRoot().FindNode("user").FindNode("phone"); str::inpl::RemoveNonDigit(phone); string sender = GateParam("originator_" + project_id); if (sender.empty()) sender = GateParam("originator"); mgr_rpc::HttpQuery http; http.EnableCookie(); http.AcceptAnyResponse(); std::stringstream out; http.Post("http://service.qtelecom.ru/public/http/", "user=" + str::url::Encode(GateParam("login")) + "&pass=" + str::url::Encode(GateParam("psw")) + "&target=" + str::url::Encode(phone) + "&message=" + str::url::Encode(message) + "&gzip=none" "&sender=" + str::url::Encode(sender) + "&action=post_sms", out); Debug("response: %s", out.str().c_str()); mgr_xml::XmlString result(out.str()); string result_str = result.GetNode("//result/error"); if (!result_str.empty()) throw mgr_err::Error(result_str); } }; } // END NAMESPACE GATE RUN_MODULE(gate::QTC)
billmgr_mod_gwqtc.xml
<?xml version="1.0" encoding="UTF-8"?> <mgrdata> <plugin name="gwqtc"> <group>gateway</group> <author>BILLmanager team</author> </plugin> <metadata name="gateway.gwqtc"> <form> <field name="login"> <input type="text" name="login" required="yes" identifier="yes"/> </field> <field name="psw"> <input type="password" name="psw" required="yes"/> </field> <field name="originator" project="yes"> <input type="text" name="originator"/> </field> </form> </metadata> <lang name="ru"> <messages name="plugin"> <msg name="desc_short_gwqtc">Q-telecom</msg> <msg name="desc_full_gwqtc">Сервер Q-telecom</msg> <msg name="price_gwqtc">Бесплатно</msg> </messages> <messages name="gateway.gwqtc"> <msg name="login">Логин</msg> <msg name="psw">Пароль</msg> <msg name="translit">Транслитерация</msg> <msg name="originator">Отправитель</msg> <msg name="hint_login">Логин в личный кабинет Q-telecomа</msg> <msg name="hint_psw">Пароль от личного кабинета</msg> <msg name="hint_translit">Транслитерация СМС сообщений при отправке</msg> <msg name="hint_originator">Подпись отправителя в СМС</msg> </messages> <messages name="gateway_include"> <msg name="module_gwqtc">Сервер Q-telecom</msg> <msg name="gwqtc">Q-telecom</msg> <msg name="desc_gwqtc">СМС шлюз</msg> </messages> </lang> <lang name="en"> <messages name="plugin"> <msg name="desc_short_gwqtc">SMS-center</msg> <msg name="desc_full_gwqtc">Server SMS-center</msg> <msg name="price_gwqtc">Free</msg> </messages> </lang> </mgrdata>
Makefile
MGR = billmgr PLUGIN = gwqtc CFLAGS += -I/usr/local/mgr5/include/billmgr CXXFLAGS += -I/usr/local/mgr5/include/billmgr WRAPPER += gwqtc gwqtc_SOURCES = gwqtc.cpp gwqtc_FOLDER = gate gwqtc_LDADD = -lmgr -lmgrdb gwqtc_DLIBS = gatemodule BASE ?= /usr/local/mgr5 include $(BASE)/src/isp.mk
Как мы с вами только что выяснили, относительно примеров изменены всего несколько строк. То есть теперь для написания плагинов хватит и небольшого опыта программирования, а партнёры смогут повысить качество выпускаемых продуктов на основе образцов.
К слову сказать, нами запланирован запуск магазина модулей, в котором разработанные вами дополнения можно будет бесплатно или за определённые деньги разместить для других компаний.
Надеемся, эта статья окажется полезной пользователям BILLmanager. Будем очень рады услышать о ваших успехах в описанном процессе.