I'm currently trying to build a provisioning service of a kind for a local instance of Open-Xchange, using Rails 2.3.8, Savon and OX's SOAP API.
Via the console, I can issue the following commands that will work;
>> client = Savon::client("http://192.168.2.195/servlet/axis2/services/OXContextService?wsdl")
=> #<Savon::Client:0x2b5151bad790 #wsdl=#<Savon::Wasabi::Document:0x2b5151bad678 #document="http://192.168.2.195/servlet/axis2//services/OXContextService?wsdl", #request=#<HTTPI::Request:0x2b5151bad628>>, #http=#<HTTPI::Request:0x2b5151bad628>, #config=#<struct Savon::Config _logger=#<Savon::Logger:0x2b5151bad6c8 #device=#<IO:0x2b514a775ad0>>, pretty_print_xml=nil, raise_errors=true, soap_version=1, env_namespace=nil, soap_header=nil>>
>> client.request :list_by_database do
?> soap.body = {
?> :auth => {
?> :login => "oxadminmaster",
?> :password => "admin_master_password"
>> },
?> :db => {
?> :id => 3
>> }
>> }
>> end
HTTPI executes HTTP GET using the net_http adapter
SOAP request: https://192.168.2.195/servlet/axis2/services/OXContextService.OXContextServiceHttpsSoap11Endpoint/
SOAPAction: "urn:listByDatabase", Content-Type: text/xml;charset=UTF-8, Content-Length: 657
<?xml version="1.0" encoding="UTF-8"?><env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ins0="http://soap.admin.openexchange.com" xmlns:ns="http://soap.admin.openexchange.com" xmlns:ins1="http://dataobjects.soap.admin.openexchange.com/xsd" xmlns:ins2="http://dataobjects.rmi.admin.openexchange.com/xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"><env:Body><ins0:listByDatabase><ins0:db><ins1:id>3</ins1:id></ins0:db><ins0:auth><ins2:login>oxadminmaster</ins2:login><ins2:password>admin_master_password</ins2:password></ins0:auth></ins0:listByDatabase></env:Body></env:Envelope>
HTTPI executes HTTP POST using the net_http adapter
warning: peer certificate won't be verified in this SSL session
SOAP response (status 200):
It works, no problems there. However, when I try the following code...
class Ox_Context_Service
extend Savon::Model
attr_accessor :data, :returnCode
document "http://192.168.2.195/servlet/axis2/services/OXContextService?wsdl"
def list_by_database oxMasterUser, oxMasterPassword
begin
response = client.request :list_by_database do
soap.body = {
:auth => {
#for the sake of testing
:login => "#{oxMasterUser}",
:password => "#{oxMasterPassword}"
},
:db => {
:id => 3
#For the sake of testing
}
}
end
if response.success?
data = response.body[:list_by_database_response][:return]
if data
#data = data
#returnCode = "#{response.http.code}"
end
end
end
rescue Savon::Error => fault
#data = {}
#returnCode = "#{fault}"
end
end
Using the following CURL...
curl localhost:4545/oxContextService/list_by_database -d 'oxUsername=oxadminmaster' -d 'oxPassword=admin_master_password'
I get...
HTTPI executes HTTP GET using the net_http adapter
SOAP request: https://192.168.2.195/servlet/axis2/services/OXContextService.OXContextServiceHttpsSoap11Endpoint/
SOAPAction: "urn:listByDatabase", Content-Type: text/xml;charset=UTF-8, Content-Length: 657
<?xml version="1.0" encoding="UTF-8"?><env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ins0="http://soap.admin.openexchange.com" xmlns:ns="http://soap.admin.openexchange.com" xmlns:ins1="http://dataobjects.soap.admin.openexchange.com/xsd" xmlns:ins2="http://dataobjects.rmi.admin.openexchange.com/xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"><env:Body><ins0:listByDatabase><ins0:auth><ins2:login>oxadminmaster</ins2:login><ins2:password>admin_master_password</ins2:password></ins0:auth><ins0:db><ins1:id>3</ins1:id></ins0:db></ins0:listByDatabase></env:Body></env:Envelope>
HTTPI executes HTTP POST using the net_http adapter
warning: peer certificate won't be verified in this SSL session
SOAP response (status 500):
<?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><soapenv:Fault><faultcode>soapenv:Server</faultcode><faultstring>Authentication failed</faultstring><detail /></soapenv:Fault></soapenv:Body></soapenv:Envelope>
So- two identical calls, two different results. What could be going wrong here, SO?
Edit: The Rails call fails because the Auth block is sent first, instead of last. I think the new question is how to enforce XML structure order without explicitly writing out the XML.
soap.body = {
:auth => {
#for the sake of testing
:login => "#{oxMasterUser}",
:password => "#{oxMasterPassword}"
},
:db => {
:id => 3
#For the sake of testing
}
:order! => [:db, :auth]
}
The order! will force a specific order based on that array. Lesson learned: Read the manual.
Related
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.
I'm working on Bing Ads API Reporting Data using Ruby and I'm using bing_ads_api_Gem in order to complete the task.
require 'bing_ads_api'
client = BingAdsApi::Api.new(
{
:authentication => {
:method => 'ClientLogin',
:developer_token => 'developer-token-goes-here',
:user_nam e => 'username-goes-here',
:password => 'password-goes-here',
:customer_id => 'customer-id-goes-here',
:customer_account_id => 'account-id-goes-here'
},
:service => {:environment => 'PRODUCTION'},
:library => {:log_level => 'DEBUG'}
})
# select the service and the API version (:v7 or :v8)
administration_service = client.service(:AdministrationService, :v8)
# send your request
result = administration_service.get_assigned_quota()
SOAP Request in XML Format
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsdl="https://adcenter.microsoft.com/v8" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<env:Header>
<wsdl:DeveloperToken>developer-token-goes-here</wsdl:DeveloperToken>
<wsdl:UserName>username-goes-here</wsdl:UserName>
<wsdl:Password>password-goes-here</wsdl:Password>
<wsdl:CustomerId>customer-id-goes-here</wsdl:CustomerId>
<wsdl:CustomerAccountId>account-id-goes-here</wsdl:CustomerAccountId>
</env:Header>
<env:Body>
<wsdl:GetAssignedQuotaRequest xmlns="https://adcenter.microsoft.com/v8" />
</env:Body>
</env:Envelope>
As I'm not obsessed with only single gem so tried with other Gems
as well.
Do let me know if anyone need more info on this.
Any help would be appreciate.
A sample request that I am trying to make looks like this:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<GetList xmlns="http://tempuri.org/">
<listRequest i:type="b:NpsListRequest" xmlns:a="http://schemas.datacontract.org/2004/07/Services.List" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:b="http://schemas.datacontract.org/2004/07/Services.List.Strategies">
<a:id>1</a:id>
</listRequest>
</GetList>
</s:Body>
</s:Envelope>
I can replicate that exactly, using Nokogiri, like so:
builder = Nokogiri::XML::Builder.new do |xml|
xml['s'].Envelope('xmlns:s' => "http://schemas.xmlsoap.org/soap/envelope/") {
xml['s'].Body {
xml.GetList('xmlns' => "http://tempuri.org/") {
xml.listRequest('i:type' => "b:NpsListRequest", 'xmlns:a' => "http://schemas.datacontract.org/2004/07/Services.List", 'xmlns:i' => "http://www.w3.org/2001/XMLSchema-instance", 'xmlns:b' => "http://schemas.datacontract.org/2004/07/Services.List.Strategies") {
xml['a'].id(1)
}
}
}
}
end
builder.to_xml
Then, I build my soap_client using Savon:
def soap_client
soap_client = Savon.client(
wsdl: "http://1.1.1.1/Api.svc?wsdl", #PLE
headers: {"Authorization" => "Basic"},
basic_auth: ['user', 'password'],
env_namespace: :soapenv,
namespace_identifier: :ser,
ssl_verify_mode: :none,
log: true,
:pretty_print_xml => true
)
end
Now, I need to make a :get_list call that looks like the above sample request.
soap_client.operations returns this:
[:get_list] So I know I'm authenticated and the client is working correctly.
I can't figure out how to actually make the :get_list call.
I would like something simple where I don't even have to use Nokogiri to build my own xml, like this:
soap_client.call :get_list, message: {id => 1}
But that doesn't seem to be a feasible solution. Any thoughts on how I can pass the XML I'm building using Nokogiri through to the :get_list call for my soap_client? I am open to other suggestions as well.
I'm using ActiveMerchant to integrate with Authorize.net CIM. I'm in the middle of writing up automated tests, and I've begun putting into place Webmock calls so that my tests aren't actually hitting Authorize.net each time that they run.
I've created XML files from the responses of raw request data, and for the most part, it's working well. However, when I mock up a successful response, ActiveMerchant for some reason still tells me that Response.success? is not true.
My function
if self.cim_customer_profile_id.nil?
ActiveMerchant::Billing::Base.mode = :test
customer_profile_information = {
:profile => {
:merchant_customer_id => self.customer.username.first(20),
:email => self.customer.email
}
}
gateway = ActiveMerchant::Billing::AuthorizeNetCimGateway.new(
:login => AUTHORIZE_NET_API_LOGIN_ID,
:password => AUTHORIZE_NET_API_TRANSACTION_KEY
)
response = gateway.create_customer_profile(customer_profile_information)
if response.success?
self.cim_customer_profile_id = response.authorization
else
raise StandardError, response.message
end
end
And then my stubbed response is:
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
<?xml version="1.0" encoding="utf-8"?>
<createCustomerProfileResponse xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns='AnetApi/xml/v1/schema/AnetApiSchema.xsd'>
<messages>
<resultCode>
Ok
</resultCode>
<message>
<code>
I00001
</code>
<text>
Successful.
</text>
</message>
</messages>
<customerProfileId>10793616</customerProfileId>
<customerPaymentProfileIdList/>
<customerShippingAddressIdList/>
<validationDirectResponseList/>
</createCustomerProfileResponse>
Is there any reason why ActiveMerchant won't function with a successful, stubbed, request? Or am I missing something that ActiveMerchant requires in order to register that the response is actually successful?
Ah, I'm so dumb. I added new lines after all of my XML tags for readability, but they're interfering with how ActiveMerchant parses and evaluates the response.
So the correct XML response mock would be:
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
<?xml version="1.0" encoding="utf-8"?>
<createCustomerProfileResponse xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns='AnetApi/xml/v1/schema/AnetApiSchema.xsd'>
<messages>
<resultCode>Ok</resultCode>
<message>
<code>I00001</code>
<text>Successful.</text>
</message>
</messages>
<customerProfileId>10793616</customerProfileId>
<customerPaymentProfileIdList/>
<customerShippingAddressIdList/>
<validationDirectResponseList/>
</createCustomerProfileResponse>
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>