gifts2017

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

Опубликовал Sergey Andreev (starik-2005) в раздел Программирование - Инструментарий

О веб-сервисах, апачах и *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>\n";
?>

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

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

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

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

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

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

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

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

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

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

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

Вот и весь 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.2015

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

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

 

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

См. также

PowerTools от 1 000
Подписаться Добавить вознаграждение

Комментарии

1. Vladimir Savelyev (gigapevt) 31.12.15 08:12
"sudo /etc/init.d/apache2 restart" можно заменить на "sudo service apache2 restart". Как то привычнее.
2. Sergey Andreev (starik-2005) 31.12.15 08:58
3. Danil (Danila-Master) 05.01.16 08:35
Поделюсь своим методом "дергать" веб-сервис. В место 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>');
можно указать логин и пароль, иначе при каждом запросе будет появлятся системное окно для авторизации.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа