Soap client request code for Savon 2.5.1 - ruby-on-rails

I am working with the Savon gem (version 2.5.1) for creating a Soap request and need if to be formatted as follows:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:soap1="urn:website.co.uk/soap:callreport7">
<soap:Header>
<soap1:callcreditheaders>
<soap1:company>?</soap1:company>
<soap1:username>?</soap1:username>
<soap1:password>?</soap1:password>
</soap1:callcreditheaders>
</soap:Header>
<soap:Body>
<soap1:Test07a>?</soap1:Test07a>
</soap:Body>
</soap:Envelope>
I have so far come up with the following:
client = Savon.client(
wsdl: "CallReport7.wsdl",
env_namespace: :soap,
soap_header: {
"soap1:callcreditheaders" => {
'soap1:company' => 'XXXX',
'soap1:username' => 'XXXX',
'soap1:password' => 'XXXX'
}
}
)
response = client.call(:test07a, message: "Test" )
This is returning an error when running in the console of:
Savon::SOAPFault: (soap:Server) An internal system error has occurred
If I remove the soap_header hash then the test runs and returns:
<?xml version="1.0" encoding="utf-8"?>
<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>
<Test07aResponse xmlns="website.co.uk/soap:callreport7">
<TestResult>
<datetime>2014-06-06T14:18:35.081125+01:00</datetime>
</TestResult>
</Test07aResponse>
</soap:Body>
</soap:Envelope>
The problem is I need the header information and I cannot work out how to format the request for this.

As usual: First create a valid request using SoapUI. Then build the equivalent (doesn't have to be exact the same) in Savon.

It turned out the problem was with the envelope. I enabled logging in my code so I could see the SOAP produced by Savon and this then allowed me to try the request in SoapUI and do some trial and error testing. Turned out the problem was with the Envelope so the below fixed the problem in my case:
client = Savon.client(
wsdl: "CallReport7.wsdl",
pretty_print_xml: true,
log: true,
env_namespace: :soap,
namespaces: {"xmlns:soap" => "http://www.w3.org/2003/05/soap-envelope", "xmlns:soap1" => "urn:website.co.uk/soap:callreport7"},
soap_header: {
"soap1:callcreditheaders" => {
'soap1:company' => 'XXXX',
'soap1:username' => 'XXXX',
'soap1:password' => 'XXXX'
}
}
)
response = client.call(:test07a, message: "Test" )
The logging line of code was the key to solving this problem for me.

Related

invalid SOAP request needs

I'm using savon to make requests against a SOAP service.
Regardless, I'm having trouble making Savon client call.
below mentioned are my ruby code
client = Savon.client(
wsdl: "https://<URL>",
soap_header: { 'Content-Type:' => "text/xml"},
log: true,
pretty_print_xml: true
)
client.call(:get_active_employees_info,:xmlns =>"http://tempuri.org/") do
message("AppID" => "*******","Username" => "*****","Password" => "******")
end
which return
Savon::HTTPError: HTTP error (400)
but same snippets run on Postman
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<GetActiveEmployeesInfo xmlns="http://tempuri.org/">
<AppID>**********</AppID>
<Username>********</Username>
<Password>**********</Password>
</GetActiveEmployeesInfo>
</soap12:Body>
</soap12:Envelope>
I think that the problem is related to the request body that you are building.
Since you have a working example, I would start by checking the request's body build by savon. To do this, use the following code:
ops = client.operation(:get_active_employees_info)
puts ops.build(message: {"AppID" => "*******","Username" => "*****","Password" => "******"}).pretty
Then, compare generated message with the one from Postman. I hope it helps.

Savon using built in request builder instead of raw xml

If i use savon with raw xml everything works fine, this is the raw xml example:
request = client.call(:authenticate, xml:'<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="xxxx/">
<SOAP-ENV:Body>
<ns1:authenticate>
<ns1:username>user</ns1:username>
<ns1:password>pwd</ns1:password>
<ns1:cultureInfo>it</ns1:cultureInfo>
</ns1:authenticate>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>')
If I use the builtin method to call the method I got an error, this is the code:
credentials={ username: 'user', password: 'pwd!!', cultureInfo: "it" }
response = client.call(:authenticate, message: credentials)
This is the xml produced by the above code:
<?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:wsdl="http://tempuri.org/"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body>
<wsdl:authenticate>
<username>user</username>
<password>pwd</password>
<cultureInfo>it</cultureInfo>
</wsdl:authenticate>
</env:Body>
</env:Envelope>
Any Idea?
I usually do just this (untested). It's not pretty but it works.
credentials = { 'ns1:username' => 'user',
'ns1:password' => 'pwd!!',
'ns1:cultureInfo' => "it" }
response = client.call(:authenticate, message: credentials)
You might want to adapt the use of ns1 to the actually used namespace in your case.

How to remove headers set by Savon?

I need to hit a SOAP service, however, the server won't accept my request but throws an error due to the below header and footer in the request.
As per the logs, the request/response looks like below:
SOAP **request**: http://www.url.co.au/wserv/wslms.php
SOAPAction: "insertlmsdata", Content-Type: text/xml;charset=UTF-8, Content-Length: 938
<?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="urn:lmsdataautomation" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body>
<tns:insertlmsdata>
<lmsinfo>
<userCred>
<clientCode>code</clientCode>
<username>name</username>
<password>ee##!</password>
</userCred>
<lead>
<requestno>3</requestno>
<firstname>Meckinsey</firstname>
<lastname>Meth</lastname>
<email>meckinsey.meth#er.com</email>
<mobileno>4233333333</mobileno>
<keyword>Romali</keyword>
<requestMessage>looking for Romali</requestMessage>
<responseMessage>Romadd</responseMessage>
<operator>you</operator>
<circle>Romaon</circle>
<requestDate>20-04-2017</requestDate>
<shortCode>2222</shortCode>
<category>DOM</category>
<city>Sydney</city>
<destination>Perth</destination>
</lead>
</lmsinfo>
</tns:insertlmsdata>
</env:Body>
</env:Envelope>
HTTPI POST request to www.egggo.co.au (excon)
SOAP **response** (status 200)
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:lmsdataautomation" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:insertlmsdataResponse>
<output xsi:type="xsd:string"><output>Either parsed xml is not valid or contains special chars like & "'</output></output>
</ns1:insertlmsdataResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I have looked thoroughly Savon Documentation, couldn't find anything relevant. Can I configure Savon to not add headers, footer, envelope and just the body?
Basically to ignore the below data:
SOAP request: http://www.url.co.au/wserv/wslms.php
SOAPAction: "insertlmsdata", Content-Type: text/xml;charset=UTF-8, Content-Length: 938
Otherwise, the SOAP server rejects the request. Please help, TIA
Adding the body of the request:
client = Savon.client(wsdl: url, log: true, logger: Rails.logger, log_level: :debug, pretty_print_xml: true, encoding: 'UTF-8')
response = client.call(:insertlmsdata, message: {'lmsinfo'=> {'userCred'=> {'clientCode' => 'code', 'username' => 'dom', 'password' => '#pass' }, 'lead' => {'requestno' => 3, 'firstname'=>'Methyl', 'lastname'=> 'Orange', 'email' => 'methyl.orange#egg.com', 'mobileno' => '55555555', 'keyword' => 'atlanta', 'requestMessage' => 'looking for atlant', 'responseMessage' => 'dd', 'operator' => 'you', 'circle' => 'sydney', 'requestDate' => '04-20-2017', 'shortCode' => 2222, 'category'=> 'DOM', 'city' => 'Sydney', 'destination' => 'Atlanta' } } })

How to organize the syntax in this SOAP request packet sent with gem Savon in a ruby script?

I am trying to send a SOAP request to a resource on the web. It is expecting to receive this:
<?xml version="1.0" encoding="utf-8"?>
<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>
<DiscoverParameterValues xmlns="http://comscore.com/">
<parameterId>loc</parameterId>
<query xmlns="http://comscore.com/ReportQuery">
<Parameter KeyId="geo" Value="124" />
</query>
</DiscoverParameterValues>
</soap:Body>
</soap:Envelope>
This is the Ruby code that Im using to send a request that will result in an XML similar to the one above.
require 'savon'
#Connect to the Comscore API
client = Savon.client(
wsdl:"https://api.comscore.com/KeyMeasures.asmx?WSDL",
basic_auth: ["username", "pw" ],
log: true, :pretty_print_xml=>true)
And this is the XML thats generated:
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tns="http://comscore.com/"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ins0="http://comscore.com/Report"
xmlns:ins1="http://comscore.com/ReportQuery"
xmlns:ins2="http://comscore.com/ReportModel"
xmlns:ins3="http://comscore.com/FetchMedia"
xmlns:ins4="http://comscore.com/Media/Response">
<env:Body>
<tns:DiscoverParameterValues>
<tns:parameterId>loc</tns:parameterId>
==> <tns:query>
<tns:Parameter>
<tns:attributes>
<tns:KeyId>geo</tns:KeyId>
<tns:Value>124</tns:Value>
</tns:attributes>
</tns:Parameter>
==> </tns:query>
</tns:DiscoverParameterValues>
</env:Body>
</env:Envelope>
As you can see there is a difference in how the XML from my code and the XML thats required looks. Ive marked it with "=>"
Here is the gem documentation page that Im using to structure my query:
http://savonrb.com/version2/locals.html
Ive tried playing around with this but I dont understand how to get the "attributes" to work right.
Any suggestions?
UPDATE:
After reading this post, I changed my ruby syntax to the following:
attributes = { "KeyId"=>"geo", "Value" =>"124"}
parameter = {
:parameterId=>"loc",
:query=>{ "Parameter" => { attributes: attributes}}
}
response = client.call(:discover_parameter_values,
message:{:parameterId=>"loc",
:query =>{ "Parameter"=> "", :attributes! =>
{ "Parameter" =>
{ "KeyId" => "geo" , "Value"=>"124" }}},
},
:attributes => {"xmlns" => "http://comscore.com/" })
My XML changed to this:
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tns="http://comscore.com/"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ins0="http://comscore.com/Report"
xmlns:ins1="http://comscore.com/ReportQuery"
xmlns:ins2="http://comscore.com/ReportModel"
xmlns:ins3="http://comscore.com/FetchMedia"
xmlns:ins4="http://comscore.com/Media/Response">
<env:Body>
<tns:DiscoverParameterValues xmlns="http://comscore.com/">
<tns:parameterId>loc</tns:parameterId>
<tns:query>
<tns:Parameter KeyId="geo" Value="124"/>
</tns:query>
</tns:DiscoverParameterValues>
</env:Body>
</env:Envelope>
So everything works EXCEPT - I cannot set "attributes" on the "query" tag.
I would like to set this as an attribute on the query: "xmlns=http://comscore.com/ReportQuery"
How do I do that?
Question: Does it work?
Savon uses the namespace qualifiert in a different way than your first example.
In the following snippet the tags within have an implicit namespace as specified in the attribute xmlns.
<DiscoverParameterValues xmlns="http://comscore.com/">
<parameterId>loc</parameterId>
<query xmlns="http://comscore.com/ReportQuery">
<Parameter KeyId="geo" Value="124" />
</query>
</DiscoverParameterValues>
Savon uses a different syntax. It defines all needed namespace in the envelope and uses the prefixes per tag later. Different syntax for the same expression.
SoapUI uses often the former variant, Savon the latter.
ParameterIdcomes in both cases from the namespace http://comscore.com/.
UPDATE response:
You can go different ways:
Is usually cheat: I just write fully qualified keys, eg.
...
:query => { "Parameter" => "", :attributes! =>
{ "Parameter" =>
{ "ins1:KeyId" => "geo", "ins1:Value" => "124" }}},
...
If you absolutely want to put the key as attribute on "query" then you can define it like this:
response = client.call(:discover_parameter_values,
message:{:parameterId=>"loc",
:query =>{ "Parameter"=> "", :attributes! =>
{ "Parameter" =>
{ "KeyId" => "geo" , "Value"=>"124" }}},
:attributes! => {'tns:query' =>
{ "xmlns" => "http://comscore.com/ReportQuery" }
},
:attributes => {"xmlns" => "http://comscore.com/" })

eBay API GetCategoryFeaturesRequest returns 'Unsupported API call' error

I am trying to get CategoryFeatures using Typhoeus::Request from eBay API. I am using Ruby Version 1.9.3 and Rails 3.2.3 with Ubuntu Server 11.04.
My code is below:
xml = <GetCategoryFeaturesRequest xmlns="urn:ebay:apis:eBLBaseComponents">
<RequesterCredentials>
<eBayAuthToken> MY_eBayAuthToken </eBayAuthToken>
</RequesterCredentials>
<WarningLevel>High</WarningLevel>
</GetCategoryFeaturesRequest>
header = {
"X-EBAY-API-DEV-NAME" => my_devID,
"X-EBAY-API-APP-NAME" => my_appID,
"X-EBAY-API-CERT-NAME" => my_certID,
"X-EBAY-API-CALL-NAME" => "GetCategoryFeatures",
"X-EBAY-API-COMPATIBILITY-LEVEL" => "1.3.0",
"X-EBAY-API-SITEID" => 1,
"Content-Type" => "text/xml",
}
url = "https://api.sandbox.ebay.com/ws/api.dll "
res = Typhoeus::Request.post(url, :body => xml, :headers => header )
I got this error:
<?xml version=\"1.0\" encoding=\"UTF-8\" ?>
<GeteBayOfficialTimeResponse xmlns=\"urn:ebay:apis:eBLBaseComponents\">
<Timestamp>2012-07-05 06:41:28</Timestamp>
<Ack>Failure</Ack><Errors>
<ShortMessage>Unsupported API call.</ShortMessage>
<LongMessage>The API call \"GeteBayOfficialTime\" is invalid or not supported in this release.</LongMessage>
<ErrorCode>2</ErrorCode>
<SeverityCode>Error</SeverityCode>
<ErrorClassification>RequestError</ErrorClassification>
</Errors>
<Build>14991382</Build>
</GeteBayOfficialTimeResponse>
Does anyone know how to fix it?
Try to test your XMl in the test tool :
https://developer.ebay.com/DevZone/build-test/test-tool/default.aspx
I run this XML and it works:
<?xml version="1.0" encoding="utf-8"?>
<GetCategoryFeaturesRequest xmlns="urn:ebay:apis:eBLBaseComponents">
<RequesterCredentials>
<eBayAuthToken> my_Token </eBayAuthToken>
</RequesterCredentials>
</GetCategoryFeaturesRequest>

Resources