使用 Savon 在 Ruby on Rails 中进行 SOAP 调用在信封和主要操作方面变得很奇怪

2024-03-03

在使用 Savon.rb 的 Rails 项目中,我尝试进行非常复杂的 SOAP 调用。至少复杂到 Savon 构建者太麻烦了,所以我决定直接操作 :xml。

首先我启动客户端:

@client = Savon.client(
            :endpoint => 'https://testservice.postnl.com/CIF_SB/BarcodeWebService/1_1/BarcodeWebService.svc',
            :wsdl     => 'https://testservice.postnl.com/CIF_SB/BarcodeWebService/1_1/?wsdl')

然后我以以下形式进行调用:

@request = @client.build_request(:generate_barcode,
             xml: %Q{ ... see soap call (with ruby interpolation) ... } 

我添加了一个格式正确的l Time.now, format: :postnl_api字符串,其余部分仍然是硬编码的。包括留言号码。

以下是 Savon 在这种情况下实际进行调用的方式,使用以下命令检索@request.body.

我的应用程序中的 SOAP 调用

<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:wsdl="http://tempuri.org/"
  xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://postnl.nl/cif/services/BarcodeWebService/IBarcodeWebService/GenerateBarcode
    </Action>
    <Security xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <UsernameToken>
        <Username>devc_!R4xc8p9</Username>
        <Password>xxxxxxxx</Password>
      </UsernameToken>
    </Security>
  </s:Header>
  <s:Body>
    <wsdl:GenerateBarcode>
      <d6p1:Customer>
        <d6p1:CustomerCode>DEVC</d6p1:CustomerCode>
        <d6p1:CustomerNumber>11223344</d6p1:CustomerNumber>
      </d6p1:Customer>
      <d6p1:Barcode>
        <d6p1:Type>3S</d6p1:Type>
        <d6p1:Range>DEVC</d6p1:Range>
        <d6p1:Serie>1000000-2000000</d6p1:Serie>
      </d6p1:Barcode>
    </wsdl:GenerateBarcode>
  </s:Body>
</s:Envelope>

接下来是一次调用的样子,因为我已经看到这个调用在公司的沙箱环境中取得了成功。

SOAP 调用应该是这样的

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://postnl.nl/cif/services/BarcodeWebService/IBarcodeWebService/GenerateBarcode</Action>
    <Security xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <wsse:UsernameToken xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
        <wsse:Username>devc_!R4xc8p9</wsse:Username>
        <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">xxxxxxxx</wsse:Password>
      </wsse:UsernameToken>
    </Security>
  </s:Header>
  <s:Body>
    <GenerateBarcode xmlns:d6p1="http://postnl.nl/cif/domain/BarcodeWebService/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://postnl.nl/cif/services/BarcodeWebService/">
      <d6p1:Message>
        <d6p1:MessageID>5</d6p1:MessageID>
        <d6p1:MessageTimeStamp>28-06-2017 14:15:41</d6p1:MessageTimeStamp>
      </d6p1:Message>
      <d6p1:Customer>
        <d6p1:CustomerCode>DEVC</d6p1:CustomerCode>
        <d6p1:CustomerNumber>11223344</d6p1:CustomerNumber>
      </d6p1:Customer>
      <d6p1:Barcode>
        <d6p1:Type>3S</d6p1:Type>
        <d6p1:Range>DEVC</d6p1:Range>
        <d6p1:Serie>1000000-2000000</d6p1:Serie>
      </d6p1:Barcode>
    </GenerateBarcode>
  </s:Body>
</s:Envelope>

似乎关闭的主要事情(顺便说一句,使用 Savon 构建器也是如此)是envelope的属性和主要操作:generate_barcode形状及其属性。我不明白为什么我得到前缀wsdl: before GenerateBarcode.

我告诉 Savon 获取我的 xml 并完全像那样构建它,但它不起作用。按原样发送我的版本会返回错误400.

使用克里斯的部分进行编辑

使用 @Chris 他的回答,我可以拨打以下电话:

设置通话

@client = Savon.client(
                 :endpoint                => 'https://testservice.postnl.com/CIF_SB/BarcodeWebService/1_1/BarcodeWebService.svc',
                 :wsdl                    => 'https://testservice.postnl.com/CIF_SB/BarcodeWebService/1_1/?wsdl',
                 :log                     => true,
                 :wsse_auth               => [ENV['postnl_username'], ENV['postnl_password']],
                 :pretty_print_xml        => true,
                 :convert_request_keys_to => :camelcase,
                 :env_namespace           => :s)

     message =  {
                  "d6p1:Message" => {
                    "d6p1:MessageID" =>  "7",
                    "d6p1:MessageTimeStamp" => I18n.l( Time.now, format: :postnl_api)
                },
                  "d6p1:Customer" => {
                    "d6p1:CustomerCode" => "DEVC",
                    "d6p1:CustomerNumber" =>  "11223344"},
                    "d6p1:Barcode" => {
                      "d6p1:Type" => "3S",
                      "d6p1:Range" => "DEVC",
                      "d6p1:Serie" => "1000000-2000000" } 
                }
     @client.call(:generate_barcode, :message => message, :soap_header => { "Action" => "http://postnl.nl/cif/services/BarcodeWebService/IBarcodeWebService/GenerateBarcode"})

Call

<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wsdl="http://tempuri.org/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <Action>http://postnl.nl/cif/services/BarcodeWebService/IBarcodeWebService/GenerateBarcode</Action>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="UsernameToken-1">
        <wsse:Username>devc_!R4xc8p9</wsse:Username>
        <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">098fd559930983af31ef6630a0bb0c1974156561</wsse:Password>
      </wsse:UsernameToken>
    </wsse:Security>
  </s:Header>
  <s:Body>
    <wsdl:GenerateBarcode>
      <d6p1:Message>
        <d6p1:MessageID>7</d6p1:MessageID>
        <d6p1:MessageTimeStamp>17-07-2017 22:13:35</d6p1:MessageTimeStamp>
      </d6p1:Message>
      <d6p1:Customer>
        <d6p1:CustomerCode>DEVC</d6p1:CustomerCode>
        <d6p1:CustomerNumber>11223344</d6p1:CustomerNumber>
      </d6p1:Customer>
      <d6p1:Barcode>
        <d6p1:Type>3S</d6p1:Type>
        <d6p1:Range>DEVC</d6p1:Range>
        <d6p1:Serie>1000000-2000000</d6p1:Serie>
      </d6p1:Barcode>
    </wsdl:GenerateBarcode>
  </s:Body>
</s:Envelope>

Response:

<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <s:Fault>
      <faultcode xmlns:a="http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher">a:InternalServiceFault</faultcode>
      <faultstring xml:lang="en-US">The server was unable to process the request due to an internal error.  For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the &lt;serviceDebug&gt; configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework SDK documentation and inspect the server trace logs.</faultstring>
    </s:Fault>
  </s:Body>
</s:Envelope>

好的,这有效(已验证)

@client = Savon.client(
             :wsdl                    => 'https://testservice.postnl.com/CIF_SB/BarcodeWebService/1_1/?wsdl',
             :log                     => true,
             :wsse_auth               => ['devc_!R4xc8p9', 'xxx'],
             :pretty_print_xml        => true,
             :convert_request_keys_to => :camelcase,
             :env_namespace           => :s,
             :namespace_identifier    => nil
            )

 message =  {
              "d6p1:Message" => {
                "d6p1:MessageID" =>  "10",
                "d6p1:MessageTimeStamp" => Time.now.strftime("%d-%m-%Y %H:%M:%S")
            },
              "d6p1:Customer" => {
                "d6p1:CustomerCode" => "DEVC",
                "d6p1:CustomerNumber" =>  "11223344"},
                "d6p1:Barcode" => {
                  "d6p1:Type" => "3S",
                  "d6p1:Range" => "DEVC",
                  "d6p1:Serie" => "1000000-2000000" } 
            }


attributes = { "xmlns:d6p1" => "http://postnl.nl/cif/domain/BarcodeWebService/", 
               "xmlns:i" => "http://www.w3.org/2001/XMLSchema-instance", 
               "xmlns" => "http://postnl.nl/cif/services/BarcodeWebService/"}

@client.call(:generate_barcode, :attributes => attributes, 
             :message => message, 
             :soap_header => { "Action" => "http://postnl.nl/cif/services/BarcodeWebService/IBarcodeWebService/GenerateBarcode"})

所以诀窍是添加:namespace_identifier => nil并发送attributes。设置命名空间标识符会删除wsdl from GenerateBarcodeans 属性设置一些命名空间GenerateBarcode标签。现在我记得为什么我这么讨厌 SOAP 了:(

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Savon 在 Ruby on Rails 中进行 SOAP 调用在信封和主要操作方面变得很奇怪 的相关文章

  • 缓存日期早于 1900 年的模型时出现编组错误

    我有一些具有 published on 属性的活动记录模型 当我尝试缓存 Publication on 日期早于 1900 年 1 月 1 日的模型时 出现如下错误 Marshalling error for key popular pro
  • database.yml 的所有可能键是什么

    我刚刚发现reconnect true配置选项可以在database yml文件 还有哪些其他可能的配置选项 是否有所有选项的完整参考 已知的关键示例 default default adapter mysql2 encoding utf8
  • 如何选择将特定节点作为子节点的第一个前同级节点?

    我一直在尝试编写一个 XPath 语句 它将选择节点的第一个前同级节点 该兄弟节点应该有一个特定的节点作为其子节点 例如 a a
  • ActiveSupport::JSON 解码哈希丢失符号

    我正在尝试序列化和反序列化哈希 当散列被解除序列化时 密钥被解除符号化 例如不是更多 一 而是 一 从 Rails 控制台 gt gt h one gt 1 two gt two one gt 1 two gt two gt gt j Ac
  • 具有预加载功能的 ActiveRecord::Calculations 是否会进行多个数据库查询?

    我的困惑源于这个问题 https stackoverflow com q 19462024 1860929 其中 OP 的模型如下 class Quote lt ActiveRecord Base has many items def ca
  • 如何在 python 中更新/修改 XML 文件?

    我有一个 XML 文档 我想在它包含数据后对其进行更新 我考虑过打开 XML 文件 a 追加 模式 问题是新数据将写入根结束标记之后 如何删除文件的最后一行 然后从该点开始写入数据 然后关闭根标签 当然 我可以读取整个文件并进行一些字符串操
  • Odoo:使得无法在树视图中编辑记录?

    在 Odoo 中 您可以使其无法从树视图中创建或删除记录 如下所示
  • Rails 销毁除最新的 n 条记录之外的所有记录

    如何使用 Rails 的 ActiveRecord 销毁除最新的 n 条记录之外的所有记录 我可以使用 order 和 limit 获取最新的 n 条记录 但如何销毁逆函数 这些方法中的任何一个都可以做到这一点 Fetch your lat
  • 批量修改XML文件

    好的 所以我不太熟悉使用 For F 如果文件是静态的并且有一组可以跳过然后从中提取数据的行 我可以修改它 我目前正在尝试修改 XML 文件 该文件将具有不同数量的行 但始终具有以下内容
  • 使用 NSXMLParser 在 Swift 中解析分层 XML

    我确实在以我实际可以使用的形式获取分层 XML 值时遇到问题 因此我们将不胜感激 我对 Swift 和 IOS 开发还很陌生 所以说实话我并不完全理解解析器 但我希望在这之后我能理解 下面是我尝试解析的示例 XML 它来自肥皂网络服务 连接
  • 用于输入地址的自动完成文本框是个好主意吗?

    通过传统形式输入我的地址让我发疯 为什么我必须输入我的城市 州 and邮政编码何时可以从我的邮政编码推断出我的城市和州 从下拉列表中选择您的状态是一件很痛苦的事情 通常您无法使用 Tab 键进入它 您必须使用鼠标等 替代文本 http im
  • 使用 Sandcastles 将图像嵌入 CHM 帮助文件

    我正在使用 Sandcastles 为我的项目生成 CHM 帮助文件 我想要一个可以分发的独立 CHM 文件 最好是单独分发 我遇到的问题是嵌入图像appears该图像需要与 CHM 文件分开存在于用户系统上 当我查看 CHM 文件的来源时
  • 将 Java 对象图保存为 XML 文件

    将任意 Java 对象图保存为 XML 文件 并能够在以后重新水合对象 的最简单易用的技术是什么 这里最简单的方法是序列化对象图 Java 1 4 内置了对 XML 序列化的支持 我成功使用的一个解决方案是 XStream http x s
  • 没有路线匹配... Rails Engine

    所以我不断收到错误 No route matches action gt create controller gt xaaron api keys 测试中抛出的是 it should not create an api key for th
  • Rails 复选框不起作用 - 提交表单时没有错误

    我在 Rails 中的复选框遇到问题 我有两个模型 User 和authorized users 具有以下关联 class AuthorizedUser lt ActiveRecord Base has one user as gt use
  • Rails:仅当满足某些条件时如何运行 before_save?

    我有一个 before save 方法 我称之为重命名上传的图像 before save randomize file name def randomize file name extension File extname screen f
  • 复制除根节点和属性 XSLT 之外的 XML 文件内容

    我正在处理一个小的 XSLT 文件来复制 XML 文件的内容并删除声明和根节点 根节点具有名称空间属性 我目前正在使用它 除了现在名称空间属性现在被复制到直接子节点之外 这是到目前为止我的 xslt 文件 没什么大或复杂的
  • Rails 3.1 引擎迁移不起作用

    我正在创建一个带有迁移的 Rails 3 1 引擎 rake db migration 在该引擎和主机应用程序内运行良好 但我需要将此引擎包含到另一个 Rails 引擎中 第二个引擎包含用于测试的虚拟应用程序 我将这一行添加到该虚拟应用程序
  • Ruby on Rails - 复选框未保存到数据库?

    我有一个迁移 它使用布尔值并在其视图中生成一个复选框 但是 无论我单击什么 保存到数据库的值都不会受到影响 我的迁移看起来像这样 def self up create table blogposts do t t string title
  • Rails:统计用户未读通知的数量

    我目前有一个处理用户活动通知系统的活动模型 当发生某些操作 例如创建新文章 时 活动观察者会创建一个新活动 现在我想记录当前用户尚未看到的这些活动通知中有多少 类似于 facebook 上的通知宝石 每次用户单击通知链接时 数字应重置为 0

随机推荐