How do you deal with nested namespaces in Savon? - ruby

If I have the following SOAP request:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://test.org/" xmlns:hon="http://schemas.datacontract.org/2004/07/TEST.RVU.Entity">
<soapenv:Header/>
<soapenv:Body>
<tem:Authenticate>
<!--Optional:-->
<tem:authenticationDet>
<!--Optional:-->
<hon:AccountType>0</hon:AccountType>
<!--Optional:-->
<hon:Password>bacon</hon:Password>
<!--Optional:-->
<hon:UserName>smith</hon:UserName>
</tem:authenticationDet>
</tem:Authenticate>
</soapenv:Body>
</soapenv:Envelope>
How do I write down a valid soap request using the Savon gem that includes the tem: and hon: namespaces?
Thanks

You need to set the additional namespace.
The script could look like this:
#!ruby
require "savon"
Savon.configure do |c|
c.pretty_print_xml = true
c.env_namespace = :soapenv
end
client = Savon::Client.new do
wsdl.namespace = "http://test.org"
wsdl.endpoint = "http://www.your-real-endpoint.com"
end
resp = client.request :tem, 'Authenticate' do
soap.namespaces["xmlns:hon"] = "http://schemas.datacontract.org/2004/08/TEST.RVU.Entity"
soap.body = { "tem:authenticationDet" =>
{ "hon:AccountType" => 0,
"hon:Password" => "bacon",
"hon:UserName" => "smith" }
}
end

Related

Add attribute in Savon request

How can I add the attribute 'updateVersion' in the request, when using the following format:
response = client.call(
:method, :message => { extID => 'X-1234', ..., '#updateVersion' => '0' }
)
I need to set the updateVersion to 0 for my call to be successful and of course the extID.
When using response = client.call( :method, xml: "xml") then it is working as expected, but I'd like to see/test the other option.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:int="http://www.url">
<soapenv:Body>
<int:policyInList>
<!--0 to 1000 repetitions:-->
<int:policyID main="true" system_id="0" updateVersion="?">
<extID>X-1234</extID>
</int:policyID>
</int:policyInList>
</soapenv:Body>
</soapenv:Envelope>

Close AccountingPeriod in Zuora via SOAP

I am trying to call the update method of the Zuora Soap API so as to 'CloseAccountingPeriod'. What is the correct way to do this
require 'savon'
message = {'username' => 'username','password' => 'password' }
client = Savon.client(wsdl: 'zuora.a.75.0.wsdl')
response = client.call(:login, message: message)
#response = client.call :update do
soap.header = {
}
soap.body = {
:Status=> "closed",
:ids=>"4028e699235ea4de0123777131fd5d68"
}
end
The Zuora Soap looks like this:
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv=
"http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<ns1:SessionHeader xmlns:ns1=
"http://api.zuora.com/" soapenv:mustUnderstand="0">
<ns1:session>[replace with your session]</ns1:session>
</ns1:SessionHeader>
</soapenv:Header>
<soapenv:Body>
<ns1:update xmlns:ns1="http://api.zuora.com/">
<ns1:zObjects xmlns:ns2="http://object.api.zuora.com/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="ns2:AccountingPeriod">
<ns2:Id>402892a83711418b01371142cc5801a9</ns2:Id>
<ns2:Status>Closed</ns2:Status>
</ns1:zObjects>
</ns1:update>
</soapenv:Body>
</soapenv:Envelope>
That example is correct
The minimum required data is
session key
32 char id of the AccountingPeriod
Status "Closed"

Savon 2 returns nothing in Rails 4

Here is my Savon 2
client = Savon::Client.new(wsdl: "http://www.webservicex.net/uszip.asmx?WSDL")
client.operations
response = client.call(:get_info_by_zip, :message => { us_zip: "90210" })
response.to_hash
And response is:
{:get_info_by_zip_response=>{:#xmlns=>"http://www.webserviceX.NET"}}
In the SoapUI:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://www.webserviceX.NET">
<soapenv:Header/>
<soapenv:Body>
<web:GetInfoByZIP>
<!--Optional:-->
<web:USZip>90210</web:USZip>
</web:GetInfoByZIP>
</soapenv:Body>
</soapenv:Envelope>
I get this 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>
<GetInfoByZIPResponse xmlns="http://www.webserviceX.NET">
<GetInfoByZIPResult>
<NewDataSet xmlns="">
<Table>
<CITY>Beverly Hills</CITY>
<STATE>CA</STATE>
<ZIP>90210</ZIP>
<AREA_CODE>310</AREA_CODE>
<TIME_ZONE>P</TIME_ZONE>
</Table>
</NewDataSet>
</GetInfoByZIPResult>
</GetInfoByZIPResponse>
</soap:Body>
</soap:Envelope>
For the life of me I cant figure it out. Can someone please have a look and let me know what am I doing wrong?
Thanks
Your tag within the message seems wrong, instead us_zip you should use "USZip" (in quotes!).
This works for me:
#!ruby
require 'savon'
require 'pp'
WSDL_URL = 'http://www.webservicex.net/uszip.asmx?wsdl'
client = Savon.client(
wsdl: WSDL_URL,
log: true, # set true to switch on logging
log_level: :debug,
pretty_print_xml: true
)
zip = ARGV[0] || "98052"
response = client.call(:get_info_by_zip,
message: { "USZip" => zip }
)
pp response.to_hash

Convert this XML request to a proper Savon request

Can somebody convert this:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://test.org/" xmlns:hon="http://schemas.datacontract.org/2004/07/TEST.RVU.Entity">
<soapenv:Header/>
<soapenv:Body>
<tem:Authenticate>
<!--Optional:-->
<tem:authenticationDet>
<!--Optional:-->
<hon:AccountType>0</hon:AccountType>
<!--Optional:-->
<hon:Password>bacon</hon:Password>
<!--Optional:-->
<hon:UserName>smith</hon:UserName>
</tem:authenticationDet>
</tem:Authenticate>
</soapenv:Body>
</soapenv:Envelope>
now using Soap gem SAVON, how can I write this in a correct syntax that the client.request method can deal with it?
I tried this:
client.request :tem, :authenticate, body: { "authenticationDet" => { "AccountType" => 0, "Password" => "bacon", "UserName" => "smith"}}
but I get a HTTP 400 error.
Any advice?
You need to set the additional namespace.
The SOAP action has to be in quotes to match yours.
The script could look like this:
#!ruby
require "savon"
Savon.configure do |c|
c.pretty_print_xml = true
c.env_namespace = :soapenv
end
client = Savon::Client.new do
wsdl.namespace = "http://test.org"
wsdl.endpoint = "http://localhost"
end
resp = client.request :tem, 'Authenticate' do
soap.namespaces["xmlns:hon"] = "http://schemas.datacontract.org/2004/08/TEST.RVU.Entity"
soap.body = { "tem:authenticationDet" =>
{ "hon:AccountType" => 0,
"hon:Password" => "bacon",
"hon:UserName" => "smith" }
}
end

Ruby and Savon Error: POST method not supported by this URL

I am a newbie to savon and SOAP.
I am trying to create a request to netsuite wsdl service. When I run it, I get the following error:
D, [2012-02-23T15:05:08.714815 #2284] DEBUG -- : HTTPI executes HTTP POST using the httpclient adapter
D, [2012-02-23T15:05:19.670815 #2284] DEBUG -- : SOAP response (status 405):
c:/Ruby187/lib/ruby/gems/1.8/gems/savon-0.9.9/lib/savon/soap/response.rb:107:in
`raise_errors': HTTP error (405): HTTP method POST is not supported by this URL
(Savon::HTTP::Error)
It seems that I need to use a get instead of post, but I cannot figure out how to set up the request to be a get. Any help would be appreciated.
client = Savon::Client.new do
wsdl.endpoint = "https://webservices.netsuite.com/wsdl/v2011_2_0"
wsdl.namespace = "urn:messages_2011_2.platform.webservices.netsuite.com"
wsdl.namespace = "urn:core_2011_2.platform.webservices.netsuite.com"
end
response = client.request(:body ) do
soap.element_form_default = :qualified
soap.body = {"urn:login" =>
{
"urn:passport" =>
{
"urnl:email" => "foo#bar.com",
"urnl:password" => "foobar123",
"urnl:account" => "12345"
}
}
}
end
below is the soap request as seen in SOAPUi
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:messages_2011_2.platform.webservices.netsuite.com" xmlns:urn1="urn:core_2011_2.platform.webservices.netsuite.com">
<soapenv:Header>
<urn:partnerInfo> </urn:partnerInfo>
<urn:applicationInfo> </urn:applicationInfo>
</soapenv:Header>
<soapenv:Body>
<urn:login>
<urn:passport>
<urn1:email>foo#bar.com</urn1:email>
<urn1:password>foobar123</urn1:password>
<urn1:account>12345</urn1:account>
</urn:passport>
</urn:login>
</soapenv:Body>
</soapenv:Envelope>
thanks
You're code is almost correct. I changed the SOAP endpoint, specified the urn1 namespace within the request block and moved the SOAP action from the request body Hash to the request method.
client = Savon::Client.new do
wsdl.endpoint = "https://webservices.netsuite.com/services/NetSuitePort_2011_2"
wsdl.namespace = "urn:messages_2011_2.platform.webservices.netsuite.com"
end
response = client.request(:urn, :login) do
soap.namespaces["xmlns:urn1"] = "urn:core_2011_2.platform.webservices.netsuite.com"
soap.body = {
"urn1:passport" => {
"urn1:email" => "foo#bar.com",
"urn1:password" => "foobar123",
"urn1:account" => "12345"
}
}
end
Hope that helps!
Cheers,
Daniel

Resources