Страница 1 из 7
Работа с Меркурием
Добавлено: 07 Август 2018, 9:52
finsoftrz
Глянул сегодня с утра, что за зверь. В общем, обмен xml-файлами с их сервисами. Интерфейс можно делать по разному, в том числе через curl.exe, по аналогии с Егаис. Вот такой пример для получения ответа работает:
Код: Выделить всё
'curl.exe -d @"' & 'req.xml' & '" -H "Content-Type: text/xml; charset=utf-8" -u ' & 'user' & ':' & 'pswd' & ' https://api2.vetrf.ru:8002/platform/services/2.0/EnterpriseService' & ' -o ' & 'resp.xml'
Файлик req.xml делаем по их документации в зависимости от запроса. Он должен быть в кодировке utf8. В ответ получаем resp.xml (тоже в utf8), который парсим. Его вид тоже описан в документации и зависит от запроса. При наличии опыта работы с Егаис все выглядит очень похоже, объектная обвязка идентичная.
Работа с Меркурием
Добавлено: 07 Август 2018, 13:42
Игорь Столяров
Классно !
А я пробовал, где-то пол-года назад, подключиться через LibCurl, но чего-то не задалось …
А можно просить какой-нибудь заведомо правильный req.xml ? Я бы тоже попробовал что-нибудь поиметь с Меркурия.
Работа с Меркурием
Добавлено: 07 Август 2018, 14:02
finsoftrz
Запрос 3 первых организаций с фрагментом в названии. Дальше я тоже пока не дошел...
Код: Выделить всё
fsFileMakerL.AddOutLine('<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://api.vetrf.ru/schema/cdm/registry/ws-definitions/v2" xmlns:bs="http://api.vetrf.ru/schema/cdm/base" xmlns:dt="http://api.vetrf.ru/schema/cdm/dictionary/v2">')
fsFileMakerL.AddOutLine(' <soapenv:Header/>')
fsFileMakerL.AddOutLine(' <soapenv:Body>')
fsFileMakerL.AddOutLine(' <ws:getRussianEnterpriseListRequest>')
fsFileMakerL.AddOutLine(' <bs:listOptions>')
fsFileMakerL.AddOutLine(' <bs:count>3</bs:count>')
fsFileMakerL.AddOutLine(' <bs:offset>0</bs:offset>')
fsFileMakerL.AddOutLine(' </bs:listOptions>')
fsFileMakerL.AddOutLine(' <dt:enterprise>')
fsFileMakerL.AddOutLine(' <dt:name>"ПЕРЕСВЕТ"</dt:name>')
fsFileMakerL.AddOutLine(' </dt:enterprise>')
fsFileMakerL.AddOutLine(' </ws:getRussianEnterpriseListRequest>')
fsFileMakerL.AddOutLine(' </soapenv:Body>')
fsFileMakerL.AddOutLine('</soapenv:Envelope>')
Работа с Меркурием
Добавлено: 07 Август 2018, 14:04
Игорь Столяров
Спасибо ! Для теста - подойдёт.
Я вот нечто похожее пробовал запихнуть туда сразу через LibCurl ...
Работа с Меркурием
Добавлено: 07 Август 2018, 15:10
finsoftrz
У меня работа с Егаис через curl.exe, поскольку там все примеры в доке на нем. Ну и подумал, зачем зоопарк плодить со всеми этими делами, пусть будет curl.exe. Другие тоже, видимо, после Егаиса его задействуют. Хотя сами меркурианцы рекомендуют soapUI.
Работа с Меркурием
Добавлено: 07 Август 2018, 16:21
Игорь Столяров
finsoftrz писал(а): ↑07 Август 2018, 15:10Хотя сами меркурианцы рекомендуют soapUI
Это не беда. Плохо, что они (как я понял) не довели сей чудный сервис до ума и не прикрутили к нему вариант обмена в JSON.
В Clarion JSON более дружелюбен, чем XML ...
Работа с Меркурием
Добавлено: 08 Август 2018, 18:53
Yufil
У себя среди старых программ нашёл фрагмент с загрузкой адресных данных через SOAP, и парсинг результатов, используя SOAPUi и самопальные модули Chttp и Cstr
https://mega.nz/#!0l5mCYaZ!lK3UXugElajL ... pOOcyTm8HU , там рутинка soaprequest ( стр.213) . Если интересно, попробую объяснить, что там творится и найду весь антураж ( классы и всё такое )...
Работа с Меркурием
Добавлено: 26 Август 2018, 16:42
finsoftrz
Вот еще пример запроса всех стран.
Код: Выделить всё
sendRequest_r routine !послать запрос
DATA
lor:queue queue, pre()
lor:name string(128), name('dt:name')
lor:uuid string(80), name('bs:uuid')
lor:guid string(80), name('bs:guid')
.
lor:err byte
CODE
Loc:NameTmp=GetNameTmp(FsAccess:ActiveUserDir,'xml',0)
Loc:NameOutTmp=GetNameTmp(FsAccess:ActiveUserDir,'xml',1)
fsFileMakerL.init(Loc:NameTmp)
fsFileMakerL.AddOutLine('<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://api.vetrf.ru/schema/cdm/registry/ws-definitions/v2" xmlns:base="http://api.vetrf.ru/schema/cdm/base">')
fsFileMakerL.AddOutLine(' <soapenv:Header/>')
fsFileMakerL.AddOutLine(' <soapenv:Body>')
fsFileMakerL.AddOutLine(' <ws:getAllCountryListRequest>')
fsFileMakerL.AddOutLine(' <base:listOptions>')
fsFileMakerL.AddOutLine(' <base:count>10</base:count>')
fsFileMakerL.AddOutLine(' <base:offset>0</base:offset>')
fsFileMakerL.AddOutLine(' </base:listOptions>')
fsFileMakerL.AddOutLine(' </ws:getAllCountryListRequest>')
fsFileMakerL.AddOutLine(' </soapenv:Body>')
fsFileMakerL.AddOutLine('</soapenv:Envelope>')
if fsFileMakerL.MakeFile(1)=0
fsFileMakerL.kill
exit
.
fsFileMakerL.kill
if fsCurlL.StartProcess('curl\curl.exe -d @"' & clip(Loc:NameTmp) & '" -H "Content-Type: text/xml; charset=utf-8" -u ' & clip('peresvet-180801') & ':' & clip('b6WHf9r3') & clip(' https://api2.vetrf.ru:8002/platform/services/2.0/IkarService') & ' -o ' & clip(Loc:NameOutTmp)).
if ~exists(Loc:NameOutTmp)
FsMessagePr('Ошибка отправки запроса!')
exit
.
lor:err=0
Loc:NameTmp=Loc:NameOutTmp
Loc:NameVbsTmp=GetNameTmp(FsAccess:ActiveUserDir,'vbs',0)
Loc:NameOutTmp=GetNameTmp(FsAccess:ActiveUserDir,'txt',0)
!читаем ответ
fsXmlPar.init(Loc:NameTmp,Loc:NameVbsTmp,Loc:NameOutTmp)
fsXmlPar.LoadQueue('dt:country','lor:queue',lor:queue)
fsXmlPar.MakeScript(1)
if fsXmlPar.ErrorCode<>0
FsMessagePr('Ошибка! ' & clip(fsXmlPar.ErrorMessage))
lor:err=1
.
fsXmlPar.kill
if lor:err=0 and records(lor:queue)<>0
remove(Loc:NameTmp)
remove(Loc:NameOutTmp)
fsViewQueue('',lor:queue)
elsif lor:err=0
run('notepad.exe ' & Loc:NameTmp)
run('notepad.exe ' & Loc:NameOutTmp)
.
free(lor:queue)
Работа с Меркурием
Добавлено: 08 Сентябрь 2018, 13:49
finsoftrz
Посмотрел подробнее эту тему. В общем, принципы взаимодействия похожи на Егаис и несколько проще (нет локальной инфраструктуры со всеми вытекающими). Создаем xml нужного вида (копируем образец из вики), применяем в нем идентификаторы и логины, полученные в Россельхознадзоре. Шлем на один из сервисов. Их несколько, в зависимости от типа запроса. В ответ получаем в виде xml либо сразу нужную информацию (например, всякие справочники), либо идентификатор запроса (для более сложных операций). Во втором случае через некоторое время шлем запрос на получение результата, указав в нем идентификатор, присвоенный основному запросу. Получаем результат. Для розницы несложно, там только гасить всд требуется. Для опта и, тем более, производства надо вникать в разные тонкости бизнес-процессов глазами меркурианцев...
Технически в словаре несколько структур (для розницы 4 таблицы насчитал) и dll.
Работа с Меркурием
Добавлено: 25 Сентябрь 2018, 9:16
finsoftrz
Попробовал вчера получение всд в рабочем контуре. В общем, система пока явно не справляется с нагрузкой. Запрос проходит с десятой попытки, иначе вываливается отказ по неизвестной причине. Поглядел на форумах, народ стонет, начиная с июля. Большинство используют веб интерфейс, который работает более стабильно. А в шлюз все ставят на автомат и долбят его запросами через определенные промежутки времени, пока запрос наконец не пройдет...
Работа с Меркурием
Добавлено: 27 Декабрь 2018, 18:18
finsoftrz
Дошли руки до гашения ВСД. Обмен с сервером Ветис через curl.exe. Долбим несколько попыток на получение списка непогашенных ВСД, если сервер перегружен и возвращает ошибку.
Основная проблема в том, что информация в запросе на гашение сверяется сервером с содержимым исходного ВСД. Это сопоставление не "тэг в тэг" и не документировано. Приходится уточнять по мере тестирования. Для этого сохраняем последний полученный xml со списком непогашенных ВСД и xml последнего отправленного запроса на гашения. В случае ошибки смотрим их содержание и пытаемся понять... Один из примеров. В запросе на гашение присутствует информация о номере транспорта. Берем ее из аналогичного тэга в ВСД. Но если в ВСД есть информация о маршруте и в нем указан второй транспорт после перегрузки, то передавать в запросе на гашение надо номер этого второго транспорта, хотя он в других тэгах...
Работа с Меркурием
Добавлено: 14 Июнь 2019, 18:11
Игорь Столяров
На основе кода Юрия, сделал простой парсер XML ответов под Меркурий.
Вроде бы тащит всё - буду благодарен, если есть желающие присоединится к проверке.
Код: Выделить всё
LoadQueueFromXML PROCEDURE (*IDynStr xBuffer_,*Queue xMyQueue_, String xTagRow_)
Loc:XMLCount LONG(1)
Loc:XMLDoc &Document,AUTO
Loc:RetValue LONG(0) ! Возвращает кол-во добавленных строк в xMyQueue_
Loc:Value CSTRING(256)
Loc:FlagRecord BYTE(False)
Loc:TagParent CSTRING(81)
Loc:TagName CSTRING(81)
Loc:Column LONG
Loc:Field ANY
Loc:AttrIndex LONG
Loc:FlagData BYTE(False)
Loc:XMLList Queue(DOMQueue)
end
MyParentNode &node,auto
nnm &NamedNodeMap,auto
ANode &Node,Auto
CODE
Loc:XMLDoc &= XMLStringToDOM(xBuffer_.Str())
If ~(Loc:XMLDoc &= NULL)
FillDOMQueue(Loc:XMLDoc,Loc:XMLList)
!ViewXML(Loc:XMLDoc)
Loop While(Loc:XMLCount <= Records(Loc:XMLList))
Get(Loc:XMLList,Loc:XMLCount)
Loc:TagName = Lower(Loc:XMLList.Node.GetNodeName()) ! Сразу получаем имя тега - он нужен для поиска начала строки
If Loc:FlagRecord ! Если ведётся запись строки
MyParentNode &= Loc:XMLList.node.GetParentNode() ! Родительский тег
If (MyParentNode &= NULL) then Message('Ошибка ParentNode !').
Loc:TagParent = Lower(MyParentNode.GetNodeName())
! --- Получаем данные тега из следующей строки
Get(Loc:XMLList,Loc:XMLCount + 1)
If ~ErrorCode() and (Loc:XMLList.Node.GetNodeName() = '#text')
Loc:XMLCount += 1
! --- Поиск поля в очереди
Loc:Column = 1
Loop While(Who(xMyQueue_,Loc:Column) <> '')
If Lower(Who(xMyQueue_,Loc:Column)) = (Loc:TagParent & '!' & Loc:TagName)
Loc:Field &= What(xMyQueue_,Loc:Column)
If ~(Loc:Field &= NULL)
! Что бы не конвертировать из UTF-8 в ANSI цифры и GUID
If (IsString(Loc:Field) = False) Or (Size(What(xMyQueue_,Loc:Column)) = 36)
Loc:Value = Loc:XMLList.Node.GetNodeValue()
else ! Перекодировать строку UTF-8 в ANSI
Loc:Value = UTF8toANSI(Loc:XMLList.Node.GetNodeValue())
end
If Lower(Loc:Value) = 'true'
Loc:Field = True
elsIf Lower(Loc:Value) = 'false'
Loc:Field = False
else
Loc:Field = Loc:Value
end
Loc:FlagData = True ! В записи есть данные
end
end
Loc:Column += 1
end
end
end
! --- Поиск тега начала строки с данными
If Loc:TagName = Lower(xTagRow_)
If Loc:FlagRecord ! Если велась запись
If Loc:FlagData ! Если в буфере есть данные
Add(xMyQueue_) ! Добавить запись
If ~ErrorCode() then Loc:RetValue += 1.
end
else
Loc:FlagRecord = True ! Начать запись
end
Clear(xMyQueue_) ! Очистить буфер записи
Loc:FlagData = False ! В буфере нет данных
end
Loc:XMLCount += 1
end
If Loc:FlagData ! Если в буфере есть данные - добавить последнюю запись
Add(xMyQueue_)
If ~ErrorCode() then Loc:RetValue += 1.
end
Free(Loc:XMLList)
Loc:XMLDoc.Release()
end
Return(Loc:RetValue)
Ну и на примере, опубликованного здесь ранее, получения справочника стран:
Код: Выделить всё
Loc:MyCountry Queue ! Список стран (УКАЗЫВЕТСЯ ИМЯ ПОЛЯ С РОДИТЕЛЬСКИМ ТЕГОМ, Т.К. В XML ИМЕНА НЕ УНИКАЛЬНЫ !!!)
UUID String(36), Name('dt:country!bs:uuid') ! Идентификатор версии
GUID String(36), Name('dt:country!bs:guid') ! Глобальный идентификатор страны в реестре системы Икар
Status Short, Name('dt:country!bs:status') ! Статус записи
Name CString(129), Name('dt:country!dt:name') ! Название страны (например, Белоруссия)
FullName CString(256), Name('dt:country!dt:fullName') ! Полное название страны (например, Республика Беларусь)
EnglishName CString(129), Name('dt:country!dt:englishName') ! Название страны на английском языке
Code String(2), Name('dt:country!dt:code') ! Двухбуквенный код страны в соответствии со стандартом ISO 3166-1 alpha-2
Code3 String(3), Name('dt:country!dt:code3') ! Трёхбуквенный код страны в соответствии со стандартом ISO 3166-1 alpha-3
end
Loc:Buffer &IDynStr
RLoad Long
Code
! Выполнили запрос и получили текст XML ответа в Loc:Buffer (см. LibCURL)
RLoad = LoadQueueFromXML(Loc:Buffer,Loc:MyCountry,'dt:country') ! Указываем тег строки с данными
Message('Загружено стран: ' & RLoad) ! Ну а список стран - в Loc:MyCountry :)
Работа с Меркурием
Добавлено: 14 Июнь 2019, 21:08
finsoftrz
Игорь, получилось список стран прочитать?
Работа с Меркурием
Добавлено: 14 Июнь 2019, 21:36
Игорь Столяров
finsoftrz писал(а): ↑14 Июнь 2019, 21:08Игорь, получилось список стран прочитать?
Спасибо, да, конечно. Страны, ед. измерения и т.д. - всё грузится.
Конкретно со странами - был затык из-за неправильного тега в шапке запроса из примера на сайте Ветис.API.
Взял шапку с Вашего примера в этой ветке форума - всё загрузилось с полутыка …
Работа с Меркурием
Добавлено: 14 Июнь 2019, 22:11
finsoftrz
Да, я тоже разобрался. Тот вариант, который я посылал Вам, был для тестового контура. Надо правильно указать адрес сервиса и пространство имен.
Для рабочего контура доступ к адресам (икар):
https://api.vetrf.ru/platform/services/2.0/IkarService
Запрос стран для рабочего контура (важно правильно указать адреса в 2-3 строках):
Код: Выделить всё
fsFileMakerL.AddOutLine('<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"')
fsFileMakerL.AddOutLine(' xmlns:ws="http://api.vetrf.ru/schema/cdm/registry/ws-definitions/v2"')
fsFileMakerL.AddOutLine(' xmlns:base="http://api.vetrf.ru/schema/cdm/base">')
fsFileMakerL.AddOutLine(' <soapenv:Header/>')
fsFileMakerL.AddOutLine(' <soapenv:Body>')
fsFileMakerL.AddOutLine(' <ws:getAllCountryListRequest>')
fsFileMakerL.AddOutLine(' <base:listOptions>')
fsFileMakerL.AddOutLine(' <base:count>100</base:count>')
fsFileMakerL.AddOutLine(' <base:offset>' & Loc:Sm & '</base:offset>')
fsFileMakerL.AddOutLine(' </base:listOptions>')
fsFileMakerL.AddOutLine(' </ws:getAllCountryListRequest>')
fsFileMakerL.AddOutLine(' </soapenv:Body>')
fsFileMakerL.AddOutLine('</soapenv:Envelope>')