Дай дернуть! О веб-сервисах, Linux’ах и добрых поисковых сайтах

О веб-сервисах, апачах и *nix’ах.
— установим на новенький убунту старенький апач с php.
— дернем сервис из php-скрипта.
— создадим приложение, позволяющее дергать произвольный сервис с произвольными данными.
— ну и что там получится по пути в лес…

Начнем…

Как оказалось, лучшее — враг хорошего. По всей видимости, именно этим постулатом руководствовались создатели 1С, когда пилили в ней последние фичи с HTTP-сервисами и прочей OData. Иначе как объяснить, что 1С не работает с новыми версиями Apache 2.4 (по крайней мере в Linux’е). И если пользоваться необновленными программами — это любимое дело пользователей окон, то с Linux такая тема так просто не проходит — если уж он обновляется, то методично и капитально. Правда, в отличие от последних версий окошек, в Linux можно и не запускать обновление, просто проигнорировав зеленый значек на панели приложений (если у Вас Unity и Ubuntu).

Установка апача 2.2 для 1С

Для того, чтобы поставить старую версию apache, нужно всего-ничего: создать пару-тройку файлов со следующим содержимым:

1. /etc/apt/sources.list.d/ubuntu1204.list со следующим содержимым:

deb http://ru.archive.ubuntu.com/ubuntu/ precise main

Этот файл позволяет устанавливать пакеты с дистрибутива Ubuntu 12.04. В этом дистрибутиве апач еще старый — версии 2.2.

2. Создадим три файла в каталоге /etc/apt/preferences.d/:

2.1. apache22

Package: apache*
Pin: release a=precise
Pin-Priority: 500

2.2. libapache2

Package: libapache2*
Pin: release a=precise
Pin-Priority: 500

2.3. php5

Package: php5*
Pin: release a=precise
Pin-Priority: 500

Суть этих записей в том, что при установке пакетов, начинающихся с apache, libapache2 и php5 будет использоваться источник «precise» (Ubuntu 12.04), который мы указали в первом файле.

Дальше все просто для Linux:

sudo apt-get install apache2 php5 libapache2-mod-php5

Ждем, пока пакеты скачаются и установятся, и вот у нас апач 2.2 + php. Дальше можно поставить серверную 1С и постгрес. Как ее поставить, я вам не буду рассказывать, ибо количество людей, это рассказавших, давно уже перевалило за тысячу. Если поискать в гугле, то найдется масса мануалов:

http://sibtone.ru/?id=1c8.3ubuntu

http://www.avtomat.biz/blog/ustanovka-1s-predpriyatie-83-v-ubuntu-linux#.VoLGgXWLTCI

Ну и Инфостарт тут тоже чуток отметился форумом: http://forum.infostart.ru/forum74/topic119091/

Публикация 1С на вебсервисе

Для публикации я использую утилиту wininst, которая идет в поставке с 1С. Для этого пишу такое заклинание:

cd /opt/1C/v8.3/x86_64/
sudo ./webinst -apache22 -wsdir test -dir /var/www/TestPub -connstr "Srvr=192.168.1.5;Ref=utdemo" -confPath /etc/apache2/httpd.conf

В данном конкретном случае я опубликовал базу utdemo, расположенную на сервере 192.168.1.5 (параметр -connstr). Каталог вебсервера /var/www/TestPub. Имя публикации «test», путь к файлу конфига апача «/etc/apache2/httpd.conf».

Перезапускаем сервер:

sudo /etc/init.d/apache2 restart

В итоге у нас появился каталог /var/www/TestPub и в нем файл default.vrd, а в файле /etc/apache2/httpd.conf появились следующие строчки:

# 1c publication
Alias "/test" "/var/www/TestPub/"
<Directory "/var/www/TestPub/">
AllowOverride All
Options None
Order allow,deny
Allow from all
SetHandler 1c-application
ManagedApplicationDescriptor "/var/www/TestPub/default.vrd"
</Directory>

Проверяем, для этого пришем в браузере http://localhost/test. Все работает!

Публикуем веб-сервисы

Для этого нам нужно залезть шаловливыми ручками в наш файл default.vrd, в котором описаны веб-инструменты. Сейчас он в таком виде:

<point xmlns="http://v8.1c.ru/8.2/virtual-resource-system"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
base="/test"
ib="Srvr=192.168.1.5;Ref=utdemo"/>

Для того, чтобы опубликовать веб-сервисы, надо их список добавить в файл. Точка входа в сервис добавляется после тега ws вот таком вот образом:

<ws>
<point name="Exchange"
alias="exchange.1cws"
enable="true"/>
<point name="Exchange_2_0_1_6"
alias="exchange_2_0_1_6.1cws"
enable="true"/>
<point name="InterfaceVersion"
alias="InterfaceVersion.1cws"
enable="true"/>
<point name="ManagedApplication_1_0_0_1"
alias="ManagedApplication_1_0_0_1.1cws"
enable="true"/>
<point name="MessageExchange"
alias="messageexchange.1cws"
enable="true"/>
<point name="MessageExchange_2_0_1_6"
alias="messageexchange_2_0_1_6.1cws"
enable="true"/>
<point name="MobileService"
alias="mobile.1cws"
enable="true"/>
<point name="RemoteAdministrationOfExchange"
alias="RemoteAdministrationOfExchange.1cws"
enable="true"/>
<point name="RemoteAdministrationOfExchange_2_0_1_6"
alias="RemoteAdministrationOfExchange_2_0_1_6.1cws"
enable="true"/>
<point name="RemoteAdministrationOfExchange_2_1_6_1"
alias="RemoteAdministrationOfExchange_2_1_6_1.1cws"
enable="true"/>
<point name="RemoteControl"
alias="RemoteControl.1cws"
enable="true"/>
<point name="SiteExchange"
alias="ExchangeWithSites.1cws"
enable="true"/>
</ws>

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

Для того, чтобы получить wsdl-файл для сервиса от 1С, в браузере надо написать так:

http://localhost/test/ws/ИмяСервиса?wsdl

В качестве имени введем стандартное «Федоров (администратор)» и получим наш xml.

 

Веб-сервисы опубликованы и дергаются. Дело за малым — использовать дергание в мирных научных целях и заставить 1С выдать в браузер не абстрактный малокомунужный XML, а какой-нибудь не менее абстрактный, но всем понятный пример типа «Hello, World!».

Для этого давайте напишем php-скриптик, который будет дергать наш сервис:

<?php
function Connect1C(){
if (!function_exists('is_soap_fault')){
print 'Не настроен web сервер. Не найден модуль php-soap.';
return false;
}
try {
$Клиент1С = new SoapClient('http://192.168.1.5/test/ws/RemoteControl?wsdl',
array('login'          => 'Федоров (администратор)',
'password'       => '',
'soap_version'   => SOAP_1_2,
'cache_wsdl'     => WSDL_CACHE_NONE, //WSDL_CACHE_MEMORY, //, WSDL_CACHE_NONE, WSDL_CACHE_DISK or WSDL_CACHE_BOTH
'exceptions'     => true,
'trace'          => 1));
}catch(SoapFault $e) {
trigger_error('Ошибка подключения или внутренняя ошибка сервера. Не удалось связаться с базой 1С.', E_ERROR);
}
if (is_soap_fault($Клиент1С)){
trigger_error('Ошибка подключения или внутренняя ошибка сервера. Не удалось связаться с базой 1С.', E_ERROR);
return false;
}
return $Клиент1С;
}

function GetData($idc){
if (is_object($idc)){

try {

$ret1c = $idc->GetCurrentState();

} catch (SoapFault $e) {
echo "Ошибка</br>";
var_dump($e);
var_dump($ret1c);
}
}
else{
echo 'Не удалось подключиться к 1С<br>';
}
return $ret1c;
}

$idc = Connect1C();
$ret1c = GetData($idc);
echo $ret1c->return."<br>
";
?>

Итак, давайте разберемся, что в этом коде что делает. Собственно, здесь определены две функции: Connect1C() — устанавливает соединение с 1С, и GetData() — дергает нужный нам веб-сервис.

Для подключения алгоритм такой:

1. Проверяем, есть ли расширение для SOAP. Если нет — возвращаемся с ошибкой.

2. Создаем объект «SoapClient», и инициализируем его. В качестве аргументов передаем точку входа в наш сервис и ассоциативный массив параметров с логином, паролем, версией SOAP и прочими рюшками.

3. Если не произошло никаких исключений, то возвращаем полученный объект.

Для дергания сервиса алгоритм еще проще:

1. Проверяем, существует ли объект. Если нет — возвращаемся.

2. Дергаем функцию сервиса по имени.

3. Если ошибок на было, то возврашаем результат.

Результат функции содержится в параметре return. В итоге мы просто выводим его на нашу страницу: 

echo $ret1c->return."<br>
";

Вот и весь Hello, world! Остается только в 1С поменять тип возвращаемого параметра для функции GetCurrentState веб-сервиса RemoteControl и вместо Возврат Истина написать Возврат «Hello, World!»:

 

Параметры функций веб-сервисов.

Остается разобраться с вопросом о том, как передавать в функцию веб-сервиса параметры. В принципе достаточно просто:

function GetData($idc){
if (is_object($idc)){

try {
$params["Number"] = $_GET["Number"];
$params["ID"] = $_GET["ID"];
$params["bt"] = $_GET["bt"];
$params["Type"] = $_GET["Type"];
$params["Date"] = $_GET["Date"];

$ret1c = $idc->GetDocument($params);

} catch (SoapFault $e) {
echo "АЩИБКА!!! </br>";
var_dump($e);
var_dump($ret1c);
}
}
else{
echo 'Не удалося подключиться к 1С<br>';
}
return $ret1c;
}

В данном случае я передаю параметры Number, ID, bt, Type и Date в функцию GetDocument одного из вебсервисов, а данные для я беру из формы веб-страницы. Т.е. вебстраница была дернута так: localhost/mtscript.php?Number=1&ID=001&bt=123&Type=001&Date=29.12.2024

В итоге все эти данные будет переданы в функцию вебсервиса.

Приложение для дергания сервисов создадим позднее, когда все проспятся от новогодних хлопот.

 

С новым годом, уважаемые граждане, с новым сервисом!

4 Comments

  1. gigapevt

    «sudo /etc/init.d/apache2 restart» можно заменить на «sudo service apache2 restart». Как то привычнее.

    Reply
  2. starik-2005

    (1) gigapevt, можно и так.

    Reply
  3. Danila-Master

    Поделюсь своим методом «дергать» веб-сервис. В место PHP, я использую HTML+javascript.

    В моей базе есть веб-сервис, куда нужно передать ИИН (Идентификационный индивидуальный номер), а веб-сервис вернет ФИО сотрудника. Вот такой маленький пример.

    Код:

    <html>
    <head>
    <title>SOAP JavaScript Client Test</title>
    <script type=»text/javascript»>
    function soap() {
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.open(‘POST’, ‘http://1c-web/zup/ws/ws1.1cws?GetFIO’, true, ‘<Login>’, ‘<password>’);
    // build SOAP request
    
    var iin = document.getElementById(«iin»).value;
    var sr =
    ‘<soap:Envelope xmlns:soap=»http://www.w3.org/2003/05/soap-envelope» xmlns:zup=»http://1c-web/zup»>’ +
    ‘<soap:Header/>’ +
    ‘<soap:Body>’ +
    ‘<zup:GetFIO>’ +
    ‘<zup:iin>’ + iin + ‘</zup:iin>’ +
    ‘</zup:GetFIO>’ +
    ‘</soap:Body>’ +
    ‘</soap:Envelope>’;
    
    xmlhttp.onreadystatechange = function () {
    if (xmlhttp.readyState == 4) {
    if (xmlhttp.status == 200) {
    //alert(xmlhttp.responseText);
    var memo = document.getElementById(«memo»);
    memo.innerHTML = xmlhttp.responseText;
    }
    }
    }
    // Send the POST request
    xmlhttp.setRequestHeader(‘Content-Type’, ‘text/xml’);
    xmlhttp.setRequestHeader(‘charset’, ‘utf8’);
    xmlhttp.send(sr);
    // send request
    // …
    
    }
    </script>
    </head>
    <body>
    <form name=»Demo» action=»» method=»post»>
    <div>
    ИИН: <INPUT id=»iin» name=»iin»/>
    
    <input type=»button» value=»Soap» onclick=»soap();» />
    <p id=»memo»> </p>
    </div>
    </form>
    </body>
    <html>

    Показать

    В строке

    xmlhttp.open(‘POST’, ‘http://1c-web/zup/ws/ws1.1cws?GetFIO’, true, ‘<Login>’, ‘<password>’);

    можно указать логин и пароль, иначе при каждом запросе будет появлятся системное окно для авторизации.

    Reply
  4. kanyukov

    (3)

    SOAP JavaScript Client Test

    function soap() {

    var xmlhttp = new XMLHttpRequest();

    xmlhttp.open(‘POST’, ‘http://1c-web/zup/ws/ws1.1cws?GetFIO’, true, », »);

    // build SOAP request

    var iin = document.getElementById(«iin»).value;

    var sr =

    » +

    » +

    » +

    » +

    » + iin + » +

    » +

    » +

    »;

    xmlhttp.onreadystatechange = function () {

    if (xmlhttp.readyState == 4) {

    if (xmlhttp.status == 200) {

    //alert(xmlhttp.responseText);

    var memo = document.getElementById(«memo»);

    memo.innerHTML = xmlhttp.responseText;

    }

    }

    }

    // Send the POST request

    xmlhttp.setRequestHeader(‘Content-Type’, ‘text/xml’);

    xmlhttp.setRequestHeader(‘charset’, ‘utf8’);

    xmlhttp.send(sr);

    // send request

    // …

    }

    ИИН:

    Показать

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *