PHP SOAP Header construction - php

So basically I want the SOAP header to be like this:
<soapenv:Header>
<v1:loginDetails>
<v11:Id>0</v11:Id>
<v11:username>MEMBERS</v11:username>
$ <v11:password>0x909711E5,0xE301F82A,0x0E2783CC,0xAF6BC3DB,0x57727CFB</v11:password>
</v1:loginDetails>
</soapenv:Header>
<soapenv:Body>
<v11:GetNextAvailableMemberNumberRequest>
<v11:Id>1</v11:Id>
<v11:memberId>1</v11:memberId>
</v11:GetNextAvailableNumberRequest>
</soapenv:Body>
</soapenv:Envelope>
But instead, now I have this:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www..com/membership/types/v1_0">
<SOAP-ENV:Header>
<ns1:loginDetails>
<item><key>siteId</key><value>0</value></item>
<item><key>Username</key><value>MEMBERSHIP</value></item>
<item><key>Password</key><value>P#ssw0rd</value></item>
</ns1:loginDetails>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:GetNextAvailableMemberNumberRequest/>
<param1>1</param1>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
And this is the php code that I'm currently using:
$client = new SOAPClient('http://192.168.180.128:8010//membershipService?wsdl',array('trace' => true));
$client->__setSoapHeaders(null);
$headerbody = array ('siteId' => '0','Username' => 'MEMBERSHIP',
'Password' => 'P#ssw0rd');
$header = new SOAPHeader('http://www.com/club/services/membership/types/v1_0','loginDetails',$headerbody);
$client->__setSoapHeaders($header);
Where have I gone wrong? I seems unable to construct the header properly.

Just try to use an anonymous class instead of an array :
// Use standard class and set magic properties.
$header = new stdClass();
$header->siteId = '0';
$header->Username = 'MEMBERSHIP';
$header->Password = 'P#ssw0rd';

Casting the array of parameters to an object works pretty well
$auth = (object)array(
'Username' => 'AzureDiamond',
'Password' => 'hunter2',
);
$header = new SOAPHeader('http://my.ns/','loginDetails',$auth);
However, I find that it still doesn't get namespaces quite right. The above produces
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns2="http://my.ns/">
<SOAP-ENV:Header>
<ns2:loginDetails>
<Username>AzureDiamond</Username>
<Password>hunter2</Password>
</ns2:loginDetails>
</SOAP-ENV:Header>
....
And you'll see that although the 'loginDetails' tag is in the requested namespace, it's child elements are not.

I just encountered a very similar problem.
To fix it, you need to use the SoapVar class. This allows you to control what namespace to use for each tag.
$client = new SOAPClient('http://192.168.180.128:8010//membershipService?wsdl',array('trace' => true));
$ns = 'http://www.com/club/services/membership/types/v1_0';
$headerbody = new SoapVar([
new SoapVar('0', XSD_STRING, null, null, 'siteId', $ns),
new SoapVar('MEMBERSHIP', XSD_STRING, null, null, 'Username', $ns),
new SoapVar('P#ssw0rd', XSD_STRING, null, null, 'Password', $ns),
], SOAP_ENC_OBJECT);
$header = new SOAPHeader($ns,'loginDetails',$headerbody);
$client->__setSoapHeaders($header);
Your request's soap header should look something like this with this:
<SOAP-ENV:Header>
<ns1:loginDetails>
<ns1:siteId>0</ns2:siteId>
<ns1:Username>MEMBERSHIP</ns2:Username>
<ns1:Password>P#ssw0rd</ns2:Password>
</ns1:loginDetails>
</SOAP-ENV:Header>

There was typo:
$header = NEW stdClass() ;

$headerbody = array ('Id' => '0','username' => 'MEMBERSHIP',
'password' => 'P#ssw0rd');
Please refer the link
http://php.net/manual/en/class.soapheader.php
Also make sure that you are passing correct namespace (first parameter) in SOAPHeader constructor

Related

Soap requests with Curl PHP

How can I make Soap request using Curl php by using below soap format and url? I have tried avaliable solutions online and none of them worked out.
$soap_request = '<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:alisonwsdl" 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:Header>
<credentials>
<alisonOrgId>9ReXlYlpOThe24AWisE</alisonOrgId>
<alisonOrgKey>C2owrOtRegikaroXaji</alisonOrgKey>
</credentials>
</soap:Header>
<SOAP-ENV:Body>
<q1:login xmlns:q1="urn:alisonwsdl">
<email xsi:type="xsd:string">email</email>
<firstname xsi:type="xsd:string">fname</firstname>
<lastname xsi:type="xsd:string">lname</lastname>
<city xsi:type="xsd:string">city</city>
<country xsi:type="xsd:string">country</country>
<external_id xsi:type="xsd:string"></external_id>
</q1:login>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>';
Url
https://alison.com/api/service.php?wsdl
Assuming you already have php_soap extension installed, you can access the SOAP API like this:
<?php
$client = new SoapClient('https://alison.com/api/service.php?wsdl', array(
'stream_context' => stream_context_create(array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
))
));
You might want to define the header for authentication as well
$auth = array(
'alisonOrgId' => '9ReXlYlpOThe24AWisE',
'alisonOrgKey' => 'C2owrOtRegikaroXaji'
);
$header = new SoapHeader('https://alison.com/api/service.php?wsdl', 'credentials', $auth, false);
$client->__setSoapHeaders($header);
Then you can get the list of functions available
// Get function list
$functions = $client->__getFunctions ();
echo "<pre>";
var_dump ($functions);
echo "</pre>";
die;
Or call a function right away, like this:
// Run the function
$obj = $client->__soapCall("emailExists", array(
"email" => "test#email.com"
));
echo "<pre>";
var_dump ($obj);
echo "</pre>";
die;
After struggling for a week I was able to find something in this tutorial here on youtube https://www.youtube.com/watch?v=6V_myufS89A and I was able to send requests to the API successifuly, first read my xml format above before continuing with my solution
$options = array('trace'=> true, "exception" => 0);
$client = new \SoapClient('your url to wsdl',$options);
//if you have Authorization parameters in your xml like mine above use SoapVar and SoapHeader as me below
$params = new \stdClass();
$params->alisonOrgId = 'value here';
$params->alisonOrgKey = 'value here';
$authentication_parameters = new \SoapVar($params,SOAP_ENC_OBJECT);
$header = new \SoapHeader('your url to wsdl','credentials',$authentication_parameters);
$client->__setSoapHeaders(array($header));
print_r($client->__soapCall("Function here",'Function parameter here or left it as null if has no parameter'));
//or call your function by
print_r($client->yourFunction($function_parameters));
}
Hope this will help someone out there struggling with soap requests that contains authentication informations

Interacting with a soap API without WSDL in PHP

Recently got access to a soap API for a hotel management service. They have provided documentation which shows a basic example of a request:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<Auth xmlns="http://xxxx/xxxxAPI">
<FromSystemId ID="1">CompanyName</FromSystemId>
<UserName>username</UserName>
<Password>password</Password>
</Auth>
</soapenv:Header>
<soapenv:Body>
<GetRegions Timestamp="2016-04-11" Version="1.0" Lang="en"
xmlns="http://xxxx/xxxxAPI">
<Country Code="GB" />
</GetRegions>
</soapenv:Body>
</soapenv:Envelope>
They have also provided a list of functions in their documentation and the parameters required for each of the functions. But i am abit confused on how to perform a request as i have never used a soap API before. They also haven't provided a WSDL, does this matter?
Anyway, here is how i thought to try and perform a request
$soapURL = "http://xxxx/xxxxAPI" ;
$soapParameters = Array('login' => "username", 'password' => "password") ;
$soapFunction = "getRegions";
$soapFunctionParameters = Array('countrycode' => 'GB');
$soapClient = new SoapClient($soapURL, $soapParameters);
$soapResult = $soapClient->__soapCall($soapFunction,
$soapFunctionParameters) ;
if(is_array($soapResult) && isset($soapResult['someFunctionResult'])) {
// Process result.
} else {
// Unexpected result
if(function_exists("debug_message")) {
debug_message("Unexpected soapResult for {$soapFunction}: ".print_r($soapResult, TRUE)) ;
}
}
Am i going about this the right way? i am unable to test this right now as i haven't received my authentication but wanted to make a start on it now.
Any help would be great.
Here is a small example.
$opts = array(
'location' => 'http://xxxx/xxxxAPI',
'uri' => 'urn:http://test-uri/'
);
$client = new SOAPClient(null, $opts);
$headerData = array(
'FromSystemId' => 'CompanyName',
'UserName' => 'username',
'Password' => 'password',
);
// Create Soap Header.
$header = new SOAPHeader('http://xxxx/xxxxAPI', 'Auth', $headerData);
// Set the Headers of Soap Client.
$client->__setSoapHeaders($header);
$result = $client->__soapCall('getRegions', array('GB'));
// $return = $client->__soapCall('getRegions', array(new SoapParam(new SoapVar('GB', XSD_STRING), 'countryCode')));
var_dump($result);
They also haven't provided a WSDL, does this matter?
To be able to add the HEADER attributes they must be mentioned in WSDL. If they not exist in WSDL they WILL NOT appear as attributes but rather <item><key/><value/></item> elements.
Tipp: If you know how the request has to be and you have no WSDL, then try to generate the HTTP header and XML body manually and execute the request with CURL or Guzzle.
Example with Guzzle:
$soapContent = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<Auth xmlns="http://xxxx/xxxxAPI">
<FromSystemId ID="1">CompanyName</FromSystemId>
<UserName>username</UserName>
<Password>password</Password>
</Auth>
</soapenv:Header>
<soapenv:Body>
<GetRegions Timestamp="2016-04-11" Version="1.0" Lang="en"
xmlns="http://xxxx/xxxxAPI">
<Country Code="GB" />
</GetRegions>
</soapenv:Body>
</soapenv:Envelope>';
$client = new GuzzleHttp\Client([
'headers' => [ 'SOAPAction' => '"urn:http://xxxx/xxxxAPI/#getRegions"' ]
]);
$response = $client->post('http://xxxx/xxxxAPI',
['body' => $soapContent]
);
echo $response;

PHP SOAP complex types

I have a working XML request body, which I'm trying to send via PHP to a SOAP server:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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:tns="urn:servicewsdl" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<mns:getQuote xmlns:mns="urn:getquoteswsdl" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<authorisation xsi:type="tns:Authorisation">
<username xsi:type="xsd:string">****</username>
<password xsi:type="xsd:string">****</password>
</authorisation>
<symbol xsi:type="xsd:string">****</symbol>
</mns:getQuote>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I tried passing the params in an array like so:
$result = $client->getQuote(array('username' => '****', 'password' => '****'), array('symbol' => '****'));
but it returns me an error:
SOAP-ERROR: Encoding: object has no 'username' property
you probably need to put the username/password array inside authorisation like:
$result = $client->getQuote(array('authorisation'=>array('username' => '****', 'password' => '****')), array('symbol' => '****'));
or, maybe you should send it an object instead:
$params = new stdClass();
$params->authorisation = new stdClass();
$params->authorisation->username = '****';
$params->authorisation->password = '****';
$params->symbol = '****';
$result = $client->getQuote($params);
EDIT: From the comments, in the end, getQuote was accessed via PHP in this method:
$auth = new stdClass();
$auth->username = '****';
$auth->password = '****';
$symbol = '****';
$result = $client->getQuote($auth, $symbol);
I had a heck of a time working with PHP and SOAP as well. I seem to recall a similar situation where I used the standard PHP class (new stdClass()) to help build the object with params. Here's the questions/answer page.
How can I add Attributes to a PHP SoapVar Object?
I hope it helps.

How to set this soap header on a SOAP CALL PHP?

<SOAP-ENV:Header>
<Seguridad>
<usuario>0000000000</usuario>
<password>9FDBDE265822755C50dHD5D33B61580736ECB94978BC40DDD2D4220CB63FE7E</password>
<fechaSistema>02/01/2015</fechaSistema>
</Seguridad>
</SOAP-ENV:Header>
I need to add this header to the soap call, but, the examples that I found need some namespace, and result so different of this.
I used NuSoap.php
$wsdl = "https://www.convolmiscelaneapruebas.pemex.com/ServiciosCVWEB/ServicioEnviaCONVOLService/ServicioEnviaCONVOLService.wsdl";
$client = new nusoap_client($wsdl,TRUE);
$header =
"<Seguridad>
<usuario>0001250000</usuario>
<password>4e671bf08913dn8k09d6359262117c8e67a5507b165f727288a487040bf2a1780</password>
<fechaSistema>02/01/2015</fechaSistema>
</Seguridad>";
$operation = array('arg0' => '2012-08-25',
'arg1' => '11:48:46',
'arg2'=>'12095866a6l9b7dbcd44640189c57hlZ5918192739040eb52ba5b==',
'arg3'=>'ZmU5866axMzc3ZDQyJmdAyZjM2YTc57Db7dbcd446401YTM1Mg3Ng=='
);
$client->setHeaders($header);
$res = $client->call('enviaCONVOL',$operation);

Create this SOAP XML request with PHP's SOAP extension

I'm trying to recreate this XML request using PHP's SOAP extension and having trouble doing it:
<?xml version="1.0"?>
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://services.web.stormpost.skylist.com">
<soapenv:Header>
<authInfo xmlns:soap="http://skylist.com/services/SoapRequestProcessor" xsi:type="soap:authentication">
<!--You may enter the following 2 items in any order-->
<username xsi:type="xsd:string">****#example.com</username>
<password xsi:type="xsd:string">*******</password>
</authInfo>
</soapenv:Header>
<soapenv:Body>
<ser:doImportFromTemplate soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<impTempId xsi:type="xsd:int">7</impTempId>
<data xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:string">
Joe|Doe|joe#example.com John|Doe|john#example.com </data>
</ser:doImportFromTemplate>
</soapenv:Body>
</soapenv:Envelope>
Here is my testing code so far:
// set connection params
$wsdl = 'http://api.stormpost.datranmedia.com/services/SoapRequestProcessor?wsdl';
$namespace = 'https://api.stormpost.datranmedia.com/services/SoapRequestProcessor';
$credentials = (object)array(
'username' => '****#example.com',
'password' => '*******'
);
$auth_values = new SoapVar($credentials, SOAP_ENC_OBJECT);
$header = new SoapHeader($namespace, "authInfo", $auth_values);
// set client, headers, and call function
$client = new SoapClient($wsdl, array('trace' => true));
$client->__setSoapHeaders(array($header));
$client->__soapCall("doImportFromTemplate", array(7, 'Joe|Doe|joe#example.com John|Doe|john#example.com'));
It doesn't seem to be implementing the authInfo node correctly with the xsi:type="soap:authentication" among other things. How should I change my code to output this XML? I'm having trouble finding good implementation examples.
I struggled with the php SOAP client myself a while ago, i didn't really got a full understanding but this worked for me:
$auth_values = array('username' => '****#example.com', 'password' => '*******');
$header = new SoapHeader($namespace, "authInfo", $auth_values, false);
// set client, headers, and call function
$client = new SoapClient($wsdl, array('trace' => true));
$client->__setSoapHeaders(array($header));

Categories