soap4r SOAP::FaultError - ruby

I am new to soap and I am having the problems with it already! I am using soap4r gem.
gem 'soap4r', :git => 'git://github.com/felipec/soap4r.git'
require 'soap/wsdlDriver'
require 'soap/rpc/driver'
require 'soap/mapping/mapping.rb'
And I initialize the rpc driver as follows:
def initialize
#username = "username"
#password = "password"
endpoint = "https://someurl.php"
namespace = "abc:somenamespace"
#driver = SOAP::RPC::Driver.new(endpoint, namespace)
end
When I visit the endpoint from the browser I am getting this error:
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode xsi:type="xsd:string">SOAP-ENV:Client</faultcode>
<faultactor xsi:type="xsd:string"/>
<faultstring xsi:type="xsd:string">Operation '' is not defined in the WSDL for this service
</faultstring>
<detail xsi:type="xsd:string"/>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Also, when I do this from irb:
client = SOAP::WSDLDriverFactory.new("endpoint?wsdl").create_rpc_driver
I am getting this error:
RuntimeError: part: return cannot be resolved
from /home/sadiksha/.rvm/rubies/ruby-1.8.7-p358/lib/ruby/1.8/wsdl/soap/methodDefCreator.rb:144:in `rpcdefinedtype'
from /home/sadiksha/.rvm/rubies/ruby-1.8.7-p358/lib/ruby/1.8/wsdl/soap/methodDefCreator.rb:56:in `collect_rpcparameter'
.
.
.
But when I do this:
client = SOAP::WSDLDriverFactory.new(endpoint).createDriver
and list methods by
client.methods(false)
and I have one method getName. When I try to access that method by client.getName({:username => "username", :password => "password") it gives me error saying
SOAP::FaultError: Username doesn't exist
from
I am sorry for making it too long! I have been searching about it for a long time now. But was not able to find the specific answer. I hope someone will have answer to my question. I am thinking that it might be some authentication error.

Using the following can help you trouble shoot whats going on. It will dump the generated and received XML to console.
myWebServiceInstance.wiredump_dev = STDERR

Related

how to specify namespace in SOAP request with 'savon' gem?

I am using recent version of savon gem and trying to send a SOAP request i am getting this error about invalid url:
Invalid URL: %7Bendpoint%20address%7D (ArgumentError)
from /home/vagrant/.rvm/gems/ruby-2.1.0/gems/httpi-2.3.0/lib/httpi/request.rb:27:in `url='
from /home/vagrant/.rvm/gems/ruby-2.1.0/gems/savon-2.8.0/lib/savon/operation.rb:103:in `build_request'
from /home/vagrant/.rvm/gems/ruby-2.1.0/gems/savon-2.8.0/lib/savon/operation.rb:51:in `call'
from /home/vagrant/.rvm/gems/ruby-2.1.0/gems/savon-2.8.0/lib/savon/client.rb:36:in `call'
My code is:
require "savon"
require "excon"
Excon.defaults[:ssl_verify_peer] = false
class Payback
attr_reader :connection, :client, :operation, :message
SOAP_URL = "https://partnertest.payback.in/PBExternalServices/v1/soap?wsdl"
def initialize operation, message
#client = Savon.client(wsdl: "https://partnertest.payback.in/PBExternalServices/v1/soap?wsdl", ssl_verify_mode: :none)
#operation = operation
#message = message
end
def response
#response ||= client.call(operation, message: message)
end
end
this is how i am using it.(I know something is wrong with namespaces)
payback = Payback.new :get_account_balance,
{"typ:Authentication" => { "typ1:Principal" => { "typ1:PrincipalValue" => 9899012182,
"typ1:PrincipalClassifier" => 3 }}}
payback.response
I need to construct this XML with savon
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:typ="http://www.payback.net/lmsglobal/ws/v1/extint/types" xmlns:typ1="http://www.payback.net/lmsglobal/xsd/v1/types">
<soapenv:Header/>
<soapenv:Body>
<typ:GetAccountBalanceRequest>
<typ:Authentication>
<typ1:Principal>
<typ1:PrincipalValue>9899012182</typ1:PrincipalValue>
<typ1:PrincipalClassifier>3</typ1:PrincipalClassifier>
</typ1:Principal>
</typ:Authentication>
</typ:GetAccountBalanceRequest>
</soapenv:Body>
</soapenv:Envelope>
i don't know what i am doing wrong here, please help.
I noticed that on line 5820 of the WSDL file the location looks like this:
<soap:address location="{endpoint address}"/>
Could it be the problem?
Edited 1.
Open up in your browser: https://partnertest.payback.in/PBExternalServices/v1/soap?wsdl
Search for {endpoint address} string on the page.
I'm far from understand this particular WSDL document, but I wonder if there must be something else in place of {endpoint address}, like a real URI. E.g. could it be the WSDL document that has the problem?
Edited 2
Tried to remove the typ and typ1 which were not recognized by the service. Ended up with a working code that returns a valid response:
puts Savon.client(
wsdl: 'https://partnertest.payback.in/PBExternalServices/v1/soap?wsdl',
endpoint: 'https://partnertest.payback.in/PBExternalServices/v1/soap',
ssl_verify_mode: :none
).call(
:get_account_balance,
:message => {
'Authentication' => {
'Principal' => {
'PrincipalValue' => 9899012182,
'PrincipalClassifier' => 3
}
}
}
)

Savon: WCF Soap service with wsse auth: AddressFilter mismatch at the EndpointDispatcher

I am trying to create SOAPClient using Savon - rubygem.
Its a WCF soap service with WSSE auth over https. Here is the code that I tried:
require 'savon'
client = Savon::Client.new do
wsdl.document = "https://svc.sxxxxxify.com:8081/ConfSet.svc?wsdl"
config.soap_version = 2
wsse.credentials "aa5#xxasxsaxsh.com", "test123"
end
p client.wsdl.soap_actions
response = client.request :get_user_clients
p response
But I get this error:
http://www.w3.org/2005/08/addressing/soap/fault2012-10-26T06:07:42.247Z2012-10-26T06:12:42.247Zs:Sendera:DestinationUnreachableThe message with To '' cannot be processed at the
receiver, due to an AddressFilter mismatch at the EndpointDispatcher.
Check that the sender and receiver's EndpointAddresses
agree.
.
The message with To '' cannot be processed at the receiver, due to an
AddressFilter mismatch at the EndpointDispatcher. Check that the
sender and receiver's EndpointAddresses agree. (Savon::SOAP::Fault)
Please help me solve this problem
I had the some problem. I've solved the 'To' problem by providing a header entry and a new namespace. The 'Action' header was also necessary though, and I only discovered that after inspecting SoapUI logs. Here is what worked for me:
#service_url = 'https://svc.sxxxxxify.com:8081/ConfSet.svc/service'
#action = 'your_action'
#client = Savon.client(:wsdl => "#{#service_url}?wsdl", :soap_version => 2,
:namespaces => {"xmlns:x" => "http://www.w3.org/2005/08/addressing"},
:soap_header => {"x:To" => #service_url, "x:Action" => "http://tempuri.org/#{#action}"})

Rails savon, two wsdl

I'm developing on Rails and I'm using the gem Savon (http://savonrb.com).
What I have to do is to integrate myself with a service that I wsdl has two, one for authentication and the other for various functions.
There are two wsdl:
"https://.../authentication.asmx?wsdl"
"https://.../lists.asmx?wsdl"
What I do first is this:
client = Savon::Client.new do |wsdl, http|
http.auth.ssl.verify_mode = :none
wsdl.document = "https://.../authentication.asmx?wsdl"
end
response = client.request :soap, :login, :body => {:username => "...", :password => "..."}
Once logged in I would need to use the second wsdl to perform my function, but I can not declare another client within authentication lose the first thing I said.
response = client.request :get_list_collection do
soap.endpoint = URI(URI.escape("https://.../lists.asmx?wsdl"))
end
I've tried many but I found no solution.
Any idea how to solve this problem?

API Call With Savon SOAP Client Results In ContractFilter mismatch at the EndpointDispatcher Error

I've run into an issue where the Savon Ruby Gem generates a SOAP API call that fails, however when I copy and paste the exact same XML message into SOAP-UI it succeeds.
I send this message:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tem="http://tempuri.org/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:vis="http://schemas.datacontract.org/2004/07/Vision.SecureOriginCommand.ServiceContracts">
<soapenv:Body>
<tem:CameraConfiguration>
<tem:request>
<vis:ClientToken>5555</vis:ClientToken>
<vis:DeviceID>26219</vis:DeviceID>
<vis:Enabled>1</vis:Enabled>
<vis:Interval>60</vis:Interval>
</tem:request>
</tem:CameraConfiguration>
</soapenv:Body>
To this API (A remote web camera configuration):
https://oapqa.onasset.com/Services/SecureOriginCommand.svc?wsdl
But it fails with this message:
SOAP response (status 500):
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<s:Fault><faultcode xmlns:a="http://schemas.microsoft.com/ws/2005/05/addressing/none">a:ActionNotSupported</faultcode>
<faultstring xml:lang="en-US">The message with Action 'oapSetSentryReportingIntervalRequest' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None)</faultstring>
</s:Fault>
</s:Body>
My first thought was that I must have made a typo in the action name. But
no, when I try the exact same message in SOAP-UI I get the following
success:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<CameraConfigurationResponse xmlns="http://tempuri.org/">
<CameraConfigurationResult xmlns:a="http://schemas.datacontract.org/2004/07/Vision.SecureOriginCommand.ServiceContracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:Error/>
<a:Result>true</a:Result>
</CameraConfigurationResult>
</CameraConfigurationResponse>
</s:Body>
</s:Envelope>
This leads me to believe that the issue is not being caused by the format
of my xml message but with the way I'm configuring my client. Here is the actual code:
Savon.configure do |config|
config.log = :debug
config.env_namespace = :soapenv
config.raise_errors = false
end
# TODO Enable ssl certficate verification
client = Savon::Client.new do
wsdl.document = TARGET_SO_WSDL
http.auth.ssl.verify_mode = :none
end
resp = client.request 'tem', 'CameraConfiguration' do
soap.namespaces['xmlns:vis'] = 'http://schemas.datacontract.org/2004/07/Vision.SecureOriginCommand.ServiceContracts'
soap.namespaces['xmlns:tem'] = 'http://tempuri.org/'
soap.body = {
'tem:request' => {
'vis:ClientToken' => ON_ASSET_API_KEY,
'vis:DeviceID' => webcam.gps_device.device_id,
'vis:Enabled' => 1,
'vis:Interval' => webcam.report_interval
}
}
end
I've spoken to the developer who maintains the API I'm trying to
access. I thought his response could provide a clue:
Binding on the RemoteSentryService was set to mexHttpBinding instead of mexHttpsBinding.
I don’t think this should give you a fault exception, because its working on .NET simulator client I have. And this endpoint is only used to generate the wsdl (MetaExchange Binding). But, given you are using a different client, I would still give it a shot.
I also regenerated the proxy from wsdl and updated my sample simulator and it looks good.
Is this issue a known issue with Savon and Microsoft SOAP
endpoints or HTTPS? Or is this issue something only I'm encountering?
Debugged it and noticed that Savon unfortunately doesn't send the correct SOAPAction HTTP header. FYI: After sending a SOAP request via soapUI, you can click on the "RAW" tab (vertically aligned on the request window) to investigate further.
Here's the complete example:
client = Savon::Client.new do
wsdl.document = TARGET_SO_WSDL
http.auth.ssl.verify_mode = :none
end
resp = client.request 'tem', 'CameraConfiguration' do
# Notice, that the SOAPAction needs to the wrapped in double quotes:
http.headers['SOAPAction'] = %("http://tempuri.org/ISecureOriginCommand/CameraConfiguration")
soap.namespaces['xmlns:vis'] = 'http://schemas.datacontract.org/2004/07/Vision.SecureOriginCommand.ServiceContracts'
soap.body = {
'tem:request' => {
'vis:ClientToken' => 5555,
'vis:DeviceID' => 26219,
'vis:Enabled' => 1,
'vis:Interval' => 60
}
}
end
Hope it works for you!

Case problem in SOAP message tag names using savon

I'm using Ruby 1.9.2 with savon 0.9.2 on Windows 7 Professional 64 bit.
I need to call a web SOAP service that requires a security token that I get from a second web SOAP service. The code I use is as follows:
require 'savon'
client = Savon::Client.new "http://some.url?wsdl"
client.wsdl.soap_actions
start_session_response = client.request :start_session do
soap.input = ["StartSession", {:xmlns => "http://some.schema" } ]
soap.body = { :userName => "User", :password => "password" }
end
do_something_response = client.request :do_something do
soap.input = [ "DoSomething", { :xmlns => "http://some.schema"} ]
soap.body = { :securityToken => start_session_response.to_hash[:start_session_response][:security_token] }
end
This results in XML that looks like:
<?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://some.schema"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body>
<DoSomething xmlns="http://some.schema">
<wsdl:securityToken>
<wsdl:tokenType>sessiontoken</wsdl:tokenType>
<wsdl:token>
.
.
.
</wsdl:token>
</wsdl:securityToken>
</DoSomething>
</env:Body>
</env:Envelope>
Never mind the weird namespace convention (or is that just me) in this XML that is savon doing its thing.
The problem I face is that the tags inside the securitytoken tag all start with a lower case letter where they should be upper case. So <tokenType> and <token> should have been <TokenType> and <Token>.
In my opinion the definition of these tags are all in the WSDL that is used to create the savon client. That definition seems not to be used or used incorrectly.
What can I do to get the correct XML/SOAP message from savon?
For later releases of Savon, you should be able to supply a 'global' option of convert_request_keys_to when you initialize your Savon client:
# In Savon 2
Savon.client wsdl:"http://some.url?wsdl", convert_request_keys_to: :camelcase
According to comments in the source file, it accepts one of :lower_camelcase, :camelcase, :upcase, or :none.
I had a similar problem with Savon and ended up using strings in stead of symbols for my hash keys, you could try something like:
soap.body = { 'TokenType'=> 'some_value', 'Token' => 'some_value' }
Savon uses Gyoku for the conversion of tags I believe. To change the symbol conversion you can insert the following statement:
Gyoku.convert_symbols_to :camelcase # or one of [:none, :lover_camelcase]
hope that helps.

Resources