There a Webservice on my server written in php that update a customer in an Acomba table. The service update correctly the customer but when i receive the response the webpage crash because the xml is not properly closed. I call the Webservice with ajax.
I didn't wrote either the call or the webservice but i have to fix it...
Logged error:
SoapFault exception: [Client] looks like we got no XML document in C:\inetpub\wwwroot\eureka\ajax\syncContratAvenant.php:85
Stack trace:
C:\inetpub\wwwroot\eureka\ajax\syncContratAvenant.php(85): SoapClient->__soapCall('saveClientAvena...', Array)
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:SOAP_AvenantAcomba" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body><ns1:saveClientAvenant><param0 xsi:type="ns2:Map"><item><key xsi:type="xsd:string">noContrat</key><value xsi:type="xsd:string">FP00000000</value></item>
<item><key xsi:type="xsd:string">acombaUidClient</key><value xsi:type="xsd:string">945</value></item><item><key xsi:type="xsd:string">name</key><value xsi:type="xsd:string">Test</value></item><item><key xsi:type="xsd:string">institution</key><value xsi:type="xsd:string">000</value></item><item><key xsi:type="xsd:string">folio</key><value xsi:type="xsd:string">000000</value></item><item><key xsi:type="xsd:string">transit</key><value xsi:type="xsd:string">00000</value></item><item><key xsi:type="xsd:string">zip</key><value xsi:type="xsd:string">XXX XXX</value></item><item><key xsi:type="xsd:string">adress</key><value xsi:type="xsd:string">2 testtown</value></item><item><key xsi:type="xsd:string">phone</key><value xsi:type="xsd:string"></value></item><item><key xsi:type="xsd:string">city</key><value xsi:type="xsd:string">Test</value></item></param0></ns1:saveClientAvenant>
</SOAP-ENV:Body></SOAP-ENV:Envelope>
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:SOAP_AvenantAcomba" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body><ns1:saveClientAvenantResponse><return xsi:type="ns2:Map"><item><key xsi:type="xsd:string">reponse</key><value xsi:type="xsd:boolean">true</value></item><item><key xsi:type="xsd:string">errorMessage</key><value xsi:type="xsd:string"></value></item></return></ns1:saveClientAvenantResponse>
</SOAP-ENV:Body></SOAP-ENV:Envelop
Notice how the envelope is not properly closed there... don't know why through....
The call :
$client = new SoapClient(null, array('location' => ACOMBA_WEB_SERVICE_Avenant,
'uri' => "urn:SOAP_AvenantAcomba",
'trace' => 1,
'encoding' => 'ISO-8859-1'));
$info = array($arraySOAP => array(
'noContrat' => getNoContratTxt($contract->getCols('noContract')),
'acombaUidClient' => $contract->getCols('acombaUidClient'),
'name' => $contract->getCols('name') ,
'institution' => $contract->getCols('noInstitution'),
'folio' => $contract->getCols('noFolio'),
'transit' => $contract->getCols('noTransit'),
'zip' => makeSQasDQ($contract->getCols('zipAddAssurer')),
'adress' => makeSQasDQ(utf8_decode($contract->getCols('noAddAssurer') . ' ' . $contract->getCols('streetAddAssurer'))),
'phone' => '',
'city' => makeSQasDQ(utf8_decode($contract->getCols('townAddAssurer'))))
);
$resultClient = $client->__soapCall('saveClientAvenant', $info); // crash here
The service :
<?php
require_once('variables.php');
set_time_limit(900);
function saveClientAvenant($arraySOAP){
$conn = odbc_connect(ACOMBA_DRIVER, ACOMBA_USER, base64_decode(ACOMBA_PASS));
if (odbc_commit($conn)) {
try {
$nxtContrat = $arraySOAP['noContrat'];
$nom = $arraySOAP['name'];
$noInstitution = $arraySOAP['institution'];
$noFolio = $arraySOAP['folio'];
$noTransit = $arraySOAP['transit'];
$zipCode = $arraySOAP['zip'];
$adress = $arraySOAP['adress'];
$phone = $arraySOAP['phone'];
$city = $arraySOAP['city'];
$acombaUidClient = $arraySOAP['acombaUidClient'];
$sqlQuery = "UPDATE " . TABLE_ACOMBA_CLIENT . "
SET
CuSortKey = '$nom',
CuName = '$nom',
CuAddress = '$adress',
CuCity = '$city',
CuPostalCode = '$zipCode',
CuPhoneNumber1 = '$phone',
CuInstitutionNumber = '$noInstitution',
CuBranchNumber = '$noTransit',
CuAccountNumber = '$noFolio'
WHERE
CuUnique = $acombaUidClient
";
if (!odbc_exec($conn, $sqlQuery)) {
throw new Exception($sqlQuery . odbc_errormsg());
}
} catch (Exception $e) {
return array('reponse' => false,
'errorMessage' => $e->getMessage() );
}
odbc_close($conn);
return array('reponse' => true,
'errorMessage' => '' );
}
}
$server = new SOAPServer(null, array('uri' => 'urn:SOAP_AvenantAcomba',
'encoding' => 'ISO-8859-1'));
$server->addFunction('saveClientAvenant');
$HTTP_RAW_POST_DATA = file_get_contents('php://input');
$server->handle();
?>
Have you tried changing:
'encoding' => 'ISO-8859-1'
to:
'encoding'=>'UTF-8'
?
I would expect a slightly different content length with those, which is what i see as your issue.
I have experienced the same issue with invalid SOAP XML, specifically it missing </SOAP-ENV:Envelope missing its closing > when our server has been using Brotli compression to compress the XML, for some reason Brotli and Soap don't work well together.
Related
I'm trying to make a SOAP request using PHP and I don't seem to be able to seperate my parameters I need to send with the call. I can use the service through out a SOAP testing tool, and the snippet I'm using there is (with ccn3 and ccn2 removed):
<?xml version="1.0" encoding="utf-8"?>
<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>
<tns:GetUser>
<tns:auth>
<ccn3:Username>testuser</ccn3:Username>
<ccn3:Password>testpass</ccn3:Password>
<ccn3:AuthID>55125621</ccn3:AuthID>
</tns:auth>
<tns:user>
<ccn2:Address>Testvägen 1</ccn2:Address>
<ccn2:CustNo/>
<ccn2:FirstName/>
<ccn2:LastName/>
<ccn2:SSN>1234567890</ccn2:SSN>
</tns:user>
</tns:GetUser>
</soap:Body>
</soap:Envelope>
This do work and gives the desired answer from the service. But when connecting to it through php it doesn't. The php code I'm currently using looks like this:
<?php
$username = "testuser";
$password = "testpass";
$authID = 55125621;
$client = new SoapClient("https://url/service.svc?wsdl");
$param = array(
'Username'=>$username,
'Password'=>$password,
'AuthID'=>$AuthID,
'Address'=>'Testvägen 1',
'SSN'=>'1234567890',
'FistName'=>'',
'LastName'=>''
);
$res = $client->GetUser($param);
echo "<pre>";
print_r($res);
echo "</pre>";
?>
In my XML query I'm using two "groups" of parameters. I send auth data towards my ccn3 (tns:auth) and my data to ccn2 (tns:user). I'm guessing that's my problem, but how do I do this seperation in php?
Try this:
$params = array(
'auth' => array(
'Username' => $username,
'Password' => $password,
'AuthID' => $AuthID,
),
'user' => array(
'Address' => 'Testvägen 1',
'SSN' => '1234567890',
'FistName' => '',
'LastName' => ''
));
$res = $client->GetUser($params);
I am logging into a server with soap and retreiving a token, no problem....
I then add the token to the soap:header.
This is what I am trying create.
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Header>
<WSAuthorization xmlns="http://url.com/testing/">
<Token>string</Token>
</WSAuthorization>
</soap12:Header>
<soap12:Body>
<ImportDrugTest xmlns="http://url.com/testing/">
<specimenID>int</specimenID>
<midasNumber>string</midasNumber>
<specimenComments>string</specimenComments>
<nonRXDrugsUsed>string</nonRXDrugsUsed>
<testCode>string</testCode>
<testDate>dateTime</testDate>
<testResult>string</testResult>
<collectionDate>dateTime</collectionDate>
<lastName>string</lastName>
<firstName>string</firstName>
<middleName>string</middleName>
<CRUDFlag>string</CRUDFlag>
</ImportDrugTest>
</soap12:Body>
</soap12:Envelope>
This is what I am getting
<?xml version="1.0" encoding="UTF-8"?>
<soap-env:envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://url.com/testing/">
<soap-env:header>
<ns1:wsauthorization />
</soap-env:header>
<soap-env:body>
<ns1:importdrugtest>
<ns1:specimenid>605431024</ns1:specimenid>
<ns1:midasnumber>7700MD2005000001.00</ns1:midasnumber>
<ns1:specimencomments>Miscellaneous</ns1:specimencomments>
<ns1:nonrxdrugsused>N/A</ns1:nonrxdrugsused>
<ns1:testcode>025000</ns1:testcode>
<ns1:testdate>2012-09-24</ns1:testdate>
<ns1:testresult>Negative</ns1:testresult>
<ns1:collectiondate>2012-09-25</ns1:collectiondate>
<ns1:lastname>Last</ns1:lastname>
<ns1:firstname>First</ns1:firstname>
<ns1:middlename>Middle</ns1:middlename>
<ns1:crudflag>C</ns1:crudflag>
</ns1:importdrugtest>
</soap-env:body>
</soap-env:envelope>
Here is my code. Note: I have already stared a new SoapClient() and regeived the token.
$ns = 'http://url.com/testing/';
// $headerParams = array('WSAuthorization'=>array('token'=>$token)); tried this also
$headerParams = array('token'=>$token);
$header = new SoapHeader($ns, 'WSAuthorization', $headerParams);
$client->__setSoapHeaders($header);
$param = array('ImportTest' => array(
'specimenID' => '0605431024',
'midasNumber' => '7700MD2005000001.00',
'county' => '03',
'site' => '00',
'specimenComments' => 'Miscellaneous',
'nonRXDrugsUsed' => 'N/A',
'testCode' => '025000',
'testDate' => '2012-09-24',
'testResult' => 'Negative',
'collectionDate' => '2012-09-25',
'lastName' => 'Last',
'firstName' => 'First',
'middleName' => 'Middle',
'CRUDFlag' => 'C'
));
$result = $client->__soapCall('ImportDrugTest', $param);
Update 12/31/14:
I modified the code and added print_r($header):
$ns = "http://url.com/testing/";
$headerParams = array('token'=>$token);
$header = new SoapHeader($ns, 'WSAuthorization', $headerParams);
print_r($header);
$client->__setSoapHeaders(array($header)); // even tried $client->__setSoapHeaders($header);
I get this:
SoapHeader Object
(
[namespace] => http://url.com/testing/
[name] => WSAuthorization
[data] => Array
(
[token] => UDjVSzGt9J4fKuRuoFHau3gy4CoLo//VlnuZv5oy5tjKPffIeSc+dx7EEDIfosVkVHDD0G/ZBANnCzPmRBo6CIusRL5rak5QdYI9jD7209c=
)
[mustUnderstand] =>
)
But __getLastRequest() gives me this:
<soap-env:header>
<ns1:wsauthorization />
</soap-env:header>
What am I missing?
This works:
$headerParams = array('Token' => $token);
$header = new SoapHeader($NameSpace, 'WSAuthorization', $headerParams, false);
The problem I was having was caused by the token not being parsed from the response.
I am pulling my hair out. I have tried many different ways, but nothing works:
<?php
// Proxy is for Fiddler
$soap = new soapClient( 'http://testi.lemonsoft.eu:22000/CTP/lemonweb/userservices.svc?wsdl', array(
'proxy_host' => 'localhost',
'proxy_port' => '8888'
));
try {
$test = new stdClass();
$test->UserName = "foo";
$test->Password = "bar";
$test->CompanyDatabase = "baz";
// This should work:
print_r($soap->LogIn($test));
/** The rest are alternative experiments, no avail: **/
print_r($soap->LogIn(array($test)));
print_r($soap->LogIn(array('parameters' => $test)));
print_r($soap->login(array(
'UserName' => 'foo',
'Password' =>'bar',
'CompanyDatabase' => 'baz'
)));
print_r($soap->__soapCall('LogIn', array('parameters' => $test)));
print_r($soap->__soapCall('LogIn', array('parameters' => array(
'UserName' => 'foo',
'Password' =>'bar',
'CompanyDatabase' => 'baz'
))));
print_r($soap->LogIn(new SoapParam($test, "LogIn")));
print_r($soap->LogIn(new SoapParam(array(
'UserName' => 'foo',
'Password' =>'bar',
'CompanyDatabase' => 'baz'
), "LogIn")));
print_r($soap->__soapCall('LogIn', array('parameters' => array(
new SoapParam(array(
'UserName' => 'foo',
'Password' =>'bar',
'CompanyDatabase' => 'baz'
), "LogIn")
))));
} catch (SoapFault $fault) {
print_r($fault);
}
?>
I captured the requests with fiddler and the response always looks like this:
<?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:LogIn/>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
as if the LogIn parameters are never sent. Does the empty ns1:LogIn tag really mean that? Can there be some instance inbetween, which I can not control, for some reason stripping the parameters? According to my understanding the method LogIn takes one parameter, which, according to the documentation, should be a PHP stdClass.
Try this:
class LogInInfo{
public $UserName = '1';
public $Password = '2';
public $CompanyDatabase = '3';
}
ini_set('display_error', 1);
error_reporting(E_ALL);
$client = new SoapClient('http://testi.lemonsoft.eu:22000/CTP/LemonWeb/UserServices.svc?singleWsdl', array(
'classmap'=>array('LogInInfo'=>'LogInInfo'),
'debug'=>true,
'trace'=>true
));
try {
$info = new LogInInfo();
$resp = $client->LogIn($info);
} catch(Exception $e) {
var_dump($e);
}
print_r($client->__getLastRequest());
Result:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://schemas.datacontract.org/2004/07/Lemonsoft.LemonsoftServiceLibrary.User" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="http://tempuri.org/">
<SOAP-ENV:Body>
<ns2:LogIn xsi:type="ns1:LogInInfo">
<ns1:CompanyDatabase>3</ns1:CompanyDatabase>
<ns1:Password>2</ns1:Password>
<ns1:UserName>1</ns1:UserName>
</ns2:LogIn>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Can you show content of the WSDL file?
ns1:LogIn tag means that method LogIn is from ns1 namespace (defined above).
The only way I manage to pass the params in SOAP request from PHP is like this:
// __setSoapHeaders here
$listCriteriaXML = '<List xmlns="LINKHERE">
<listCriteria>
<ListCriterion>
<Name>DateNeeded</Name>
<SingleValue>' . date("Y-m-d", strtotime("+120 days")) . '</SingleValue>
</ListCriterion>
<ListCriterion>
<Name>limitresults</Name>
<SingleValue>false</SingleValue>
</ListCriterion>
</listCriteria>
</List>';
$listCriteria = new SoapVar($listCriteriaXML, XSD_ANYXML);
$response = $client->List($listCriteria);
echo $client->__getLastRequest();
I'm trying to make a request with the PHP SoapClient in non-WSDL mode. I'm passing parameters as a multi-dimensional object as shown in the below code snippet:
$params = new stdClass;
$params->Characteristic = new stdClass;
$params->Characteristic->Name = 'PRODUCT_TYPE';
$params->Characteristic->CharacteristicValue = new stdClass;
$params->Characteristic->CharacteristicValue->Value = $type;
$params->Characteristic->CharacteristicValue->Type = 'STRING';
$client = new SoapClient(NULL, array( 'trace' => true, 'exceptions' => true, 'uri' => $uri, 'location' => $location,
'connection_timeout'=>9999,
'features' => SOAP_SINGLE_ELEMENT_ARRAYS,
'soap_version' => SOAP_1_1, 'encoding' => 'ISO-8859-1',
'use' => SOAP_LITERAL
));
$response = $client->thisIsTheFunction($params);
The generated XML is almost right apart from being wrapped in a tag:
<soap-env:envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://[removed]">
<soap-env:body>
<ns1:thisisthefunction>
<param0>
<characteristic>
<name>PRODUCT_TYPE</name>
<characteristicvalue>
<value>Adhoc</value>
<type>STRING</type>
</characteristicvalue>
</characteristic>
</param0>
</ns1:thisisthefunction>
</soap-env:body>
</soap-env:envelope>
The problem is this is being detected as malformed by the service. Is there any way we can remove this extra tag?
I think if you want remove param0 and put characteristicValue in this place, you need to use a SoapParam (http://www.php.net/manual/en/class.soapparam.php).
In fact, your call must proceed like that :
$response = $client->thisIsTheFunction(new SoapParam($params->Characteristic, 'ns1:Characteristic'));
Now, your generated XML looks like that :
<soap-env:envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://[removed]">
<soap-env:body>
<ns1:thisisthefunction>
<ns1:characteristic>
<name>PRODUCT_TYPE</name>
<characteristicvalue>
<value>Adhoc</value>
<type>STRING</type>
</characteristicvalue>
</ns1:characteristic>
</ns1:thisisthefunction>
</soap-env:body>
Good luck !
I am using PHP SoapClient in WSDL mode.
This is what the expected SOAP request should look like:
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns="http://xml.m4u.com.au/2009">
<soapenv:Header/>
<soapenv:Body>
<ns:sendMessages>
<ns:authentication>
<ns:userId>Username</ns:userId>
<ns:password>Password</ns:password>
</ns:authentication>
<ns:requestBody>
<ns:messages>
<ns:message>
<ns:recipients>
<ns:recipient>61400000001</ns:recipient>
</ns:recipients>
<ns:content>Message Content</ns:content>
</ns:message>
</ns:messages>
</ns:requestBody>
</ns:sendMessages>
</soapenv:Body>
</soapenv:Envelope>
And this is what PHP SoapClient is sending:
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://xml.m4u.com.au/2009">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ns1:sendMessages>
<ns1:authentication>
<userId>Username</userId>
<password>Password</password>
</ns1:authentication>
<ns1:requestBody>
<messages>
<message>
<recipients>
<recipient>61400000001</recipient>
</recipients>
<content>Message Content</content>
</message>
</messages>
</ns1:requestBody>
</ns1:sendMessages>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
This is how I constructed the client and params:
function sendMessages($recipient, $content) {
$authenticationType = new SoapVar(array('userId' => $this->username, 'password' => $this->password), SOAP_ENC_OBJECT);
$recipientsType = new SoapVar(array('recipient' => $recipient), SOAP_ENC_OBJECT);
$messageType = new SoapVar(array('recipients' => $recipientsType, 'content' => $content), SOAP_ENC_OBJECT);
$messagesType = new SoapVar(array('message' => $messageType), SOAP_ENC_OBJECT);
$requestBodyType = new SoapVar(array('messages' => $messagesType), SOAP_ENC_OBJECT);
$params = array(
'authentication' => $authenticationType,
'requestBody' => $requestBodyType
);
try {
$this->soapClient = new SoapClient($this->wsdl, array('trace' => 1));
$this->soapClient->__setSoapHeaders(array());
return $this->soapClient->sendMessages($params);
} catch (SoapFault $fault) {
echo '<h2>Request</h2><pre>' . htmlspecialchars($this->soapClient->__getLastRequest(), ENT_QUOTES) . '</pre>';
trigger_error("SOAP Fault: (faultcode: {$fault->faultcode}, faultstring: {$fault->faultstring})", E_USER_ERROR);
}
}
Why is 'ns1' present for 'authentication' and 'requestBody' but missing for their child nodes?
What am I doing wrong? The WSDL is located here => http://soap.m4u.com.au/?wsdl
Appreciate anyone who can help.
You must specify the URI of the namespace to encode the object. This will include everything necessary (including your missing namespace). The acronym of the namespace name is irrelevant.
This:
$authenticationType = new SoapVar(array('userId' => $this->username, 'password' => $this->password), SOAP_ENC_OBJECT);
should be:
$authenticationType = new SoapVar(array('userId' => $this->username, 'password' => $this->password), SOAP_ENC_OBJECT, "authentication","http://xml.m4u.com.au/2009");
The problem you're seeing with the namespace serialization comes from using soapvar without all the parameters. When it serializes the request prior to sending it assumes the namespace is already included. If, instead, you had created each as a simple array and included them in $params it would include the namespace for the internal parameters correctly. By way of demonstration:
$authenticationType = array('userId' => $this->username, 'password' => $this->password)
try using nusoap library. Below is sample code:
<?php
$wsdl = "http://soap.m4u.com.au/?wsdl";
// generate request veriables
$data = array();
$action = ""; // ws action
$param = ""; //parameters
$options = array(
'location' => 'http://soap.m4u.com.au',
'uri' => ''
);
// eof generate request veriables
//$client = new soap_client($wsdl, $options);// create soap client
$client = new nusoap_client($wsdl, 'wsdl');
$client->setCredentials($api_username, $api_password);// set crendencials
$opt = $client->call($action, $param, '', '', false, true);
print_r($opt);
?>