Из структуры биллинга можно определить два способа взаимодействия с ним извне:
обращение к базе данных - допустимо для выборок данных либо для быстрого внесения изменений, не предполагающих реакции сервера; |
обращение к серверу биллинга - выполнение действий аналогично оператору из АРМ биллинга посредством обращений сторонней системы. |
При выполнении обращений к серверу биллинга помимо записи данных в БД могут производится различные дополнительные обработки самим сервером. Например: разблокировка модулей по платежу.
К серверу биллинга возможно обращаться из сторонних приложений посредством HTTP запросов. Пример запросов можно изучить вызывая различные действия в клиентском приложении, запущенном в через client_debug.bat (.sh). Запросы и ответы распечатываются в log файл. Биллинг поддерживает несколько вариантов протоколов обращений для различных действий, их можно определить по внешнему виду запросов.
Более ранний протокол. Подразумевает передачу параметров в HTTP запросе с получением XML ответа. Примерный вид запроса и ответа в логе клиента:
http://billing:8081/executer?module=npay&action=ServiceSetList&mid=6&BGBillingSecret=ONM13dhRxs8VDD9wFCzpPOrU& [ length = 159 ] xml = <?xml version="1.0" encoding="UTF-8"?><data secret="B802E452DF43140146D0EC4219C847D1" status="ok"><list><item id="0" title="Полный набор услуг"/></list></data>
Дополнительно необходимо добавить в запрос параметры
и с логином и паролем пользователя биллинга, от лица которого отправляется запрос. Рекомендуется добавить к запросу параметр , это предотвратит создание HTTP сессий, уменьшит потребление памяти на сервере.В целях отладки запросы можно отправлять прямо в браузере.
Более новые вызовы реализованы как Web-сервисы, пример обращения к ним вы можете посмотреть в WiKi. Используется Basic авторизация.
Примерный вид запроса и ответа:
http://billing:8081/executer/ru.bitel.bgbilling.kernel.module/ServiceService?wsdl -> {http://service.common.module.kernel.bgbilling.bitel.ru/}ServiceService:serviceList <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns5:serviceList xmlns:ns5="http://service.common.module.kernel.bgbilling.bitel.ru/" xmlns:common="http://common.bitel.ru" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><moduleId>9</moduleId></ns5:serviceList></S:Body></S:Envelope> <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Header/><S:Body><ns5:serviceListResponse xmlns:ns5="http://service.common.module.kernel.bgbilling.bitel.ru/" xmlns:common="http://common.bitel.ru" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xml="http://www.w3.org/XML/1998/namespace"><return id="15" moduleId="9" title="Рекламный блок на Board.ufanet.ru в одном разделе (справа)" unit="0" using="true"/><return id="7" moduleId="9" title="Рекламный блок на Board.ufanet.ru в разделе "Авторынок" (справа)" unit="0" using="true"/><return id="12" moduleId="9" title="Рекламный блок на Board.ufanet.ru в разделе "Аудио, видео, фототехника" (справа)" unit="0" using="true"/><return id="6" moduleId="9" title="Рекламный блок на Board.ufanet.ru в разделе "Компьютеры" (справа)" unit="0" using="true"/>
Для более простого обращения к Web сервисам возможно использование протокола JSON RPC.
Запрос выглядит следующим образом, пример:
http://127.0.0.1:8080/bgbilling/executer/json/ru.bitel.bgbilling.kernel.contract.api/ContractService {"method" : "contractList", "user" :{ "user" : "shamil", "pswd" : "xxxx" }, "params" : { "title" : "0", "fc" : -1, "groupMask" : 0, "subContracts" : false, "closed" : true, "hidden" : false, "page" : { "pageIndex" : 2, "pageSize" : 2 } } }
URL запроса определяет Web-сервис, JSON запрос передаётся в теле запроса, кодировка UTF-8. Обязательные параметры:
- вызываемая функция сервиса; |
- объект с логином и паролем пользователя, от лица которого выполняется действие; |
- объект со всем остальными параметрами сервиса. |
Обязательно указание значений всех параметров с примитивными типами: int, boolean.
Примерный вид корректного ответа:
{"status":"ok","message":"", "data": { "page":{"pageSize":2,"pageIndex":2,"pageCount":49,"recordCount":97,"pageFirstRecordNumber":2}, "return": [{"id":353023,"title":"0022010","groups":0,"password":"bg2rFZ2PEX","dateFrom":"2010-01-02","dateTo":null,"balanceMode":0,"paramGroupId":14,"personType":0,"comment":"","hidden":false,"superCid":0,"dependSubList":"","status":0,"statusTimeChange":"2010-01-13","titlePatternId":0,"balanceSubMode":0,"sub":false,"independSub":false,"balanceLimit":0.00,"super":false,"dependSub":false}, {"id":353209,"title":"06-10-10/И-Г/0","groups":0,"password":"9351220759","dateFrom":"2010-10-06","dateTo":null,"balanceMode":1,"paramGroupId":14,"personType":0,"comment":"","hidden":false,"superCid":0,"dependSubList":"","status":0,"statusTimeChange":"2010-10-06","titlePatternId":0,"balanceSubMode":0,"sub":false,"independSub":false,"balanceLimit":0.00,"super":false,"dependSub":false}]}}
В
возвращается в случае корректного ответа, либо - ошибка. При этом в выводится текст ошибки.Там выглядит сообщение об ошибке:
{"status":"error","message":"Неправильный пароль.","data":{}}
В случае корректного ответа в
возвращаются результаты выполнения. Возвращаемый методом параметр под ключом .Также возможен возврат результатов из параметров сервиса посредством объекта типа
.Для работы с сервисом необходимо найти его класс в JavaDoc, например: ContractService. Далее определить имена и типы передаваемых параметров, переходя к JavaDoc описаниям других классов, если понадобится.
Некоторую сложность представляет передача параметров, в роли которых могут выступать классы-потомки указанного в JavaDoc класса. Для примера рассмотрим параметр FilterEntityAttr. В JavaDoc данного класса находим:
указанного ранее сервиса, метод . В качестве параметров передаются наследники объекта@JsonTypeInfo(use=NAME, include=PROPERTY, property="type") @JsonSubTypes(value={ @JsonSubTypes.Type(name="Address",value=FilterEntityAttrAddress.class), @JsonSubTypes.Type(name="Date",value=FilterEntityAttrDate.class), @JsonSubTypes.Type(name="House",value=FilterEntityAttrHouse.class), @JsonSubTypes.Type(name="Int",value=FilterEntityAttrInt.class), @JsonSubTypes.Type(name="List",value=FilterEntityAttrList.class), @JsonSubTypes.Type(name="Text",value=FilterEntityAttrText.class), @JsonSubTypes.Type(name="Email",value=FilterEntityAttrEmail.class)})
Данные строки означают, что объекты маркируются дополнительным полем
, в зависимости от которого определяется класс переданного объекта. Вот так, например, выглядит запрос фильтрации договоров по текстовому параметру:{"method" : "contractList", "user" :{ "user" : "shamil", "pswd" : "xxxx" }, "params" : { "fc" : -1, "groupMask" : 0, "subContracts" : false, "closed" : true, "hidden" : false, "page" : { "pageIndex" : 1, "pageSize" : 2 }, "entityFilter" : [ { "type" : "Text", "entitySpecAttrIds" : [2], "value" : "1" } ] } }
Для тестирования запросов удобно использовать плагин браузера позволяющий отправку запросов (типа HttpRequester для FF), либо штатную возможность браузера.