使用Savon在Ruby on Rails中进行SOAP调用时,在envelope和主要操作方面出现了问题

6
在使用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形状以及其属性。我不明白为什么在GenerateBarcode之前会出现前缀wsdl:
我告诉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"})

调用

<?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>

响应:

<?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>

你正在使用哪个版本的Savon? - Chris
版本2,你推荐使用3了吗? - Code-MonKy
1个回答

4

好的,这个可以正常工作(已验证)

@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。设置namespace_identifier会将GenerateBarcode中的wsdl删除,并在GenerateBarcode标记上设置一些命名空间。现在我记得为什么我如此讨厌SOAP :(

非常感谢您花时间研究我的问题。将您的答案与旧答案结合起来,我能够进行调用并获得上面编辑中的响应。我的沙盒密码哈希值为“098fd559930983af31ef6630a0bb0c1974156561”。目前还不确定故障在哪里。 - Code-MonKy
非常感谢!不幸的是,悬赏已经过期了,出于某种原因我现在只能选择100...对此很抱歉。无论如何,它已经过期了。 - Code-MonKy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接