Тем, кто хочет срезать путь:
С наступающим, коллеги!
Как, наверное, многим уже известно, разработчики ЕГАИС взяли на себя только серверную часть системы и транспортную службу (УТМ), переложив значительную часть работы по разработке клиентской части ЕГАИС на организации оптовой и розничной торговли алкоголем.
Практика покажет, как разработчики справились со своей частью системы. Форум информационного портала ЕГАИС http://egais2016.ru/forum/ переполнен темами о проблемах с УТМ и серверной частью ЕГАИС.
В целом же, в совокупности с клиентской частью, разрабатываемой разношерстной ордой штатных программистов организаций алкогольной отрасли, а также коммерческими решениями разного уровня качества, от системы ЕГАИС сложно ожидать качественного результата.
Вам повезет, если служба УТМ с первого раза установится и заработает. ПО бесплатное, но шаманский бубен для танцев с ним уже за ваш счет. Техподержка со стороны разработчика ЕГАИС (ФГУП "ЦентрИнформ") оказывается в недостаточном объеме, фактически её нет.
Документация доступна в личном кабинете на сайте egais.ru, для доступа в который необходим крипто-ключ. Но интернет не без добрых людей, и вот она у вас в руках. Подвох в том, что документацией назвать этот сборник примеров можно лишь с большой натяжкой. Отсутствует самое необходимое - описание форматов обмена, структуры полей, правил их заполнения. Разработка интеграции по приведенным примерам xml запросов больше похоже на игру "угадайка", чем на разработку интеграции по техзаданию.
Методом "научного тыка" за истекший квартал было выявлено множество "подводных камней" при интеграции с УТМ ЕГАИС, итак...
Специфический формат http запроса к УТМ
УТМ не принимает xml объекты в http запросе так, как это делают "нормальные веб-сервисы". Т.е. запрос к примеру HttpRequest.Send(XMLobject) не будет принят веб-сервисом.
При детальном анализе приведенных в документации примеров работы утилиты curl выяснилось, что xml запрос отправляется файлом, вложенным в тело http запроса. Получить детали отправки запроса утилитой curl можно с помощью параметров -v и --trace-ascii
C:\Users\Palmer>d:\curl\curl -F "xml_file=@d:\curl\rests.xml" http://localhost:8080/opt/in/QueryRests -v
* About to connect() to localhost port 8080 (#0)
* Trying localhost...
* Adding handle: conn: 0x981460
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x981460) send_pipe: 1, recv_pipe: 0
* Connected to localhost port 8080 (#0)
> POST /opt/in/QueryRests HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:8080
> Accept: */*
> Content-Length: 578
> Expect: 100-continue
> Content-Type: multipart/form-data; boundary=----------------------------8d32aca7ce7b
>
< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
< Content-Type: text/xml;charset=UTF-8
< Content-Length: 261
* Server Jetty(8.1.14.v20131031) is not blacklisted
< Server: Jetty(8.1.14.v20131031)
<
<?xml version="1.0" encoding="UTF-8" standalone="no"?><A><url>f541c64f-85fb-4e8d-8c29-9d604aaf451b</url><sign>7D75C3A62F
DBE2740AE8EC695008DF27FFA8F1258D8101A5B962370086892772B2573C5C4C6D7E1D15A6EC0E383EDE432C11F63F8976BD17052401EF3B9D5CD3</
sign><ver>2</ver></A>* Connection #0 to host localhost left intact
boundary - это случайным образом сгененерированный разделитель, которые обрамляет вложение
d:\curl\curl -F "xml_file=@d:\curl\rests.xml" http://localhost:8080/opt/in/QueryRests --trace-ascii d:\curl\trace.txt
== Info: About to connect() to localhost port 8080 (#0)
== Info: Trying localhost...
== Info: Adding handle: conn: 0x4a1508
== Info: Adding handle: send: 0
== Info: Adding handle: recv: 0
== Info: Curl_addHandleToPipeline: length: 1
== Info: - Conn 0 (0x4a1508) send_pipe: 1, recv_pipe: 0
== Info: Connected to localhost (localhost) port 8080 (#0)
=> Send header, 228 bytes (0xe4)
0000: POST /opt/in/QueryRests HTTP/1.1
0022: User-Agent: curl/7.30.0
003b: Host: localhost:8080
0054: Accept: */*
0061: Content-Length: 578
0076: Expect: 100-continue
008c: Content-Type: multipart/form-data; boundary=--------------------
00cc: --------83e52bad6452
00e2:
<= Recv header, 23 bytes (0x17)
0000: HTTP/1.1 100 Continue
=> Send data, 148 bytes (0x94)
0000: ------------------------------83e52bad6452
002c: Content-Disposition: form-data; name="xml_file"; filename="rests
006c: .xml"
0073: Content-Type: application/xml
0092:
=> Send data, 382 bytes (0x17e)
0000: ...<?xml version="1.0" encoding="UTF-8"?>
002b: <ns:Documents Version="1.0"
0048: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
007f: xmlns:ns="http://fsrar.ru/WEGAIS/WB_DOC_SINGLE_01"
00b3: xmlns:qp="http://fsrar.ru/WEGAIS/QueryParameters">....
00eb: <ns:Owner>
00f7: <ns:FSRAR_ID>030000000000</ns:FSRAR_ID>
0120: </ns:Owner>
012d: <ns:Document>
013c: <ns:QueryRests>
014d: </ns:QueryRests>
015f: </ns:Document>
016f: </ns:Documents>
=> Send data, 48 bytes (0x30)
0000:
0002: ------------------------------83e52bad6452--
<= Recv header, 17 bytes (0x11)
0000: HTTP/1.1 200 OK
<= Recv header, 38 bytes (0x26)
0000: Content-Type: text/xml;charset=UTF-8
<= Recv header, 21 bytes (0x15)
0000: Content-Length: 261
== Info: Server Jetty(8.1.14.v20131031) is not blacklisted
<= Recv header, 33 bytes (0x21)
0000: Server: Jetty(8.1.14.v20131031)
<= Recv header, 2 bytes (0x2)
0000:
<= Recv data, 261 bytes (0x105)
0000: <?xml version="1.0" encoding="UTF-8" standalone="no"?><A><url>ec
0040: 24fa9c-9f50-4383-b8bb-f2f76ccac7e5</url><sign>F7593B4E7742DA4C8A
0080: A8E393B99D5AB06BFE86757C38DAC31E81514D3175ED06BCC86069CF06732856
00c0: 4B30651DBE97ABB5EC109C7BBA378BA559585BB47ABE90</sign><ver>2</ver
0100: ></A>
== Info: Connection #0 to host localhost left intact
Причем xml ответы на запросы УТМ возвращает уже нормальным способом, и с ними можно сразу работать как с xml объектами класса MSXML.DOMDocument.
Решение
Пример рабочего алгоритма формирования http запроса к УТМ на платформе 1С 7.7
Пример рабочего алгоритма формирования http запроса к УТМ на платформе 1С 8
УТМ не дружит с кириллицей
В ответах на ошибочные запросы (а у вас при отладке интеграции они будут), содержащие описание ошибки, вместо символов кириллицы отображаются ?????.
Решение
Найти описание ошибки в нормальной кодировке можно в логах УТМ:
C:\TT\transporter\logs\transport_info.log
C:\TT\transporter\logs\transport_error.log
Схема работы ЕГАИС
На информационном портале ЕГАИС приведена следующая схема работы ЕГАИС:
Однако производители и импортеры работают в "старом" ЕГАИС, который с "новым" ЕГАИС полностью так и не состыковали. Схема работы с ними полностью не реализована, и вероятно по факту выглядит так:
Решение
Учесть в своих алгоритмах обмена данными с УТМ, что от производителя/импортера не нужно ждать подтверждения на акт расхождений. Вместо него от сервера ЕГАИС сразу приходит квитанция о том, что ТТН проведена.
Нумерация ТТН
По этой же причине в ТТН от производителей/импортеров не соблюдается уникальность нумерации ТТН. По одной бумажной ТТН от производителя через ЕГАИС может прийти несколько электронных под одним номером, например в разбивке на импортный и отечественный товар. Остальным же система не даст отправить еще раз ТТН с тем же номером и датой.
Решение
Нумерацию загруженных ТТН нужно вести по уникальному идентификатору в системе ЕГАИС (тег wbr:WBRegId в FORMBREGINFO)
Двухкомпонентный формат ТТН
Каждая ТТН приходит парой xml файлов, WAYBILL и FORMBREGINFO. И в них нет идентификатора, по которому их было бы можно сопоставить друг другу.
Идентификатор ТТН есть только в FORMBREGINFO, в WAYBILL его нет. В обоих есть тег identity, но он не обязателен к заполнению, поэтому не подходит на эту роль.
Решение
Однозначное сопоставление достигается по составному ключу: номер ТТН + дата ТТН + идентификатор грузоотправителя + identity
Составной ключ для WAYBILL: wb:NUMBER + wb:Date + wb:Shipper/oref:ClientRegId + wb:Identity
Составной ключ для FORMBREGINFO: wbr:WBNUMBER + wbr:WBDate + wbr:Shipper/oref:ClientRegId + wbr:Identity
Единица измерения отсутствует
В каких единицах измерения указано количество можно узнать только по ТТН, в ней есть признак типа продукции фасованная/нефасованная (packed/unpacked). В зависимости от этого признака, количество указано соответственно в штуках/декалитрах. Справочник номенклатуры ЕГАИС такого признака не содержит. Ваши остатки в ЕГАИС - тоже. В каких единицах измерения отображаются ваши остатки, а также в каких делать ввод остатка - можно только угадывать. Если не угадали - это выяснится только в момент реализации.
Решение
Добавить признак типа продукции в справочник номенклатуры, заполнять его при получении ТТН с этой продукцией, и использовать в дальнейшем. Не допускать смешивания в одной ТТН номенклатуры с разными признаками. Вопрос с единицей измерения ввода остатков номенклатуры, которую еще не получали - остается открытым.
Размерность полей даных
В xsd-схемах формата обмена с УТМ самая популярная размерность полей данных - строка 50 символов.
Сами данные по факту занимают гораздо меньше. Те, кто ограничил размерность полей в своих базах данных интеграций длиной по факту, в дальнейшем могут столкнуться с потерей данных при внезапном увеличении их длины. Прецедент уже был при внезапном объявлении текущей ЕГАИС тестовой и появлении дополнительного префикса "TEST- в идентификаторах. Размерность некоторых полей в xsd-схемах была изменена буквально за неделю до Нового Года.
Решение
После записи данных, полученных из ЕГАИС в вашу базу данных, необходимо проверять результат на предмет потери исходной длины/точности. И следите за обновлением xsd-схем в веб-интерфейсе УТМ ЕГАИС.
Порядок позиций документа в xml
Порядок позиций в xml файлов может не соответствовать порядку позиций в документе. Например документ состоит из нескольких xml файлов, в которых разный порядок позиций (ACTCHARGEON и INVENTORYREGINFO). Данные могут перемешаться при последовательной записи "в лоб" позиций в базу данных.
Решение
Необходимо учитывать номер идентификатор позиции, указанный в теге Identity. Данные по позиции из второго xml файла дописывать в соответствующую ей позицию документа, спозиционировавшись на неё по номеру идентификатору позиции из тега Identity. Идентификатор позиции имеет тип данных - строка 50 символов.
Некорректные данные
Файлы xml (например WAYBILL), которые формируются клиентской частью ЕГАИС грузоотправителя, пересылаются грузополучателю в исходном виде "как есть", даже если они сформированы с ошибками и не соответствуют описанному в документации формату. Например используются префиксы тегов, отличные от префиксов, приведенных в примерах в документации.
Решение
Необходимо проверять получаемые данные на соответствие формату хотя бы поверхностно, и обязательно сохранять исходные данные перед удалением из базы данных УТМ для последующего разбирательства.
Необязательные теги
Некоторые ключевые теги объявлены необязательными, и могут отсутствовать в полученных xml. Например Identity во всех документах, IsAccept в WAYBILLACT, IsConfirm в WAYBILLTICKET.
Решение
Изучить утвержденный формат и обеспечить корректную обработку в алгоритмах отсутствия необязательных тегов либо заполнение их значением по-умолчанию.
Продолжение следует...