How to translate PHP SoapClient request example to RoR? - php

I'd like to use some web service via its API. In documentation I found an example request written with PHP SoapClient. But I am using RoR and I have no PHP experience. Could someone tell me how should I write the same in RoR, or at least translate it to plain HTTP terminology?
<?php
$soap = new SoapClient(“https://secure.przelewy24.pl/external/wsdl/service.php?wsdl”);
$test = $soap->TestAccess(“9999”, “anuniquekeyretrievedfromprzelewy24”);
if ($test)
echo ‘Access granted’;
else
echo ‘Access denied’;
?>
Edit: particularly I'd like to know what should I do with TestAccess method, because there's no methods in plain HTTP. Should I join this name with URL?

To make your life easier, check out a gem that allows you to simplify SOAP access, like savon.
Then the code could be translated as
# create a client for the service
client = Savon.client(wsdl: 'https://secure.przelewy24.pl/external/wsdl/service.php?wsdl')
This will automatically parse the possible methods to client that are offered in the SOAP API (defined in the WSDL). To list the possible operations, type
client.operations
In your case this will list
[:test_access, :trn_refund, :trn_by_session_id, :trn_full_by_session_id, :trn_list_by_date, :trn_list_by_batch, :trn_full_by_batch, :payment_methods, :currency_exchange, :refund_by_id, :trn_register, :trn_internal_register, :check_nip, :company_register, :company_update, :batch_list, :trn_dispatch, :charge_back, :trn_check_funds, :check_merchant_funds, :transfer_merchant_funds, :verify_transaction, :register_transaction, :deny_transaction, :batch_details]
Then to call the method, do the following
response = client.call(:test_access, message: { test_access_in: 9999 })
response = client.call(:test_access, message: {
test_access_in: 9999 }
test_access_out: "anuniquekeyretrievedfromprzelewy24"
)
response.body
=> {:test_access_response=>{:return=>false}}
this gets a result, but I have no idea what it means.

I've included an entire controller method that we use in production as an example but essentially you want to pass in your xml/wsdl request as the body of the HTTP request and then parse the response as xml, or what we used below which is rexml for easier traversing of the returned doc.
def get_chrome_styles
require 'net/http'
require 'net/https'
require 'rexml/document'
require 'rexml/formatters/pretty'
xml = '<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:description7b.services.chrome.com">
<soapenv:Header/>
<soapenv:Body>
<urn:StylesRequest modelId="' + params[:model_id] + '">
<urn:accountInfo number="[redacted]" secret="[redacted]" country="US" language="en" behalfOf="trace"/>
<!--Optional:-->
</urn:StylesRequest>
</soapenv:Body>
</soapenv:Envelope>'
base_url = 'http://services.chromedata.com/Description/7b?wsdl'
uri = URI.parse( base_url )
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new("/Description/7b?wsdl")
request.add_field('Content-Type', 'text/xml; charset=utf-8')
request.body = xml
response = http.request( request )
doc = REXML::Document.new(response.body)
options = []
doc.get_elements('//style').each do |division|
puts division
options << { :id => division.attributes['id'], :val => division.text }
end
respond_to do |format|
format.json { render :json => options.to_json }
end
end

Related

PHP -> Curl -> Soap Response (Get data from xml tags)

I have a Curl response with Soap XML data.
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/><SOAP-ENV:Body><ns2:GetAccountMovementsResponseIo xmlns:ns2="http://www.mygemini.com/schemas/mygemini">
<ns2:result>
<ns2:pager>
<ns2:pageIndex>0</ns2:pageIndex>
<ns2:pageSize>700</ns2:pageSize>
</ns2:pager>
<ns2:totalCount>3</ns2:totalCount>
</ns2:result>
<ns2:accountMovement>
<ns2:movementId>002147575330.2</ns2:movementId>
<ns2:paymentId>95694091</ns2:paymentId>
<ns2:externalPaymentId>2147575330</ns2:externalPaymentId>
<ns2:debitCredit>1</ns2:debitCredit>
<ns2:valueDate>2018-12-13T00:00:00+04:00</ns2:valueDate>
<ns2:description>გადარიცხვა პირად ანგარიშზე</ns2:description>
<ns2:amount>
<ns2:amount>10000</ns2:amount>
<ns2:currency>GEL</ns2:currency>
</ns2:amount>
<ns2:accountNumber>GE44TB7142536020100005</ns2:accountNumber>
<ns2:accountName>კლიენტი:1425</ns2:accountName>
<ns2:additionalInformation>კლიენტი:1425, 123456786, TBCBGE22, GE17TB7142536020100006</ns2:additionalInformation>
<ns2:documentDate>2018-12-13T00:00:00+04:00</ns2:documentDate>
<ns2:documentNumber>1544698824</ns2:documentNumber>
<ns2:partnerAccountNumber>GE17TB7142536020100006</ns2:partnerAccountNumber>
<ns2:partnerName>კლიენტი:1425, 123456786</ns2:partnerName>
<ns2:partnerTaxCode>123456786</ns2:partnerTaxCode>
<ns2:partnerBankCode>TBCBGE22</ns2:partnerBankCode>
<ns2:partnerBank>სს თიბისი ბანკი</ns2:partnerBank>
<ns2:taxpayerCode>123456786</ns2:taxpayerCode>
<ns2:taxpayerName>კლიენტი:1425, 123456786</ns2:taxpayerName>
<ns2:operationCode>GII</ns2:operationCode>
<ns2:partnerDocumentType>0</ns2:partnerDocumentType>
<ns2:statusCode>3</ns2:statusCode>
<ns2:transactionType>1</ns2:transactionType>
</ns2:accountMovement>
<ns2:accountMovement>
<ns2:movementId>002147575330.1</ns2:movementId>
<ns2:paymentId>95694091</ns2:paymentId>
<ns2:externalPaymentId>2147575330</ns2:externalPaymentId>
<ns2:debitCredit>0</ns2:debitCredit>
<ns2:valueDate>2018-12-13T00:00:00+04:00</ns2:valueDate>
<ns2:description>გადარიცხვა პირად ანგარიშზე</ns2:description>
<ns2:amount>
<ns2:amount>10000</ns2:amount>
<ns2:currency>GEL</ns2:currency>
</ns2:amount>
<ns2:accountNumber>GE17TB7142536020100006</ns2:accountNumber>
<ns2:accountName>კლიენტი:1425, 123456786</ns2:accountName>
<ns2:additionalInformation>კლიენტი:1425, TBCBGE22, GE44TB7142536020100005</ns2:additionalInformation>
<ns2:documentDate>2018-12-13T00:00:00+04:00</ns2:documentDate>
<ns2:documentNumber>1544698824</ns2:documentNumber>
<ns2:partnerAccountNumber>GE44TB7142536020100005</ns2:partnerAccountNumber>
<ns2:partnerName>კლიენტი:1425</ns2:partnerName>
<ns2:partnerTaxCode>123456786</ns2:partnerTaxCode>
<ns2:partnerBankCode>TBCBGE22</ns2:partnerBankCode>
<ns2:partnerBank>სს თიბისი ბანკი</ns2:partnerBank>
<ns2:taxpayerCode>123456786</ns2:taxpayerCode>
<ns2:taxpayerName>კლიენტი:1425, 123456786</ns2:taxpayerName>
<ns2:operationCode>GII</ns2:operationCode>
<ns2:partnerDocumentType>0</ns2:partnerDocumentType>
<ns2:statusCode>3</ns2:statusCode>
<ns2:transactionType>1</ns2:transactionType></ns2:accountMovement>
<ns2:accountMovement><ns2:movementId>002147575329.2</ns2:movementId>
<ns2:externalPaymentId>2147575329</ns2:externalPaymentId>
<ns2:debitCredit>1</ns2:debitCredit>
<ns2:valueDate>2018-12-13T00:00:00+04:00</ns2:valueDate>
<ns2:description>ანგარიშზე თანხის შეტანა</ns2:description><ns2:amount>
<ns2:amount>100000</ns2:amount><ns2:currency>GEL</ns2:currency></ns2:amount>
<ns2:accountNumber>GE17TB7142536020100006</ns2:accountNumber>
<ns2:accountName>კლიენტი:1425</ns2:accountName>
<ns2:additionalInformation>სახელი:3928462 გვარი3928462</ns2:additionalInformation>
<ns2:documentDate>2018-12-13T00:00:00+04:00</ns2:documentDate>
<ns2:documentNumber>63946130</ns2:documentNumber>
<ns2:partnerAccountNumber>GE78TB0000000000060000</ns2:partnerAccountNumber>
<ns2:partnerName>სახელი:3928462 გვარი3928462</ns2:partnerName>
<ns2:partnerTaxCode>00000000000</ns2:partnerTaxCode>
<ns2:partnerBankCode>TBCBGE22</ns2:partnerBankCode><ns2:partnerBank>ს.ს. „თიბისი ბანკი”</ns2:partnerBank>
<ns2:operationCode>01</ns2:operationCode>
<ns2:partnerPersonalNumber>00000000000</ns2:partnerPersonalNumber>
<ns2:partnerDocumentType>6</ns2:partnerDocumentType>
<ns2:partnerDocumentNumber>DC102086</ns2:partnerDocumentNumber>
<ns2:statusCode>3</ns2:statusCode>
<ns2:transactionType>20</ns2:transactionType>
</ns2:accountMovement>
</ns2:GetAccountMovementsResponseIo>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I would like to get data inside tags one by one
<ns2:paymentId>, <ns2:externalPaymentId>, <ns2:debitCredit> etc.
Kindly note that this is dummy data of a bank statement, and in real life responses have multiple tags with the same name per each transaction. For example, if there are 11 transactions, there will be 11 <ns2:paymentId> tags and I need to get data one by one.
Using SimpleXML you can read the code and the data much easier. The only thing is that you need to respect the namespaces. So first register the ns2 namespace so that you can then you can fetch the <ns2:accountMovement> elements. The loop over these, but to access the child elements in the namespace, use children("http://www.mygemini.com/schemas/mygemini") to get them into the $data variable, then each access is via this (i.e. $data->paymentId)...
$xml = simplexml_load_string($xmlContent);
$xml->registerXPathNamespace("ns2", "http://www.mygemini.com/schemas/mygemini");
$movements = $xml->xpath("//ns2:GetAccountMovementsResponseIo/ns2:accountMovement");
foreach ( $movements as $accMove ) {
$data = $accMove->children("http://www.mygemini.com/schemas/mygemini");
echo "paymentId ->".$data->paymentId.PHP_EOL;
echo "externalPaymentId ->".$data->externalPaymentId.PHP_EOL;
echo "debitCredit ->".$data->debitCredit.PHP_EOL;
}

soap query with php and wsdl to get result

I'm having trouble finding a good example of how to do a soap call with a wsdl in php.
I found this example, but it's tied to the google function:
doGoogleSearch
$hits = $soap->doGoogleSearch('your google key',$query,0,10,
true,'',false,'lang_en','','');
I found this example for a wsdl, but I'm not seeing where my query goes:
missingQuery
So basically, this is what I have so far, but there's a lot missing:
$wsdlDB = "htmlString?wsdl";
// xml string for login and query I know works in soapUI with $var
$query = "$query =
'<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tri="http://blah/dbOurs/">
<soapenv:Header/>
<soapenv:Body>
<tri:sendTransaction>
<loginName>unernm</loginName>
<loginPassword>pw</loginPassword>
...
</soapenv:Body>
</soapenv:Envelope>'
$result = "not sure where this ties in either";
$WSDL = new SOAP_WSDL($wsdlDB);
$soap = $WSDL->getProxy();
$hits = $soap->($query, $result);
//then I will extract $varAnswer from $result with regex probably
This is really unclear. Does anyone have any helpful info on how to submit the query to the DB with the WSDL? I shouldn't have to give the soap call a specific function to do the query with. It's supposed to get that from the wsdl definition.
Why not use the built in SoapClient. It will convert the input to the function into a Soap Message and extract the return message into an object; based on the WSDL.
A simple sample is shown below.
$blzCode = '10010424'; // Code to lookup
$wsdlDB = "http://www.thomas-bayer.com/axis2/services/BLZService?wsdl"; // WSDL URL
$client = new SoapClient($wsdlDB); // Create the client based on the WSDL
$returnValue = $client->GetBank(array('blz' => $blzCode)); // Pass in the Parameters to the call (Based on the WSDL's definition)
$bankDetails = $returnValue->details; // Extract the results
$bankName = $bankDetails->bezeichnung; // Extract some portion of the inner result
echo "Blz Code {$blzCode}'s bank name is {$bankName}" . PHP_EOL; // Do something with the data

Django 1.8 (on Python 3) - Make a SOAP request with pysimplesoap

Since one week I'm trying to retrieve some datas from a Dolibarr application including Dolibarr's webservices.
In few words, I'm trying to make a soap request to retrieve user's informations.
At first, I tried to instantiate SoapClient with 'wsdl' and 'trace' parameters, in vain.. SoapClient's object was never been create !
Secondly, I made a made a classical SoapClient's object without 'wsdl', however I used : 'location', 'action', 'namespace', 'soap_ns', 'trace'; It was a success (I think) but It did't work when I called Client's call method.. My dolibarrkey did't match my key on the webservice, but their keys are the same (copy & paste).
For more explanations take a look to dolibarr api (to retrieve datas) with the xlm dataformat.
Link to getUser web service (click on getUser to show parameters):
http://barrdoli.yhapps.com/webservices/server_user.php
Link to xml dataformat (for the SOAP request maybe):
http://barrdoli.yhapps.com/webservices/server_user.php?wsdl
from pysimplesoap.client import SoapClient, SoapFault
import sys
def listThirdParties():
# create a simple consumer
try:
# client = SoapClient(
# "[MyAppDomain]/webservices/server_user.php")
# print(client)
# client = SoapClient(wsdl="[MyAppDomain]/webservices/server_user.php?wsdl", trace=True)
client = SoapClient(
location = "[myAppDomain]/webservices/server_user.php",
action = '[myAppDomain]/webservices/server_user.php?wsdl', # SOAPAction
namespace = "[myAppDomain]/webservices/server_user.php",
soap_ns='soap',
trace = True,
)
print("connected bitch")
except:
print("error connect")
message = dict()
message['use'] = "encoded"
message["namespace"] = "http://www.dolibarr.org/ns/"
message["encodingStyle"] = "http://schemas.xmlsoap.org/soap/encoding/"
message["message"] = "getUserRequest"
parts = dict()
auth = dict()
auth['dolibarrkey'] = '********************************'
auth['sourceapplication'] = 'WebServicesDolibarrUser'
auth['login'] = '********'
auth['password'] = '********'
auth['entity'] = ''
parts["authentication"] = auth
parts["id"] = 1
parts["ref"] = "ref"
parts["ref_ext"] = "ref_ext"
message["parts"] = parts
# call the remote method
response = client.call(method='getUser', kwargs=message)
# extract and convert the returned value
# result = response.getUser
# return int(result)
print(response)
pass
I've "BAD_VALUE_FOR_SECURITY_KEY" into a xlm response, I think it's my request which made with a bad xml dataformat..
shell response :
-------- RESPONSE -------
b'<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 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/" xmlns:tns="http://www.dolibarr.org/ns/"><SOAP-ENV:Body><ns1:getUserResponse xmlns:ns1="http://barrdoli.yhapps.com/webservices/server_user.php"><result xsi:type="tns:result"><result_code xsi:type="xsd:string">BAD_VALUE_FOR_SECURITY_KEY</result_code><result_label xsi:type="xsd:string">Value provided into dolibarrkey entry field does not match security key defined in Webservice module setup</result_label></result><user xsi:nil="true" xsi:type="tns:user"/></ns1:getUserResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>'
I really want to know how should I do to make a working soap request with a clean xlm dataformat.
Thanks
Did you try to setup WebService Security (WSSE) with client object? Following examples are taken from https://code.google.com/p/pysimplesoap/wiki/SoapClient
client['wsse:Security'] = {
'wsse:UsernameToken': {
'wsse:Username': 'testwservice',
'wsse:Password': 'testwservicepsw',
}
}
or try to Setup AuthHeaderElement authentication header
client['AuthHeaderElement'] = {'username': 'mariano', 'password': 'clave'}

OAuth signature_invalid error using PesaPal API with Ruby

I'm having a real nightmare trying to get the PesaPal API to work for me using Ruby...
I appreciate that it's probably not the most commonly used API but if there's anybody online here who has more experience using OAuth, and/or PHP experience who could offer a fresh pair of eyes I'd appreciate it.
So the PesaPal developer site is here: http://developer.pesapal.com
Their API docs don't give away too many clues about how to use OAuth with their site and I don't understand PHP well enough to be sure I've read their PHP sample correctly.
Here's my attempt at implementing this in Ruby:
require 'oauth'
require 'uri'
key = '<my sandbox key>'
sec = '<my sandbox secret>'
API_DOMAIN = 'https://demo.pesapal.com'
# An XML string of param data to include with our request
RAW_XML = %{<?xml version=\"1.0\" encoding=\"utf-8\"?><PesapalDirectOrderInfo xmlns:xsi=\"http://www.w3.org/2001/XMLSchemainstance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" Amount=\"12.34\" Description=\"Bob Test 1\" Type=\"MERCHANT\" Reference=\"808\" FirstName=\"Bo\" LastName=\"Tester\" Email=\"bodacious#bodacious.com\" xmlns=\"http://www.pesapal.com\" />}
# Escape the XML
#post_xml = URI.escape(RAW_XML)
# Create a new OAuth Consumer
#consumer = OAuth::Consumer.new(key, sec, {
site: API_DOMAIN,
scheme: :query_string
})
# The signed request object
#signed_request = #consumer.create_signed_request('get', "#{API_DOMAIN}/API/PostPesapalDirectOrderV4")
# Join the pesapal_request_data and oauth_callback with '&' for valid URL params
#params = {
oauth_callback: URI.escape('http://localhost:3000'),
pesapal_request_data: #post_xml,
}.map { |k,v| "#{k}=#{v}" }.join('&')
# This is the URL we should redirect to
puts redirect_url = "#{#signed_request.path}&#{#params}"
When I try to visit the URL returned by this code, I get: Problem: signature_invalid | Advice: > | back from the API.
Can anyone think of what I'm doing wrong here?
Thanks
Check out the pesapal RubyGem here ... https://rubygems.org/gems/pesapal ... it handles all that stuff for you.
I had the same problem and I solved it by creating a method to manually sign the url. create your own method to get the oauth_nonce like this.
def nonce
Array.new( 5 ) { rand(256) }.pack('C*').unpack('H*').first
end
The signature method looks like this:
def signature
key = percent_encode( #consumer_secret ) + '&' + percent_encode( #token_secret )
digest = OpenSSL::Digest::Digest.new( 'sha1' )
hmac = OpenSSL::HMAC.digest( digest, key, #base_str )
Base64.encode64( hmac ).chomp.gsub( /\n/, '' )
end
This is the #base_str instance variable:
#base_str = [#req_method,
percent_encode( req_url ),
percent_encode( query_string )
].join( '&' )
This is the query_string method:
def query_string
pairs = []
#params.sort.each { | key, val |
pairs.push( "#{ percent_encode( key ) }=#{ percent_encode( val.to_s ) }" )
}
pairs.join '&'
end
You can then use the signature method above to get the oauth_signature param to use in the resulting url
I know the OP was interested in a solution that addresses the Ruby domain, but I feel it may be helpful to note that I was getting a similar problem on PHP and the solution was to ensure I had no white space in the XML post data structure.
WRONG:
<?xml version="1.0" encoding="utf-8"?>
<PesapalDirectOrderInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
Amount="200"
Currency="KES"
Description="Computer Accessory"
Type="MERCHANT"
Reference="dd19f9ede4db6f0a13b7053111f02825"
FirstName="Stack"
LastName="Overflow"
Email="so#stackoverflow.com"
PhoneNumber=""
xmlns="http://www.pesapal.com" >
<lineitems>
<lineitem uniqueid="29"
particulars="Keyboard"
quantity="1"
unitcost="200"
subtotal="200.00" >
</lineitem>
</lineitems>
</PesapalDirectOrderInfo>
CORRECT:
<?xml version="1.0" encoding="utf-8"?><PesapalDirectOrderInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Amount="200" Currency="KES" Description="Computer Accessory" Type="MERCHANT" Reference="dd19f9ede4db6f0a13b7053111f02825" FirstName="Stack" LastName="Overflow" Email="so#stackoverflow.com" PhoneNumber="" xmlns="http://www.pesapal.com" ><lineitems><lineitem uniqueid="29" particulars="Keyboard" quantity="1" unitcost="200" subtotal="200.00" ></lineitem></lineitems></PesapalDirectOrderInfo>

building a php object equal to xml tag

i am developing an app in php it pulls data from Reuters API i am trying to add the request parameters before making SOAP call , i have the xml which must be generated from my request it must look like this :
<HeadlineMLRequest>
<Filter>
<MetaDataConstraint class="companies" xmlns="http://schemas.reuters.com/ns/2006/04/14/rmds/webservices/news/filter">
<Value>MSFT.O</Value>
</MetaDataConstraint>
</Filter>
</HeadlineMLRequest>
when i build my request parameter object i tried this
protected function getRequest() {
$retval->HeadlineMLRequest->MaxCount = 10;
$retval->HeadlineMLRequest->Filter->MetaDataConstraint->class = "companies";
$retval->HeadlineMLRequest->Filter->MetaDataConstraint->Value = "MSFT.O";
return $retval;
}
but when i echo last xml request i find it like this
<ns1:headlinemlrequest>
<ns1:maxcount>
10
</ns1:maxcount>
<ns1:filter>
<ns2:metadataconstraint class="companies">
<ns2:value>
</ns2:value>
</ns2:metadataconstraint>
</ns1:filter>
if you notice Value is empty although i set it with "MSFT.O" , any help please?
Complex requests with php soap are not well documented and most examples show only basic techniques.
Try the following:
$metaData = '<MetaDataConstraint class="companies" xmlns="http://schemas.reuters.com/ns/2006/04/14/rmds/webservices/news/filter">
<Value>MSFT.O</Value>
</MetaDataConstraint>';
$xmlvar = new SoapVar($metaData, XSD_ANYXML);
$retval->HeadlineMLRequest->Filter->MetaDataConstraint = $xmlVar;

Categories