Savon неправильно форматирует запрос XML

Я работаю над проектом, который требует работы с SOAP API... и мне очень понравился внешний вид Savon для решения этой проблемы. Это мой первый раз, когда я работаю с API вне учебника Академии кода...

Короче говоря, независимо от того, что я делаю ... сторонний API продолжал говорить о плохом ключе API ... поскольку их отчеты об ошибках довольно слабы. У меня был код для всего этого здесь, но я удалил его после того, как научился устанавливать гем для регистрации исходящих http-запросов. При этом я добрался до источника проблемы... и мог бы использовать некоторые советы.

Короче говоря, Savon не генерирует тот же исходящий XML, что и SOAPUI.

Использование SOAPUI (что мы хотим...)

<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sec="http://secure.treasury.exchange/">
   <soapenv:Header/>
   <soapenv:Body>
      <sec:GetAccountBalance soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
         <GetAccountBalanceRequest xsi:type="sec:GetAccountBalanceRequest">
            <!--You may enter the following 2 items in any order-->
            <ApiKey xsi:type="xsd:string">xxx</ApiKey>
            <AccountNumber xsi:type="xsd:string">123</AccountNumber>
         </GetAccountBalanceRequest>
      </sec:GetAccountBalance>
   </soapenv:Body>
</soapenv:Envelope>

Это то, что генерирует Савон

<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tns="http://secure.treasury.exchange/"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
    <env:Body>
        <tns:GetAccountBalance>
            <apiKey>xxx</apiKey>
            <accountNumber>123</accountNumber>
        </tns:GetAccountBalance>
    </env:Body>
</env:Envelope>

Я предполагаю, что есть некоторые переменные, которые мне нужно установить в конфигурации, чтобы связать Савона с тем, что делает пользовательский интерфейс SOAP...

Любой совет?

ОБНОВЛЕНИЕ: найдено грязное решение.

https://www.reddit.com/r/ruby/comments/289wfn/soap_issues_with_savon/

В двух словах, вы можете определить xml: переменную... которую вы можете использовать, чтобы определить точный xml, который вы хотите запросить savon. Выглядит некрасиво, но, по крайней мере, пока работает.

Я буду следить за лучшим решением.


person tkz79    schedule 04.04.2016    source источник


Ответы (2)


Попробуйте использовать строковые ключи для вашего хеша:

client.call(:get_account_balance, сообщение: { "ApiKey" => "XXX", "AccountNumber" => "1234" })

person Anthony E    schedule 04.04.2016
comment
Ага.. уже пробовал. Все еще говорит неверный ключ API. С тех пор я также пытался загрузить API в SOAPUI... и также получаю сообщение об ошибке "Неправильный ключ API". - person tkz79; 05.04.2016
comment
Сделал большой шаг ближе после распечатки исходящих http-запросов с помощью httplog... кажется, что xml не создается должным образом. Я обновил свой пост с соответствующими подробностями. - person tkz79; 06.04.2016
comment
Последнее замечание для тех, кто появится в будущем... более официальный способ принудительно использовать эти переменные - добавить convert_request_keys_to :camelcase к клиентскому вызову. - person tkz79; 06.04.2016

Чтобы атрибуты XSI отображались правильно, я обнаружил, что мне нужно отформатировать их следующим образом, для которого я не смог найти много документации: '@xsi:type' => 'xsd:string'.

Итак, для следующего XML:

<GetAccountBalanceRequest xsi:type="sec:GetAccountBalanceRequest">
  <ApiKey xsi:type="xsd:string">xxx</ApiKey>
  <AccountNumber xsi:type="xsd:string">123</AccountNumber>
</GetAccountBalanceRequest>

Могу поспорить, что вам, вероятно, понадобится хэш, который выглядит примерно так, как показано ниже, для использования в вызове SOAP:

{
  'GetAccountBalanceRequest' => {
    '@xsi:type' => 'sec:GetAccountBalanceRequest',
    'ApiKey' => {
      '@xsi:type' => 'xsd:string',
      'ID' => 'xxx'
    },
    'AccountNumber' => {
      '@xsi:type' => 'xsd:string',
      'ID' => '123'
    }
  }
}

Не уверен насчет дополнительных ID хэшей, которые я добавил; они могут вам не понадобиться, и вместо этого вы можете просто указать значение идентификатора, но в прошлый раз, когда я использовал это, значения типа XSI должны были быть хешем хэшей.

Редактировать:

Чтобы атрибуты отображались правильно, вам нужно посмотреть на гем Gyoku, gem, который Савон использует для перевода хэшей Ruby в XML. В частности, документацию по использованию явных XML-атрибутов. Глядя на это, мы можем получить XML, который вы ищете, со следующим хешем:

{
  "sec:GetAccountBalance" => {
    "@soapenv:encodingStyle" => "http://schemas.xmlsoap.org/soap/encoding/",
    "GetAccountBalanceRequest" => {
      "@xsi:type" => "sec:GetAccountBalanceRequest",
      "ApiKey" => {
        "@xsi:type" => "xsd:string",
        :content! => 'xxx'
      },
      "AccountNumber" => {
        "@xsi:type" => "xsd:string",
        :content! => "123"
      }
    }
  }
}

Это также можно проверить с помощью простого скрипта Ruby:

hash_to_xml.rb

require 'gyoku'

puts Gyoku.xml(
  {
    "sec:GetAccountBalance" => {
      "@soapenv:encodingStyle" => "http://schemas.xmlsoap.org/soap/encoding/",
      "GetAccountBalanceRequest" => {
        "@xsi:type" => "sec:GetAccountBalanceRequest",
        "ApiKey" => {
          "@xsi:type" => "xsd:string",
          :content! => 'xxx'
        },
        "AccountNumber" => {
          "@xsi:type" => "xsd:string",
          :content! => "123"
        }
      }
    }
  }
)

А затем запустите его:

$ ruby hash_to_xml.rb
# =>
# <sec:GetAccountBalance soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
#   <GetAccountBalanceRequest xsi:type="sec:GetAccountBalanceRequest">
#     <ApiKey xsi:type="xsd:string">xxx</ApiKey>
#     <AccountNumber xsi:type="xsd:string">123</AccountNumber>
#   </GetAccountBalanceRequest>
# </sec:GetAccountBalance>
person Paul Fioravanti    schedule 06.04.2016
comment
Это направление, которое я как раз собирался изучить, когда нашел грязное решение! Я понял, что уже потерял слишком много часов без прогресса, поэтому решил, что мне нужно вернуться к завершению главных приоритетов этого спринта. Как только я это сделаю, я попробую и отпишусь о результате. Благодарность!! - person tkz79; 06.04.2016
comment
@ tkz79 вы нашли решение, которое сработало для вас? - person Paul Fioravanti; 24.04.2016
comment
Да... Я не пробовал что-то подобное выше... но вы можете решить эту проблему, определив параметр xml в ответном вызове... а затем предоставив точный код xml, который вы хотите сгенерировать для вызова. - person tkz79; 25.04.2016
comment
@ tkz79, не могли бы вы подумать о том, чтобы добавить ответ на свой вопрос (и даже принять его), поскольку мне было бы любопытно посмотреть, что вы в итоге сделали. - person Paul Fioravanti; 25.04.2016
comment
@ tkz79 Немного поздно, но я обновил свой ответ после прочтения документации Gyoku gem. - person Paul Fioravanti; 05.08.2016