Содержание статей: 1С:Предприятие 8. Веб-сервисы
Предыдущая статья: 1С:Предприятие 8. Веб-сервисы. Фасеты как способ ограничить значения данных
Веб-сервисы идеально подходят для обмена данными между различными информационными системами. В этой статье я продемонстрирую, как можно сделать синхронизацию товаров с сайтом на простых примерах. В примерах будет использован язык PHP.
Самым простым случаем является вызов операций веб-сервисов 1С с сайта при необходимости. Например, при открытии сайта можно получить актуальный список товаров и их остатки.
Давайте для примера создадим простенькую базу 1С с одним справочником номенклатура, в котором будут храниться все необходимые данные, включая остатки.
И в этой базе создадим веб-сервис, который будет выдавать список товаров.
На рисунке изображен модуль ws-операции ПолучитьНоменклатуру() и ПакетXDTO, который содержит описание полей выгружаемой номенклатуры. Мы не используем отборы и выгружаем сразу весь список товаров. Более подробное о создании веб-сервисов в среде 1С вы сможете узнать на странице 1С:Предприятие 8. Веб-сервисы. Реализация веб-сервиса.
Для получения списка товаров на стороне сайта будет необходимо вызвать ws-операцию ПолучитьНоменклатуру() веб-сервиса "WebСервис" без параметров. В ответ будет получен массив объектов "Номенклатура" с полями:
Предыдущая статья: 1С:Предприятие 8. Веб-сервисы. Фасеты как способ ограничить значения данных
Веб-сервисы идеально подходят для обмена данными между различными информационными системами. В этой статье я продемонстрирую, как можно сделать синхронизацию товаров с сайтом на простых примерах. В примерах будет использован язык PHP.
Самым простым случаем является вызов операций веб-сервисов 1С с сайта при необходимости. Например, при открытии сайта можно получить актуальный список товаров и их остатки.
Давайте для примера создадим простенькую базу 1С с одним справочником номенклатура, в котором будут храниться все необходимые данные, включая остатки.
И в этой базе создадим веб-сервис, который будет выдавать список товаров.
На рисунке изображен модуль ws-операции ПолучитьНоменклатуру() и ПакетXDTO, который содержит описание полей выгружаемой номенклатуры. Мы не используем отборы и выгружаем сразу весь список товаров. Более подробное о создании веб-сервисов в среде 1С вы сможете узнать на странице 1С:Предприятие 8. Веб-сервисы. Реализация веб-сервиса.
Для получения списка товаров на стороне сайта будет необходимо вызвать ws-операцию ПолучитьНоменклатуру() веб-сервиса "WebСервис" без параметров. В ответ будет получен массив объектов "Номенклатура" с полями:
- УникальныйИдентификатор
- Наименование
- Цена
- Остаток
Поле УникальныйИдентификатор необходимо для однозначного определения товара независимо от наименования.
Для работы с веб-сервисами в PHP существует класс SoapClient. Довольно легко с ним работать. Достаточно в вызове конструктора класса указать путь к WSDL веб-сервиса, логин пароль и уже можно работать. Давайте создадим страничку, например index1.php, и запишем туда следующий код:
<?php
header("Content-Type: text/html; charset=UTF-8");
$SoapClient1C = new SoapClient("http://ghostaz.no-ip.org/sync/ws/WebСервис?wsdl");
$List = $SoapClient1C->ПолучитьНоменклатуру();
if(is_array($List->return->Список ))
{
foreach ( $List->return->Список as $key)
echo $key->УникальныйИдентификатор." ".$key->Наименование." ".$key->Цена." ".$key->Остаток." "."<br>";
} else
echo $List->return->Список->УникальныйИдентификатор." ".$List->return->Список->Наименование." ".$List->return->Список->Цена." ".$List->return->Список->Остаток;
?>
1С работает с UTF-8 потому в первой строке мы указываем кодировку. Далее мы создаем объект $SoapClient1C. ПРи его создании указываем ссылку на WSDL для нашего веб-сервиса. Узнать как формируется строка ссылки можно в статье 1С:Предприятие 8. Веб-сервисы. Публикация и тестирование.
В строке
$List = $SoapClient1C->ПолучитьНоменклатуру();
мы вызываем ws-операцию ПолучитьНоменклатуру(). Результат операции записываем в переменную &List.
Далее мы проверяем является ли этот результат массивом или содержит один элемент. Признаюсь честно, я не знаю почему 1C не выдает массив из одного элемента, а выдает просто объект и не знаю как это изменить. Ведь в таком случае приходится отдельно отрабатывать такой случай. В общем как вы видите, если результат операции является массивом, то код перебирает все элементы и выводит на экран, в противном случае выводит один элемент.
В результате запуска index1.php на экран будет выведено примерно следующее:
c5c291c5-3fe9-11e3-824f-083e8e40aa90 Гайки 120 5
2d490b6d-4f6a-11e3-beaf-28924a4e4c34 Гвозди 145 5
2d490b6d-4f6a-11e3-beaf-28924a4e4c34 Гвозди 145 5
Это список товаров, которые заведены в базе 1С, с наименованием, ценой и количеством.
Этот способ синхронизации малопригоден для рабочих сайтов, так как при каждом открытии сайта или обновлении будет инициировано обращение к базе 1С, что замедлит работу сайта и увеличит трафик. Давайте улучшим текущую схему.
Для вывода на экран актуальных данных совсем не обязательно обращаться к базе 1С так часто, достаточно обратиться за получением остатков в момент их изменения и выводить эти данные до следующего изменения. Таким образом необходимо инициировать синхронизацию лишь в момент изменения данных в базе 1С, а полученные данные хранить на стороне хостинга. Момент, когда происходит изменение данных знает 1С, соответственно только она может инициировать синхронизацию. Для синхронизации она может вызвать какой либо скрипт, который из веб-сервиса получит остатки и запишет их в базу данных. План такой:
- Пользователь меняет справочник Номенклатура;
- Информационная база вызывает скрипт sync.php;
- Скрипт sync.php вызывает ws-операцию ПолучитьНоменклатуру() и помещает результат в таблицу tovar;
- Пользователь запускает index2.php, который выводит содержимое таблицы tovary.
На стороне базы 1С необходимо осуществить вызов скрипта sync.php. Данный вызов будем делать в процедуре ПослеЗаписиНаСервере формы справочника Номенклатура. Это крайне не оптимально, стоит использовать фоновые задания для вызова скриптов.
В данном коде мы используем GET запрос и вызываем скрипт "http://sync.ghostaz.ru/sync.php". Все что скрипт выводит на экран, мы увидим во временном файле. Название файла хранится в переменной "УИ".
Для такой схемы нам нужно иметь базу данных и таблицу. Мы создадим таблицу с четырьмя полями:
- UID CHAR(36)
- Name VARCHAR(25)
- Cena REAL
- Ost REAL
Давайте посмотрим на результируюий код скрипта синхронизации. В комментариях я опишу назначение команд.
<?php
// устанавливаем кодировку
header("Content-Type: text/html; charset=UTF-8");
// создаем подключение к СУБД
$Link = mysql_connect ("localhost", "Логин", "Пароль") ;
// выбираем нужную базу данных
$rv = mysql_select_db("ghostaz", $Link);
// создаем таблицу товары если ее еще нет
mysql_query("CREATE TABLE IF NOT EXISTS tovary (UID CHAR(36) PRIMARY KEY, Name VARCHAR(25), Cena REAL, Ost REAL)");
// очищаем таблицу перед заполнением
mysql_query("DELETE FROM tovary");
// создаем клиент для веб-сервисов и вызываем операцию, которая в $List помещает массив номенклатуры
$SoapClient1C = new SoapClient("http://ghostaz.no-ip.org/sync/ws/WebСервис?wsdl");
$List = $SoapClient1C->ПолучитьНоменклатуру();
// если ws-операция вернула массив
if(is_array($List->return->Список ))
{
// то перебираем весь список
foreach ( $List->return->Список as $key)
// и доавляем номенклатуру в базу
mysql_query("INSERT INTO tovary VALUES ('".$key->УникальныйИдентификатор."', '".$key->Наименование."', ".$key->Цена.", ".$key->Остаток.")");
} else
// если же это не массив, то одно единственное значение вносим в базу
mysql_query("INSERT INTO tovary VALUES ('".$key->return->Список->УникальныйИдентификатор."', '".$key->return->Список->Наименование."', ".$key->return->Список->Цена.", ".$key->return->Список->Остаток.")");
// проверяме что синхронизация прошла - выводим содержимое таблицы
$sql=mysql_query("SELECT * FROM tovary");
while($row = mysql_fetch_array($sql)) echo $row['UID']." ".$row['Name']." ".$row['Cena']." ".$row['Ost'].'<br>';
// закрываем соединение
mysql_close ($Link);
?>
Код файла index2.php может теперь содержать только вывод таблицы:
<?php
// устанавливаем кодировку
header("Content-Type: text/html; charset=UTF-8");
// создаем подключение к СУБД
$Link = mysql_connect ("localhost", "Логин", "Пароль") ;
// выбираем нужную базу данных
$rv = mysql_select_db("ghostaz", $Link);
//выводим содержимое таблицы
$sql=mysql_query("SELECT * FROM tovary");
while($row = mysql_fetch_array($sql)) echo $row['UID']." ".$row['Name']." ".$row['Cena']." ".$row['Ost'].'<br>';
// закрываем соединение
mysql_close ($Link);
?>
От себя добавлю, что данный способ синхронизации отлично работает в коммерческих проектах. Скорость отработки довольно высока. К примеру сложные и большие запросы отрабатываются за 0,2 секунды. Быстрые же запросы к веб-сервису могут заполнить 30 тысяч записей таблицы за 16 секунд.
Владимир! Подскажите, как передать на сайт фотографию из 1С? Какого типа будет этот параметр?
ОтветитьУдалитьЯ вам предлагаю посмотреть код Библиотеки стандартных подсистем. Там есть веб сервис Files. Используется тип File, в котором сами бинарные данные передаются через base64Binary (http://www.w3.org/2001/XMLSchema).
УдалитьСпасибо, Владимир! Посмотрю!
УдалитьУстановила БСП 2.1 - к сожалению не нашла там такого веб-сервиса Files...
УдалитьВ версии 1.2 был.
УдалитьВладимир! Передать картинку через веб-сервис - получилось! Но это работает только когда маленькие картинки. На больших картинках (например 3Мб) выдает ошибку. Веб-сервис сторонней программы. Я из 1С его вызываю и передаю ему картинку.
УдалитьОшибка: {Форма.Синхронизация_ФизЛиц_С_ИС.Форма(203)}: Ошибка при вызове метода контекста (AddPhoto): Ошибка вызова операции сервиса: {www.ххххххххх.ru/}:HRM:AddPhoto(): Ошибка SOAP сервера: Исключение при запуске расширений, указанных в файле конфигурации. ---> Превышена максимальная длина запроса.
Мне говорят, что где-то в 1С нужно увеличить какой-то параметр????
Вопрос: эта ошибка у меня в 1С? Нужно где-то что-то донастроить - чтобы работать с большими файлами? Или эта ошибка в сторонней программе?
Форма.Синхронизация_ФизЛиц_С_ИС.Форма это ваша форма?
УдалитьФайлы объемом более 300кб я не передавал. Ошибки такой не видел. Ошибка возникла на стороне сервера, значит у них. В платформе 1С параметров не встречал.
УдалитьФорма.Синхронизация_ФизЛиц_С_ИС. - да, это моя форма, в ней вызывается сторонний веб-сервис, который возвращает вышеуказанную ошибку.
УдалитьЕще для размышления:
разработчики сторонней программы и этого стороннего веб-сервиса говорят, что у них все работает. И Говорят, что нужно где-то в 1С настроить такой параметр и приводят для примера настройку из другой программы:
в общем смысл такой, что нужно увеличить настройку размера передаваемого значения.
Но они могут ошибаться, т.к. не могут четко объяснить что к чему....
Еще есть такая информация: что нужно поправить настройки web.config:
Инет говорит следующее:
Для исправления этой ситуации следует править следующую строку в Web.config:
110
Красным выделены интересующие нас «максимальная длина запроса» (в килобайтах) и «максимальное время обработки запроса» (в секундах).
Для наиболее полной информации по редактированию данного файла следует смотреть раздел MSDN «Изменение файлов конфигурации ASP.NET» (http://msdn.microsoft.com/ru-ru/library/ackhksh7.aspx).
Я написала свой веб-сервис в 1С, чтобы передать картинку. Вызываю его из SOAPUI - все отрабатывает - возвращает двоичный код картинки.
Что из этого следует? Где все-таки надо настраивать?
Разработчики сторонней программы мне говорят, я где-то в 1С должна установить какой-то параметр больше.
Удалитьдля этого мне приводят пример, как это делается в другой программе:
bindings
basicHttpBinding
binding name="DirectorySoap" maxReceivedMessageSize = "2147483647"
readerQuotas maxArrayLength="2147483647"/
/binding
/basicHttpBinding
/bindings
Это похоже на настройку IIS. Вы его используете? Не пробовали использовать апач?
УдалитьFatal error: Uncaught SoapFault exception: [soap:Client] Неизвестная ошибка. {WebСервис.ПолучитьНомеклатуру.Модуль(27)}: Значение не является значением объектного типа (Добавить) по причине: {WebСервис.ПолучитьНомеклатуру.Модуль(27)}: Значение не является значением объектного типа (Добавить) in C:\inetpub\wwwroot\wsClient\nomen.php:5 Stack trace: #0 C:\inetpub\wwwroot\wsClient\nomen.php(5): SoapClient->__call('\xD0\x9F\xD0\xBE\xD0\xBB\xD1\x83\xD1\x87\xD0\xB8\xD1\x82\xD1...', Array) #1 C:\inetpub\wwwroot\wsClient\nomen.php(5): SoapClient->ПолучитьНоменклатуру() #2 {main} thrown in C:\inetpub\wwwroot\wsClient\nomen.php on line 5
ОтветитьУдалитьУ меня выдается такая ошибка. было бы хорошо если бы расписали какие типы данных принимают свойства и типы пакетов XDTO