WSCOMUN  2.1.2
Web Services Comunes para PHP/GVHidra
WSComunFClient.php
1 <?php
13 namespace WSCOMUN;
25 use DOMDocument;
26 use Exception;
29 use WSClientFirma;
30 use stdClass;
31 
32 
37 define('DEBUG', false);
38 
42 require_once 'WSSSoapClient.php';
46 require_once ('WSCMIME/WSCMime.php');
47 
48 
76 {
80  const KEYCLIENTE_AUTENTICA = 'autentica';
81  const KEYCLIENTE_AUTORIZA = 'autoriza';
82  const KEYCLIENTE_FIRMA = 'firma';
83  const KEYCLIENTE_GDE = 'gde';
84  const KEYCLIENTE_SALT = 'salt';
85  const KEYCLIENTE_CSV = 'csv';
86  const KEYCLIENTE_CATASTRO = 'catastro';
87  const KEYCLIENTE_CATASTRO_BIENES = 'catbienes';
88  const KEYCLIENTE_GDE2 = 'gde2';
89  const KEYCLIENTE_PF = 'pfcons';
90  const KEYCLIENTE_PF_MOD = 'pfmod';
91  const KEYCLIENTE_PF_ADM = 'pfadm';
92  const KEYCLIENTE_GVLOGIN = 'gvlogin';
93  const KEYCLIENTE_REGDEPARTAMENTAL = 'regdepartamental';
94  const KEYCLIENTE_DGT_CONDUCTORVEHICULOS = 'dgt_conductorvehiculos';
95  const KEYCLIENTE_DGT_DATOSVEHICULO = 'dgt_datosvehiculo';
96 
97 
101  const TIPOBUSQUEDA_USUARIO = 'USUARIO';
102  const TIPOBUSQUEDA_GRUPO = 'GRUPO';
103 
104 
105 
111  protected static $MYSOAPOP_TRACE = true; //Necesario para tratar las cabeceras MTOM
112  protected static $MYSOAPOP_WSDL_CACHE = WSDL_CACHE_BOTH;//Desarrollo WSDL_CACHE_NONE, produccion WSDL_CACHE_BOTH
113  protected static $MYSOAPOP_SOAP_VERSION = SOAP_1_1;//Los end points son soap 1, no soap 2
114 
115 
116 
120  protected static $NAMESPACE_GVA = 'http://dgm.gva.es/ayf/war/schemas/v2_00';
121  protected static $NAMESPACE_GDE = 'urn:es:gva:dgm:tra:gde:vista:model';
122  protected static $NAMESPACE_SALT = 'http://salt.ws.edu.gva.es/';
123  protected static $NAMESPACE_CSVGVA = 'urn:es:gva:dgm:tra:csvgva';
124  protected static $NAMESPACE_GDE2 = 'urn:es:gva:dgm:tra:gde:vista:v2:model';
125  protected static $NAMESPACE_CAT_ESP = 'http://intermediacion.redsara.es/scsp/esquemas/datosespecificos';
126  protected static $NAMESPACE_CAT_PET = 'http://intermediacion.redsara.es/scsp/esquemas/V3/peticion';
127  protected static $NAMESPACE_CAT_SR = 'http://intermediacion.redsara.es/scsp/esquemas/V3/solicitudRespuesta';
128  protected static $NAMESPACE_PF = null; // 'urn:juntadeandalucia:cice:pfirma:type:v2.0';
129  protected static $NAMESPACE_PF_MOD = null; // 'urn:juntadeandalucia:cice:pfirma:type:v2.0';
130  protected static $NAMESPACE_PF_ADM = null; // 'urn:juntadeandalucia:cice:pfirma:type:v2.0';
131  protected static $NAMESPACE_LOGIN = 'urn:es:gva:gvlogin:sso:model';
132  protected static $NAMESPACE_REGDEPARTAMENTAL = 'urn:es:gva:mastin:departamental:model';
133  protected static $NAMESPACE_DGT_CONDUCTORVEHICULOS = 'http://intermediacion.redsara.es/scsp/esquemas/datosespecificos';
134  protected static $NAMESPACE_DGT_DATOSVEHICULO = 'http://intermediacion.redsara.es/scsp/esquemas/datosespecificos';
135 
140  private $v_wsdl;
141 
142 
148  private $WSDLTimeOut;
149 
155  protected $v_clienteWS;
156 
157 
163  private $keyFile='';
164 
170  protected $passPhrase=null;
171 
177  private $certFile='';
178 
179 
180 
186  private $_debugMode;
187 
193  private $_debugInfo;
194 
200  protected $vTrazabilidad;
201 
202 
208  private $idApp;
209 
210 
216  private $nsCert;
217 
218 
224  protected $userToken = '';
225 
226 
232  protected $passUserToken = '';
233 
234 
240  protected $enableTrazabilidadPAI = true;
241 
242 
248  protected $enableWSSecurity = true;
249 
250  /* ----------------------------------------------------------------------- */
251  /* --------------------------- Métodos públicos -------------------------- */
252  /* ----------------------------------------------------------------------- */
253 
254 
266  public function __construct($v_wsdl, $v_opciones=null)
267  {
268  if (!is_array($v_wsdl))
269  {
270  throw new Exception (
271  __CLASS__.':'.__METHOD__.'['.__FILE__.'-'.__LINE__.']'.
272  'v_wsdl debe ser un array asociativo (autenticacion,autorizacion,firma) con las URI de los WSDL'
273  );
274  }
275  //Inicializamos el array asociativo de URIs WSDL
276  $this->v_wsdl = $v_wsdl;
277 
278  //Inicializamos el array asociativo de clientes
279  $this->v_clienteWS = array
280  (
281  self::KEYCLIENTE_AUTENTICA => null,
282  self::KEYCLIENTE_AUTORIZA => null,
283  self::KEYCLIENTE_CATASTRO => null,
284  self::KEYCLIENTE_CATASTRO_BIENES => null,
285  self::KEYCLIENTE_CSV => null,
286  self::KEYCLIENTE_FIRMA => null,
287  self::KEYCLIENTE_GDE => null,
288  self::KEYCLIENTE_GDE2 => null,
289  self::KEYCLIENTE_PF => null,
290  self::KEYCLIENTE_PF_ADM => null,
291  self::KEYCLIENTE_PF_MOD => null,
292  self::KEYCLIENTE_SALT => null,
293  self::KEYCLIENTE_GVLOGIN => null,
294  self::KEYCLIENTE_REGDEPARTAMENTAL => null,
295  self::KEYCLIENTE_DGT_CONDUCTORVEHICULOS => null,
296  self::KEYCLIENTE_DGT_DATOSVEHICULO => null
297  );
298 
299 
300  $this->nsCert = null;
301  $this->enableWSSecurity = true;
302  $this->enableTrazabilidadPAI = true;
303  $this->idApp=null;
304 
305  if (is_array($v_opciones))
306  {
307  //Fijamos datos del certificado
308  if (array_key_exists('certFile', $v_opciones))
309  {
310  $this->setCertFile($v_opciones['certFile']);
311  $this->nsCert = $this->getCertificateSerial();
312  }
313 
314  if (array_key_exists('keyFile', $v_opciones))
315  {
316  $this->setKeyFile($v_opciones['keyFile']);
317  }
318 
319  if (array_key_exists('passPhrase', $v_opciones))
320  {
321  $this->setPassPhrase($v_opciones['passPhrase']);
322  }
323 
324  if (array_key_exists('enableWSSecurity', $v_opciones))
325  {
326  $this->enableWSSecurity = $v_opciones['enableWSSecurity'] && true;
327  }
328 
329  if (array_key_exists('userToken', $v_opciones))
330  {
331  $this->userToken = $v_opciones['userToken'];
332  }
333 
334  if (array_key_exists('passUserToken', $v_opciones))
335  {
336  $this->passUserToken = $v_opciones['passUserToken'];
337  }
338 
339  if (array_key_exists('enableTrazabilidadPAI', $v_opciones))
340  {
341  $this->enableTrazabilidadPAI = $v_opciones['enableTrazabilidadPAI'] && true;
342  }
343 
344 
345  if (array_key_exists('idApp', $v_opciones))
346  {
347  $this->idApp = $v_opciones['idApp'];
348  }
349  }//Fin opciones
350 
351  $this->vTrazabilidad = array
352  (
353  'idApp' => $this->idApp,
354  'nsCert'=> $this->nsCert
355  );
356 
357  /* Opciones de DEBUG y tiempos de espera */
358  $this->setDebugMode(DEBUG);
359  $this->_debugInfo = array();
360  $this->WSDLTimeOut = 20;
361  }//Fin __construct
362 
363 
377  public static function makeWSClient($wsID, $v_wsdl, $v_opciones=null)
378  {
379  $wsClient = NULL;
380  switch ($wsID)
381  {
382  //CATASTRO
383  case self::KEYCLIENTE_CATASTRO:
384  case self::KEYCLIENTE_CATASTRO_BIENES:
385  require_once 'WS/CATASTRO/WSClientCatastro.php';
386  require_once 'WS/CATASTRO/ComposerCatastro.php';
387  require_once 'WS/CATASTRO/objCatastro.php';
389  $wsClient = new WSClientCatastro($v_wsdl, $v_opciones);
390  break;
391 
392  //CSV
393  case self::KEYCLIENTE_CSV:
394  require_once 'WS/CSV/WSClientCSV.php';
396  $wsClient = new WSClientCSV($v_wsdl, $v_opciones);
397  break;
398 
399  //SAFE
400  case self::KEYCLIENTE_AUTENTICA:
401  require_once 'WS/SAFE/WSClientAutentica.php';
402  $wsClient = new WSClientAutentica($v_wsdl, $v_opciones);
403  break;
404 
405  case self::KEYCLIENTE_AUTORIZA:
406  require_once 'WS/SAFE/WSClientAutoriza.php';
407  $wsClient = new WSClientAutoriza($v_wsdl, $v_opciones);
408  break;
409 
410  case self::KEYCLIENTE_FIRMA:
411  require_once 'WS/SAFE/WSClientFirma.php';
412  $wsClient = new WSClientFirma($v_wsdl, $v_opciones);
413  break;
414 
415  //GDE
416  case self::KEYCLIENTE_GDE:
417  require_once 'WS/GDE/WSClientGDE.php';
419  $wsClient = new WSClientGDE($v_wsdl, $v_opciones);
420  break;
421 
422  case self::KEYCLIENTE_GDE2:
423  require_once 'WS/GDE/WSClientGDE2.php';
424  require_once 'WS/GDE/ComposerGDE2.php';
426  $wsClient = new WSClientGDE2($v_wsdl, $v_opciones);
427  break;
428 
429  case self::KEYCLIENTE_SALT:
430  require_once 'WS/SALT/WSClientSALT.php';
432  $wsClient = new WSClientSALT($v_wsdl, $v_opciones);
433  break;
434 
435  //GVLOGIN
436  case self::KEYCLIENTE_GVLOGIN:
437  require_once 'WS/GVLOGIN/WSClientGVLogin.php';
439  $wsClient = new WSClientGVLogin($v_wsdl, $v_opciones);
440  break;
441 
442  //PORTAFIRMAS
443  case self::KEYCLIENTE_PF:
444  case self::KEYCLIENTE_PF_MOD:
445  case self::KEYCLIENTE_PF_ADM:
446  require_once 'WS/PORTAFIRMAS/WSClientPortafirmas.php';
447  require_once 'WS/PORTAFIRMAS/ComposerPortafirmas.php';
449  $wsClient = new WSClientPortafirmas($v_wsdl, $v_opciones);
450  break;
451 
452  // REGISTRO DEPARTAMENTAL
453  case self::KEYCLIENTE_REGDEPARTAMENTAL:
454  require_once 'WS/REGDEPARTAMENTAL/WSClientRegDepartamental.php';
455  require_once 'WS/REGDEPARTAMENTAL/ComposerRegDepartamental.php';
457  $wsClient = new WSClientRegDepartamental($v_wsdl, $v_opciones);
458  break;
459 
460  // DGT_CONDUCTORVEHICULOS
461  case self::KEYCLIENTE_DGT_CONDUCTORVEHICULOS:
462  require_once 'WS/DGT/CONDUCTORVEHICULOS/WSClientConductorVehiculos.php';
463  require_once 'WS/DGT/CONDUCTORVEHICULOS/Composer.php';
465  $wsClient = new WSClientConductorVehiculos($v_wsdl, $v_opciones);
466  break;
467 
468  // DGT_DATOSVEHICULO
469  case self::KEYCLIENTE_DGT_DATOSVEHICULO:
470  require_once 'WS/DGT/DATOSVEHICULO/WSClientDatosVehiculo.php';
471  require_once 'WS/DGT/DATOSVEHICULO/Composer.php';
473  $wsClient = new WSClientDatosVehiculo($v_wsdl, $v_opciones);
474  break;
475 
476 
477  default:
478  $wsClient = NULL;
479  if (DEBUG)
480  {
481  error_log('Clave cliente no reconocida. ('.$wsClient.')');
482  }
483  break;
484  }
485 
486  if (is_array($v_opciones))
487  {
488  //Fijamos datos del certificado
489  if (array_key_exists('certFile', $v_opciones))
490  {
491  $wsClient->setCertFile($v_opciones['certFile']);
492  $wsClient->nsCert = $wsClient->getCertificateSerial();
493  }
494 
495  if (array_key_exists('keyFile', $v_opciones))
496  {
497  $wsClient->setKeyFile($v_opciones['keyFile']);
498  }
499 
500  if (array_key_exists('passPhrase', $v_opciones))
501  {
502  $wsClient->setPassPhrase($v_opciones['passPhrase']);
503  }
504 
505  if (array_key_exists('enableWSSecurity', $v_opciones))
506  {
507  $wsClient->enableWSSecurity = $v_opciones['enableWSSecurity'] && true;
508  }
509 
510  if (array_key_exists('userToken', $v_opciones))
511  {
512  $wsClient->userToken = $v_opciones['userToken'];
513  }
514 
515  if (array_key_exists('passUserToken', $v_opciones))
516  {
517  $wsClient->passUserToken = $v_opciones['passUserToken'];
518  }
519 
520  if (array_key_exists('enableTrazabilidadPAI', $v_opciones))
521  {
522  $wsClient->enableTrazabilidadPAI = $v_opciones['enableTrazabilidadPAI'] && true;
523  }
524 
525 
526  if (array_key_exists('idApp', $v_opciones))
527  {
528  $wsClient->idApp = $v_opciones['idApp'];
529  }
530 
531  $wsClient->loadTracertPAI($v_opciones);
532  }//Fin opciones
533 
534  return $wsClient;
535 
536  }//Fin makeWSClient
537 
538 
545  public function getDebugMode()
546  {
547  return($this->_debugMode);
548  }//getDebugMode
549 
550 
557  public function getDebugInfo()
558  {
559  return $this->_debugInfo;
560  }//Fin getDebugInfo
561 
562 
563 
570  public function setDebugMode($activo)
571  {
572  self::$MYSOAPOP_TRACE = true;//Necesario para tratar MTOM
573  $this->_debugMode = $activo;
574  if ($activo)
575  {
576  self::$MYSOAPOP_WSDL_CACHE = WSDL_CACHE_NONE;
577  }
578  else
579  {
580  self::$MYSOAPOP_WSDL_CACHE = WSDL_CACHE_MEMORY;//Sólo en memoria
581  $this->_debugInfo = array();//Vaciamos las trazas de debug
582  }
583  }//setDebugMode
584 
585 
592  public function addDebugInfo($info)
593  {
594  if (!empty($info))
595  {
596  $this->_debugInfo[] = $info;
597  }
598 
599  }//addDebugInfo
600 
601 
602 
609  public function setKeyFile($pathKey)
610  {
611  $this->keyFile = $pathKey;
612  }//setKeyFile
613 
614 
621  public function setPassPhrase($passphrase)
622  {
623  $this->passPhrase = $passphrase;
624  }//setPassPhrase
625 
626 
633  public function setCertFile($pathCert)
634  {
635  $this->certFile = $pathCert;
636  }//setCertFile
637 
638 
645  public function setWSDLTimeOut($segs)
646  {
647  $this->WSDLTimeOut = $segs;
648  }//setCertFile
649 
650 
651 
658  public function getCertificateSerial($set=true)
659  {
660  if (empty($this->certFile))
661  {
662  throw new Exception('No se ha fijado valor para el certificado o el mismo no existe.');
663  }
664 
665  $certFile = realpath($this->certFile);
666  if ($certFile === false)
667  {
668  throw new Exception('No existe el fichero de cetificado: '.$this->certFile);
669  }
670 
671  $cert = file_get_contents($certFile);
672  if ($cert === false)
673  {
674  throw new Exception('No puede leerse el certificado : '.$certFile);
675  }
676 
677  $v_certData = openssl_x509_parse($cert, true);
678  $nsCert = strtoupper(self::numberBaseConvert($v_certData['serialNumber']));
679  if ($set==true)
680  {
681  $this->nsCert = $nsCert;
682  }
683  return $nsCert;
684  }//getCertificateSerial
685 
686 
693  public static function getCertificateInfo($ruta, $formato = null)
694  {
695  $certPath = null;
696  $cert = null;
697  $certContent = null;
698 
699  $certPath = realpath($ruta);
700 
701  $certContent = file_get_contents($certPath);
702  if ($certContent === false)
703  {
704  throw new Exception (
705  __CLASS__.':'.__METHOD__.'['.__FILE__.']-L'.__LINE__.
706  '. El certificado no se encuentra en la ruta: '.$certPath
707  );
708  }
709 
710  if (empty($formato))
711  {
712  $formato = pathinfo($certPath, PATHINFO_EXTENSION);
713  }
714 
715  $formato = trim(strtoupper($formato));
716  switch ($formato)
717  {
718  case 'PK12':
719  case 'P12':
720  $v_certPEM = array();
721  openssl_pkcs12_read($certContent, $v_certPEM, '');
722  $cert = $v_certPEM['cert'];
723  break;
724 
725  case 'PEM':
726  case 'CRT':
727  $cert = $certContent;
728  break;
729  }
730 
731  $v_certData = openssl_x509_parse($cert, true);
732  if ($v_certData === false)
733  {
734  throw new Exception (
735  __CLASS__.':'.__METHOD__.'['.__FILE__.']-L'.__LINE__.'.'.
736  'El formato del certificado no se corresponde con '.$formato
737  );
738  }
739  return $v_certData;
740  }//getCertificateInfo
741 
742 
743 
744 
745 
752  public function loadTracertPAI($vTrazabilidadPAI)
753  {
754  if (!is_array($vTrazabilidadPAI))
755  {
756  throw new Exception('Las opciones de trazabilidad deben ser un array asociativo [idApp, nsCert]');
757  }
758 
759  if (array_key_exists('idApp', $vTrazabilidadPAI))
760  {
761  $this->idApp = $vTrazabilidadPAI['idApp'];
762  }
763 
764  if (array_key_exists('nsCert', $vTrazabilidadPAI))
765  {
766  $this->nsCert = $vTrazabilidadPAI['nsCert'];
767  }
768  }//loadTracertPAI
769 
770 
775  public function enableWSSecurity()
776  {
777  $this->enableWSSecurity = true;
778  }//enableWSSecurity
779 
780 
785  public function disableWSSecurity()
786  {
787  $this->enableWSSecurity = false;
788  }//disableWSSecurity
789 
790 
795  public function enableTrazabilidadPAI()
796  {
797  $this->enableTrazabilidadPAI = true;
798  }//enableTrazabilidadPAI
799 
800 
805  public function disableTrazabilidadPAI()
806  {
807  $this->enableTrazabilidadPAI = false;
808  }//disableTrazabilidadPAI
809 
810 
811 
819  public function __getClient($tipo)
820  {
821  // Si esta vacío el tipo, nada
822  if (empty($tipo)) return null;
823 
824  $tipo = trim(strtolower($tipo));
825  try
826  {
827  $this->__clienteOn($tipo);
828 
829  if (!is_object($this->v_clienteWS[$tipo]))
830  return null;
831  else
832  return ($this->v_clienteWS[$tipo]);
833  }
834  catch (Exception $e)
835  {
836  throw $e;
837  }
838  }// Fin __getClient
839 
840 
841 
842 
843  /* ----------------------------------------------------------------------- */
844  /* --------------------- Métodos privados / protegidos ------------------- */
845  /* ----------------------------------------------------------------------- */
846 
847  // --------------- Métodos propios de la clase ---------------- */
848 
857  protected function __clienteOn($tipo, $trazabilidadPai=true, $opcionesClienteWS = null)
858  {
859  $vTiposCliente = array();
860  if (!empty($tipo))
861  {
862  $tipo = trim(strtolower($tipo));
863 
864  if (array_key_exists($tipo, $this->v_clienteWS))
865  {
866  $vTiposCliente = array($tipo);
867  }
868  else
869  {
870  if ($this->getDebugMode())
871  {
872  $this->addDebugInfo(__CLASS__.':'.__METHOD__.'['.__FILE__.'-'.__LINE__.']'.' Tipo de cliente WS ('.$tipo.') no reconocido.');
873  }
874  throw new Exception (
875  __CLASS__.':'.__METHOD__.'['.__FILE__.']-L'.__LINE__.'.'.
876  'Tipo de cliente WS ('.$tipo.') no reconocido'
877  );
878  }
879  }
880 
881  $streamContext = stream_context_create (
882  array (
883  'ssl' => array (
884  'verify_peer' => false,
885  'verify_peer_name' => false,
886  'allow_self_signed' => true
887  )
888  ,'http'=>array (
889  'user_agent' => 'WSSSoapClient',
890  'timeout' => $this->WSDLTimeOut
891  )
892  ,'https' => array (
893  'timeout' => $this->WSDLTimeOut
894  )
895  )
896  );
897 
898  if (!is_array($opcionesClienteWS))//Opciones SOAP por DEFECTO
899  {
900  /*
901  Creamos un contexto para perfilar la conexión HTTP/HTTPS del cliente
902  con las opciones siguientes facilitamos el acceso a WS servidor vía HTTPS
903  */
904  $opcionesClienteWS = array (
905  'soap_version' => SOAP_1_1,
906  'stream_context' => $streamContext,
907  'user_agent' => 'WSSSoapClient',
908  'exceptions' => true,
909  'cache_wsdl' => self::$MYSOAPOP_WSDL_CACHE,
910  'trace' => self::$MYSOAPOP_TRACE //NECESARIO PARA TRATAR MTOM
911  );
912  }
913  else //Opciones que se sobrecargan por necesidad
914  {
915  $opcionesClienteWS['soap_version'] = SOAP_1_1;//v1.1
916  //$opcionesClienteWS['stream_context'] = $streamContext;//REVIEW: ¿Relajamos validación SSL si vienen opciones del cliente?
917  $opcionesClienteWS['user_agent'] = 'WSSSoapClient';
918  $opcionesClienteWS['exceptions'] = true;
919  $opcionesClienteWS['cache_wsdl'] = self::$MYSOAPOP_WSDL_CACHE;
920  $opcionesClienteWS['trace'] = self::$MYSOAPOP_TRACE; //NECESARIO PARA TRATAR MTOM
921  }
922 
923  if ($this->getDebugMode())
924  {
925  $this->addDebugInfo("Opciones:\n ".print_r($opcionesClienteWS, true));
926  }
927 
928  foreach ($vTiposCliente as $claveTipo)
929  {
930  if (is_object($this->v_clienteWS[$claveTipo])) continue;
931  try
932  {
933  //Comprobamos accesibilidad de la URL
934  if (ini_get('allow_url_fopen') == true)//Si tenemos acceso a allow_url_open
935  {
936  $fd = fopen($this->v_wsdl[$claveTipo], 'r', false, $streamContext);
937  if ($fd==false)
938  {
939  throw new Exception('allow_url_fopen activo. La URL '.$this->v_wsdl[$claveTipo].' no puede alcanzarse.');
940  }
941  fclose($fd);
942  }
943  /*
944  elseif (function_exists('curl_version'))//Si tenemos acceso CURL utilizamos la extensión
945  {
946  if ($this->getDebugMode())
947  {
948  $this->addDebugInfo(__CLASS__.':'.__METHOD__.'['.__FILE__.'-'.__LINE__.']'.' allow_url_fopen NO ACTIVO');
949  }
950  $url = strtolower(str_replace(' ', '%20', trim($this->v_wsdl[$claveTipo])));
951 
952  $cd = curl_init($url);
953  if ($cd===false)
954  {
955  $mensaje = "CURL. La URL $url no puede alcanzarse";
956  curl_close($cd);
957  $this->addDebugInfo(__CLASS__.':'.__METHOD__.'['.__FILE__.'-'.__LINE__.']'.$mensaje);
958  throw new Exception($mensaje);
959  }
960 
961  @curl_setopt($cd, CURLOPT_HEADER,true); // we want headers
962  @curl_setopt($cd, CURLOPT_NOBODY, true); // dont need body
963  @curl_setopt($cd, CURLOPT_RETURNTRANSFER, true);
964  @curl_setopt($cd, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
965  @curl_setopt($cd, CURLOPT_CONNECTTIMEOUT, 20);
966  @curl_setopt($cd, CURLOPT_SSL_VERIFYPEER, false);
967  @curl_setopt($cd, CURLOPT_FOLLOWLOCATION, true);
968  @curl_setopt($cd, CURLOPT_MAXREDIRS, 10); // fairly random number, but
969  curl_exec($cd);
970  $codError = @curl_errno($cd);
971  if ($codError!=0)
972  {
973  $mensaje = "CURL. La URL $url no puede alcanzarse. Error: [$codError]";
974  curl_close($cd);
975  $this->addDebugInfo(__CLASS__.':'.__METHOD__.'['.__FILE__.'-'.__LINE__.']'.$mensaje);
976  throw new Exception($mensaje);
977  }
978  $httpcode = curl_getinfo($cd, CURLINFO_HTTP_CODE);
979 
980  curl_close($cd);
981  if (($httpcode!=200))
982  {
983  $mensaje = "CURL. La URL $url no puede alcanzarse: $httpcode";
984  curl_close($cd);
985  $this->addDebugInfo(__CLASS__.':'.__METHOD__.'['.__FILE__.'-'.__LINE__.']'.$mensaje);
986  throw new Exception($mensaje);
987  }
988  echo "CURL: La URL es accesible.";
989  exit;
990  }
991  */
992  else//No lanzamos excepción, sólo registramos la posibilidad
993  {
994  if ($this->getDebugMode())
995  {
996  $this->addDebugInfo(__CLASS__.':'.__METHOD__.'['.__FILE__.'-'.__LINE__.']'.' allow_url_fopen NO ACTIVO y Extensión CURL NO ACTIVA');
997  }
998  }
999 
1000  //Si llegamos aquí no hemos podido comprobar la accesibilidad del WSDL previamente, así que saltará la excepción si no es alcanzable
1001  $clienteWS = new WSSSoapClient($this->v_wsdl[$claveTipo], $opcionesClienteWS);
1002 
1003  if ($this->enableWSSecurity == true)
1004  {
1005  $clienteWS->setCertFile($this->certFile); //Certificado (sin key) PEM
1006  $clienteWS->setKeyFile($this->keyFile); //Acceso al fichero .key extraido del pk12 formato PEM
1007  $clienteWS->setPassPhrase($this->passPhrase);
1008  $clienteWS->setUserToken($this->userToken, $this->passUserToken);
1009  $clienteWS->enableWSSecurity();
1010  }
1011  else
1012  {
1013  $clienteWS->disableWSSecurity();
1014  }
1015 
1016  if ($this->enableTrazabilidadPAI)
1017  {
1018  $clienteWS->loadTracertPAI($this->vTrazabilidad);
1019  }
1020  $this->v_clienteWS[$claveTipo] = $clienteWS;
1021  }
1022  catch (Exception $e)
1023  {
1024  if ($this->getDebugMode())
1025  {
1026  $this->addDebugInfo(__CLASS__.':'.__METHOD__.'['.__FILE__.'-'.__LINE__.']'."\n");
1027  if (is_object($clienteWS))
1028  {
1029  $this->addDebugInfo("RqH:\n ".$clienteWS->__getLastRequestHeaders());
1030  $this->addDebugInfo("Rq:\n ".$clienteWS->__getLastRequest());
1031  $this->addDebugInfo("RsH:\n ".$clienteWS->__getLastResponse());
1032  $this->addDebugInfo("Rs:\n ".$clienteWS->__getLastResponseHeaders());
1033  }
1034  else
1035  $this->addDebugInfo("\n");
1036  }
1037  throw $e;
1038  }
1039  }//Fin foreach
1040  }// Fin __clienteOn
1041 
1042 
1043 
1051  protected function array2ObjectTree($array)
1052  {
1053  if (!is_array($array)) return;
1054 
1055  if (is_numeric(key($array)))
1056  {
1057  foreach ($array as $key => $value)
1058  {
1059  $array[$key] = $this->array2ObjectTree($value);
1060  }
1061  return $array;
1062  }
1063  $Object = new stdClass;
1064  foreach ($array as $key => $value)
1065  {
1066  if (is_array($value))
1067  {
1068  $Object->$key = $this->array2ObjectTree($value);
1069  }
1070  else
1071  {
1072  $Object->$key = $value;
1073  }
1074  }
1075  return $Object;
1076  }//Fin array2ObjectTree
1077 
1085  protected function objectTree2array($obj)
1086  {
1087  if (is_array($obj) || is_object($obj))
1088  {
1089  $result = array();
1090  foreach ($obj as $key => $value)
1091  {
1092  $result[$key] = $this->objectTree2array($value);
1093  }
1094  return $result;
1095  }
1096  return $obj;
1097  }//Fin objectTree2array
1098 
1099 
1100  protected function tratarExcepcionEstandar($e, $clienteWS)
1101  {
1102  // Comprueba si es una excepcion de PAI, y la lanza en dicho caso como excepcion especifica de PAI
1103  WSComunPAIException::tryToThrow($e);
1104 
1105  // Tratamiento estandar
1106  if ($this->getDebugMode())
1107  {
1108  $this->addDebugInfo(__CLASS__.':'.__METHOD__.'['.__FILE__.'-'.__LINE__.']'."\n");
1109  if (is_object($clienteWS))
1110  {
1111  $this->addDebugInfo("RqH:\n ".$clienteWS->__getLastRequestHeaders());
1112  $this->addDebugInfo("Rq:\n ".$clienteWS->__getLastRequest());
1113  $this->addDebugInfo("RsH:\n ".$clienteWS->__getLastResponse());
1114  $this->addDebugInfo("Rs:\n ".$clienteWS->__getLastResponseHeaders());
1115  }
1116  throw $e;
1117  }
1118  else
1119  {
1120  throw $e;
1121  }
1122  }//tratarExcepcionEstandar
1123 
1124 
1125 
1135  protected function tratarMTOMEstandar($response, $itemToReturn = null)
1136  {
1137  //Comprobamos si existen anexos
1138  $mimeBoundary = '--MIME_Boundary';//Probamos con --MIME Boundary hasta mejora de detección
1139  $vBodyResponse = explode($mimeBoundary, $response); //Fraccionamos la respuesta.
1140  $numElementos = count($vBodyResponse);
1141 
1142  $srcData='';
1143  if ($numElementos<=1)
1144  {
1145  $mimeBoundary = '--uuid:';//Probamos de nuevo con --uuid hasta mejora de detección
1146  $vBodyResponse = explode($mimeBoundary, $response); //Fraccionamos la respuesta.
1147  $numElementos = count($vBodyResponse);
1148  $srcData = $response;
1149  }
1150  elseif ($numElementos>1)
1151  {
1152  $srcData = $vBodyResponse[1];
1153  }
1154 
1155  $vRespuesta = array();
1156  ini_set('pcre.backtrack_limit','100000000'); //Valor por defecto = 1000000 (aprox. 100KBytes)
1157  preg_match("/<[a-z]*:Envelope.*?>(.*)<\/[a-z]*:Envelope>/is", $srcData, $vRespuesta);
1158  if (preg_last_error()!=PREG_NO_ERROR)
1159  {
1160  //Si falta intentamos obtener el anexo con otro sistema
1161  $start = stripos($srcData, ':Envelope');
1162  $start = strripos($srcData, '<', $start - strlen($srcData));
1163  $end = strripos($srcData, ':Envelope>');
1164  $cadenaRespuesta = substr($srcData, $start, $end);
1165  }
1166  elseif (count($vRespuesta)<1)
1167  {
1168  throw new Exception('No puede ubicarse RESPONSE dentro de MTOM');
1169  }
1170  else
1171  {
1172  $cadenaRespuesta = $vRespuesta[0];
1173  unset($vRespuesta);
1174  }
1175 
1176  $dom = new DOMDocument('1.0');
1177  $dom->loadXML($cadenaRespuesta);//Cargamo el XML
1178  $xpath = new \DOMXpath($dom);
1179  $vNodoRespuesta = $xpath->query("/*[local-name()='Envelope']/*[local-name()='Body']/*/*[local-name()='respuesta']");
1180  $subStrXpath='';
1181  if (!empty($itemToReturn))
1182  {
1183  $subStrXpath = "/*[local-name()='{$itemToReturn}']";
1184  }
1185  $vNodoRespuesta = $xpath->query("/*[local-name()='Envelope']/*[local-name()='Body']/*".$subStrXpath);
1186  $nodoRespuesta = $vNodoRespuesta->item(0);
1187 
1188  if ($numElementos>0)
1189  {
1190  $oMimeParser = new WSCMimeParser();
1191  $oMime = $oMimeParser->decodeMTOM($vBodyResponse);
1192  unset($oMime->body);$oMime->body=null;gc_collect_cycles();
1193 
1194  $vNodoInclude = $xpath->query("//*[local-name()='Include']");
1195  foreach ($vNodoInclude as $nodoItem)//Recorremos los nodosXML include y sustituidmos por el contenido
1196  {
1197  $subIdBuscado = (string) $nodoItem->getAttribute('href');
1198  $subIdBuscado = urldecode($subIdBuscado);
1199  $idBuscado = '<'.substr($subIdBuscado, 4).'>';
1200  foreach ($oMime->parts as &$parte)
1201  {
1202  if ($idBuscado == ($parte->headers['content-id']))
1203  {
1204  if ( strtolower(substr($parte->mimetype, 0, 4)) !== 'text')//Si el tipo mime no es texto, convertimos a B64 por ser contenido binario
1205  {
1206  $parte->body = base64_encode($parte->body);
1207  }
1208  $textNode = $dom->createTextNode(($parte->body));
1209  $nodoItem->parentNode->replaceChild($textNode, $nodoItem);
1210  }
1211  }//Fin for partes
1212  }//Fin for nodos
1213  }
1214  return($this->xml_to_array($nodoRespuesta));
1215  }//tratarMTOMEstandar
1216 
1217 
1218 
1219 
1220  protected function xml_to_array(&$root)
1221  {
1222  $result = array();
1223  if ($root->hasAttributes())
1224  {
1225  $attrs = $root->attributes;
1226  foreach ($attrs as $attr)
1227  {
1228  $result['@attributes'][$attr->name] = $attr->value;
1229  }
1230  }
1231  if ($root->hasChildNodes())
1232  {
1233  $children = $root->childNodes;
1234  if ($children->length == 1)
1235  {
1236  $child = $children->item(0);
1237  if ($child->nodeType == XML_TEXT_NODE)
1238  {
1239  $result['_value'] = $child->nodeValue;
1240  return count($result) == 1 ? $result['_value'] : $result;
1241  }
1242  }
1243  $groups = array();
1244  foreach ($children as $child)
1245  {
1246  if (!isset($result[$child->nodeName]))
1247  {
1248  $result[$child->nodeName] = $this->xml_to_array($child);
1249  }
1250  else
1251  {
1252  if (!isset($groups[$child->nodeName]))
1253  {
1254  $result[$child->nodeName] = array($result[$child->nodeName]);
1255  $groups[$child->nodeName] = 1;
1256  }
1257  $result[$child->nodeName][] = $this->xml_to_array($child);
1258  }
1259  }
1260  }
1261  return $result;
1262  }//xml_to_array
1263 
1264 
1276  public static function numberBaseConvert($numstring, $frombase=10, $tobase=16)
1277  {
1278  $chars = "0123456789abcdefghijklmnopqrstuvwxyz";
1279  $tostring = substr($chars, 0, $tobase);
1280  $length = strlen($numstring);
1281  $result = '';
1282  $number = array();
1283  for ($i = 0; $i < $length; $i++)
1284  {
1285  $number[$i] = strpos($chars, $numstring{$i});
1286  }
1287  do
1288  {
1289  $divide = 0;
1290  $newlen = 0;
1291  for ($i = 0; $i < $length; $i++)
1292  {
1293  $divide = $divide * $frombase + $number[$i];
1294  if ($divide >= $tobase)
1295  {
1296  $number[$newlen++] = (int)($divide / $tobase);
1297  $divide = $divide % $tobase;
1298  } elseif ($newlen > 0)
1299  {
1300  $number[$newlen++] = 0;
1301  }
1302  }
1303  $length = $newlen;
1304  $result = $tostring{$divide} . $result;
1305  } while ($newlen != 0);
1306 
1307  return $result;
1308  }//numberBaseConvert
1309 
1315  public static function getClientIP()
1316  {
1317  if (getenv('HTTP_CLIENT_IP'))
1318  {
1319  $ip = getenv('HTTP_CLIENT_IP');
1320  }
1321  else if(getenv('HTTP_X_FORWARDED_FOR'))
1322  {
1323  $ip = getenv('HTTP_X_FORWARDED_FOR');
1324  }
1325  else if (getenv('HTTP_X_FORWARDED'))
1326  {
1327  $ip = getenv('HTTP_X_FORWARDED');
1328  }
1329  else if(getenv('HTTP_FORWARDED_FOR'))
1330  {
1331  $ip = getenv('HTTP_FORWARDED_FOR');
1332  }
1333  else if(getenv('HTTP_FORWARDED'))
1334  {
1335  $ip = getenv('HTTP_FORWARDED');
1336  }
1337  else if(getenv('REMOTE_ADDR'))
1338  {
1339  $ip = getenv('REMOTE_ADDR');
1340  }
1341  else
1342  {
1343  $ip = 'UNKNOWN';
1344  }
1345  return $ip;
1346  }//Fin getClientIP
1347 
1348 
1349 
1350 
1351 }//Fin WSComunFClient
1352 
1353 
1354 
1355 
1363 {
1364 
1365  const ERROR_SERVICIO = '0101';
1366  const TIMESTAMP_INVALIDO = '0230';
1367  const ORGANISMO_NO_AUTORIZADO = '0301';
1368  const CERTIFICADO_CADUCADO = '0302';
1369  const CERTIFICADO_REVOCADO = '0303';
1370  const FIRMA_PETICION_NO_VALIDA = '0305';
1371  const PETICION_SIN_NODO_FIRMA = '0307';
1372  const ESTRUCURA_XML_NO_CORRESPONDE_A_ESQUEMA = '0401';
1373  const MENSAJE_XML_INVALIDO = '0403';
1374  const OPERACION_SOLICITADA_INCORRECTA = '0800';
1375  const FALTA_CABECERA_TRAZABILIDAD = '0807';
1376  const INFO_TRAZABILIDAD_INCOHERENTE = '0808';
1377  const ERROR_GENERAL_INDEFINIDO = '0904';
1378 
1379 
1380  private $CodigoEstado = '';
1381  private $CodigoEstadoSecundario = '';
1382  private $LiteralError = '';
1383  private $LiteralErrorSec = '';
1384 
1385  public function getCodigoEstado() {
1386  return $this->CodigoEstado;
1387  }
1388  public function getCodigoEstadoSecundario() {
1389  return $this->CodigoEstadoSecundario;
1390  }
1391  public function getLiteralError() {
1392  return $this->LiteralError;
1393  }
1394  public function getLiteralErrorSec() {
1395  return $this->LiteralErrorSec;
1396  }
1397 
1398 
1399 
1400  public function __construct($soapFault) {
1401  // Extrae la informacion básica del error
1402  $faultCode = intval($soapFault->detail->Atributos->Estado->CodigoEstado);
1403  $faultString = $soapFault->detail->Atributos->Estado->LiteralError;
1404 
1405  // asegúrese de que todo está asignado apropiadamente
1406  parent::__construct($faultString, $faultCode, $soapFault);
1407 
1408  // Extrae información detallada del error
1409  $this->CodigoEstado = $soapFault->detail->Atributos->Estado->CodigoEstado;
1410  $this->CodigoEstadoSecundario = $soapFault->detail->Atributos->Estado->CodigoEstadoSecundario;
1411  $this->LiteralError = $soapFault->detail->Atributos->Estado->LiteralError;
1412  $this->LiteralErrorSec = $soapFault->detail->Atributos->Estado->LiteralErrorSec;
1413  }
1414 
1415  public function __toString() {
1416  return __CLASS__ . ": [{$this->code}] {$this->message}\n";
1417  }
1418 
1419 
1420 
1428  public static function tryToThrow($e) {
1429  // Si es un SoapFault y su codigo es soap-env:PAI, asumimos que se trata de una excepcion especifica
1430  if (($e instanceof \SoapFault) && ($e->faultcode == 'soap-env:PAI')) {
1431  // Excepcion especifica detallada
1432  throw new WSComunPAIException($e);
1433  }
1434 
1435  return false;
1436  }
1437 
1438 }
1439 
1440 ?>
tratarMTOMEstandar($response, $itemToReturn=null)
static numberBaseConvert($numstring, $frombase=10, $tobase=16)
__construct($v_wsdl, $v_opciones=null)
static getCertificateInfo($ruta, $formato=null)
const DEBUG
loadTracertPAI($vTrazabilidadPAI)
__clienteOn($tipo, $trazabilidadPai=true, $opcionesClienteWS=null)