Savon没有正确格式化请求XML

时间:2016-04-04 22:31:53

标签: ruby-on-rails ruby xml api savon

我正在开发一个需要使用SOAP api的项目...并且非常喜欢Savon的解决方案。这是我第一次使用代码学院教程之外的API ...

长话短说,无论我做什么......第三方API一直说糟糕的api密钥......因为他们的错误报告非常弱。我在这里获得了所有这些的代码 - 但在学习安装gem以记录传出的http请求后删除了它。在这样做的时候,我已经找到了问题的根源......并且可以使用一些指导。

简而言之 - Savon没有生成与SOAPUI相同的传出XML。

使用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>

我假设我需要在配置中设置一些变量来将Savon连接到SOAP UI正在做什么......

有什么建议吗?

更新:找到了肮脏的解决方案。

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

简而言之,您可以定义一个xml:variable ...,您可以使用它来定义您希望savon请求的确切xml。它看起来不漂亮,但至少它现在正在运作。

我会密切关注更好的解决方案。

2 个答案:

答案 0 :(得分:1)

尝试使用字符串键作为哈希:

client.call(:get_account_balance,message:{“ApiKey”=&gt;“XXX”,“AccountNumber”=&gt;“1234”})

答案 1 :(得分:1)

为了让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哈希值;你可能不需要它们,而只需要输入ID值,但是上次我使用它时,XSI类型值需要是散列哈希值。

编辑:

为了正确显示属性,您需要查看Gyoku gem,即Savon用于将Ruby哈希值转换为XML的gem。具体而言,the documentation on using explicit XML attributes。看一下,我们可以使用以下哈希来获取您正在寻找的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>