To start off with, I am a beginner at soap.
I am trying to make a soap call to a service and was given a working sample that comes from talend. What I need is to make a similar call in PHP.
The output from talend is as follows, (extracted from the HTTP request)
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<root>
<request>
<username>a#a.com</username>
<password>md5sumlookalike</password>
<webservice>GetCust</webservice>
<refid>12343321</refid>
<message>reserv#123</message>
</request>
</root>
</soap:Body>
</soap:Envelope>
So I wrote a little bit of PHP as it works as a scripting language as well for where it will be called from. Trying to understand how to make a soap call I came up with this bit.
<?php
// Yes I know about the diffrent port issue here. So I wgeted and stored it for use next to script
# $soapClient = new SoapClient("http://123.123.123.123:8088/services", array("trace" => true));
$soapClient = new SoapClient("wsdl", array("trace" => true));
$error = 0;
try {
$info = $soapClient->__soapCall("invoke",
array
(
new SoapParam("a#a.com", "username"),
new SoapParam("md5sumish", "password"),
new SoapParam("GetCust", "webservice"),
new SoapParam("1234321", "refid"),
new SoapParam("reserv#123", "message")
)
);
} catch (SoapFault $fault) {
$error = 1;
echo 'ERROR: '.$fault->faultcode.'-'.$fault->faultstring;
}
if ($error == 0) {
print_r($output_headers);
echo 'maybe it worked\n';
unset($soapClient);
}
?>
I end up seeing the following in the HTTP request via wireshark. The server just does not know what to do with this and does not respond. I am unsure what/where I need to go from here.
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://talend.org/esb/service/job">
<SOAP-ENV:Body>
<ns1:invokeInput>a#a.com</ns1:invokeInput>
<password>md5sumish</password>
<webservice>GetCust</webservice>
<refid>1234321</refid>
<message>reserv#123</message>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
So I have to ask is how to get rid of the ns1:invokeInput and make it username. Along with bring the rest of the format into line so the request looks like the output from talend?
Here is a working little script I did in php to call a talend tutorial service exported as soap:
//....
if (sizeof($_POST) > 0) {
$name = $_POST['name'];
$city = $_POST['city'];
$client = new SoapClient("http://192.168.32.205:8080/DirectoryService/services/DirectoryService?wsdl", array( 'trace' => 1));
$result = $client->runJob(array(
'--context_param',
'Name=' . $_POST['name'],
'--context_param',
'City=' . $_POST['city']
));
}
//...
Talend seems to be very "basic" regarding how parameters are given.
With this code it was working fine.
Related
I need send request for authenticate a SOAP via PHP SoapClient, but the request mount is result on "Not Found" after send.
On resume, using postman (plugin for chrome) i receive sucessful and the format XML mounted on a service is one and on another service is other. (each service mounted the XML different)
Via Postman i send this format (XML):
Work Correctly: I receive the correct response from server.
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<AutenticarUsuario xmlns="http://tempuri.org/PortalUAU_WS/Autenticador">
<Login>example</Login>
<Senha>123456</Senha>
</AutenticarUsuario>
</soap:Body>
</soap:Envelope>
Via SoapClient(PHP) he mount this format (XML):
Don't Work: I Receive "Not Found" no errors, no exceptions only "Not Found".
CODE PHP
public function authUauWeb(){
$soap = new \SoapClient($this->_wsEndpoint . 'Autenticador.asmx?WSDL', ['trace' => 1]);
$result = $soap->AutenticarUsuario(['Login' => $this->_wsData->user, 'Senha' => $this->_wsData->pass]);
//GET COOKIE SESSION
$headers = $soap->__getLastResponseHeaders();
$headers_init = strpos($headers, 'PortalUAU=');
if($headers_init !== false){
$headers = substr($headers, $headers_init);
$headers_end = strpos($headers, ';');
$headers = substr($headers, 0, $headers_end);
$headers = explode('=', $headers);
}
if(isset($result->AutenticarUsuarioResult) && $result->AutenticarUsuarioResult == 'True' && gettype($headers) == 'array'){
$this->_wsConnected = $headers;
}else{
$this->_wsConnected = false;
}
return $this->_wsConnected;
}
XML STRUCTURE FROM PHP
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tempuri.org/PortalUAU_WS/Autenticador" xmlns:ns2="http://200.178.248.110:90/PortalUAU_WS_HLG/Autenticador.asmx" xmlns:ns3="text/xml; charset=utf-8">
<SOAP-ENV:Header>
<ns2:SOAPAction/>
<ns3:ContentType/>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:AutenticarUsuario>
<ns1:Login>example</ns1:Login>
<ns1:Senha>123456</ns1:Senha>
</ns1:AutenticarUsuario>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
As we say here on Brazil "My kick" is about this soap vs SOAP-ENV and ns1: present on tags from xml.
Thanks!
I need to a value from this SOAP response. The value is in the loginresponse / return element. Here's the response:
<soap-env:envelope 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/">
<soap-env:body soap-env:encodingstyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="urn:DBCentralIntf-IDBCentral">
<ns1:loginresponse>
<return xsi:type="xsd:string"><**THIS IS THE VALUE I NEED**></return>
</ns1:loginresponse>
</soap-env:body>
Here's how I'm trying to parse:
$response = curl_exec($ch);
curl_close($ch);
$xml = simplexml_load_string($response, NULL, NULL, "http://schemas.xmlsoap.org/soap/envelope/");
$ns = $xml->getNamespaces(true);
$soap = $xml->children($ns['SOAP-ENV']);
$res = $soap->Body->children($ns['NS1']);
print_r($res->LoginResponse->Return);
But I get an empty object.
Thanks for your help!
Instead of using cURL and attempting to parse the XML response, consider using the PHP SOAP client. You may need to install PHP SOAP or enable it in your PHP configuration. (I'm using PHP on Windows, so I just had to uncomment extension=php_soap.dll in php.ini.)
If you have SOAP installed, you can get the WSDL from the provider of the web service you're using. Based on Googling this value in the XML you showed: xmlns:ns1="urn:DBCentralIntf-IDBCentral", I'm guessing you can find it here, but you'll probably have better luck finding it since you know for sure what web service you're using.
After you have the WSDL, using the PHP SOAP client is super easy:
$client = new SoapClient('path/to/your.wsdl');
$response = $client->Login(['username', 'password']);
$theValueYouNeed = $response->loginresponse->return;
UPDATE:
Removing the namespaces clears things up a bit (although a hack). Here my new code:
$response = curl_exec($ch);
curl_close($ch);
$cleanxml = str_ireplace(['SOAP-ENV:', 'SOAP:'], '', $response);
$cleanxml = str_ireplace('NS1:','', $cleanxml);
$xml = simplexml_load_string($cleanxml);
echo $xml->Body->LoginResponse->return[0];
I'm trying to adapt the following PHP code in Perl. It's a bioDBnet SOAP API. I tried following the example on the SOAP::WSDL module (under SYNOPSIS) but it doesn't connect. I get an error message:
ATTEMPT 1
#!perl -w
use SOAP::WSDL;
my $client = SOAP::WSDL->new(
wsdl => "http://biodbnet.abcc.ncifcrf.gov/webServices/bioDBnet.wsdl",
);
Error message: cannot import document for namespace >http://schemas.xmlsoap.org/soap/encoding/< without location at /Library/Perl/5.16/SOAP/WSDL/Expat/WSDLParser.pm line 90.
ATTEMPT 2
Next I tried using the SOAP::LITE module. I followed the sample code from HERE (under 6.b. client).
#!perl -w
use SOAP::Lite;
my $client = SOAP::Lite ->
service('http://biodbnet.abcc.ncifcrf.gov/webServices/bioDBnet.wsdl');
my %db2dbParams;
$db2dbParams{'input'} = "Gene Symbol";
$db2dbParams{'outputs'} = "Gene ID, Ensembl Gene ID";
$db2dbParams{'inputValues'} = "MYC,A1BG";
$db2dbParams{'taxonId'} = "9606";
$db2dbRes = $client->db2db(%db2dbParams);
print $db2dbRes;
The code above doesn't print anything. How do I get the bioDBnet SOAP API to work for Perl?
Don't use a SOAP::Lite service method, mostly it doesn't work.
Build the soap structure manually. I tried to follow the php xml as much as possible, though most of prefixes is not necessary.
use strict;
use warnings;
use Data::Dumper;
use SOAP::Lite;
#use SOAP::Lite +trace=>'all';
$uri = 'urn:bioDBnet';
$proxy = 'http://biodbnet.abcc.ncifcrf.gov/webServices/biodbnetSoapServer.php';
$tns = 'urn:bioDBnet';
$soap = SOAP::Lite->new(uri => $uri,proxy => $proxy);
$soap->envprefix('SOAP-ENV');
$soap->encprefix('SOAP-ENC');
$soap->ns($tns,'tns1');
$soap->on_action(sub{$tns.'#db2db'});
#request = (SOAP::Data->name(db2dbParams => \SOAP::Data->value(
SOAP::Data->name(input => 'Gene Symbol'),
SOAP::Data->name(outputs => 'Gene ID, Ensembl Gene ID'),
SOAP::Data->name(inputValues => 'MYC,A1BG'),
SOAP::Data->name(taxonId => 9606),
))->type('ns1:db2dbParams'),
);
$db2db = $soap->db2db(#request);
if ($match = $db2db->match('/Envelope/Body/db2dbResponse')) {
print "match ok: $match\n";
$result = $db2db->result;
print Dumper($result);
} else {
print "match nok: $match\n";
}
This produces the required output from the server.
Your second scripts works, except the db2db part.
My guess is that the SOAP XML envelope send to the server is not in a good shape, when sending with SOAP::LITE.
I've enabled debugging on the second line:
#!/usr/bin/perl -w
use SOAP::Lite +trace =>'debug';
#use SOAP::Lite;
my $client = SOAP::Lite->service('http://biodbnet.abcc.ncifcrf.gov/webServices/bioDBnet.wsdl');
$inputs = $client->getInputs();
print $inputs;
$input = "Gene Symbol";
$outputs = $client->getOutputsForInput($input);
print $outputs;
$dirOutputs = $client->getDirectOutputsForInput($input);
print $dirOutputs;
.. From your Attempt 2:
# doesn't work, the created XML envelope is not in a good shape
my %db2dbParams;
$db2dbParams{'input'} = "Gene Symbol";
$db2dbParams{'outputs'} = "Gene ID, Ensembl Gene ID";
$db2dbParams{'inputValues'} = "MYC,A1BG";
$db2dbParams{'taxonId'} = "9606";
$db2dbRes = $client->db2db(%db2dbParams);
print $db2dbRes;
.. I also tried to rewrite this using SOAP:Data...but failed.
# doesn't work, the created XML envelope is not in a good shape
$db2dbRes = $client->db2db(
SOAP::Data->name("db2dbParams")->type("ns1:db2dbParams")->prefix("ns1:db2db")->uri("urn:bioDBnet") =>
SOAP::Data->type("string")->name("input" => "Gene Symbol"),
SOAP::Data->type("string")->name("inputValues" => "MYC,MTOR"),
SOAP::Data->type("string")->name("outputs" => "Gene ID, Affy ID"),
SOAP::Data->type("string")->name("taxonId" => "9606")
);
print $db2dbRes;
Switched over to PHP to see a working request.
I've enabled debugging on the PHP script to print the request headers
and fetch the working XML request done from PHP and reuse it as POST content from PERL. Basically, by adding the trace parameter on the SoapClient and then dumping the last reqeust headers.
<?php
$wsdl = "http://biodbnet.abcc.ncifcrf.gov/webServices/bioDBnet.wsdl";
$client = new SoapClient($wsdl, ['trace' => 1]);
$inputs = $client->getInputs();
print $inputs;
$input = "Gene Symbol";
$outputs = $client->getOutputsForInput($input);
print $outputs;
$dirOutputs = $client->getDirectOutputsForInput($input);
print $dirOutputs;
$db2dbParams['input'] = "Gene Symbol";
$db2dbParams['outputs'] = "Gene ID, Ensembl Gene ID";
$db2dbParams['inputValues'] = "MYC,A1BG";
$db2dbParams['taxonId'] = "9606";
$db2dbRes = $client->db2db($db2dbParams);
print $db2dbRes;
echo "====== REQUEST HEADERS =====" . PHP_EOL;
var_dump($client->__getLastRequestHeaders());
echo "========= REQUEST ==========" . PHP_EOL;
var_dump($client->__getLastRequest());
echo "========= RESPONSE =========" . PHP_EOL;
var_dump($db2dbRes);
This prints headers together with XML and the expected output is:
Gene Symbol Gene ID Ensembl Gene ID
MYC 4609 ENSG00000136997
A1BG 1 ENSG00000121410
I'm included the "working" XML request data into $message and do a POST request.
#!/usr/bin/perl -w
use strict;
use LWP::UserAgent;
use HTTP::Request;
my $message = '<?xml version="1.0" encoding="UTF-8" ?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="urn:bioDBnet" 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:db2db>
<db2dbParams xsi:type="ns1:db2dbParams">
<input xsi:type="xsd:string">Gene Symbol</input>
<taxonId xsi:type="xsd:string">9606</taxonId>
<inputValues xsi:type="xsd:string">MYC,A1BG</inputValues>
<outputs xsi:type="xsd:string">Gene ID, Ensembl Gene ID</outputs>
</db2dbParams>
</ns1:db2db>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>';
my $userAgent = LWP::UserAgent->new();
my $request = HTTP::Request->new(POST => 'http://biodbnet.abcc.ncifcrf.gov/webServices/biodbnetSoapServer.php'); # ?debug=1
$request->content($message);
$request->content_type("text/xml; charset=utf-8");
my $response = $userAgent->request($request);
if($response->code == 200) {
print $response->as_string;
}
else {
print $response->error_as_HTML;
}
Finally: next to header output we finally got some data:
<?xml version="1.0" encoding="UTF-8" ?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://biodbnet.abcc.ncifcrf.gov/webServices/bioDBnet"
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:db2dbResponse>
<return xsi:type="xsd:string">Gene Symbol Gene ID Ensembl Gene ID
MYC 4609 ENSG00000136997 A1BG 1 ENSG00000121410
</return>
</ns1:db2dbResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Now, all you need to do is to extract the return element inside the ns1:db2dbResponse from $response->as_string (probably using LibXML).
In other words: this bypasses SOAP::Lite and uses LWP and a simply POST request with XML, the parsing the XML response. You lose the automatical extraction and have to handle return data manually.
im trying to use the php soap client to make a soap call, but it keeps giving me " Request cannot be blank. Please provide request details. ". What am I doing wrong here?
$username = 'myusername_example';
$password = '123456787';
$url = "http://trail.dexceldesigns.com/m2m/APIwsdls/SessionService/SessionService.wsdl";
$soapclient = new \SoapClient($url);
try{
$params = array(
'Username' => $username,
'Password' => $password
);
$response = $soapclient->LogIn($params);
}
catch(\SoapFault $fault)
{
echo '<br/>'.$fault->getLine();
echo '<br/>Message: '.$fault->getMessage();
echo '<br/>Trace: '.$fault->getTraceAsString();
echo '<br/><br/>'.$fault->getCode();
echo '<br/><br/>'.$fault->getFile();
}
var_dump($soapclient->__getLastRequest());
EDIT:
Output for var_dump($soapclient->__getLastRequest()); is always coming as NULL
EDIT:2 (this is the request according to the documentation)
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://schemas.datacontract.org/2004/07/NPhase.UnifiedWebService.APIs.v2.Contract.SessionService" xmlns:ns2="http://nphase.com/unifiedwebservice/v2">
<SOAP-ENV:Body>
<ns2:LogIn>
<ns2:Input>
<ns1:Username>?</ns1:Username>
<ns1:Password>?</ns1:Password>
</ns2:Input>
</ns2:LogIn>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I'm trying to send user registrations with soap to another server. I'm creating an xml with DOMdocument and than after saveXML I'm running the soap which should return an xml with registration id plus all the data I sent in my xml.
But the Soap returns unknown error. exactly this: stdClass Object ( [RegisztracioInsResult] => stdClass Object ( [any] => 5Unknown error ) )
and this is how I send my xml.
/*xml creation with DOMdocument*/
$xml = saveXML();
$url = 'http://mx.biopont.com/services/Vision.asmx?wsdl';
$trace = '1';
$client = new SoapClient($url, array('trace' => $trace, "exceptions" => 0, 'features' => SOAP_SINGLE_ELEMENT_ARRAYS));
$params = $client->RegisztracioIns(array('xml' => $xml));
$print_r($params);
If I click on the description of the RegisztracioIns service at this URL http://mx.biopont.com/services/Vision.asmx it shows me this:
POST /services/Vision.asmx HTTP/1.1
Host: mx.biopont.com
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://mx.biopont.com/services/RegisztracioIns"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<RegisztracioIns xmlns="http://mx.biopont.com/services/">
<xml>string</xml>
</RegisztracioIns>
</soap:Body>
</soap:Envelope>
According to this I think I'm doing the upload correctly but maybe not I don't have much experience with soap.
Is there anything I'm missing? I also tried to save the xml to my server an than get the contents with file_get_contents(). but the result was the same.
You should be able to do something like this:
$res = $client->__soapCall( 'RegisztracioIns', array('xml'=>'my string to send'));
To have the wsdl wrap 'my string to send' in the proper tags.
You are doing something similar, but I dont think the wsdl is actually wrapping the string you are trying to pass, and passing nothing instead, resulting in unknown error.
You can examine the outgoing xml using $client->__getLastRequest();.
(Also, you have a small typo in your code on the last line should be print_r($params);.)
Failing that you could try to write the xml yourself using SoapVar() and setting the type to XSD_ANYXML.
It seems cleaner to me when the wsdl wraps everything for you, but its better than banging your head against the wall until it does.
I made an attempt to do just that with your wsdl. Give this a try:
$wsdl = "http://mx.biopont.com/services/Vision.asmx?wsdl";
$client = new SoapClient($wsdl, array( 'soap_version' => SOAP_1_1,
'trace' => true,
));
try {
$xml = "<RegisztracioIns xmlns='http://mx.biopont.com/services/'>
<xml>string</xml>
</RegisztracioIns>";
$args= array(new SoapVar($xml, XSD_ANYXML));
$res = $client->__soapCall( 'RegisztracioIns', $args );
var_dump($res);
} catch (SoapFault $e) {
echo "Error: {$e}";
}
print_r($client->__getLastRequest());
print_r($client->__getLastResponse());
I can't exactly read the response I am getting with that given that it is Hungarian (I think?). So let me know if that works for you.