I'm attempting to utilize the ruby gem Savon to connect to a web service provided by propertyware (http://propertyware.com/apidocs/Getting-Started). I've successfully connected to the service via SoapUI and executed an echoString request. When I try to do the same via Ruby I get a null user authentication error.
Here's what I've tried in Ruby...
require 'rubygems'
require 'savon'
client = Savon::Client.new do
wsdl.document = 'http://propertyware.com/pw/services/PWServices?wsdl'
wsse.credentials 'username', 'pwd'
end
response = client.request :web, :echo_string, :body => {:arg => "Hello world."}
Which produces the following xml...
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:web="http://propertyware.com/pw/services/PWServices"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ins0="http://propertyware.com/pw/services/PWServices"
xmlns:ins1="http://criteria.soap.propertyware.com"
xmlns:ins2="urn:PWServices"
xmlns:ins3="http://soap.propertyware.com"
xmlns:ins4="http://xml.apache.org/xml-soap">
<env:Header>
<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>user</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">pwd</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</env:Header>
<env:Body>
<web:echoString>
<arg>Hello world.</arg>
</web:echoString>
</env:Body>
</env:Envelope>
Here's the xml produced by SoapUI...
<soapenv:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:web="http://webservices" >
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-1" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>user</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">pwd</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">R41mCRd+tY+xthhE/YISLQ==</wsse:Nonce>
<wsu:Created>2011-10-25T09:52:40.220Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<web:echoString soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<arg xsi:type="xsd:string">?</arg>
</web:echoString>
</soapenv:Body>
</soapenv:Envelope>
One obvious difference is that SoapUI includes a nonce key and a createdAt timestamp. I'm not sure how to make savon do that without moving to digest auth. (and fwiw that doesn't work).
I'm not real savoy in the ways of web services - any guidance would be much appreciated.
Also - here's the response when I attempt to connect via savon:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<soapenv:Fault>
<faultcode xmlns:ns1="http://xml.apache.org/axis/">ns1:Server.Unauthenticated</faultcode>
<faultstring>User 'null' not authenticated (unknown user)</faultstring>
<detail>
<ns2:hostname xmlns:ns2="http://xml.apache.org/axis/">rcpppwwwapt012.realpage.com</ns2:hostname>
</detail>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>
TIA!
Bob
Try setting the digest in the wsse to true. This will instruct Savon to add the nonce and createdAt to the request:
wsse.credentials 'username', 'pwd', :digest
See the comments of this object for more info
In Savon version 2 you need following:
client = Savon.client do
wsdl 'https://webservice/theservice.wsdl'
wsse_auth("user", "pass", :digest)
end
I believe the first step would be to deal with the error.
<faultstring>User 'null' not authenticated (unknown user)</faultstring>
Your credentials aren't being passed to the service.
Related
Here is what the service is supposed to look like (from Soap UI):
<wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-044848C648B0DCCFBC14248931953381">
<wsse:Username>26613</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">h3hzoxJgSNIrNsJTc8gGwdNGhe0=</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">JvR9+Aefno3PVz++ik/47w==</wsse:Nonce>
<wsu:Created>2015-02-25T19:39:55.336Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
and here is what savon produces:
<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>26613</wsse:Username>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">NmU4NWNiYWIxM2M0ZmYyN2IxZjJiNGQ0MGZmZDJkNjJiODJmNmM5OQ==</wsse:Nonce>
<wsu:Created>2015-02-25T16:55:40Z</wsu:Created>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">lr8M7oMCjEsh7Maj07AyW4CoTlE=</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
One thing I noticed that is different is the mustUnderstand line. I've tried to add like so:
client = Savon.client(
wsdl: 'gofish?wsdl',
pretty_print_xml: true,
log: true,
log_level: :debug,
env_namespace: :soapenv,
soap_header: {'wsse:Security' => 'mustUnderstand="1"'}
)
But this generates the following:
<wsse:Security>mustUnderstand="1"</wsse:Security>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
Which is not exactly what I want. Any thoughts on how to get inside the wsse:Security element like the SoapUI has it?
EDIT:
Based upon Steffen's suggestion, I get the following results:
<soapenv:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cmn="http://www.sircon.com/WebServices/services/OnboardingServices.wsdl" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" soapenv:mustUnderstand="1">
<soapenv:Header>
<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>26613</wsse:Username>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">NTcyN2QyNjliYmMxZjg2Yjc2YjA0MTY0NjE5MjdjZjQ4ZGY0YzlhYQ==
</wsse:Nonce>
<wsu:Created>2015-02-25T21:28:53Z</wsu:Created>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">h8Qfcn6gA4swa/l+LmJR+RdCSto=</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<cmn:RecruiterOnboardingRequest>
<some>key</some>
<and>another one</and>
</cmn:RecruiterOnboardingRequest>
</soapenv:Body>
</soapenv:Envelope>
EDIT 2:
Opened a ticket around this issue here: https://github.com/savonrb/savon/issues/667. Feel free to check it out to learn more.
I think you would need to define namespaces in your client, eg.
client = Savon.client(
wsdl: 'gofish?wsdl',
pretty_print_xml: true,
log: true,
log_level: :debug,
env_namespace: :soapenv,
namespaces: {'soapenv:mustUnderstand' => "1"}
)
You probably have to list all the other namespaces you need as well.
You con try something crazy. Go to your gem directory and find the file
...akami-1.2.2/lib/akami/wsse.rb
change line #158 from
:attributes! => { "wsse:Security" => { "xmlns:wsse" => WSE_NAMESPACE } }
to
:attributes! => { "wsse:Security" =>
{ "mustUnderstand" => "1",
"xmlns:wsse" => WSE_NAMESPACE} }
That's not pretty but it might work
I'm trying to write code in Ruby with the Savon gem (v2) that fetches account information from a SOAP api, but I'm having an issue with passing an Array.
CampaignIds is supposed to be an array of integers.
Here is my code:
client = Savon.client(wsdl: "https://api7secure.publicaster.com/Pub7APIV1/Campaign.svc?singleWsdl")
message = {
"EncryptedAccountID" => api_key,
"APIPassword" => api_password,
"CampaignIds" => [3,4],
"StartDate" => yesterday,
"EndDate" => yesterday,
"IncludeTests" => false
}
client.call(:get_comparative_report_details_data, message: message)
which produces the following request:
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ins0="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns:tns="http://BlueSkyFactory.Publicaster7.Public.API" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<env:Body>
<tns:GetComparativeReportDetailsData>
<tns:EncryptedAccountID>*****</tns:EncryptedAccountID>
<tns:APIPassword>*****</tns:APIPassword>
<tns:CampaignIds>3</tns:CampaignIds>
<tns:CampaignIds>4</tns:CampaignIds>
<tns:StartDate>2014-01-06</tns:StartDate>
<tns:EndDate>2014-01-06</tns:EndDate>
<tns:IncludeTests>false</tns:IncludeTests>
</tns:GetComparativeReportDetailsData>
</env:Body>
</env:Envelope>
whereas, if I play around in SOUP UI, the request should look like:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:blu="http://BlueSkyFactory.Publicaster7.Public.API" xmlns:arr="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<soapenv:Header/>
<soapenv:Body>
<blu:GetComparativeReportData>
<blu:EncryptedAccountID>*****</blu:EncryptedAccountID>
<blu:APIPassword>*****</blu:APIPassword>
<blu:CampaignIds>
<arr:int>3</arr:int>
<arr:int>4</arr:int>
</blu:CampaignIds>
<blu:StartDate>2014-01-06T16:21:47-05:00</blu:StartDate>
<blu:EndDate>2014-01-07T16:21:47-05:00</blu:EndDate>
<blu:IncludeTests>false</blu:IncludeTests>
</blu:GetComparativeReportData>
</soapenv:Body>
</soapenv:Envelope>
Any Ideas?
You can try this syntax :
message = {
...
"CampaignIds" => {"int" => [3,4]},
...
}
That'll produce this output :
<CampaignIds>
<int>3</int>
<int>4</int>
</CampaignIds>
Hope this helps.
I just experienced the same issue and found a solution, that's not dependent on having a permissive SOAP endpoint. You can configure this behavior as a global using the unwrap key. This key is given as an option to Gyoku which generates the XML for Savon.
client = Savon.client(wsdl: 'https://example.com/wsdl', unwrap: true)
client.call(:cook_meal, message: { 'Ingredients' => ['tomato', 'basil', 'mozzarella'] })
Although the issue is old, better late than never.
I am trying to get the pan info from the income tax of india web API.
The standard XML for the request is this
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:pan="http://panws.dit.tcs.com/" xmlns:typ="http://panws.dit.tcs.com/types/">
<soapenv:Header/>
<soapenv:Body>
<pan:getPanInfo>
<login>
<typ:userName>xxxxxxxxx</typ:userName>
<typ:password>xxxxxxxxxx</typ:password>
</login>
<panNo>
<typ:panNo>xxxxxxxxxxxxx</typ:panNo>
</panNo>
</pan:getPanInfo>
</soapenv:Body>
</soapenv:Envelope>
I am using SAVON ruby gem to submit the request in the above format. My code is
client = Savon.client do |globals|
globals.wsdl 'https://incometaxindiaefiling.gov.in/e-FilingWS/ditws/PanWS.wsdl'
end
client.call(:get_pan_info, message: {
"login" => {
"typ:userName" => "xxxxxxxxxx",
"typ:password" => "xxxxxxxxxxxxxxxx"
},
"panNo" => {
"typ:panNo" => "xxxxxxxxxxxxxxx"
}
})
It creates the XML to be submitted is here:
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://panws.dit.tcs.com/" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ins0="http://panws.dit.tcs.com/types/">
<env:Body>
<tns:getPanInfo>
<tns:login>
<typ:userName>xxxxxxx</typ:userName>
<typ:password>xxxxxxxxxxxx</typ:password>
</tns:login>
<tns:panNo>
<typ:panNo>xxxxxxxxxxxxxx</typ:panNo>
</tns:panNo>
</tns:getPanInfo>
</env:Body>
</env:Envelope>
and it gives 500 External server Error,
Can any body please point me out where i am wrong or how to create the same XML for the request.
You should set the correct env_namespace :
Savon.client(env_namespace: :soapenv)
Ctrl+F for env_namespace here
I have this (working) example in php:
$usernameToken = new SoapHeaderUsernameToken( $password, $username );
$soapHeaders[] = new SoapHeader("urn:localhost-catalog", 'UsernameToken', $usernameToken);
$client = new SoapClient("my_client_url");
$client->__setSoapHeaders( $soapHeaders );
But I want a client in Ruby. I'm using the savon gem, which can do authentication for you. So far, I have the following method:
def my_soap_client
client = Savon::Client.new do
wsdl.document = "my_client_url"
end
client.wsse.credentials "usr", "pass" # Adding :digest doesn't seem to help
return client
end
# I make requests like this:
my_soap_client.request :wsdl, "getProductGroups", :parent_id => 1
I can successfully list available actions, but if I try to make a request, the result is always "(SOAP-ENV:Client) Missing parameter". Also, it doesn't matter if I pass correct credentials or fake ones. That is why I believe the authentication fails.
Hope someone can help!
Using Wireshark sniffer I intercepted SOAP request that your PHP code sends. It looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="urn:examples:helloservice"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ns2="urn:localhost-catalog"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Header>
<ns2:UsernameToken>
<Password>pass</Password>
<Username>login</Username>
</ns2:UsernameToken>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:getProductGroups>
<parentId>1</parentId>
</ns1:getProductGroups>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Here you can see that this code adds ns2 namespace for UsernameToken header.
Then I intercepted SOAP request that sends your Ruby 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://www.ecerami.com/wsdl/HelloService.wsdl"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-1"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>usr</wsse:Username>
<wsse:Password
Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">
pass
</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</env:Header>
<env:Body>
<wsdl:getProductGroups>
<parentId>1</parentId>
</wsdl:getProductGroups>
</env:Body>
</env:Envelope>
You can see the difference - UsernameToken is wrapped into Security element and namespace for UsernameToken is "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
Your PHP code uses custom authorization and savon does not support it via wsse property. I looked into Savon source code, it uses Akami.wsse and in its code there is no possibility to set namespace. This means you need to manually construct headers. Here is the code in Ruby that generates SOAP request like you possibly need:
require 'savon'
client = Savon::Client.new do
wsdl.document = "test.wsdl"
end
client.request :wsdl, "sayHello" do
soap.namespaces["xmlns:ns2"] = "urn:localhost-catalog"
soap.header = { "ns2:UsernameToken" =>
{"Password" => "pass", "Username" => "login"}
}
soap.body = { :parent_id => 1 }
end
It generate the following SOAP request:
<?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://www.ecerami.com/wsdl/HelloService.wsdl"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns2="urn:localhost-catalog">
<env:Header>
<ns2:UsernameToken>
<Password>pass</Password>
<Username>login</Username>
</ns2:UsernameToken>
</env:Header>
<env:Body>
<wsdl:sayHello>
<parentId>1</parentId>
</wsdl:sayHello>
</env:Body>
</env:Envelope>
Hope this helps!
to set a header in Savon use the following expression:
client.request :wsdl, "getProductGroups" do
soap.header = { :header_key => "your header goes here",
:attributes! => { :attr => "your attribute" }
}
soap.body = { :parent_id => 1 }
end
perhaps that helps you.
-st
I have the following WSDL, generated from soapUI. When I test the
request from soapUI, it works fine but throws exception from savon.
I am using savon 0.9.2 on Linux.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/
envelope/" xmlns:mes="http://www.domain.com/sub/05/00/Messages">
<soapenv:Header/>
<soapenv:Body>
<mes:loginRequest>
<!--Optional:-->
<mes:Username>admin</mes:Username>
<!--Optional:-->
<mes:Password>pass</mes:Password>
<!--Optional:-->
<mes:ImpersonationUsername></mes:ImpersonationUsername>
<!--Optional:-->
<mes:ApplicationName></mes:ApplicationName>
</mes:loginRequest>
</soapenv:Body>
</soapenv:Envelope>
The script, which causes Errors:
require 'rubygems'
require 'savon'
require 'pp'
client = Savon::Client.new "http://domain/Service.asmx?WSDL"
response = client.request(:mes, "login") do
soap.body = {
"mes:Username" => "test",
"mes:Password" => "test",
"mes:ImpersonationUsername"=>"Test",
"mes:ApplicationName"=>"test"
}
end
pp response.to_hash
The Output:
D, [2011-05-10T16:06:14.316827 #11254] DEBUG -- : <?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><LoginResult xmlns="http://www.domain.com/sub/
05/00/
Messages"><ErrorDetails><Items><SfExceptionItem><ExceptionType>System.NullReferenceException</
ExceptionType><AssemblyName>mscorlib, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b73a5c561934e089</
AssemblyName><Message>Object reference not set to an instance of an
object.</Message></SfExceptionItem></Items><FaultCode>UnknownError</
FaultCode><Message>Object reference not set to an instance of an
object.</Message></ErrorDetails></LoginResult></soap:Body></
soap:Envelope>
{:login_result=>
{:error_details=>
{:items=>
{:sf_exception_item=>
{:message=>"Object reference not set to an instance of an
object.",
:exception_type=>"System.NullReferenceException",
:assembly_name=>
"mscorlib, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b73a5c561934e089"}},
:message=>"Object reference not set to an instance of an
object.",
:fault_code=>"UnknownError"},
:xmlns=>
"http://www.domain.com/sub/05/00/Messages"}}
The output from SoapUI is the following:
<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>
<LoginResult xmlns="http://domain/sub/05/00/Messages">
<UserTicket>95bfaa81149f4c118c8724b837235cd5</UserTicket>
</LoginResult>
</soap:Body>
</soap:Envelope>
You might want to set the namespace in your savon request: client.namespaces["xmlns:mes"] = "http://www.domain.com/sub/05/00/Messages"
the request you send creates the following soap message
<?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:mes="urn:namespace.com"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body>
<mes:login>
<mes:Username>test</mes:Username>
<mes:Password>test</mes:Password>
<mes:ImpersonationUsername>Test</mes:ImpersonationUsername>
<mes:ApplicationName>test</mes:ApplicationName>
</mes:login>
</env:Body>
I guess that's not what your intention is?
please insert the following lines into your code after the .new
Savon.configure do |c|
c.log = true
end
that shows the outgoing message.