Небольшая шпаргалка о том, как взаимодействовать из Андроида с базой 1С. Предполагается, что в 1С уже описан веб-сервис и он опубликован. В моем случае использована база на платформе 8.3, управляемые формы, веб-сервер Apache 2.2, 1С и Апач расположены на одном сервере под управлением Windows 2008 R2.
Для работы с веб-сервисами в Android используется библиотека KSoap2, на момент написания этой заметки файл для импорта в проект назывался так:
ksoap2-android-assembly-3.6.2-jar-with-dependencies.jar
Для вызова понадобятся несколько ключевых параметров:
private static final String NAMESPACE = "www.URI.com";
private static final String URL = "http://***.***.***.***/kk-base/ws/AgentExchange";
private static final String SOAP_ACTION = "www.URI.com#AgentExchange";
private static final String USER_PASSWORD = "ИмяПользователя:Пароль";
NAMESPACE — пространство имен, задается в конфигураторе 1С, непосредственно в свойствах веб-сервиса
URL — состоит из адреса сервера, на котором опубликована конфигурация, имени конфигурации, которое задано при публикации и имени веб-сервиса: http://< адрес сервера>/< имя конфигурации>/ws/< имя веб-сервиса>
SOAP_ACTION — имя команды сервиса, состоит из имени пространства имен и имени сервиса; во всех примерах в это имя еще включают имя самой операции, т.е. метода, если смотреть в конфигурации 1С, но у меня работает без него, возможно это «фишка» сервиса в 1С: < пространство имен>#< имя веб-сервиса>[:< имя операции>]
USER_PASSWORD — строка из имени и пароля пользователя, как они заданы для авторизации в 1С
Обращение к веб-сервису должно происходить асинхронно, отдельно от основного UI, по этому понадобится отдельный подкласс, унаследованный от AsyncTask. В приведенном ниже коде происходит обращение к методу GetOrders, который принимает строковый параметр с именем «Данные», значение параметра — «ping». В ответ на строку «ping» сервис должен ответить «1» если передача разрешена или «0» если сервис не готов или пользователю запрещен обмен — это все сконфигурировано на стороне 1С.
После выполнения обмена данными с сервисом в процедуре doInBackground, строка-результат передается в процедуру onPostExecute, в которой текст выводится в textView в основном приложении.
Веб-сервис всегда возвращает ответ в виде SoapObject, у которого необходимо прочитать свойства и таким образом проанализировать результат. Если сервис отвечает простыми данными, обычно строкой, то значением свойства уже и будет ответ. Если ответ «сложный», например, список товаров, где каждый товар имеет свойства, то внутри основного объекта будут вложенные объекты типа SoapObject у которых необходимо обращаться к свойствам и так далее. Эта структура определяется в 1С, по этому количество и идентификаторы свойств соответствуют конфигурации.
Обращение к свойству возможно по индексу или имени, например:
itemProperty.getProperty("Наименование")
здесь «Наименование» это идентификатор свойства, который задан в конфигураторе 1С.
Ниже приведен пример функции, выполняющей запрос к веб-сервису. Ссылка на GitHub: ksoap2-example.
@Nullable | |
private SoapObject getData(String objectCode) { | |
errorText = ""; | |
SoapObject request = new SoapObject(NAMESPACE, "get"); | |
PropertyInfo param = new PropertyInfo(); | |
param.setName("objectCode"); | |
param.setValue(objectCode); | |
request.addProperty(param); | |
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); | |
envelope.setOutputSoapObject(request); | |
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL); | |
androidHttpTransport.setXmlVersionTag("<?xml version=\"1.0\" encoding=\"utf-8\"?>"); | |
//авторизация | |
List<HeaderProperty> headerList = new ArrayList<HeaderProperty>(); | |
headerList.add(new HeaderProperty("Authorization", "Basic "+org.kobjects.base64.Base64.encode(USER_PASSWORD.getBytes()))); | |
//выполнение запроса к веб-сервису | |
try { | |
androidHttpTransport.call(SOAP_ACTION, envelope, headerList); | |
} catch (IOException e) { | |
errorText = "CONNECTION_ERROR"; | |
return null; | |
} catch (XmlPullParserException e) { | |
errorText = "XML_ERROR"; | |
return null; | |
} | |
Object result = envelope.bodyIn; | |
if (result != null) { | |
try { | |
return (SoapObject) result; | |
}catch (Exception e){ | |
Log.e("KSOAP", result.toString()); | |
} | |
} | |
return null; | |
} |