【问题标题】:Savon not formatting request XML properlySavon 没有正确格式化请求 XML
【发布时间】:2016-07-24 16:02:40
【问题描述】:

我正在处理一个需要使用 SOAP api 的项目...并且非常喜欢 Savon 解决此问题的外观。这是我第一次在代码学院教程之外使用 API...

长话短说,无论我做什么...第三方 API 一直在说错误的 api 密钥...因为他们的错误报告很弱。我在这里拥有所有这些的代码 - 但在学习安装 gem 以记录传出的 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>

这就是 Savon 正在生成的内容

<?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: 变量...您可以使用它来定义您希望 savon 请求的确切 xml。它看起来并不漂亮,但至少它现在可以工作。

我会留意更好的解决方案。

【问题讨论】:

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


    【解决方案1】:

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

    client.call(:get_account_balance, message: { "ApiKey" => "XXX", "AccountNumber" => "1234" })

    【讨论】:

    • 是的.. 也试过了。仍然说 API 密钥不正确。从那以后,我也尝试在 SOAPUI 中加载 API ...并且还收到错误的 API 密钥错误。
    • 在使用 httplog 打印出传出的 http 请求后又迈出了一大步……似乎 xml 没有正确创建。我已经用相关细节更新了我的帖子。
    • 对任何未来的人来说最后一点......强制这些变量的更正式的方法是在客户端调用中添加convert_request_keys_to :camelcase
    【解决方案2】:

    为了让 XSI 属性正确显示,我发现我必须以以下方式格式化它们,但我找不到太多文档:'@xsi:type' =&gt; '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>
    

    【讨论】:

    • 这是我刚要探索的方向,当时我发现了肮脏的解决方案!我想我已经浪费了太多时间而没有进展,所以我想我需要重新完成这个 sprint 的首要任务。一旦我这样做,我会试一试并发布结果。感谢!!
    • @tkz79 你最终得到了适合你的解决方案吗?
    • 是的...我还没有尝试类似上面的东西...但是您可以通过在响应调用中定义 xml 参数来解决它...然后提供您的确切 xml 代码希望为通话生成。
    • @tkz79 你会考虑为你自己的问题添加一个答案(甚至接受它),因为我很想知道你最终做了什么。
    • @tkz79 有点晚了,但我在阅读 Gyoku gem 文档后更新了我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-22
    • 1970-01-01
    • 1970-01-01
    • 2021-12-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多