passing multiple WSDL header variables to SOAP server - php

I am using SOAP web services for the first time and i am having a problem in calling the SOAP server. I searched through WSDL SOAP request not i am not able to solve my problem. This is the snippet of my WSDL
<s:complexType name="VerHeader">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="HD1" type="s:string"/>
<s:element minOccurs="0" maxOccurs="1" name="HD2" type="s:string"/>
<s:element minOccurs="0" maxOccurs="1" name="HD3" type="s:string"/>
</s:sequence>
<s:anyAttribute/>
</s:complexType>
I have to send username, password and some ID in these HD1, HD2 and HD3 variables. I have also tried these links Passing a PHP array in a SOAP call and Sending a Soap Header with a WSDL Soap Request with PHP
Here is what i have tried but not working, every time i run my code it send failure message, can you figure it out what's wrong with my code or my logic?
$soap = new SoapClient("http://example.com/verifyrecord.asmx?WSDL");
$header = array('HD1'=>'000000023','HD2'=>'val2','HD3'=>'val2');
$header = new SoapHeader('http://www.example.com/', 'VerHeader ', $header);
$soap->__setSoapHeaders(array($header));

Solved the problem. I solved it not by using php functions but creating an xml file manually and sending it to the soap server. I've posted an example of my answer so that it might be helpful to others. Thanks all for the help.
// the xml to send
$xml = '<?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:Header>
<VerHeader xmlns="http://www.example.com/">
<HD1>000000000117</HD1>
<HD1>user</HD1>
<HD1>password</HD1>
</VerHeader>
</soap:Header>
<soap:Body>
<m:VerifyTransaction xmlns:m="http://www.example.com/">
<m:object1>45344</m:object1>
<m:object2>5545437</m:object2>
</m:VerifyTransaction>
</soap:Body>
</soap:Envelope>';
// build your http request
$context = stream_context_create(array(
'http' => array(
'method' => 'POST',
'header' => "Content-type: text/xml\r\n",
'validateRequest'=>false,
'content' => $xml,
'timeout' => 10,
),
));
// send it
echo $xmlstring = file_get_contents('http://example.com/VerifyThis/VerifyThis.asmx?wsdl', false, $context);

shouldn't this
new SoapHeader('http://www.example.com/', 'VerHeader ', $header);
be
new SoapHeader('http://www.example.com/verifyrecord', 'VerHeader ', $header);

try like this i did used this for my uk mail api .. and it worked
<?php
$LoginWebRequest = new stdClass();
$LoginWebRequest->Username = 'xxx cant show here xxx';
$LoginWebRequest->Password = 'xxx cant show here xxx';
//echo "<pre>"; print_r($LoginWebRequest); "</pre>"; exit;
$Login = new stdClass();
$Login->loginWebRequest = $LoginWebRequest;
//echo "<pre>"; print_r($Login); "</pre>"; exit;
$soapClient = new SoapClient('https://qa-api.ukmail.com/Services/UKMAuthenticationServices/UKMAuthenticationService.svc?wsdl');
$LoginResponse = $soapClient->Login($Login);
?>

Related

how can i use the function CREATE in soap webservice in Navision in PHP?

Here you can see documentation. It is in C# . I tried to make a working example using PHP. I managed to execute the Read & ReadMultiple functions in PHP. This is my try:
require ("./NTLMSoapClient.php");
$client = new NTLMSoapClient(null, array(
'cache_wsdl' => WSDL_CACHE_NONE,
'trace' => true,
'location' => "http://83.166.204.26:7147/TEST/WS/Harmont%20Blaine_TEST/Page/WebItem",
'uri' => "urn:microsoft-dynamics-schemas/page/webitem",
));
$client->user = "xxxxxx";
$client->password = "xxxxxxxxx";
try{
$resp = $client->Create(new SoapVar('555554', XSD_STRING, null, null, 'ns1:No' ));
echo "REQUEST:\n" . htmlentities($client->__getLastRequest()) . "\n";
}catch(SoapFault $sf){
//echo "REQUEST:\n" . htmlentities($client->__getLastRequest()) . "\n";
print '<pre>';
print_r($sf);
print '</pre>';
}
print '<pre>';var_dump($resp); print '</pre>';
It returns me NULL for some reason. Any idea why is not working?
Freddy Kristiansen did a wonderful series of blog posts with detailed explanation how to connect to Nav web services from different environments.
First part is here:
Connecting to NAV Web Services from …
The second part:
Connecting to NAV Web Services from PHP
Client can receive NULL response for several reasons. First of them - client application is unable to authenticate on the web service. This can happen if the server side uses SPNEGO protocol instead of NTLM. You need to set the key "ServicesUseNTLMAuthentication" in CustomSettings.config, as Freddy described in the first of his posts.
If you can read data from the service, but cannot create a record, this means that the request successfully passes authentication, and the problem is likely in the SOAP message format.
This is what Nav expects to receive in Create request
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<Create xmlns="urn:microsoft-dynamics-schemas/page/customer">
<Customer>
<No>555554</No>
<Name>NewCustomer</Name>
</Customer>
</Create>
</soap:Body>
</soap:Envelope>
To achieve this result, you could replace standard HTTP stream wrapper with NTLMStream wrapper (see the post "Connecting to NAV web services from PHP" above.
Now, this is all you need to do to read a customer record:
$client = new NTLMSoapClient("http://192.168.0.101:7047/DynamicsNAV71/WS/".rawurlencode($company)."/Page/Customer");
$resp = $client -> Read(array('No' => '10000'));
Creating new records becomes much easier as well:
$client = new NTLMSoapClient("http://192.168.0.101:7047/DynamicsNAV71/WS/".rawurlencode($company)."/Page/Customer");
class CustomerWrapper
{
public $Customer;
}
$cw = new CustomerWrapper;
$cw -> Customer -> No = "555554";
$cw -> Customer -> Name = "NewCustomerName";
$cw -> Customer -> E_Mail = "john.doe#cronuscorp.net";
$resp = $client -> Create($customer);
THIS is the solution :
$resp = $client->Create(new SoapVar('5555195', XSD_STRING, null, null, 'ns1:WebItem' ));
I have to change the No to WebItem
see here:
<xsd:element name="Create">
<xsd:complexType>
<xsd:sequence>
<xsd:element minOccurs="1" maxOccurs="1" name="WebItem" type="tns:WebItem"/></xsd:sequence></xsd:complexType>
</xsd:element>

How can I add custom elements to the detail section of a SoapFault using PHP's SOAP library

I am building a service against Sonos' Music API (SMAPI). Sometimes I have to send back a response in the following format:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>Client.NOT_LINKED_RETRY</faultcode>
<faultstring>Link Code not found retry...</faultstring>
<detail>
<ExceptionInfo>NOT_LINKED_RETRY</ExceptionInfo>
<SonosError>5</SonosError>
</detail>
</soap:Fault>
</soap:Body>
</soap:Envelope>
I am building my service using the PHP SOAP library and for the above response I tried throwing a SoapFault like this:
throw new SoapFault('Client.NOT_LINKED_RETRY', 'Link Code not found retry...');
But when I try this the response that is sent back looks like this:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>Client.NOT_LINKED_RETRY</faultcode>
<faultstring>Link Code not found retry...</faultstring>
<detail>
<SonosError/>
</detail>
</soap:Fault>
</soap:Body>
</soap:Envelope>
Notice that there is no ExceptionInfo and that SonosError is empty. Is it possible to set ExceptionInfo and SonosError using SoapFault? I tried all kinds of things, but couldn't get it working, so as a work around I am doing this now:
http_response_code(500);
header("Content-type: text/xml");
$ret = '<?xml version="1.0" encoding="UTF-8"?>'."\n";
$ret .= '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">';
$ret .= '<SOAP-ENV:Body>';
$ret .= '<SOAP-ENV:Fault>';
$ret .= '<faultcode>Client.NOT_LINKED_RETRY</faultcode>';
$ret .= '<faultstring>Link Code not found retry...</faultstring>';
$ret .= '<detail>';
$ret .= '<ExceptionInfo>NOT_LINKED_RETRY</ExceptionInfo>';
$ret .= '<SonosError>5</SonosError>';
$ret .= '</detail>';
$ret .= '</SOAP-ENV:Fault>';
$ret .= '</SOAP-ENV:Body>';
$ret .= '</SOAP-ENV:Envelope>'."\n";
echo $ret; exit;
Not sure if it's relevant but the WSDL can be found here.
Update: when I try the suggestion below like this:
$detail = new StdClass();
$detail->SonosError = 5;
$detail->ExceptionInfo = 'NOT_LINKED_RETRY';
throw new SoapFault(
'Client.NOT_LINKED_RETRY',
'Link Code not found retry...',
NULL,
$detail
);
I get:
<detail>
<customFault>
<SonosError>5</SonosError>
<ExceptionInfo>NOT_LINKED_RETRY</ExceptionInfo>
</customFault>
</detail>
This is almost what I need, except for <customFault> tag. Is there a way to get rid of it and have SonosError and ExceptionInfo in <detail> directly?
The fact that you don't see the ExceptionInfo tag is because it is not defined in the wsdl. On the other hand SonosError is defined.
First thing first, in order to fill the SonosError you have to pass the arguments.
From here you can see that the constructor has more parameters
SoapFault('code', 'string', 'actor', 'detail', 'name', 'header');
In order to pass the SonosError call it like this
$detail = new StdClass();
$detail->SonosError = 5;
throw new SoapFault('Client.NOT_LINKED_RETRY', 'Link Code not found retry...', null, $details);
As for the ExceptionInfo, the wsdl must be changed. As it is now, the details tag is represented by this sections
<wsdl:message name="customFault">
<wsdl:part name="customFault" element="tns:SonosError"/>
</wsdl:message>
<xs:element name="SonosError" type="xs:int"/>
If you change the above sections with these, you will have what you need.
<wsdl:message name="customFault">
<wsdl:part name="customFault" type="tns:customFaultType" />
</wsdl:message>
<xs:complexType name="customFaultType">
<xs:sequence>
<xs:element name="SonosError" type="xs:int"/>
<xs:element name="ExceptionInfo" type="xs:string"/>
</xs:sequence>
</xs:complexType>
And of course you add the parameter and the array becomes like this
$detail = new StdClass();
$detail->SonosError = 5;
$detail->ExceptionInfo = 'NOT_LINKED_RETRY';

SOAP WSDL PHP client connecting to .Net Server

I need to integrate a web service, and its being like to days, and the closest I get is the following, maybe some of you have more experience than me in this kind of web service.
The XML request I need to generate is the following
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v2="http://v2.services.cangooroo.net/" xmlns:can="Cangooroo.Webservice.V2">
<soapenv:Header/>
<soapenv:Body>
<v2:getCityData>
<v2:credentialClient>
<can:UserName>?</can:UserName>
<can:Password>?</can:Password>
</v2:credentialClient>
<v2:countryId>US</v2:countryId>
</v2:getCities>
</soapenv:Body>
</soapenv:Envelope>
My PHP code
$client = new SoapClient("http://v2.cangooroo.net/ws/2013/common_a.asmx?WSDL", array(
"trace" => 1,
"compression" => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP,
));
$login = array();
$login[] = new SoapVar('*', XSD_STRING, null, null, 'UserName', 'Cangooroo.Webservice.V2' );
$login[] = new SoapVar('*', XSD_STRING, null, null, 'Password', 'Cangooroo.Webservice.V2' );
$rest = array();
$rest[] = new SoapVar($login, SOAP_ENC_OBJECT, null, null, 'credentialClient' );
$rest[] = new SoapVar('US', XSD_STRING, null, null, 'countryId');
$options = array('location' => 'http://v2.cangooroo.net/ws/2013/common_a.asmx');
try {
$resp = $client->__soapCall('getCityData', $rest, $options);
print_r($resp);
echo "Request:<pre>" . htmlentities($client->__getLastRequest()) . "</pre>";
}catch (SoapFault $e){
echo "REQUEST:<pre>" . htmlentities($client->__getLastRequest()) . "</pre>";
/*print_r($e);*/
The actual xml the PHP code above generates
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="Cangooroo.Webservice.V2" xmlns:ns2="http://ws_2013.services.cangooroo.net/">
<SOAP-ENV:Body>
<ns2:getCityData>
<ns1:UserName>*</ns1:UserName>
<ns1:Password>*</ns1:Password>
</ns2:getCityData><countryId>US</countryId></SOAP-ENV:Body></SOAP-ENV:Envelope>
Iam not really sure if this is the best way to do it, but I tryed others, with __soapCall,
__doRequest, this last one I got the soapClient php core class extended (as a try) to connect, and nothing seems to work. Pls, I could use a little help here. Tks guys.
If you check the wsdl file in http://v2.cangooroo.net/ws/2013/common_a.asmx?WSDL you can see the definition of the getCityData
<s:element name="getCityData">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="credential" type="s1:ClientCredential"/>
<s:element minOccurs="0" maxOccurs="1" name="countryId" type="s:string"/>
</s:sequence>
</s:complexType>
</s:element>
the operation getCityData has a credential parameter, not a credentialClient that is what you have in the code that you posted. I've tried with this code:
$wsdlAddress = "http://v2.cangooroo.net/ws/2013/common_a.asmx?WSDL";
$options = array(
"soap_version" => SOAP_1_2,
"cache_wsdl" => WSDL_CACHE_NONE,
"exceptions" => false
);
$webServiceClient = new SoapClient($wsdlAddress, $options);
$requestData = array(
"countryId" => "US",
"credential" => array(
"UserName" => "username",
"Password" => "Password",
),
);
$response = $webServiceClient->__soapCall("getCityData", array("getCityData" => $requestData));
echo "<h2>getCityData Operation Test:</h2>";
echo "<pre>";
print_r($response);
echo "</pre>";
in the response i can see Err: Login_Fail - Invalid user or password., i think i'm getting a valid response. Try with my code and adapt it to your needs.
Happy coding

How is PHP 5.3 SOAP request formed?

I am trying to write some code to talk to the SmarterMail API, but I can't seem to make PHP format the request properly. The [ugly] code I have so far is:
<?php
function array_to_params($in_arr) {
$out_arr = array();
foreach( $in_arr as $key => $value ) {
$out_arr[] = new SoapParam($value, $key);
}
return $out_arr;
}
echo "<pre>";
$soapClient = new SoapClient(
"http://mailserver.net/Services/svcDomainAdmin.asmx?WSDL",
array('trace' => true)
);
var_dump($soapClient->__getTypes());die();
$soap_user_params = array(
'blank' => 'blank', //if I don't have a dummy entry the first parameter doesn't show up.
'AuthUserName' => 'admin',
'AuthPassword' => 'derp'
);
$soap_user_params = array_to_params($soap_user_params);
$error = FALSE;
try {
$info = $soapClient->__soapCall("GetAllDomains", $soap_user_params);
// $info = $soapClient->GetAllDomains($soap_user_params); //same results
} catch (SoapFault $fault) {
$error = TRUE;
printf("Error %s: %s\n", $fault->faultcode, $fault->faultstring);
}
if( !$error ) {
var_dump($info);
echo "\nRequest: " . htmlentities($soapClient->__getLastRequest());
}
echo "</pre>";
?>
For reference, the WSDL for this function is:
<s:element name="GetAllDomains">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="AuthUserName" type="s:string"/>
<s:element minOccurs="0" maxOccurs="1" name="AuthPassword" type="s:string"/>
</s:sequence>
</s:complexType>
</s:element>
The example request given is:
<?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>
<GetAllDomains xmlns="http://tempuri.org/">
<AuthUserName>string</AuthUserName>
<AuthPassword>string</AuthPassword>
</GetAllDomains>
</soap:Body>
</soap:Envelope>
But the request generated by my code is:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tempuri.org/">
<SOAP-ENV:Body>
<ns1:GetAllDomains/>
<AuthUserName>admin</AuthUserName>
<AuthPassword>derp</AuthPassword>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
You can see that the username and password parameters are not contained within the GetAllDomains section for some reason. As well, in the code you can see that I have to pass a dummy parameter in first because whatever is first does not show up in the request. Also, I cannot simply pass in an associative array because the keys are not used as parameter names, it puts in 'param1' and 'param2' instead.
I should note that the server accepts the request and spits back a message about the auth failing. There is a built-in SOAP request tester on the server, and when the request fits the given example it works normally.
Everything I've looked up in the PHP docs and through Google seems to indicate that it should not be this difficult. :(
Any help is GREATLY appreciated.
note: I am running PHP 5.3.8 on Apache 2.2 on FreeBSD, built and installed via ports today.
post-answer-edit:
Thanks to Gian's answer below I've gotten this working and greatly simplified the code:
<?php
echo "<pre>";
$soapClient = new SoapClient( "http://mailserver.net/Services/svcDomainAdmin.asmx?WSDL", array( 'trace' => true ) );
$soap_user_params = array(
'AuthUserName' => 'admin',
'AuthPassword' => 'derp'
);
try {
$info = $soapClient->__soapCall("GetAllDomains", array( 'parameters' => $soap_user_params ) );
var_dump($info);
echo "\nRequest:\n" . htmlentities($soapClient->__getLastRequest());
} catch (SoapFault $fault) {
printf("Error %s: %s\n", $fault->faultcode, $fault->faultstring);
}
echo "</pre>";
My apologies for the mis-directed close. I misunderstood what you were trying to do at first.
Sifting through the soapCall documentation comments, there are a couple things I'd suggest trying. First off, this:
$soap_user_params = array(
'parameters' => array (
'AuthUserName' => 'admin',
'AuthPassword' => 'derp'
)
);
Apparently your parameters need to be an element in an associative array with the key 'parameters'. Weird, huh?
Failing that, you may need to nest this even deeper! The _ array entry does not appear to be documented anywhere obvious, but this seems to be something that the commenters on the PHP docs were suggesting. So maybe this:
$soap_user_params = array(
'parameters' => array (
'AuthUserName' => array('_' => 'admin'),
'AuthPassword' => array('_' => 'derp')
)
);

Error establishing a SOAP connection to a WSDL service in PHP

I am trying to connect a wsdl service. Other methods don't work without login. But when I tried the login I got a httpheaders error. My wsdl link : http://dgpysws.teias.gov.tr/dgpys/services/EVDServis?wsdl
when i look this link=
http://dgpysws.teias.gov.tr/dgpys/services/EVDServis.wsdl
<xs:element name="login">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="loginMessage" nillable="true" type="dgp:LoginMessage"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="LoginMessage">
<xs:sequence>
<xs:element minOccurs="0" name="Password" nillable="true" type="dgp:StringValue"/>
<xs:element minOccurs="0" name="UserName" nillable="true" type="dgp:StringValue"/>
</xs:sequence>
</xs:complexType>
Here is my php code;
<?php
// Turn up error reporting
ini_set ("display_errors", "1");
error_reporting (E_ALL|E_STRICT);
// Turn off WSDL caching
ini_set ('soap.wsdl_cache_enabled', 0);
$Password = 'deneeme';
$UserName = 'demnenee';
$search_query = new StdClass();
$search_query->oLoginRequest = new StdClass();
$search_query->oLoginRequest->Password = $Password;
$search_query->oLoginRequest->Username = $UserName;
echo "Setting up SOAP options\n";
$soap_options = array(
'trace' => 1, // traces let us look at the actual SOAP messages later
'exceptions' => 1 );
$wsdl = "http://dgpysws.teias.gov.tr/dgpys/services/EVDServis?wsdl";
echo "Checking SoapClient exists\n";
echo '<br>';
if (!class_exists('SoapClient'))
{
die ("You haven't installed the PHP-Soap module.");
}
echo "Creating webservice connection to $wsdl\n";
$webservice = new SoapClient($wsdl,$soap_options);
try {
$result = $webservice->login($search_query);
// perform some logic, output the data to Asterisk, or whatever you want to do with it.
} catch (SOAPFault $f) {
// handle the fault here
echo 'Hata:' . $f;
}
echo "Script complete\n\n";
?>
I am getting this error when run php file;
Setting up SOAP options Checking SoapClient exists
Creating webservice connection to http://dgpysws.teias.gov.tr/dgpys/services/EVDServis?wsdl Hata:SoapFault exception: [HTTP] Error Fetching http headers in C:\xampp\htdocs\test\pmum.php:36 Stack trace: #0 [internal function]: SoapClient->__doRequest('__call('login', Array) #2 C:\xampp\htdocs\test\pmum.php(36): SoapClient->login(Object(stdClass)) #3 {main}Script complete
$client = new SoapClient("http://dgpysws.teias.gov.tr/dgpys/services/EVDServis.wsdl");
$p1->loginMessage->UserName->v = "Deneme";
$p1->loginMessage->Password->v = "Deneme";
$deneme = $client->login($p1);
var_dump($deneme);
worked for me!

Categories