ZF-5022: Zend_Soap_Autodiscover throws SoapFault VersionMismatch
Description
I have the following class used to set up the zend soap server:
<?php
/**
* Webservice_Lmpbec
*
*
*
*
/
class Webservice_Lmpbec
{
/ /**
* Zend_Db_Adapter
*
* @var Zend_Db_Adapter_Abstract
*/
private $_zendDb;
/**
* Input Data
*
* @var Webservice_Cldatac
*/
private $cldatac;
/**
* Output Data
*
* @var Webservice_Clbec
*/
private $clbec;
/**
* Error de validación
*
* @var array
*/
private $error;
/**
* Constructor for this class
*
* sets up the Db connection
*
*/
function __construct ()
{
$config = Zend_Registry::get('config');
$this->_zendDb = Zend_Db::factory($config->database);
$this->clbec = new Webservice_Clbec();
}
/**
* fetchBec
*
* Recieves client info including CID and
* checks if already registered on the local DB
* if so return BEC else registers the client and returns his
* BEC id
*
* @param Webservice_Cldatac $input
* @return Webservice_Clbec
*/
public function fetchBec(Webservice_Cldatac $input)
{
$this->setCldatac($input);
$this->clbec->fecha = date('d/m/Y');
$this->clbec->hora = date('H:i:s');
$this->clbec->referencia = $this->cldatac->referencia;
if (!$this->authenticate() || !$this->validaData()){
$this->clbec->respuesta = 'FAILED';
$this->clbec->cd_respuesta = 1;
$this->clbec->bec = '';
} else {
$this->clbec->respuesta = 'OK';
$this->clbec->cd_respuesta = 0;
$this->clbec->bec = '655765';
}
return $this->clbec;
}
private function validaData()
{
$emailValidator = new Zend_Validate_EmailAddress();
$dateValidator = new Zend_Validate_Date('Y-m-d');
$valid = true;
if($this->cldatac->apaterno == ''){
$this->clbec->cd_error = 4;
$this->clbec->nb_error = 'Apaterno es un campo obligatorio.';
$valid = false;
} elseif ($this->cldatac->nombre == '') {
$this->clbec->cd_error = 4;
$this->clbec->nb_error = 'El nombre es un campo obligatorio';
$valid = false;
} elseif ($this->cldatac->cid == ''){
$this->clbec->cd_error = 3;
$this->clbec->nb_error = 'CID es un campo obligatorio';
} elseif (!$emailValidator->isValid($this->cldatac->email)) {
$this->clbec->cd_error = 5;
$this->clbec->nb_error = 'Dirección email inválida';
$valid = false;
} elseif (!$dateValidator->isValid($this->cldatac->fnyear.'-'.$this->cldatac->fnmonth.'-'.$this->cldatac->fnday)) {
$this->clbec->cd_error = 6;
$this->clbec->nb_error = 'Fecha de nacimiento inválida';
$valid = false;
}
return $valid;
}
/**
* Webservice authentication
*
* @param string $user
* @param string $pass
* @return boolean
*/
private function authenticate()
{
$sql = "SELECT * FROM ws_user WHERE ws_user = ? AND ws_password = SHA1(?)";
$result = $this->_zendDb->fetchAll($sql,array($this->cldatac->user,$this->cldatac->pass));
if(count($result) == 1){
return true;
} else {
$this->clbec->nb_error = 'Usuario o contraseña inválidos';
$this->clbec->cd_error = 1;
return false;
}
}
/**
* Check if client exists in DB
*
* @return boolean
*/
private function clientExists()
{
$sql = "SELECT * FROM cliente " .
"WHERE ( cliente_pnombre = ? " .
"AND cliente_snombre = ? " .
"AND cliente_apaterno = ? " .
"AND cliente_amaterno = ? ) " .
"OR ( cliente_email = ? ) " .
"LIMIT 1";
$result = $this->_zendDb->fetchAll(
$sql,
array(
$this->cldatac->nombre,
$this->cldatac->snombre,
$this->cldatac->apaterno,
$this->cldatac->amaterno,
$this->cldatac->email,
)
);
if (count($result) == 1){
return true;
} else {
return false;
}
}
/**
* getBec
*
* Returns Client BEC from an existent client
*
* @return string
*/
private function getBec()
{
$sql = "SELECT cliente_bec FROM cliente " .
"WHERE ( cliente_pnombre = ? " .
"AND cliente_snombre = ? " .
"AND cliente_apaterno = ? " .
"AND cliente_amaterno = ? ) " .
"OR ( cliente_email = ? ) " .
"LIMIT 1";
$bec = $this->_zendDb->fetchOne(
$sql,
array(
$this->cldatac->nombre,
$this->cldatac->snombre,
$this->cldatac->apaterno,
$this->cldatac->amaterno,
$this->cldatac->email,
)
);
return $bec;
}
/**
* @return Webservice_Cldatac
*/
private function getCldatac ()
{
return $this->cldatac;
}
/**
* @param Webservice_Cldatac $cldatac
*/
private function setCldatac (Webservice_Cldatac $cldatac)
{
$this->cldatac = $cldatac;
}
/**
* @return Webservice_Clbec
*/
private function getClbec ()
{
return $this->clbec;
}
/**
* @param Webservice_Clbec $clbec
*/
private function setClbec (Webservice_Clbec $clbec)
{
$this->clbec = $clbec;
}
}
Which makes use of Webservice_Clbec and Webservice_Cldatac to be translated as complexTypes by Autodiscovery. WSDL seems ok actually pretty much the same as one generated by nusoap server class. Finally, when I instantiate Zend_Soap_Client or SoapClient and call the method fetchBec the following exception is thrown:
Fatal error: Uncaught SoapFault exception: [VersionMismatch] Wrong Version in C:\Users\sivemax01\Zend\workspaces\DefaultWorkspace\library\Zend\Soap\Client.php:887 Stack trace: #0 [internal function]: SoapClient->__call('fetchBec', Array) #1 C:\Users\sivemax01\Zend\workspaces\DefaultWorkspace\library\Zend\Soap\Client.php(887): Zend_Soap_Client_Common->fetchBec(Array) #2 [internal function]: Zend_Soap_Client->__call(Array, Array) #3 C:\Users\sivemax01\Zend\workspaces\DefaultWorkspace\lmp\html\client.php(70): Zend_Soap_Client->fetchBec('fetchBec', Array) #4 {main} thrown in C:\Users\sivemax01\Zend\workspaces\DefaultWorkspace\library\Zend\Soap\Client.php on line 887
I am using xampp 1.6.8 on Windows Vista which comes with php 5.2.6. I tried disabling php_soap.dll but useless, I also tested this code on a centos server using php 5.2.1 but still similar error.
I even tried a simpler class with no db adapters, no complex types:
<?php
class myclass {
public function method($input)
{ return $input }
}
Obviously adding phpdoc but still same error, I guess this means something is wrong with my server configuration but I don't know what. Any Ideas?
Erick Martinez
** Update
I´ve been trying to use SoapServer and SoapClient in the same way (Zend_Soap_Server and Zend_Soap_Client rely on them as I understand) with excactly the same error: Wrong Version, so it seem is not a Zend_Framework Issue but rather a php one, still I can't figure out what is causing the problem or if anyone has succeeded implementing the SoapServer, under which configuration.
When executed over CENTOS php 5.2.5 I get some DTD fault (SOAP can't manage DTD or something) , hmm...
Weird thing is I have been working with nusoap and works like a charm, even when I use SoapClient to instanciate some methods. I wish this could be fixed I kind of liked the Zend_Soap API, it seems more modular.
Comment
I see what you say, thing is I generate what it seems to be a correct WSDL then I pass the uri of the WSDL as the first parameter to the Zend_Soap_Server or else I save the generated WSDL (I can even use an IDE to edit it diagramatically) but when I instantiate Zend_Soap_Client and , if I specify the uri of the WSDL the fault message is presented or if I specify the uri of the server (which I don't understand what's the use if you are working id wsdl mode and soapclient constructor takes wsdl uri as first parameter and makes no use of the uri/location parameter) a fault message with "Can't read WSDL file " is presented. Maybe I am missing something...
-- Update 2008/11/23
I fixed this, you were right, I was using this wrong: I had separated files one for WSDL and one for the server so I guess this was the problem (that and a bad SQL...). You are right may be Auto discover should include server, maybe you could use it by default and deactivate it with a construct parameter. Anyway it would be useful to have this information on the official documentation.
Thank you
Comments
Posted by Benjamin Eberlei (beberlei) on 2008-11-23T05:25:44.000+0000
I think you are using it wrong.
Zend_Soap_AutoDiscover is NOT a server. It only generates the WSDL File. What you have to do is specifiy the WSDL with AutoDiscover somewhere and then use Zend_Soap_Server and give the WSDL uri as the first parameter. The AutoDiscover has to generate the correct location of the Zend_Soap_Server.
I have written a tutorial that describes the steps to get Soap Server + AutoDiscover to work at server.php and server.php?wsdl repsectivly:
http://www.whitewashing.de/blog/articles/65
Maybe Zend_Soap_AutoDiscover should be integrated with Zend_Soap_Server in a Tiein component, since it somehow happens frequently, that people misunderstand the AutoDiscover component a little bit. Perhaps the manual is unclear on this issue.
Posted by Ciaran McNulty (ciaranmcnulty) on 2008-11-24T01:20:59.000+0000
I've just found this bug after having the same issue - I'd suggest it was a documentation bug more than anything else.
It would be nice if it was possible to inject a SOAP endpoint URL into the generated WSDL somehow?
Posted by Benjamin Eberlei (beberlei) on 2008-11-24T15:11:07.000+0000
this is possible using the setUri function of both autodiscover and wsdl classes.
Posted by Benjamin Eberlei (beberlei) on 2008-11-25T07:44:51.000+0000
I a version to come, AutoDiscover and Soap Server should be integrated more tightly but now i just added a note into the manual which will be inserted into 1.7.1 release manual.