Create this SOAP XML request with PHP's SOAP extension - php

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));

Related

How to set SOAP request to use SoapClient in php?

I am trying to use php SoapClient to consume this SOAP api but which seems to be not working. Can any of you please guide me?
This is the request sample:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:par="http://www.example.com/interface/">
<soapenv:Header>
<par:Header>
<par:UserName>USERNAME</par:UserName>
<par:Password>PASSWORD</par:Password>
</par:Header>
</soapenv:Header>
<soapenv:Body>
<par:GetExampResult>
<par:rollNumber>1703011</par:rollNumber>
</par:GetExampResult>
</soapenv:Body>
</soapenv:Envelope>
This is how i tried to convert it to Soap client and not working.
$username = 'USERNAME';
$password = 'PASS';
$soapURL = "http://www.example.com/interface.asmx?WSDL";
$client = new \SoapClient($soapURL);
$auth = [
'SamplingSoapHeader' => [
'UserName' => $username,
'Password' => $password,
],
];
$header = new \SoapHeader('http://www.example.com/interface/',
'RequestorCredentials', $auth);
$client->__setSoapHeaders($header);
$response = $client->GetExampResult(["rollNumber" => "1703011"]);
print_r($response);
Thanks
You wrapped your Soapheader into an additional XML Tag:
<RequestorCredentials>
<SamplingSoapHeader>
<Username>XYZ</Username>
<Password>123</Password>
</SamplingSoapHeader>
<RequestorCredentials>
In the Soapheader ctor Set the Name to SamplingSoapHeader instead of RequestorCredentials and let $auth be an Array containing only Username and Password instead of wrapping it into SamplingSoapHeader.

Soap request working in SoapUI but not in Wordpress plugin

I've been searching around for a solution to my problem, but to no avail. I'm trying to send a soap request through a Wordpress plugin using the following:
function soapRequest($soapUsername, $soapNonce, $soapDateTime, $soapPassword) {
$wsdl = 'http://www.beautyfort.com/api/wsdl/v2/wsdl.wsdl';
$trace = true;
$exceptions = false;
$client = new SoapClient($wsdl, array('trace' => $trace, 'exceptions' => $exceptions));
// Must be a stdClass (and not an array)
$auth = new stdClass();
$auth->Username = $soapUsername;
$auth->Nonce = $soapNonce;
$auth->Created = $soapDateTime;
$auth->Password = $soapPassword;
$header = new SoapHeader('http://www.beautyfort.com/api/', 'AuthHeader', $auth);
$client->__setSoapHeaders($header);
$xml_array['TestMode'] = 'true';
$xml_array['StockFileFormat'] = 'JSON';
$xml_array['SortBy'] = 'StockCode';
try {
$response = $client->GetStockFile($xml_array);
}
catch (Exception $e) {
log_me("Error!");
log_me($e -> getMessage());
log_me('Last response: '. $client->__getLastResponse());
}
log_me('Last request: '. $client->__getLastRequest());
log_me($response);
}
This produces the following request:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://www.beautyfort.com/api/">
<SOAP-ENV:Header>
<ns1:AuthHeader>
<ns1:Username>joetest</ns1:Username>
<ns1:Nonce>htflFfIKM4</ns1:Nonce>
<ns1:Created>2019-02-09T10:13:51.000Z</ns1:Created>
<ns1:Password>NGFjYTJiNzJmOWY2MzBmY2M2MjJkNjg1MDgyMWRjMzQxOGY1YTNjYQ==</ns1:Password>
</ns1:AuthHeader>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:GetStockFileRequest>
<ns1:TestMode>true</ns1:TestMode>
<ns1:StockFileFormat>JSON</ns1:StockFileFormat>
<ns1:SortBy>StockCode</ns1:SortBy>
</ns1:GetStockFileRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
And I get an invalid credentials error. I've also been testing in SoupUI and the following request works:
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:api="http://www.beautyfort.com/api/">
<soapenv:Header>
<api:AuthHeader>
<api:Username>joetest</api:Username>
<api:Nonce>tJrsRlQt6i</api:Nonce>
<api:Created>2019-02-06T23:34:11.000Z</api:Created>
<api:Password>ZTBhMmE5OGY4YTNlZWIzZTE0ZTc2ZjZiZDBhM2RhMjJmNzAxNzYwZA==</api:Password>
</api:AuthHeader>
</soapenv:Header>
<soapenv:Body>
<api:GetStockFileRequest>
<api:TestMode>true</api:TestMode>
<api:StockFileFormat>JSON</api:StockFileFormat>
<!--Optional:-->
<api:FieldDelimiter>,</api:FieldDelimiter>
<!--Optional:-->
<api:StockFileFields>
<!--1 or more repetitions:-->
<api:StockFileField>StockCode</api:StockFileField>
<api:StockFileField>Category</api:StockFileField>
<api:StockFileField>Brand</api:StockFileField>
<api:StockFileField>Collection</api:StockFileField>
<api:StockFileField>Category</api:StockFileField>
</api:StockFileFields>
<api:SortBy>StockCode</api:SortBy>
</api:GetStockFileRequest>
</soapenv:Body>
</soapenv:Envelope>
Now the only differences I can see (apart from the optional fields) is the names of the namespace, and the use of the Xml tag at the top of the request. Both of these shouldn't matter right? I'd really appreciate your help on this as I've been scratching my head for ages.
Thank you in advance!
Your perfect just need to set UTC timezone and secret format like below:
base64 encoded(sha1(Nonce . Created . Secret))

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;

Converting SOAP request from XML to PHP

I am getting desperate here, I am trying to convert an XML SOAP request which works in SoapUI to PHP. I went through so much documentation online and still cannot get to creating a correct request from within PHP. I tried using the SOAP class provided in PHP together SoapVars, SoapParams and SoapHeaders. This is the request I need to send (in XML form):
<soapenv:Envelope
xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'
xmlns:soapenc='http://schemas.xmlsoap.org/soap/encoding/'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns:wsa='http://schemas.xmlsoap.org/ws/2004/03/addressing'
xmlns:gen='http://www.polaris-uk.co.uk/GenericSchema/1_1/GenericTypes'
xmlns:Detail='http://www.polaris-uk.co.uk/GenericSchema/2/PEMFault'
xsi:SchemaLocation='http://www.polaris-uk.co.uk/GenericSchema/2/PEMFault http://ppw.imarket.co.uk/Polaris/Schema/PEMFault.xsd'>
<soapenv:Header>
<wsse:Security
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis- 200401-wss-wssecurity-secext-1.0.xsd"
soapenv:mustUnderstand="1"
soapenv:actor="http://www.imarket.co.uk/soap/actor">
<wsse:UsernameToken>
<wsse:Username>XXXXXXXXXX</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-ns2curity-secext-1.0.xsd#PasswordText">XXXXXXXXXX</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<ConfirmImarketUserIDReq xmlns="http://www.polaris-uk.co.uk/Schema/1_1/ConfirmImarketUserIDReq">
<ns1:UserID xmlns:ns1="http://www.polaris-uk.co.uk/GenericSchema/1_1/GenericTypes">XXXXXXXXXX</ns1:UserID>
<ns2:Password xmlns:ns2="http://www.polaris-uk.co.uk/GenericSchema/1_1/GenericTypes">XXXXXXXXXX</ns2:Password>
</ConfirmImarketUserIDReq>
</soapenv:Body>
</soapenv:Envelope>
I will not post any code I did until now because it is just a mess since I tried writing bits and pieces without actually putting them together at one point and it will just spam this whole post.
Please, if anyone could help with converting this into a PHP code it will be much appreciated.
Thank you in advance!
After headaches over this, I finally found a working solution, might not be the best but it works by providing Raw XML to the SOAP call:
$wsdl = "XXXX.wsdl";
$client = new SoapClient($wsdl, array( 'soap_version' => SOAP_1_1,'trace' => true,));
//=========== Header Settings ============\\
//Namespace of the Web Service
$namespace = 'http://schemas.xmlsoap.org/soap/envelope/';
$headerXML = <<<XML
<wsse:Security
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
SOAP-ENV:mustUnderstand="1" SOAP-ENV:actor="http://www.imarket.co.uk/soap/actor">
<wsse:UsernameToken>
<wsse:Username>XXXXXX</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-ns2curity-secext-1.0.xsd#PasswordText">XXXXXX</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
XML;
$headerObj = new SoapVar($headerXML, XSD_ANYXML, null, null, null);
$header = new SoapHeader($namespace , 'SessionHeader', $headerObj);
// More than one header can be provided in this array.
$client->__setSoapHeaders(array($header));
//============== Request ================\\
$xml = <<<XML
<ConfirmImarketUserIDReq xmlns="http://www.polaris-uk.co.uk/Schema/1_1/ConfirmImarketUserIDReq">
<ns1:UserID xmlns:ns1="http://www.polaris-uk.co.uk/GenericSchema/1_1/GenericTypes">XXXXXX</ns1:UserID>
<ns2:Password xmlns:ns2="http://www.polaris-uk.co.uk/GenericSchema/1_1/GenericTypes">XXXXXX</ns2:Password>
</ConfirmImarketUserIDReq>
XML;
$args = array(new SoapVar($xml, XSD_ANYXML));
try {
$response = $client->__soapCall( 'ConfirmImarketUserIDOp', $args);
var_dump($response);
}
catch (SoapFault $e) {
trigger_error("SOAP Fault: (faultcode: {$e->faultcode}, faultstring: {$e->faultstring})", E_USER_ERROR);
}
Hope this helps anyone,
Cheers!

SoapHeader formatting using PHP

I am using the following code to create a SOAPHEADER using PHP
// Instantiate the client.
$client = new SoapClient($wsdl_url, array('trace' => 1));
// Pass along login information
$soap_header = new SoapHeader(
$api_url,
'APICredentials',
array(
'DeveloperKey' => $developerKey,
'Password' => $password
)
);
$client->__setSoapHeaders($soap_header);
which created this
<SOAP-ENV:Header>
<ns2:APICredentials>
<item>
<key>DeveloperKey</key>
<value>********</value>
</item>
<item>
<key>Password</key>
<value>********</value>
</item>
</ns2:APICredentials>
</SOAP-ENV:Header>
How do I change the PHP code to create the following headers?
<soapenv:Header>
<web:APICredentials>
<web:DeveloperKey>...</web:DeveloperKey>
<web:Password>...</web:Password>
</web:APICredentials>
</soapenv:Header>
You can set this completely manual by using $soap_client->__setSoapHeaders($header);
Required SOAP Header:
<soap:Header>
<RequestorCredentials xmlns="http://namespace.example.com/">
<Token>string</Token>
<Version>string</Version>
<MerchantID>string</MerchantID>
<UserCredentials>
<UserID>string</UserID>
<Password>string</Password>
</UserCredentials>
</RequestorCredentials>
</soap:Header>
Corresponding PHP code:
<?php
$ns = 'http://namespace.example.com/'; //Namespace of the WS.
//Body of the Soap Header.
$headerbody = array('Token' => $someToken,
'Version' => $someVersion,
'MerchantID'=>$someMerchantId,
'UserCredentials'=>array('UserID'=>$UserID,
'Password'=>$Pwd));
//Create Soap Header.
$header = new SOAPHeader($ns, 'RequestorCredentials', $headerbody);
//set the Headers of Soap Client.
$soap_client->__setSoapHeaders($header);
Source: http://php.net/manual/en/soapclient.setsoapheaders.php

Categories