Была поставлена задача – принимать заказы от крупной сети в электронном виде. Сеть работает следующим образом – рассылает всем заказы (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-сервисами, обязательно выложу работающий код.
Удачи вам и не повторяйте чужих ошибок.