5

Am trying to re-write written by savon body namespace - ins0 I have this client variable:

client = Savon.client(wsdl: "https://integcert.synxis.com/interface/Contracts/ChannelConnect2004.wsdl", log_level: :debug, log: true, pretty_print_xml: true, env_namespace: :soapenv, namespaces: {"xmlns:soapenv": "http://schemas.xmlsoap.org/soap/envelope/", "xmlns:head": "http://htng.org/1.1/Header/","xmlns:ns": "http://www.opentravel.org/OTA/2003/05"}, convert_request_keys_to: :none, namespace_identifier: "ns", element_form_default: :qualified)

And when Am doing the request:

client.call(:ping, soap_header: { "head:HTNGHeader": { "head:From": { "head:Credential": { "head:userName": "******", "head:password":"*****" }}}}, message: {"ns:EchoData": "TestData"})

I've got this soap rq body:

    <soapenv:Body>
    <ins0:OTA_PingRQ>
      <ns:EchoData>TestData</ns:EchoData>
    </ins0:OTA_PingRQ>
  </soapenv:Body>

Where this ins0 is came from?

Also when I tried to define client with namespace_identifier: nil parameter and did this kind of request:

client.call(:ping, soap_header: { "head:HTNGHeader": { "head:From": { "head:Credential": { "head:userName": "******", "head:password":"*****" }}}}, message: {"ns:OTA_PingRQ": {"ns:EchoData": "TestData"}})

I've got this soap rq body:

 <soapenv:Body>
<OTA_PingRQ>
  <ns:OTA_PingRQ>
    <ns:EchoData>TestData</ns:EchoData>
  </ns:OTA_PingRQ>
</OTA_PingRQ>

And the correct body that I want to have is:

<soapenv:Body>   
   <ns:OTA_PingRQ>
   <ns:EchoData>TestData</ns:EchoData>
   </ns:OTA_PingRQ>
</soapenv:Body>

Any ideas how to remove additional nested OTA_PingRQnode or replace ins0 namespace by the custom ?

mr.freeman13
  • 93
  • 1
  • 4
  • Please post complete XML including SOAP:envelope. The namespace prefix ins0 must have been declared in the SOAP envelope. If ins0, ns are both defined "http://www.opentravel.org/OTA/2003/05" then the request would be valid. I would suggest to use SOAP UI to validate and test your generated SOAP requests. – sashwat Oct 23 '16 at 10:15

2 Answers2

2

Your idea with additional namespaces was logically correct, but it doesn't look like Savon really wants to use them everywhere. It prefers to use namespaces found in WSDL. I tried element_form_default: :qualified and element_form_default: :unqualified, but it still puts ins0 as a namespace for OTA_PingRQ node everytime. I thought if it wants ins0 then let's use ins0 then. I looked at the list of available namespaces and found appropriate one for the header as well. Have no idea why Savon doesn't want to specify namespace for header nodes automatically, so we have to specify it manually as ins1.

Here is working version of configuration:

client = Savon.client(
  wsdl: "https://integcert.synxis.com/interface/Contracts/ChannelConnect2004.wsdl", 
  log_level: :debug, 
  log: true, 
  pretty_print_xml: true, 
  namespace_identifier: :ins0, 
  element_form_default: :qualified,
  soap_header: { 
    "ins1:HTNGHeader": { 
      "ins1:From": { 
        "ins1:Credential": { 
           "ins1:userName": "******", 
           "ins1:password":"*****" 
        }
      }
    }
  }
)

client.call(:ping, message: {"EchoData": "TestData"})

Request:

<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ins0="http://www.opentravel.org/OTA/2003/05" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ins1="http://htng.org/1.1/Header/">
  <env:Header>
    <ins1:HTNGHeader>
      <ins1:From>
        <ins1:Credential>
          <ins1:userName>******</ins1:userName>
          <ins1:password>*****</ins1:password>
        </ins1:Credential>
      </ins1:From>
    </ins1:HTNGHeader>
  </env:Header>
  <env:Body>
    <ins0:OTA_PingRQ>
      <ins0:echoData>TestData</ins0:echoData>
    </ins0:OTA_PingRQ>
  </env:Body>
</env:Envelope>

Response:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Body>
    <OTA_PingRS xmlns="http://www.opentravel.org/OTA/2003/05" PrimaryLangID="en">
      <Errors>
        <Error Type="4" ShortText="Login failed"/>
      </Errors>
      <EchoData/>
    </OTA_PingRS>
  </soap:Body>
</soap:Envelope>

EDIT: Provided soap_header at the client configuration, because it's more efficient way.

SunnyMagadan
  • 1,819
  • 14
  • 12
0

There is another way to attach namespace_identifier also. First set namespace_identifier: nil in Savon client.

basic_auth = [username, password]
client = Savon.client(
    wsdl:"https://integcert.synxis.com/interface/ChannelConnect2004.wsdl",
    namespace: {},
    env_namespace: 'soapenv',
    namespace_identifier: nil,
    basic_auth: basic_auth,
    logger: Rails.logger,
    log: true,
    soap_version: 2,
    pretty_print_xml: true,
    convert_request_keys_to: :camelcase,
    namespaces: {
        'xmlns:soap' => 'http://example.com/soap-envelope',
        'xmlns:glob' => 'http://example.com/Global'
   }
)

Now while calling the operation set message_tag response = client.call(:operation_name, message_tag: 'glob:OTA_PingRQ', message: {"EchoData": "TestData"})

Output:

<soapenv:Body>   
    <glob:OTA_PingRQ>
    <EchoData>TestData</ns:EchoData>
    </glob:OTA_PingRQ>
</soapenv:Body>
For Outoput like:
<soapenv:Body>   
    <ns:OTA_PingRQ>
    <ns:EchoData>TestData</ns:EchoData>
    </ns:OTA_PingRQ>
</soapenv:Body>

client call will be same but in client config add **element_form_default: :qualified**