WSCOMUN  2.0.0
Web Services Comunes para PHP/GVHidra
WSComunFClient.php
1 <?php
13 namespace WSCOMUN;
22 use DOMDocument;
23 use Exception;
26 use WSClientFirma;
27 use stdClass;
28 
29 
34 define('DEBUG', false);
35 
39 require_once 'WSSSoapClient.php';
43 require_once ('WSCMIME/WSCMime.php');
44 
45 
73 {
77  const KEYCLIENTE_AUTENTICA = 'autentica';
78  const KEYCLIENTE_AUTORIZA = 'autoriza';
79  const KEYCLIENTE_FIRMA = 'firma';
80  const KEYCLIENTE_GDE = 'gde';
81  const KEYCLIENTE_SALT = 'salt';
82  const KEYCLIENTE_CSV = 'csv';
83  const KEYCLIENTE_CATASTRO = 'catastro';
84  const KEYCLIENTE_CATASTRO_BIENES = 'catbienes';
85  const KEYCLIENTE_GDE2 = 'gde2';
86  const KEYCLIENTE_PF = 'pfcons';
87  const KEYCLIENTE_PF_MOD = 'pfmod';
88  const KEYCLIENTE_PF_ADM = 'pfadm';
89  const KEYCLIENTE_GVLOGIN = 'gvlogin';
90 
91 
95  const TIPOBUSQUEDA_USUARIO = 'USUARIO';
96  const TIPOBUSQUEDA_GRUPO = 'GRUPO';
97 
98 
99 
105  protected static $MYSOAPOP_TRACE = true; //Necesario para tratar las cabeceras MTOM
106  protected static $MYSOAPOP_WSDL_CACHE = WSDL_CACHE_BOTH;//Desarrollo WSDL_CACHE_NONE, produccion WSDL_CACHE_BOTH
107  protected static $MYSOAPOP_SOAP_VERSION = SOAP_1_1;//Los end points son soap 1, no soap 2
108 
109 
110 
114  protected static $NAMESPACE_GVA = 'http://dgm.gva.es/ayf/war/schemas/v2_00';
115  protected static $NAMESPACE_GDE = 'urn:es:gva:dgm:tra:gde:vista:model';
116  protected static $NAMESPACE_SALT = 'http://salt.ws.edu.gva.es/';
117  protected static $NAMESPACE_CSVGVA = 'urn:es:gva:dgm:tra:csvgva';
118  protected static $NAMESPACE_GDE2 = 'urn:es:gva:dgm:tra:gde:vista:v2:model';
119  protected static $NAMESPACE_CAT_ESP = 'http://intermediacion.redsara.es/scsp/esquemas/datosespecificos';
120  protected static $NAMESPACE_CAT_PET = 'http://intermediacion.redsara.es/scsp/esquemas/V3/peticion';
121  protected static $NAMESPACE_CAT_SR = 'http://intermediacion.redsara.es/scsp/esquemas/V3/solicitudRespuesta';
122  protected static $NAMESPACE_PF = null; // 'urn:juntadeandalucia:cice:pfirma:type:v2.0';
123  protected static $NAMESPACE_PF_MOD = null; // 'urn:juntadeandalucia:cice:pfirma:type:v2.0';
124  protected static $NAMESPACE_PF_ADM = null; // 'urn:juntadeandalucia:cice:pfirma:type:v2.0';
125  protected static $NAMESPACE_LOGIN = 'urn:es:gva:gvlogin:sso:model';
126 
131  private $v_wsdl;
132 
133 
139  private $WSDLTimeOut;
140 
146  protected $v_clienteWS;
147 
148 
154  private $keyFile='';
155 
161  protected $passPhrase=null;
162 
168  private $certFile='';
169 
170 
171 
177  private $_debugMode;
178 
184  private $_debugInfo;
185 
191  protected $vTrazabilidad;
192 
193 
199  private $idApp;
200 
201 
207  private $nsCert;
208 
209 
215  protected $enableWSSecurity = true;
216 
217 
223  protected $enableTrazabilidadPAI = true;
224 
225 
226  /* ----------------------------------------------------------------------- */
227  /* --------------------------- Métodos públicos -------------------------- */
228  /* ----------------------------------------------------------------------- */
229 
230 
242  public function __construct($v_wsdl, $v_opciones=null)
243  {
244  if (!is_array($v_wsdl))
245  {
246  throw new Exception (
247  __CLASS__.':'.__METHOD__.'['.__FILE__.'-'.__LINE__.']'.
248  'v_wsdl debe ser un array asociativo (autenticacion,autorizacion,firma) con las URI de los WSDL'
249  );
250  }
251  //Inicializamos el array asociativo de URIs WSDL
252  $this->v_wsdl = $v_wsdl;
253 
254  //Inicializamos el array asociativo de clientes
255  $this->v_clienteWS = array
256  (
257  self::KEYCLIENTE_AUTENTICA => null,
258  self::KEYCLIENTE_AUTORIZA => null,
259  self::KEYCLIENTE_CATASTRO => null,
260  self::KEYCLIENTE_CATASTRO_BIENES => null,
261  self::KEYCLIENTE_CSV => null,
262  self::KEYCLIENTE_FIRMA => null,
263  self::KEYCLIENTE_GDE => null,
264  self::KEYCLIENTE_GDE2 => null,
265  self::KEYCLIENTE_PF => null,
266  self::KEYCLIENTE_PF_ADM => null,
267  self::KEYCLIENTE_PF_MOD => null,
268  self::KEYCLIENTE_SALT => null,
269  self::KEYCLIENTE_GVLOGIN => null
270  );
271 
272 
273  $this->nsCert = null;
274  $this->enableWSSecurity = true;
275  $this->enableTrazabilidadPAI = true;
276  $this->idApp=null;
277 
278  if (is_array($v_opciones))
279  {
280  //Fijamos datos del certificado
281  if (array_key_exists('certFile', $v_opciones))
282  {
283  $this->setCertFile($v_opciones['certFile']);
284  $this->nsCert = $this->getCertificateSerial();
285  }
286 
287  if (array_key_exists('keyFile', $v_opciones))
288  {
289  $this->setKeyFile($v_opciones['keyFile']);
290  }
291 
292  if (array_key_exists('passPhrase', $v_opciones))
293  {
294  $this->setPassPhrase($v_opciones['passPhrase']);
295  }
296 
297  if (array_key_exists('enableWSSecurity', $v_opciones))
298  {
299  $this->enableWSSecurity = $v_opciones['enableWSSecurity'] && true;
300  }
301 
302 
303  if (array_key_exists('enableTrazabilidadPAI', $v_opciones))
304  {
305  $this->enableTrazabilidadPAI = $v_opciones['enableTrazabilidadPAI'] && true;
306  }
307 
308 
309  if (array_key_exists('idApp', $v_opciones))
310  {
311  $this->idApp = $v_opciones['idApp'];
312  }
313  }//Fin opciones
314 
315  $this->vTrazabilidad = array
316  (
317  'idApp' => $this->idApp,
318  'nsCert'=> $this->nsCert
319  );
320 
321  /* Opciones de DEBUG y tiempos de espera */
322  $this->setDebugMode(DEBUG);
323  $this->_debugInfo = array();
324  $this->WSDLTimeOut = 15;
325  }//Fin __construct
326 
327 
341  public static function makeWSClient($wsID, $v_wsdl, $v_opciones=null)
342  {
343  $wsClient = NULL;
344  switch ($wsID)
345  {
346  //CATASTRO
347  case self::KEYCLIENTE_CATASTRO:
348  case self::KEYCLIENTE_CATASTRO_BIENES:
349  require_once 'WS/catastro/WSClientCatastro.php';
350  require_once 'WS/catastro/ComposerCatastro.php';
351  require_once 'WS/catastro/objCatastro.php';
352  $wsClient = new WSClientCatastro($v_wsdl, $v_opciones);
353  break;
354 
355  //CSV
356  case self::KEYCLIENTE_CSV:
357  require_once 'WS/CSV/WSClientCSV.php';
358  $wsClient = new WSClientCSV($v_wsdl, $v_opciones);
359  break;
360 
361  //SAFE
362  case self::KEYCLIENTE_AUTENTICA:
363  require_once 'WS/SAFE/WSClientAutentica.php';
364  $wsClient = new WSClientAutentica($v_wsdl, $v_opciones);
365  break;
366 
367  case self::KEYCLIENTE_AUTORIZA:
368  require_once 'WS/SAFE/WSClientAutoriza.php';
369  $wsClient = new WSClientAutoriza($v_wsdl, $v_opciones);
370  break;
371 
372  case self::KEYCLIENTE_FIRMA:
373  require_once 'WS/SAFE/WSClientFirma.php';
374  $wsClient = new WSClientFirma($v_wsdl, $v_opciones);
375  break;
376 
377  //GDE
378  case self::KEYCLIENTE_GDE:
379  require_once 'WS/GDE/WSClientGDE.php';
380  $wsClient = new WSClientGDE($v_wsdl, $v_opciones);
381  break;
382 
383  case self::KEYCLIENTE_GDE2:
384  require_once 'WS/GDE/WSClientGDE2.php';
385  require_once 'WS/GDE/ComposerGDE2.php';
386  $wsClient = new WSClientGDE2($v_wsdl, $v_opciones);
387  break;
388 
389  case self::KEYCLIENTE_SALT:
390  require_once 'WS/SALT/WSClientSALT.php';
391  $wsClient = new WSClientSALT($v_wsdl, $v_opciones);
392  break;
393 
394  //GVLOGIN
395  case self::KEYCLIENTE_GVLOGIN:
396  require_once 'WS/GVLOGIN/WSClientGVLogin.php';
397  $wsClient = new WSClientGVLogin($v_wsdl, $v_opciones);
398  break;
399 
400  //PORTAFIRMAS
401  case self::KEYCLIENTE_PF:
402  case self::KEYCLIENTE_PF_MOD:
403  case self::KEYCLIENTE_PF_ADM:
404  require_once 'WS/PORTAFIRMAS/WSClientPortafirmas.php';
405  require_once 'WS/PORTAFIRMAS/ComposerPortafirmas.php';
406 
407  $wsClient = new WSClientPortafirmas($v_wsdl, $v_opciones);
408  break;
409 
410  default:
411  $wsClient = NULL;
412  if (DEBUG)
413  {
414  error_log('Clave cliente no reconocida. ('.$wsClient.')');
415  }
416  break;
417  }
418 
419  if (is_array($v_opciones))
420  {
421  //Fijamos datos del certificado
422  if (array_key_exists('certFile', $v_opciones))
423  {
424  $wsClient->setCertFile($v_opciones['certFile']);
425  $wsClient->nsCert = $wsClient->getCertificateSerial();
426  }
427 
428  if (array_key_exists('keyFile', $v_opciones))
429  {
430  $wsClient->setKeyFile($v_opciones['keyFile']);
431  }
432 
433  if (array_key_exists('passPhrase', $v_opciones))
434  {
435  $wsClient->setPassPhrase($v_opciones['passPhrase']);
436  }
437 
438  if (array_key_exists('enableWSSecurity', $v_opciones))
439  {
440  $wsClient->enableWSSecurity = $v_opciones['enableWSSecurity'] && true;
441  }
442 
443 
444  if (array_key_exists('enableTrazabilidadPAI', $v_opciones))
445  {
446  $wsClient->enableTrazabilidadPAI = $v_opciones['enableTrazabilidadPAI'] && true;
447  }
448 
449 
450  if (array_key_exists('idApp', $v_opciones))
451  {
452  $wsClient->idApp = $v_opciones['idApp'];
453  }
454 
455  $wsClient->loadTracertPAI($v_opciones);
456  }//Fin opciones
457 
458  return $wsClient;
459 
460  }//Fin makeWSClient
461 
462 
469  public function getDebugMode()
470  {
471  return($this->_debugMode);
472  }//getDebugMode
473 
474 
481  public function getDebugInfo()
482  {
483  return $this->_debugInfo;
484  }//Fin getDebugInfo
485 
486 
487 
494  public function setDebugMode($activo)
495  {
496  self::$MYSOAPOP_TRACE = true;//Necesario para tratar MTOM
497  $this->_debugMode = $activo;
498  if ($activo)
499  {
500  self::$MYSOAPOP_WSDL_CACHE = WSDL_CACHE_NONE;
501  }
502  else
503  {
504  self::$MYSOAPOP_WSDL_CACHE = WSDL_CACHE_MEMORY;//Sólo en memoria
505  $this->_debugInfo = array();//Vaciamos las trazas de debug
506  }
507  }//setDebugMode
508 
509 
516  public function addDebugInfo($info)
517  {
518  if (!empty($info))
519  {
520  $this->_debugInfo[] = $info;
521  }
522 
523  }//addDebugInfo
524 
525 
526 
533  public function setKeyFile($pathKey)
534  {
535  $this->keyFile = $pathKey;
536  }//setKeyFile
537 
538 
545  public function setPassPhrase($passphrase)
546  {
547  $this->passPhrase = $passphrase;
548  }//setPassPhrase
549 
550 
557  public function setCertFile($pathCert)
558  {
559  $this->certFile = $pathCert;
560  }//setCertFile
561 
562 
569  public function setWSDLTimeOut($segs)
570  {
571  $this->WSDLTimeOut = $segs;
572  }//setCertFile
573 
574 
575 
582  public function getCertificateSerial($set=true)
583  {
584  if (empty($this->certFile))
585  {
586  throw new Exception('No se ha fijado valor para el certificado o el mismo no existe.');
587  }
588 
589  $certFile = realpath($this->certFile);
590  if ($certFile === false)
591  {
592  throw new Exception('No existe el fichero de cetificado: '.$this->certFile);
593  }
594 
595  $cert = file_get_contents($certFile);
596  if ($cert === false)
597  {
598  throw new Exception('No puede leerse el certificado : '.$certFile);
599  }
600 
601  $v_certData = openssl_x509_parse($cert, true);
602  $nsCert = strtoupper(self::numberBaseConvert($v_certData['serialNumber']));
603  if ($set==true)
604  {
605  $this->nsCert = $nsCert;
606  }
607  return $nsCert;
608  }//getCertificateSerial
609 
610 
617  public static function getCertificateInfo($ruta, $formato = null)
618  {
619  $certPath = null;
620  $cert = null;
621  $certContent = null;
622 
623  $certPath = realpath($ruta);
624 
625  $certContent = file_get_contents($certPath);
626  if ($certContent === false)
627  {
628  throw new Exception (
629  __CLASS__.':'.__METHOD__.'['.__FILE__.']-L'.__LINE__.
630  '. El certificado no se encuentra en la ruta: '.$certPath
631  );
632  }
633 
634  if (empty($formato))
635  {
636  $formato = pathinfo($certPath, PATHINFO_EXTENSION);
637  }
638 
639  $formato = trim(strtoupper($formato));
640  switch ($formato)
641  {
642  case 'PK12':
643  case 'P12':
644  $v_certPEM = array();
645  openssl_pkcs12_read($certContent, $v_certPEM, '');
646  $cert = $v_certPEM['cert'];
647  break;
648 
649  case 'PEM':
650  case 'CRT':
651  $cert = $certContent;
652  break;
653  }
654 
655  $v_certData = openssl_x509_parse($cert, true);
656  if ($v_certData === false)
657  {
658  throw new Exception (
659  __CLASS__.':'.__METHOD__.'['.__FILE__.']-L'.__LINE__.'.'.
660  'El formato del certificado no se corresponde con '.$formato
661  );
662  }
663  return $v_certData;
664  }//getCertificateInfo
665 
666 
667 
668 
669 
676  public function loadTracertPAI($vTrazabilidadPAI)
677  {
678  if (!is_array($vTrazabilidadPAI))
679  {
680  throw new Exception('Las opciones de trazabilidad deben ser un array asociativo [idApp, nsCert]');
681  }
682 
683  if (array_key_exists('idApp', $vTrazabilidadPAI))
684  {
685  $this->idApp = $vTrazabilidadPAI['idApp'];
686  }
687 
688  if (array_key_exists('nsCert', $vTrazabilidadPAI))
689  {
690  $this->nsCert = $vTrazabilidadPAI['nsCert'];
691  }
692  }//loadTracertPAI
693 
694 
699  public function enableWSSecurity()
700  {
701  $this->enableWSSecurity = true;
702  }//enableWSSecurity
703 
704 
709  public function disableWSSecurity()
710  {
711  $this->enableWSSecurity = false;
712  }//disableWSSecurity
713 
714 
719  public function enableTrazabilidadPAI()
720  {
721  $this->enableTrazabilidadPAI = true;
722  }//enableTrazabilidadPAI
723 
724 
729  public function disableTrazabilidadPAI()
730  {
731  $this->enableTrazabilidadPAI = false;
732  }//disableTrazabilidadPAI
733 
734 
735 
743  public function __getClient($tipo)
744  {
745  // Si esta vacío el tipo, nada
746  if (empty($tipo)) return null;
747 
748  $tipo = trim(strtolower($tipo));
749  try
750  {
751  $this->__clienteOn($tipo);
752 
753  if (!is_object($this->v_clienteWS[$tipo]))
754  return null;
755  else
756  return ($this->v_clienteWS[$tipo]);
757  }
758  catch (Exception $e)
759  {
760  throw $e;
761  }
762  }// Fin __getClient
763 
764 
765 
766 
767  /* ----------------------------------------------------------------------- */
768  /* --------------------- Métodos privados / protegidos ------------------- */
769  /* ----------------------------------------------------------------------- */
770 
771  // --------------- Métodos propios de la clase ---------------- */
772 
781  protected function __clienteOn($tipo, $trazabilidadPai=true, $opcionesClienteWS = null)
782  {
783  $vTiposCliente = array();
784  if (!empty($tipo))
785  {
786  $tipo = trim(strtolower($tipo));
787 
788  if (array_key_exists($tipo, $this->v_clienteWS))
789  {
790  $vTiposCliente = array($tipo);
791  }
792  else
793  {
794  if ($this->getDebugMode())
795  {
796  $this->addDebugInfo(__CLASS__.':'.__METHOD__.'['.__FILE__.'-'.__LINE__.']'.' Tipo de cliente WS ('.$tipo.') no reconocido.');
797  }
798  throw new Exception (
799  __CLASS__.':'.__METHOD__.'['.__FILE__.']-L'.__LINE__.'.'.
800  'Tipo de cliente WS ('.$tipo.') no reconocido'
801  );
802  }
803  }
804 
805  //REVIEW: Estudiar opciones de contructor para mejorar
806  /*
807  //Creamos un contexto para perfilar la conexión HTTP/HTTPS del cliente
808  $streamContext = stream_context_create (
809  array (
810  'ssl' => array (
811  'verify_peer' => false,
812  'verify_peer_name' => false,
813  'allow_self_signed' => true
814  ),
815  'http'=>array (
816  'user_agent' => 'WSSSoapClient',
817  'timeout' => $this->WSDLTimeOut
818  )
819  )
820  );*/
821  if (!is_array($opcionesClienteWS))
822  {
823 
824  //REVIEW: Si utilizamos la versión 1.2 de SOAP no funciona GDE (insertarDoc)
825  /*
826  $opcionesClienteWS = array (
827  'soap_version' => SOAP_1_2,
828  'user_agent' => 'WSSSoapClient',
829  'exceptions' => true,
830  'cache_wsdl' => self::$MYSOAPOP_WSDL_CACHE,
831  'compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP| 9,
832  'connection_timeout'=> $this->WSDLTimeOut,
833  'trace' => self::$MYSOAPOP_TRACE //NECESARIO PARA TRATAR MTOM
834  );
835  */
836 
837  $opcionesClienteWS = array (
838  'soap_version' => SOAP_1_1,
839  'user_agent' => 'WSSSoapClient',
840  'exceptions' => true,
841  'cache_wsdl' => self::$MYSOAPOP_WSDL_CACHE,
842  'trace' => self::$MYSOAPOP_TRACE //NECESARIO PARA TRATAR MTOM
843  );
844  }
845  else
846  {
847  $opcionesClienteWS['soap_version'] = SOAP_1_1;//v1.1
848  $opcionesClienteWS['user_agent'] = 'WSSSoapClient';
849  $opcionesClienteWS['exceptions'] = true;
850  $opcionesClienteWS['cache_wsdl'] = self::$MYSOAPOP_WSDL_CACHE;
851  $opcionesClienteWS['trace'] = self::$MYSOAPOP_TRACE; //NECESARIO PARA TRATAR MTOM
852  }
853 
854  if ($this->getDebugMode())
855  {
856  $this->addDebugInfo("Opciones:\n ".print_r($opcionesClienteWS, true));
857  }
858 
859  foreach ($vTiposCliente as $claveTipo)
860  {
861  if (is_object($this->v_clienteWS[$claveTipo])) continue;
862  try
863  {
864  //Comprobamos accesibilidad de la URL
865  if (ini_get('allow_url_fopen') == true)//Si tenemos acceso a allow_url_open
866  {
867  $opciones = array (
868  'http' => array (
869  'timeout' => $this->WSDLTimeOut
870  ),
871  'https' => array (
872  'timeout' => $this->WSDLTimeOut
873  ),
874  'ssl' => array (
875  'verify_peer' => false,
876  'allow_self_signed' => true
877  )
878  );
879 
880  $sc = stream_context_create($opciones);
881  $fd = fopen($this->v_wsdl[$claveTipo], 'r', false, $sc);
882  if ($fd==false)
883  {
884  throw new Exception('allow_url_fopen activo. La URL '.$this->v_wsdl[$claveTipo].' no puede alcanzarse.');
885  }
886  fclose($fd);
887  }
888  /*
889  elseif (function_exists('curl_version'))//Si tenemos acceso CURL utilizamos la extensión
890  {
891  if ($this->getDebugMode())
892  {
893  $this->addDebugInfo(__CLASS__.':'.__METHOD__.'['.__FILE__.'-'.__LINE__.']'.' allow_url_fopen NO ACTIVO');
894  }
895  $url = strtolower(str_replace(' ', '%20', trim($this->v_wsdl[$claveTipo])));
896 
897  $cd = curl_init($url);
898  if ($cd===false)
899  {
900  $mensaje = "CURL. La URL $url no puede alcanzarse";
901  curl_close($cd);
902  $this->addDebugInfo(__CLASS__.':'.__METHOD__.'['.__FILE__.'-'.__LINE__.']'.$mensaje);
903  throw new Exception($mensaje);
904  }
905 
906  @curl_setopt($cd, CURLOPT_HEADER,true); // we want headers
907  @curl_setopt($cd, CURLOPT_NOBODY, true); // dont need body
908  @curl_setopt($cd, CURLOPT_RETURNTRANSFER, true);
909  @curl_setopt($cd, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
910  @curl_setopt($cd, CURLOPT_CONNECTTIMEOUT, 20);
911  @curl_setopt($cd, CURLOPT_SSL_VERIFYPEER, false);
912  @curl_setopt($cd, CURLOPT_FOLLOWLOCATION, true);
913  @curl_setopt($cd, CURLOPT_MAXREDIRS, 10); // fairly random number, but
914  curl_exec($cd);
915  $codError = @curl_errno($cd);
916  if ($codError!=0)
917  {
918  $mensaje = "CURL. La URL $url no puede alcanzarse. Error: [$codError]";
919  curl_close($cd);
920  $this->addDebugInfo(__CLASS__.':'.__METHOD__.'['.__FILE__.'-'.__LINE__.']'.$mensaje);
921  throw new Exception($mensaje);
922  }
923  $httpcode = curl_getinfo($cd, CURLINFO_HTTP_CODE);
924 
925  curl_close($cd);
926  if (($httpcode!=200))
927  {
928  $mensaje = "CURL. La URL $url no puede alcanzarse: $httpcode";
929  curl_close($cd);
930  $this->addDebugInfo(__CLASS__.':'.__METHOD__.'['.__FILE__.'-'.__LINE__.']'.$mensaje);
931  throw new Exception($mensaje);
932  }
933  echo "CURL: La URL es accesible.";
934  exit;
935  }
936  */
937  else//No lanzamos excepción, sólo registramos la posibilidad
938  {
939  if ($this->getDebugMode())
940  {
941  $this->addDebugInfo(__CLASS__.':'.__METHOD__.'['.__FILE__.'-'.__LINE__.']'.' allow_url_fopen NO ACTIVO y Extensión CURL NO ACTIVA');
942  }
943  }
944 
945  //Si llegamos aquí no hemos podido comprobar la accesibilidad del WSDL previamente, así que saltará la excepción si no es alcanzable
946  $clienteWS = new WSSSoapClient($this->v_wsdl[$claveTipo], $opcionesClienteWS);
947 
948  if ($this->enableWSSecurity == true)
949  {
950  $clienteWS->setCertFile($this->certFile); //Certificado (sin key) PEM
951  $clienteWS->setKeyFile($this->keyFile); //Acceso al fichero .key extraido del pk12 formato PEM
952  $clienteWS->setPassPhrase($this->passPhrase);
953  $clienteWS->enableWSSecurity();
954  }
955  else
956  {
957  $clienteWS->disableWSSecurity();
958  }
959 
960  if ($this->enableTrazabilidadPAI)
961  {
962  $clienteWS->loadTracertPAI($this->vTrazabilidad);
963  }
964  $this->v_clienteWS[$claveTipo] = $clienteWS;
965  }
966  catch (Exception $e)
967  {
968  if ($this->getDebugMode())
969  {
970  $this->addDebugInfo(__CLASS__.':'.__METHOD__.'['.__FILE__.'-'.__LINE__.']'."\n");
971  if (is_object($clienteWS))
972  {
973  $this->addDebugInfo("RqH:\n ".$clienteWS->__getLastRequestHeaders());
974  $this->addDebugInfo("Rq:\n ".$clienteWS->__getLastRequest());
975  $this->addDebugInfo("RsH:\n ".$clienteWS->__getLastResponse());
976  $this->addDebugInfo("Rs:\n ".$clienteWS->__getLastResponseHeaders());
977  }
978  else
979  $this->addDebugInfo("\n");
980  }
981  throw $e;
982  }
983  }//Fin foreach
984  }// Fin __clienteOn
985 
986 
987 
995  protected function array2ObjectTree($array)
996  {
997  if (!is_array($array)) return;
998 
999  if (is_numeric(key($array)))
1000  {
1001  foreach ($array as $key => $value)
1002  {
1003  $array[$key] = $this->array2ObjectTree($value);
1004  }
1005  return $array;
1006  }
1007  $Object = new stdClass;
1008  foreach ($array as $key => $value)
1009  {
1010  if (is_array($value))
1011  {
1012  $Object->$key = $this->array2ObjectTree($value);
1013  }
1014  else
1015  {
1016  $Object->$key = $value;
1017  }
1018  }
1019  return $Object;
1020  }//Fin array2ObjectTree
1021 
1029  protected function objectTree2array($obj)
1030  {
1031  if (is_array($obj) || is_object($obj))
1032  {
1033  $result = array();
1034  foreach ($obj as $key => $value)
1035  {
1036  $result[$key] = $this->objectTree2array($value);
1037  }
1038  return $result;
1039  }
1040  return $obj;
1041  }//Fin objectTree2array
1042 
1043 
1044  protected function tratarExcepcionEstandar($e, $clienteWS)
1045  {
1046  // Comprueba si es una excepcion de PAI, y la lanza en dicho caso como excepcion especifica de PAI
1047  WSComunPAIException::tryToThrow($e);
1048 
1049  // Tratamiento estandar
1050  if ($this->getDebugMode())
1051  {
1052  $this->addDebugInfo(__CLASS__.':'.__METHOD__.'['.__FILE__.'-'.__LINE__.']'."\n");
1053  if (is_object($clienteWS))
1054  {
1055  $this->addDebugInfo("RqH:\n ".$clienteWS->__getLastRequestHeaders());
1056  $this->addDebugInfo("Rq:\n ".$clienteWS->__getLastRequest());
1057  $this->addDebugInfo("RsH:\n ".$clienteWS->__getLastResponse());
1058  $this->addDebugInfo("Rs:\n ".$clienteWS->__getLastResponseHeaders());
1059  }
1060  throw $e;
1061  }
1062  else
1063  {
1064  throw $e;
1065  }
1066  }//tratarExcepcionEstandar
1067 
1068 
1069 
1079  protected function tratarMTOMEstandar($response, $itemToReturn = null)
1080  {
1081  //Comprobamos si existen anexos
1082  $mimeBoundary = '--MIME_Boundary';//Probamos con --MIME Boundary hasta mejora de detección
1083  $vBodyResponse = explode($mimeBoundary, $response); //Fraccionamos la respuesta.
1084  $numElementos = count($vBodyResponse);
1085 
1086  $srcData='';
1087  if ($numElementos<=1)
1088  {
1089  $mimeBoundary = '--uuid:';//Probamos de nuevo con --uuid hasta mejora de detección
1090  $vBodyResponse = explode($mimeBoundary, $response); //Fraccionamos la respuesta.
1091  $numElementos = count($vBodyResponse);
1092  $srcData = $response;
1093  }
1094  elseif ($numElementos>1)
1095  {
1096  $srcData = $vBodyResponse[1];
1097  }
1098 
1099  $vRespuesta = array();
1100  ini_set('pcre.backtrack_limit','100000000'); //Valor por defecto = 1000000 (aprox. 100KBytes)
1101  preg_match("/<[a-z]*:Envelope.*?>(.*)<\/[a-z]*:Envelope>/is", $srcData, $vRespuesta);
1102  if (preg_last_error()!=PREG_NO_ERROR)
1103  {
1104  //Si falta intentamos obtener el anexo con otro sistema
1105  $start = stripos($srcData, ':Envelope');
1106  $start = strripos($srcData, '<', $start - strlen($srcData));
1107  $end = strripos($srcData, ':Envelope>');
1108  $cadenaRespuesta = substr($srcData, $start, $end);
1109  }
1110  elseif (count($vRespuesta)<1)
1111  {
1112  throw new Exception('No puede ubicarse RESPONSE dentro de MTOM');
1113  }
1114  else
1115  {
1116  $cadenaRespuesta = $vRespuesta[0];
1117  unset($vRespuesta);
1118  }
1119 
1120  $dom = new DOMDocument('1.0');
1121  $dom->loadXML($cadenaRespuesta);//Cargamo el XML
1122  $xpath = new \DOMXpath($dom);
1123  $vNodoRespuesta = $xpath->query("/*[local-name()='Envelope']/*[local-name()='Body']/*/*[local-name()='respuesta']");
1124  $subStrXpath='';
1125  if (!empty($itemToReturn))
1126  {
1127  $subStrXpath = "/*[local-name()='{$itemToReturn}']";
1128  }
1129  $vNodoRespuesta = $xpath->query("/*[local-name()='Envelope']/*[local-name()='Body']/*".$subStrXpath);
1130  $nodoRespuesta = $vNodoRespuesta->item(0);
1131 
1132  if ($numElementos>0)
1133  {
1134  $oMimeParser = new WSCMimeParser();
1135  $oMime = $oMimeParser->decodeMTOM($vBodyResponse);
1136  unset($oMime->body);$oMime->body=null;gc_collect_cycles();
1137 
1138  $vNodoInclude = $xpath->query("//*[local-name()='Include']");
1139  foreach ($vNodoInclude as $nodoItem)//Recorremos los nodosXML include y sustituidmos por el contenido
1140  {
1141  $subIdBuscado = (string) $nodoItem->getAttribute('href');
1142  $subIdBuscado = urldecode($subIdBuscado);
1143  $idBuscado = '<'.substr($subIdBuscado, 4).'>';
1144  foreach ($oMime->parts as &$parte)
1145  {
1146  if ($idBuscado == ($parte->headers['content-id']))
1147  {
1148  if ( strtolower(substr($parte->mimetype, 0, 4)) !== 'text')//Si el tipo mime no es texto, convertimos a B64 por ser contenido binario
1149  {
1150  $parte->body = base64_encode($parte->body);
1151  }
1152  $textNode = $dom->createTextNode(($parte->body));
1153  $nodoItem->parentNode->replaceChild($textNode, $nodoItem);
1154  }
1155  }//Fin for partes
1156  }//Fin for nodos
1157  }
1158  return($this->xml_to_array($nodoRespuesta));
1159  }//tratarMTOMEstandar
1160 
1161 
1162 
1163 
1164  protected function xml_to_array(&$root)
1165  {
1166  $result = array();
1167  if ($root->hasAttributes())
1168  {
1169  $attrs = $root->attributes;
1170  foreach ($attrs as $attr)
1171  {
1172  $result['@attributes'][$attr->name] = $attr->value;
1173  }
1174  }
1175  if ($root->hasChildNodes())
1176  {
1177  $children = $root->childNodes;
1178  if ($children->length == 1)
1179  {
1180  $child = $children->item(0);
1181  if ($child->nodeType == XML_TEXT_NODE)
1182  {
1183  $result['_value'] = $child->nodeValue;
1184  return count($result) == 1 ? $result['_value'] : $result;
1185  }
1186  }
1187  $groups = array();
1188  foreach ($children as $child)
1189  {
1190  if (!isset($result[$child->nodeName]))
1191  {
1192  $result[$child->nodeName] = $this->xml_to_array($child);
1193  }
1194  else
1195  {
1196  if (!isset($groups[$child->nodeName]))
1197  {
1198  $result[$child->nodeName] = array($result[$child->nodeName]);
1199  $groups[$child->nodeName] = 1;
1200  }
1201  $result[$child->nodeName][] = $this->xml_to_array($child);
1202  }
1203  }
1204  }
1205  return $result;
1206  }//xml_to_array
1207 
1208 
1220  public static function numberBaseConvert($numstring, $frombase=10, $tobase=16)
1221  {
1222  $chars = "0123456789abcdefghijklmnopqrstuvwxyz";
1223  $tostring = substr($chars, 0, $tobase);
1224  $length = strlen($numstring);
1225  $result = '';
1226  $number = array();
1227  for ($i = 0; $i < $length; $i++)
1228  {
1229  $number[$i] = strpos($chars, $numstring{$i});
1230  }
1231  do
1232  {
1233  $divide = 0;
1234  $newlen = 0;
1235  for ($i = 0; $i < $length; $i++)
1236  {
1237  $divide = $divide * $frombase + $number[$i];
1238  if ($divide >= $tobase)
1239  {
1240  $number[$newlen++] = (int)($divide / $tobase);
1241  $divide = $divide % $tobase;
1242  } elseif ($newlen > 0)
1243  {
1244  $number[$newlen++] = 0;
1245  }
1246  }
1247  $length = $newlen;
1248  $result = $tostring{$divide} . $result;
1249  } while ($newlen != 0);
1250 
1251  return $result;
1252  }//numberBaseConvert
1253 
1259  public static function getClientIP()
1260  {
1261  if (getenv('HTTP_CLIENT_IP'))
1262  {
1263  $ip = getenv('HTTP_CLIENT_IP');
1264  }
1265  else if(getenv('HTTP_X_FORWARDED_FOR'))
1266  {
1267  $ip = getenv('HTTP_X_FORWARDED_FOR');
1268  }
1269  else if (getenv('HTTP_X_FORWARDED'))
1270  {
1271  $ip = getenv('HTTP_X_FORWARDED');
1272  }
1273  else if(getenv('HTTP_FORWARDED_FOR'))
1274  {
1275  $ip = getenv('HTTP_FORWARDED_FOR');
1276  }
1277  else if(getenv('HTTP_FORWARDED'))
1278  {
1279  $ip = getenv('HTTP_FORWARDED');
1280  }
1281  else if(getenv('REMOTE_ADDR'))
1282  {
1283  $ip = getenv('REMOTE_ADDR');
1284  }
1285  else
1286  {
1287  $ip = 'UNKNOWN';
1288  }
1289  return $ip;
1290  }//Fin getClientIP
1291 
1292 
1293 
1294 
1295 }//Fin WSComunFClient
1296 
1297 
1298 
1299 
1307 {
1308 
1309  const ERROR_SERVICIO = '0101';
1310  const TIMESTAMP_INVALIDO = '0230';
1311  const ORGANISMO_NO_AUTORIZADO = '0301';
1312  const ESTRUCURA_XML_NO_CORRESPONDE_A_ESQUEMA = '0401';
1313  const MENSAJE_XML_INVALIDO = '0403';
1314  const OPERACION_SOLICITADA_INCORRECTA = '0800';
1315  const FALTA_CABECERA_TRAZABILIDAD = '0807';
1316  const ERROR_GENERAL_INDEFINIDO = '0904';
1317 
1318 
1319  private $CodigoEstado = '';
1320  private $CodigoEstadoSecundario = '';
1321  private $LiteralError = '';
1322  private $LiteralErrorSec = '';
1323 
1324  public function getCodigoEstado() {
1325  return $this->CodigoEstado;
1326  }
1327  public function getCodigoEstadoSecundario() {
1328  return $this->CodigoEstadoSecundario;
1329  }
1330  public function getLiteralError() {
1331  return $this->LiteralError;
1332  }
1333  public function getLiteralErrorSec() {
1334  return $this->LiteralErrorSec;
1335  }
1336 
1337 
1338 
1339  public function __construct($soapFault) {
1340  // Extrae la informacion básica del error
1341  $faultCode = intval($soapFault->detail->Atributos->Estado->CodigoEstado);
1342  $faultString = $soapFault->detail->Atributos->Estado->LiteralError;
1343 
1344  // asegúrese de que todo está asignado apropiadamente
1345  parent::__construct($faultString, $faultCode, $soapFault);
1346 
1347  // Extrae información detallada del error
1348  $this->CodigoEstado = $soapFault->detail->Atributos->Estado->CodigoEstado;
1349  $this->CodigoEstadoSecundario = $soapFault->detail->Atributos->Estado->CodigoEstadoSecundario;
1350  $this->LiteralError = $soapFault->detail->Atributos->Estado->LiteralError;
1351  $this->LiteralErrorSec = $soapFault->detail->Atributos->Estado->LiteralErrorSec;
1352  }
1353 
1354  public function __toString() {
1355  return __CLASS__ . ": [{$this->code}] {$this->message}\n";
1356  }
1357 
1358 
1359 
1367  public static function tryToThrow($e) {
1368  // Si es un SoapFault y su codigo es soap-env:PAI, asumimos que se trata de una excepcion especifica
1369  if (($e instanceof \SoapFault) && ($e->faultcode == 'soap-env:PAI')) {
1370  // Excepcion especifica detallada
1371  throw new WSComunPAIException($e);
1372  }
1373 
1374  return false;
1375  }
1376 
1377 }
1378 
1379 ?>
static numberBaseConvert($numstring, $frombase=10, $tobase=16)
__construct($v_wsdl, $v_opciones=null)
loadTracertPAI($vTrazabilidadPAI)
__clienteOn($tipo, $trazabilidadPai=true, $opcionesClienteWS=null)
static getCertificateInfo($ruta, $formato=null)
tratarMTOMEstandar($response, $itemToReturn=null)
static makeWSClient($wsID, $v_wsdl, $v_opciones=null)
const DEBUG