Подключение к Web-сервису ECOD для обмена документами в формате EDI (провайдер Корус)

06.06.13

Интеграция - WEB-интеграция

Подробное описание подключения из 1С 8.2 к Web-сервису ECOD для одностороннего обмена электронными документами в формате EDI (провайдер Корус).

Скачать файл

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование По подписке [?] Купить один файл
ПодключениеКWebСервисуКорус.epf
.epf 14,63Kb
78
78 Скачать (1 SM) Купить за 1 850 руб.

Была поставлена задача – принимать заказы от крупной сети в электронном виде. Сеть работает следующим образом – рассылает всем заказы (ORDERS) через провайдера Корус в формате EDI, а подтверждений обратно не принимает. Соответственно, обмен идет только в одну сторону. Ну, ещё желательно было сэкономить на модуле сопряжения, который Корус предлагает купить, и коннектиться к ним непосредственно из 1С.

После заполнения всех необходимых бумаг и получения GLN своей организации, наконец–то мне выдали описание формата обмена и способа подключения к Web–сервису.

Уже в процессе работы созрели 2 варианта технической реализации обмена – тот, который рекомендует Корус (по протоколу SOAP) и который позволяет платформа 8.2 (через XDTO). Опишу ОБА способа реализации.

Первый способ (рекомендованный Корусом).

Для обмена через протокол SOAP, необходимо установить Soap Toolkit 3 с сайта Майкрософт. Он может там быть доступен для скачивания в разобранном виде (файлы с расширением .msm), тогда лучше поискать дистрибутив в виде инсталлятора. Также желательно установить финишное обновление SOAPDSK3.0–KB827257–x86.exe, которое лежит на том же Майкрософте, но уже в виде инсталлятора. Для 64-битных систем всё должно тоже штатно установиться. Протокол слегка устаревший, но Корус пока другого не предлагает….

Следующий шаг – добавление сертификатов в файл Cacert.pem из каталога bin программы. На всякий случай, добавил и корневые сертификаты, выданные Thawte, и сертификаты сайта, на котором живёт Web–сервис. Способ добавления сертификатов подробно описан в литературе, не буду на нём заострять внимание.

Пример реально работающего кода:

// Необходимо установить Soap Toolkit 3 и обновление к нему
// В папку bin программы 1С 8.2 добавить отредактированный файл cacert.pem с сертификатами Web-сервиса
//
Процедура ПолучитьЗаказыПокупателяMSSOAP(ДатаНачала, ДатаКонца, Login="Ваш логин", Password="Ваш пароль", Partner_ID="GLN Партнера") Экспорт

   
ИмяСервиса = "https://www.ecod.pl/webserv2/EDIservice.asmx?WSDL";

    Попытка
       
oSOAPClient = Новый COMОбъект("MSSOAP.SoapClient30");
    Исключение
       
#Если Клиент Тогда
       
Сообщить(ОписаниеОшибки());
       
#КонецЕсли
       
Возврат;
    КонецПопытки;

    Попытка
       
Инициализация = oSOAPClient.mssoapinit(ИмяСервиса, "", "", "");
    Исключение
       
#Если Клиент Тогда
       
Сообщить(ОписаниеОшибки());
       
#КонецЕсли
       
Возврат;
    КонецПопытки;

    Попытка
       
Подключение = oSOAPClient.Relationships(Login, Password, "5000");
       
СтрокаХML = Подключение.item(1).text;
       
КодОшибкиПодключения = Подключение.item(0).text;
    Исключение
       
#Если Клиент Тогда
       
Сообщить(ОписаниеОшибки());
       
#КонецЕсли
       
Возврат;
    КонецПопытки;

    Если
КодОшибкиПодключения <> "00000000" Тогда
       
#Если Клиент Тогда
       
Сообщить("Код ошибки подключения = " + КодОшибкиПодключения);
       
#КонецЕсли
       
Возврат;
    КонецЕсли;

   
ДатаНачалаECOD = ПривестиДатуКВидуECOD(ДатаНачала);
   
ДатаКонцаECOD = ПривестиДатуКВидуECOD(ДатаКонца);

   
// Возвращает массив tracking-id документов, доставленных пользователю ECOD
   
Попытка
       
Доставка = oSOAPClient.ListMBEx(Login, Password, Partner_ID, "ORDER", "RU1", "XML", "P",
                       
ДатаНачалаECOD, ДатаКонцаECOD, "", "", "N", "5000");
       
СтрокаДоставки = Доставка.item(1).text;
       
КодОшибкиДоставки = Доставка.item(0).text;
    Исключение
       
#Если Клиент Тогда
       
Сообщить(ОписаниеОшибки());
       
#КонецЕсли
       
Возврат;
    КонецПопытки;

    Если
КодОшибкиДоставки <> "00000000" Тогда
       
#Если Клиент Тогда
       
Сообщить("Код ошибки идентификации документов = " + КодОшибкиДоставки);
       
#КонецЕсли
       
Возврат;
    КонецЕсли;

   
// Теперь соберём массив идентификаторов документов tracking-id
   
МассивИдентификаторов = ПолучитьМассивИдентификаторовДокументовECOD(СтрокаДоставки);

   
// Теперь для каждого идентификатора получим документ
   
Для Каждого Элемент Из МассивИдентификаторов Цикл
        Попытка
           
Документ = oSOAPClient.Receive(Login, Password, Partner_ID, "ORDER", Элемент, "XML", "R", "5000");
           
СтрокаДокументаXML = Документ.item(1).text;
           
КодОшибкиДокументаXML = Документ.item(0).text;
            Если
КодОшибкиДокументаXML <> "00000000" Тогда
               
#Если Клиент Тогда
               
Сообщить("Код ошибки доставки документа " + Элемент + " = " + КодОшибкиДокументаXML);
               
#КонецЕсли
               
Продолжить;
            КонецЕсли;
           
СформироватьЗаказПокупателяECODИзСтрокиXML(СтрокаДокументаXML);
        Исключение
           
#Если Клиент Тогда
           
Сообщить(ОписаниеОшибки());
           
#КонецЕсли
           
Продолжить;
        КонецПопытки;
    КонецЦикла;

КонецПроцедуры

Второй способ (использование возможностей платформы 8.2).

Известно, что 1С 8.2 тоже умеет работать с неродственными ей объектами, для этого нужно использовать объект Фабрика XDTO. В тексте процедуры показан динамический способ создания описания объектов Web–сервиса, подключения к нему и управления входящими документами.

Добавление сертификатов также обязательно и в этом случае.

 

Полный текст кода:

 

Процедура ПолучитьЗаказыПокупателяXDTO(ДатаНачала, ДатаКонца, Login="Ваш логин", Password="Ваш пароль", Partner_ID="GLN Партнера") Экспорт

   
Определение = Новый WSОпределения("https://www.ecod.pl/webserv2/EDIservice.asmx?WSDL");
   
Прокси = Новый WSПрокси(Определение, "http://www.comarch.com/", "EDIWebService", "EDIWebServiceSoap12");

   
Фабрика = Прокси.ФабрикаXDTO;

   
Запрос = Фабрика.Создать(Фабрика.Тип("http://www.comarch.com/", "Relationships"));
   
Запрос.Name = Login;
   
Запрос.Password = Password;
   
Запрос.Timeout = "5000";

   
РезультатRelationships = Прокси.Relationships(Запрос.Name, Запрос.Password, Запрос.Timeout);
   
// Возвращает документ XML, если операция выполнена успешно

   
КодОшибкиПодключения = РезультатRelationships.Res;
    Если
КодОшибкиПодключения <> "00000000" Тогда
       
#Если Клиент Тогда
       
Сообщить("Код ошибки подключения = " + КодОшибкиПодключения);
       
#КонецЕсли
       
Возврат;
    КонецЕсли;

   
Запрос = Фабрика.Создать(Фабрика.Тип("http://www.comarch.com/", "ListMBEx"));
   
Запрос.Name = Login;
   
Запрос.Password = Password;
   
Запрос.PartnerIln = Partner_ID;
   
Запрос.DocumentType = "ORDER";
   
Запрос.DocumentVersion = "RU1";
   
Запрос.DocumentStandard = "XML";
   
Запрос.DocumentTest = "P";
   
Запрос.DateFrom = ПривестиДатуКВидуECOD(ДатаНачала);
   
Запрос.DateTo = ПривестиДатуКВидуECOD(ДатаКонца);
   
Запрос.ItemFrom = "";
   
Запрос.ItemTo = "";
   
Запрос.DocumentStatus = "N";   // Читаем только новые документы
   
Запрос.Timeout = "5000";

   
РезультатListMBEx = Прокси.ListMBEx(Запрос.Name, Запрос.Password, Запрос.PartnerIln, Запрос.DocumentType, Запрос.DocumentVersion,
               
Запрос.DocumentStandard, Запрос.DocumentTest, Запрос.DateFrom, Запрос.DateTo, Запрос.ItemFrom, Запрос.ItemTo,
               
Запрос.DocumentStatus, Запрос.Timeout);

   
КодОшибкиДоставки = РезультатListMBEx.Res;
    Если
КодОшибкиДоставки <> "00000000" Тогда
       
#Если Клиент Тогда
       
Сообщить("Код ошибки идентификации документов = " + КодОшибкиДоставки);
       
#КонецЕсли
       
Возврат;
    КонецЕсли;

   
СтрокаДоставки = РезультатListMBEx.Cnt;
   
// Теперь соберём массив идентификаторов документов tracking-id
   
МассивИдентификаторов = ПолучитьМассивИдентификаторовДокументовECOD(СтрокаДоставки);

   
// Разберем полученные идентификаторы документов
   
Для Каждого Элемент Из МассивИдентификаторов Цикл
       
// А теперь получим файлы заказов из системы
       
Запрос = Фабрика.Создать(Фабрика.Тип("http://www.comarch.com/", "Receive"));
       
Запрос.Name = Login;
       
Запрос.Password = Password;
       
Запрос.PartnerIln = Partner_ID;
       
Запрос.DocumentType = "ORDER";
       
Запрос.TrackingId = Элемент;
       
Запрос.DocumentStandard = "XML";
       
Запрос.ChangeDocumentStatus = "R";   // Меняем статус на прочтённый
       
Запрос.Timeout = "5000";

       
РезультатReceive = Прокси.Receive(Запрос.Name, Запрос.Password, Запрос.PartnerIln, Запрос.DocumentType,
                   
Запрос.TrackingId, Запрос.DocumentStandard, , Запрос.Timeout);

       
КодОшибкиДокументаXML = РезультатReceive.Res;
       
СтрокаДокументаXML = РезультатReceive.Cnt;
        Если
КодОшибкиДокументаXML <> "00000000" Тогда
           
#Если Клиент Тогда
           
Сообщить("Код ошибки доставки документа " + Элемент + " = " + КодОшибкиДокументаXML);
           
#КонецЕсли
           
Продолжить;
        КонецЕсли;
       
СформироватьЗаказПокупателяECODИзСтрокиXML(СтрокаДокументаXML);

       
Запрос = Фабрика.Создать(Фабрика.Тип("http://www.comarch.com/", "ChangeDocumentStatus"));
       
Запрос.Name = Login;
       
Запрос.Password = Password;
       
Запрос.TrackingId = Элемент;
       
Запрос.Status = "R";   // Меняем статус на прочтённый

       
РезультатStatus = Прокси.ChangeDocumentStatus(Запрос.Name, Запрос.Password, Запрос.TrackingId, Запрос.Status);
       
КодОшибкиStatus = РезультатStatus.Res;
        Если
КодОшибкиStatus <> "00000000" Тогда
           
#Если Клиент Тогда
           
Сообщить("Код ошибки изменения статуса документа " + Элемент + " = " + КодОшибкиStatus);
           
#КонецЕсли
       
КонецЕсли;
    КонецЦикла;

КонецПроцедуры

Результат работы обеих процедур абсолютно одинаков - возвращаются документы ORDERS из Web-сервиса. Теперь задача существенно упрощается - необходимо правильно распарсить входной документ в формате XML и создать документы Заказ Покупателя. Для облегчения вашего читательского труда привожу код сервисных процедур чтения строки XML и парсинга. Ну а создать нужный документ в собственной базе из полученной структуры не составит особого труда.

 

// Читает полученную строку XML в формате ECOD (из Web-сервиса)
Процедура СформироватьЗаказПокупателяECODИзСтрокиXML(СтрокаXML, СсылкаНаОбъект = Неопределено) Экспорт

   
Чтение = Новый ЧтениеXML;
   
ДеревоЗначений = Новый ДеревоЗначений();
    Попытка
       
Чтение.УстановитьСтроку(СтрокаXML);
       
Чтение.Прочитать();
    Исключение
       
#Если Клиент Тогда
       
Сообщить("Ошибка при чтении строки XML! " + Символы.ПС + ОписаниеОшибки(), СтатусСообщения.Внимание);
       
#КонецЕсли
       
Чтение.Закрыть();
    КонецПопытки;

   
ДеревоЗначений.Колонки.Добавить("Элемент");
   
ДеревоЗначений.Колонки.Добавить("Текст");
   
Корень         = ДеревоЗначений.Строки.Добавить();
   
Корень.Элемент = Чтение.Имя;
   
Рекурсия(Корень, Чтение);
   
Дерево = ДеревоЗначений;

   
Чтение.Закрыть();

   
СтруктураДокумента = ПолучитьСтруктуруДокумента_ORDER_ECOD(Дерево);
    Если
ТипЗнч(СтруктураДокумента) = Тип("Структура") Тогда
       
ЗаказСсылка = ЗагрузитьСтруктуруВДокументЗаказ(СтруктураДокумента, СсылкаНаОбъект);
        Если
ЗаказСсылка <> Неопределено Тогда
           
СделатьЗаписьВСправочникеЗаказыПокупателяEDI(СтруктураДокумента, ЗаказСсылка);
        КонецЕсли;
    КонецЕсли;

КонецПроцедуры

Процедура
Рекурсия(СтрокаДерева, Чтение)

   
АтрибутыСоответствие = Новый Соответствие();
    Пока
Чтение.ПрочитатьАтрибут() Цикл
       
АтрибутыСоответствие.Вставить(Чтение.Имя, Чтение.Значение);
    КонецЦикла;
    Если
АтрибутыСоответствие.Количество() > 0 Тогда
       
СтрокаДерева.Атрибуты = АтрибутыСоответствие;
    Иначе
       
АтрибутыСоответствие = 0;
    КонецЕсли;
    Пока
Чтение.Прочитать() Цикл
        Если
Чтение.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
            Прервать;
        ИначеЕсли
Чтение.ТипУзла = ТипУзлаXML.Текст Тогда
           
СтрокаДерева.Текст = Чтение.Значение;
        ИначеЕсли
Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
           
Дочерний         = СтрокаДерева.Строки.Добавить();
           
Дочерний.Элемент = Чтение.Имя;
           
Рекурсия(Дочерний, Чтение);
        КонецЕсли;
    КонецЦикла;

КонецПроцедуры

// Получить структуру Заказа Покупателя
Функция ПолучитьСтруктуруДокумента_ORDER_ECOD(Дерево)

   
СтруктураДокумента = Новый Структура;

   
Узел = ПолучитьУзелДерева(Дерево.Строки, "Строка", "Document-Order");
    Если НЕ
Узел = Неопределено Тогда
       
СтрокаКорня = Узел.Строки;
    Иначе
       
#Если Клиент Тогда
       
Сообщить("Файл не является Заказом покупателя!", СтатусСообщения.Важное);
       
#КонецЕсли
       
Возврат Ложь;
    КонецЕсли;

   
// I. Order-Header (из корня)

   
Узел = ПолучитьУзелДерева(СтрокаКорня, "Строка", "Order-Header");
    Если НЕ
Узел = Неопределено Тогда
       
СтрокаДерева = Узел.Строки;
    Иначе
       
#Если Клиент Тогда
       
Сообщить("Не найдена шапка документа!", СтатусСообщения.Важное);
       
#КонецЕсли
       
Возврат Ложь;
    КонецЕсли;

   
// Номер документа
   
xmlНомерДокумента = ПолучитьЗначениеВСтрокеДерева(СтрокаДерева, "OrderNumber", Истина);
    Если НЕ
xmlНомерДокумента = Неопределено Тогда
       
СтруктураДокумента.Вставить("НомерДокумента", СокрЛП(xmlНомерДокумента));
    Иначе
        Возврат Ложь;
    КонецЕсли;

   
//  Дата Документа
   
xmlДатаДокумента = ПолучитьЗначениеВСтрокеДерева(СтрокаДерева, "OrderDate", Истина);
    Если НЕ
xmlДатаДокумента = Неопределено Тогда
       
СтруктураДокумента.Вставить("ДатаДокумента", Дата(Прав(СокрЛП(xmlДатаДокумента),2)+"."+Сред(СокрЛП(xmlДатаДокумента),6,2)+"."+Лев(СокрЛП(xmlДатаДокумента),4)+" 0:00:00"));
    Иначе
        Возврат Ложь;
    КонецЕсли;

   
// Дата Поставки(обязательное поле)
   
xmlДатаПоставки = ПолучитьЗначениеВСтрокеДерева(СтрокаДерева, "ExpectedDeliveryDate", Истина);
    Если НЕ
xmlДатапоставки = Неопределено Тогда
       
ДатаПоставки = Дата(Прав(СокрЛП(xmlДатаПоставки),2)+"."+Сред(СокрЛП(xmlДатаПоставки),6,2)+"."+Лев(СокрЛП(xmlДатаПоставки),4)+" 0:00:00");
       
СтруктураДокумента.Вставить("ДатаПоставки", ДатаПоставки);
    Иначе
        Возврат Ложь;
    КонецЕсли;

   
// Время Поставки(опциональное поле)
   
xmlВремяПоставки = ПолучитьЗначениеВСтрокеДерева(СтрокаДерева, "ExpectedDeliveryTime", Ложь);
    Если НЕ
xmlВремяПоставки = Неопределено Тогда
       
СтруктураДокумента.Вставить("ВремяПоставки", xmlВремяПоставки);
    Иначе
       
СтруктураДокумента.Вставить("ВремяПоставки", "00:00");
    КонецЕсли;

   
// Валюта(UAH,RUB,USD,EUR,MDL,BYR)(опциональное поле)
   
xmlВалюта = ПолучитьЗначениеВСтрокеДерева(СтрокаДерева, "Currency", Ложь);
    Если НЕ
xmlВалюта = Неопределено Тогда
       
СтруктураДокумента.Вставить("Валюта", ПолучитьВалюту(xmlВалюта));
    КонецЕсли;


   
// Обозначение Документа(опциональное поле)
   
xmlОбозначениеДокумента = ПолучитьЗначениеВСтрокеДерева(СтрокаДерева, "DocumentFunctionCode", Ложь);
    Если НЕ
xmlОбозначениеДокумента = Неопределено Тогда
       
СтруктураДокумента.Вставить("ОбозначениеДокумента", СокрЛП(xmlОбозначениеДокумента));
    КонецЕсли;


   
// Свободный текст(опциональное поле)
   
xmlСвободныйТекст = ПолучитьЗначениеВСтрокеДерева(СтрокаДерева, "Remarks", Ложь);
    Если НЕ
xmlСвободныйТекст = Неопределено Тогда
       
СтруктураДокумента.Вставить("СвободныйТекст", СокрЛП(xmlСвободныйТекст));
    КонецЕсли;

   
// II. Order-Summary (из корня)
   
Узел = ПолучитьУзелДерева(СтрокаКорня, "Строка", "Order-Summary");
    Если НЕ
Узел = Неопределено Тогда
       
СтрокаДерева = Узел.Строки;
    Иначе
       
#Если Клиент Тогда
       
Сообщить("Не найдены реквизиты табличной части!", СтатусСообщения.Важное);
       
#КонецЕсли
       
Возврат Ложь;
    КонецЕсли;

   
// Количество Строк(опциональное поле)
   
xmlКоличествоСтрок = ПолучитьЗначениеВСтрокеДерева(СтрокаДерева, "TotalLines", Ложь);
    Если НЕ
xmlКоличествоСтрок = Неопределено Тогда
       
СтруктураДокумента.Вставить("КоличествоСтрок", СокрЛП(xmlКоличествоСтрок));
    КонецЕсли;

   
// Общая Сумма(опциональное поле)
   
xmlОбщаяСумма = ПолучитьЗначениеВСтрокеДерева(СтрокаДерева, "TotalOrderedAmount", Ложь);
    Если НЕ
xmlОбщаяСумма = Неопределено Тогда
       
СтруктураДокумента.Вставить("ОбщаяСумма", СокрЛП(xmlОбщаяСумма));
    КонецЕсли;

   
// III. Order-Parties (из корня)
   
Узел = ПолучитьУзелДерева(СтрокаКорня, "Строка", "Order-Parties");
    Если НЕ
Узел = Неопределено Тогда
       
СтрокаУровня = Узел.Строки;
    Иначе
       
#Если Клиент Тогда
       
Сообщить("Не найдены реквизиты покупателя!", СтатусСообщения.Важное);
       
#КонецЕсли
       
Возврат Ложь;
    КонецЕсли;

   
Узел = ПолучитьУзелДерева(СтрокаУровня, "Строка", "Buyer");
    Если НЕ
Узел = Неопределено Тогда
       
СтрокаДерева = Узел.Строки;
    Иначе
       
#Если Клиент Тогда
       
Сообщить("Не найдены реквизиты покупателя!", СтатусСообщения.Важное);
       
#КонецЕсли
       
Возврат Ложь;
    КонецЕсли;

   
// Поставщик(Организация)(обязательное поле)
   
xmlПоставщикGLN = ПолучитьЗначениеВСтрокеДерева(СтрокаДерева, "ILN", Истина);
    Если НЕ
xmlПоставщикGLN = Неопределено Тогда
       
СтруктураДокумента.Вставить("ПоставщикGLN", СокрЛП(xmlПоставщикGLN));
    КонецЕсли;

   
Узел = ПолучитьУзелДерева(СтрокаУровня, "Строка", "Seller");
    Если НЕ
Узел = Неопределено Тогда
       
СтрокаДерева = Узел.Строки;
    Иначе
       
#Если Клиент Тогда
       
Сообщить("Не найдены реквизиты продавца!", СтатусСообщения.Важное);
       
#КонецЕсли
       
Возврат Ложь;
    КонецЕсли;

   
// Покупатель(контрагент)(обязательное поле)
   
xmlКонтрагентGLN = ПолучитьЗначениеВСтрокеДерева(СтрокаДерева, "ILN", Истина);
    Если НЕ
xmlКонтрагентGLN = Неопределено Тогда
       
СтруктураДокумента.Вставить("КонтрагентGLN", СокрЛП(xmlКонтрагентGLN));
    КонецЕсли;

   
xmlКонтрагентКод = ПолучитьЗначениеВСтрокеДерева(СтрокаДерева, "CodeByBuyer", Истина);
    Если НЕ
xmlКонтрагентКод = Неопределено Тогда
       
СтруктураДокумента.Вставить("КонтрагентКод", СокрЛП(xmlКонтрагентКод));
    КонецЕсли;

   
Узел = ПолучитьУзелДерева(СтрокаУровня, "Строка", "DeliveryPoint");
    Если НЕ
Узел = Неопределено Тогда
       
СтрокаДерева = Узел.Строки;
    Иначе
       
#Если Клиент Тогда
       
Сообщить("Не найдены реквизиты точки доставки!", СтатусСообщения.Важное);
       
#КонецЕсли
       
Возврат Ложь;
    КонецЕсли;

   
// Точка доставки (ДоговорКонтрагента)(опциональное поле)
   
xmlТочкаДоставкиGLN = ПолучитьЗначениеВСтрокеДерева(СтрокаДерева, "ILN", Ложь);
    Если НЕ
xmlТочкаДоставкиGLN = Неопределено Тогда
       
СтруктураДокумента.Вставить("ТочкаДоставкиGLN", СокрЛП(xmlТочкаДоставкиGLN));
    КонецЕсли;

   
// IV. Табличная часть
    // Order-Lines (из корня)
   
Узел = ПолучитьУзелДерева(СтрокаКорня, "Строка", "Order-Lines");
    Если НЕ
Узел = Неопределено Тогда
       
СтрокаУровня = Узел.Строки;
    Иначе
       
#Если Клиент Тогда
       
Сообщить("Не найдена табличная часть!", СтатусСообщения.Важное);
       
#КонецЕсли
       
Возврат Ложь;
    КонецЕсли;

   
// Создаем таблицуЗначений, в которую выгружаем табличную часть документа
   
ДокументТЧ = Новый ТаблицаЗначений;
   
ДокументТЧ.Колонки.Добавить("НомерСтрокиТЧ");
   
ДокументТЧ.Колонки.Добавить("ШтрихКод");
   
ДокументТЧ.Колонки.Добавить("КодПокупателя");
   
ДокументТЧ.Колонки.Добавить("НоменклатураНаименование");
   
ДокументТЧ.Колонки.Добавить("Количество");
   
ДокументТЧ.Колонки.Добавить("Цена");
   
ДокументТЧ.Колонки.Добавить("Сумма");
   
ДокументТЧ.Колонки.Добавить("Коэффициент");

   
ТабличнаяЧасть = ПолучитьУзелДерева(СтрокаУровня, "Массив", "Line");

    Для Каждого
Узел ИЗ ТабличнаяЧасть Цикл

        Если НЕ
Узел = Неопределено Тогда
           
СтрокаДерева = Узел.Строки;
        Иначе
           
#Если Клиент Тогда
           
Сообщить("Не найдены строки табличной части!", СтатусСообщения.Важное);
           
#КонецЕсли
           
Возврат Ложь;
        КонецЕсли;

       
Узел = ПолучитьУзелДерева(СтрокаДерева, "Строка", "Line-Item");

        Если НЕ
Узел = Неопределено Тогда
           
СтрокаДерева = Узел.Строки;
        Иначе
           
#Если Клиент Тогда
           
Сообщить("Не найдена строка табличной части!", СтатусСообщения.Важное);
           
#КонецЕсли
           
Продолжить;
        КонецЕсли;

       
НоваяСтрокаТЧ = ДокументТЧ.Добавить();

       
//Номер строки (этот параметр при создании заказа не используется, может быть проверочным)
       
xmlНомерСтрокиТЧ = ПолучитьЗначениеВСтрокеДерева(СтрокаДерева, "LineNumber", Истина);
        Если НЕ
xmlНомерСтрокиТЧ = Неопределено Тогда
           
НоваяСтрокаТЧ.НомерСтрокиТЧ = xmlНомерСтрокиТЧ;
        КонецЕсли;

       
// Определяем атрибуты номенклатуры:
        // Штрих - код номенклатуры
       
xmlШтрихКодНоменклатуры = ПолучитьЗначениеВСтрокеДерева(СтрокаДерева, "EAN", Истина);
        Если НЕ
xmlШтрихКодНоменклатуры = Неопределено Тогда
           
НоваяСтрокаТЧ.ШтрихКод = СокрЛП(xmlШтрихКодНоменклатуры);
        КонецЕсли;

       
// Код поставщика(поле поиска)
       
xmlКодПокупателя = ПолучитьЗначениеВСтрокеДерева(СтрокаДерева, "BuyerItemCode", Ложь);
        Если НЕ
xmlКодПокупателя = Неопределено Тогда
           
НоваяСтрокаТЧ.КодПокупателя = СокрЛП(xmlКодПокупателя);
        КонецЕсли;

       
// Наименование номенклатуры(опциональное поле)
       
xmlНоменклатураНаименование = ПолучитьЗначениеВСтрокеДерева(СтрокаДерева, "ItemDescription", Ложь);
        Если НЕ
xmlНоменклатураНаименование = Неопределено Тогда
           
НоваяСтрокаТЧ.НоменклатураНаименование = СокрЛП(xmlНоменклатураНаименование);
        КонецЕсли;

       
xmlКоличество = ПолучитьЗначениеВСтрокеДерева(СтрокаДерева, "OrderedQuantity", Истина);
        Если НЕ
xmlКоличество = Неопределено Тогда
            Попытка
               
НоваяСтрокаТЧ.Количество = Число(xmlКоличество);
            Исключение
               
#Если Клиент Тогда
               
Сообщить("Не определил количество!", СтатусСообщения.Важное);
               
#КонецЕсли
               
НоваяСтрокаТЧ.Количество = 0;
            КонецПопытки;
        КонецЕсли;

       
// Единицы измерения количества(опциональное поле)
       
xmlЦена = ПолучитьЗначениеВСтрокеДерева(СтрокаДерева, "OrderedUnitGrossPrice", Ложь);
        Если НЕ
xmlЦена = Неопределено Тогда
           
НоваяСтрокаТЧ.Цена = Число(xmlЦена);
        КонецЕсли;

       
// Сумма
       
xmlСумма = ПолучитьЗначениеВСтрокеДерева(СтрокаДерева, "GrossAmount", Ложь);
        Если НЕ
xmlЦена = Неопределено Тогда
           
НоваяСтрокаТЧ.Сумма = Число(xmlСумма);
        КонецЕсли;

       
НоваяСтрокаТЧ.Коэффициент = 1;

    КонецЦикла;

   
СтруктураДокумента.Вставить("ДокументТЧ", ДокументТЧ);

    Возврат
СтруктураДокумента;

КонецФункции

Функция
ПолучитьУзелДерева(СтрокаДерева, ТипУзла, ИмяПоля)

    Если
ТипУзла = "Строка" Тогда
       
xmlУзел = СтрокаДерева.Найти(ИмяПоля, "Элемент", Ложь);
    ИначеЕсли
ТипУзла = "Массив" Тогда
       
xmlУзел = СтрокаДерева.НайтиСтроки(Новый Структура("Элемент", ИмяПоля), Ложь);
    Иначе
       
xmlУзел = Неопределено;
    КонецЕсли;

    Возврат
xmlУзел;

КонецФункции

Функция
ПолучитьЗначениеВСтрокеДерева(СтрокаДерева, ИмяПоля, Обязательное)

   
xmlЗначение = СтрокаДерева.Найти(ИмяПоля, "Элемент", Ложь);

    Если
xmlЗначение = Неопределено Тогда

        Если
Обязательное Тогда
           
#Если Клиент Тогда
           
Сообщить("В файле не найдено обязательное поле """ + ИмяПоля + """", СтатусСообщения.ОченьВажное);
           
#КонецЕсли
       
КонецЕсли;

        Возврат Неопределено;

    Иначе

       
ТекстовоеЗначение = xmlЗначение.Текст;

        Если Не
ЗначениеЗаполнено(ТекстовоеЗначение) Тогда

            Если
Обязательное Тогда
               
#Если Клиент Тогда
               
Сообщить("Не заполнено обязательное поле """ + ИмяПоля + """", СтатусСообщения.Важное);
               
#КонецЕсли
           
КонецЕсли;

            Возврат Неопределено;

        Иначе

            Возврат
ТекстовоеЗначение;

        КонецЕсли;

    КонецЕсли;

КонецФункции

Функция
ПолучитьВалюту(xmlВалюта)

    Если
xmlВалюта = "UAH" Тогда
        Возврат
Справочники.Валюты.НайтиПоКоду(980);
    ИначеЕсли
xmlВалюта = "RUB" или xmlВалюта = "0" Тогда
        Возврат
Справочники.Валюты.НайтиПоКоду(643);
    ИначеЕсли
xmlВалюта = "USD" Тогда
        Возврат
Справочники.Валюты.НайтиПоКоду(840);
    ИначеЕсли
xmlВалюта = "EUR" Тогда
        Возврат
Справочники.Валюты.НайтиПоКоду(978);
    ИначеЕсли
xmlВалюта = "MDL" Тогда
        Возврат
Справочники.Валюты.НайтиПоКоду(498);
    ИначеЕсли
xmlВалюта = "BYR" Тогда
        Возврат
Справочники.Валюты.НайтиПоКоду(974);
    ИначеЕсли
xmlВалюта = "KZT" Тогда
        Возврат
Справочники.Валюты.НайтиПоКоду(398);
    Иначе
        Возврат
Справочники.Валюты.ПустаяСсылка();
    КонецЕсли;

КонецФункции

Функция ПривестиДатуКВидуECOD(ВходящаяДата) Экспорт

    Возврат
Формат(ВходящаяДата, "ДФ=""гггг-ММ-дд""");

КонецФункции

Функция ПолучитьМассивИдентификаторовДокументовECOD(СтрокаХML) Экспорт

   
МассивИдентификаторов = Новый Массив;

   
Чтение = Новый ЧтениеXML;
   
Чтение.УстановитьСтроку(СтрокаХML);
    Пока
Чтение.Прочитать() Цикл
       
ИмяУзла = Чтение.Имя;
        Если
ИмяУзла <> "tracking-id" Тогда  // Пропускаем все узлы, кроме tracking-id
           
Продолжить;
        КонецЕсли;
        Если
ИмяУзла = "tracking-id" Тогда
           
Чтение.Прочитать();
            Если
Чтение.ТипУзла = ТипУзлаXML.Текст Тогда
               
МассивИдентификаторов.Добавить(Чтение.Значение);
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
    Возврат
МассивИдентификаторов;

КонецФункции

Хочу заметить, что хотя формат EDI и является стандартом электронного документооборота, однако форматы одинаковых документов у разных провайдеров могут существенно отличаться (казалось бы должны быть одинаковы - ан нет, разные у Коруса и Эксайта например). Так что этот формат обмена тоже не универсален......

Вот, собственно, и всё...

Если буду делать двусторонний обмен с Web-сервисами, обязательно выложу работающий код.

Удачи вам и не повторяйте чужих ошибок.

 

См. также

Сайты и интернет-магазины WEB-интеграция Системный администратор Программист Пользователь Платформа 1С v8.3 Конфигурации 1cv8 1С:Управление торговлей 11 Автомобили, автосервисы Россия Управленческий учет Платные (руб)

Интеграционный модуль обмена между конфигурацией Альфа Авто 5 и Альфа Авто 6 и порталом AUTOCRM. Данный модуль универсален. Позволяет работать с несколькими обменами AUTOCRM разных брендов в одной информационной базе в ручном и автоматическом режиме.

36000 руб.

03.08.2020    17782    19    22    

16

Сайты и интернет-магазины Интеграция WEB-интеграция Платформа 1С v8.3 Конфигурации 1cv8 Управленческий учет Платные (руб)

Интеграция 1С и Битрикс 24. Разработка имеет двухстороннюю синхронизацию 1С и Bitrix24 задачами. Решение позволяет создавать пользователя в 1С из Битрикс24 и наоборот. Данная разработка технически подходит под все основные конфигурации линейки продуктов 1С:Предприятие 8.3 (платформа начиная с 8.3.23). При приобретении предоставляется 1 месяц бесплатных обновлений разработки. Доступна демо-версия продукта с подключением Вашего Битрикс24

5040 руб.

04.05.2021    19848    13    17    

16

WEB-интеграция 8.3.8 Конфигурации 1cv8 Автомобили, автосервисы Беларусь Украина Россия Казахстан Управленческий учет Платные (руб)

Расширение предназначено для конфигурации "1С:Предприятие 8. Управление Автотранспортом. ПРОФ". Функционал модуля: 1. Заполнение регистров сведений по подсистеме "Мониторинг", а именно: события по мониторингу, координаты по мониторингу, пробег и расход по мониторингу, текущее местоположение ТС по мониторингу 2. Заполнение путевого листа: пробег по мониторингу, время выезда/заезда, табличная часть ГСМ, места стоянок по геозонам. 3. Отчеты по данным загруженным в регистры сведений. 4. Предусмотрена автоматическая загрузка данных в фоновом режиме (условия работы данной загрузке читайте в описании товара) Модуль работает без включенной константы по настройкам мониторинга. Модуль формы предоставляется с открытым кодом, общий модуль защищен. Любой заинтересованный пользователь, имеет возможность скачать демо-версию расширения.

22656 руб.

25.05.2021    14422    42    8    

18

WEB-интеграция Программист Руководитель проекта Платформа 1С v8.3 Конфигурации 1cv8 1С:Франчайзи, автоматизация бизнеса Платные (руб)

Расширение значительно упрощает написание API на 1С. Веб программисты получают простой и понятный доступ к 1С. Описание API создаётся автоматически и представляется в виде удобном как для человека, так и для программной обработки.

24000 руб.

27.09.2024    1172    1    0    

3
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Alex_Japanese_Student 457 06.06.13 19:39 Сейчас в теме
доводилось с корусом работать, через их интерфейс и с их обработками. В целом работало все, один раз понять и настроить, а дальше все было гуд
2. aspirator23 339 16.06.13 16:39 Сейчас в теме
К сожалению сколько провайдеров столько форматов. Метро работает по другому, Гиперглобус по третьему.
Уж лучше 1с формат для обмена документами.
3. miroha 27.10.13 18:04 Сейчас в теме
Нас тоже крупный покупатель обязал перейти на EDI рекомендовал корус. Сначала был шок, зачем платить за каждый отправленный документ? ведь полно способов сделать это бесплатно. Для нас это сумма сотни тысяч рублей, причем сервера корус не всегда доступны и являлись узким местом в нашем обмене.

Купили у них пакет с внедрением, в итоге внедряли все сами и полностью переписали их программу для хранения данные в базе, а не файловой помойке, которая в их конфигурации тормозит. Техническая поддержка ужасная, специалисты плохо разбираться в конфигурации и все сводиться к пустой болтовне в почте между менеджерами, руководителями и программистами. Когда разобрались в принципах обмена перешли на другого более доступного по ценам провайдера. Дешевле всего стать самому провайдером или найти другой способ обмена.
msvd; gfoods; Dilovar9; partner1c; +4 Ответить
4. MICK77 15 20.12.13 18:29 Сейчас в теме
(3) miroha, Если не великая тайна и не в качестве рекламы на кого перешли? А то тоже выбираем сейчас из 4-х.
5. 10ra 06.05.14 15:30 Сейчас в теме
этот кусок кода лишний т.к. уже поменяли статус при получении XML (Receive...Запрос.ChangeDocumentStatus = "R";)
        
        Запрос = Фабрика.Создать(Фабрика.Тип("http://www.comarch.com/", "ChangeDocumentStatus"));
        Запрос.Name = Login;
        Запрос.Password = Password;
        Запрос.TrackingId = Элемент;
        Запрос.Status = "R";   // Меняем статус на прочтённый

        РезультатStatus = Прокси.ChangeDocumentStatus(Запрос.Name, Запрос.Password, Запрос.TrackingId, Запрос.Status);
        КодОшибкиStatus = РезультатStatus.Res;
        Если КодОшибкиStatus <> "00000000" Тогда
            #Если Клиент Тогда
            Сообщить("Код ошибки изменения статуса документа " + Элемент + " = " + КодОшибкиStatus);
            #КонецЕсли
        КонецЕсли;
Показать


+ почитать Техническая спецификация EDIservice
Прикрепленные файлы:
ws-edi.doc
6. vbelyaev 03.08.14 14:56 Сейчас в теме
Товарищи, меня чё-т в гугле забанили походу. Не могу найти как добавить сертификаты в cacert.pem.

Пните в нужном направлении пожалуйста)))
21. bobo93 06.10.16 12:56 Сейчас в теме
(6) vbelyaev,
Здравствуйте.
Вы не розобрались с вопросом?

"Товарищи, меня чё-т в гугле забанили походу. Не могу найти как добавить сертификаты в cacert.pem.

Пните в нужном направлении пожалуйста)))"
7. Ulus 293 10.09.14 06:33 Сейчас в теме
Хорошая статья.
Грамотно!

8. Ulus 293 10.09.14 06:38 Сейчас в теме
А мы взяли Адаптер 1С от коруса.
начали внедрять.
Но оказалось, что в серийном Адаптере нету документа "Приложение к уведомлению об отгрузки".
Это новый документ, для поставщиков алкогольной продукции.
И все ... Корус нас завтраками кормит. В службу поддержки, вставайте в очереь и.т.п.
Ужасный сервис у них.
Сейчас пробую стрести с них формат файла этого электронного документа.
Сделаем сами.

P.s. кому интересно рекомендую Е-Ком. Четко, быстро, качественно. Не реклама. Просто работаем с несколькими провайдерами.
10. Antonio 7 03.02.15 12:50 Сейчас в теме
(8) Ulus, позвольте спросить как организовывали обмен с несколькими провайдерами? Сейчас тоже оптимизируем затраты на провайдеров, и возникла необходимость использовать несколько провайдеров.
9. Pim 186 10.01.15 16:48 Сейчас в теме
Никто не делал обратную выгрузку (выгрузку подтверждений) на сайт?
11. itcmsch71 08.07.15 05:21 Сейчас в теме
Спасибо Вам большое - статья очень помогла
Вначале пользовались адаптером Коруса (купили пакет с внедрением) - но после некоторого времени общения с ними - нервы не выдержали - стряс с них пакет спецификаций и оттолкнувшись от статьи написал свой обмен - причем теперь работаем без участия операторов - те только оформляют первичные документы.
Если кому интересно - могу отдать.......
Да, еще - установка сертификатов не понадобилась......
Так работает
Shooroopik111; asrgroup; Oleg_Anat; Pipapalamm; gfoods; +5 Ответить
12. gfoods 11.07.15 12:28 Сейчас в теме
(11) itcmsch71,
Было бы очень любопытно посмотреть Вашу работу. Сам готовлюсь уйти от *%^#нутого Коруса, сил нет больше их поделками пользоваться.
Если готовы показать, то пришлите ссылку в личку.
Спасибо.
13. binex 279 20.07.15 18:05 Сейчас в теме
(11) itcmsch71, поясните пожалуйста, что значит "теперь работаем без участия операторов"?
Какие сообщения внедрили?
15. Pipapalamm 25.11.15 11:08 Сейчас в теме
(11) itcmsch71, Очень хотелось бы посмотреть на ваш обмен. Сам обдумываю уход от Корусовских "Адаптер+Коннектор".
Буду очень благодарен за конфигурацию.
Заранее спасибо!
16. Oleg_Anat 01.12.15 09:50 Сейчас в теме
(11) itcmsch71, очень заинтересовал сделанный вами обмен. Мы сейчас только начинаем работать с этой системой, вот обдумываю варианты передачи данных. Вариант корусовских адаптера и коннектора - теперь не рассматриваю - после прочтения отзывов в данной статье об их техподдержке и сервисе. Если можете поделится вашей разработкой - буду очень благодарен, заранее огромное спасибо!
17. serg1785 18.04.16 12:40 Сейчас в теме
(11) itcmsch71, заинтересовала ваша разработка - если есть возможность - поделитесь. Спасибо!
20. bsv69 24.08.16 14:41 Сейчас в теме
(11) itcmsch71, Добрый день. Если можно, вышлите обработку обмена. Спасибо.
23. Shooroopik111 132 20.09.17 17:37 Сейчас в теме
24. taasha25 13 06.03.18 16:04 Сейчас в теме
(11) Здравствуйте! Буду благодарна, если поделитесь разработкой. Спасибо!
25. taasha25 13 28.04.18 09:00 Сейчас в теме
(11) Здравствуйте! Можете поделиться обработкой выгрузки Приложения к уведомлению об отгрузке? Заранее спасибо!
14. АЛьФ 10.09.15 14:53 Сейчас в теме
На попытке сменить статус документа отваливается с ошибкой:

Результат = ПолучитьСОАП().ChangeDocumentStatus(
{W:\...\EDI.ERT(358)}: Client: Client:Incorrect number of parameters supplied for SOAP request HRESULT=0x80070057: Параметр задан неверно.
 - Client:Unspecified client error. HRESULT=0x80070057: Параметр задан неверно.


Кто-нибудь сталкивался? Я чего-то недопонял или проблема на их стороне?

Ой, чуть не забыл.

Вызов такой:

	Результат = ПолучитьСОАП().ChangeDocumentStatus(
								Идентификатор,
								Пароль,
								тзДокументы.идДокумента,
								НовыйСтатусДокумента);
18. katanovich 17.06.16 16:07 Сейчас в теме
Добрый день!
Выдает во втором варианте:
КодОшибкиПодключения = 000000001.
Логин/Пароль верные. Где можно посмотреть расшифровку ошибки?
19. asrgroup 20.06.16 09:47 Сейчас в теме
Неправильный пароль или логин. Логин надо брать из настроек ТТКонектора (обычно GLN + "ЕС")
22. кольщик 29.04.17 10:28 Сейчас в теме
А для 1с 7.7 есть какое-нибудь похожее описание??
26. Teut_Vlad 191 04.09.18 15:51 Сейчас в теме
Что за НайтиОбъектПоЗначениюСвойства?
Оставьте свое сообщение