WSCOMUN  2.0.0
Web Services Comunes para PHP/GVHidra
WSSSoapClient.php
1 <?php
2 
6 namespace WSCOMUN;
7 
8 use SoapClient;
9 use WSSESoap;
10 use XMLSecurityKey;
11 
12 require_once('XMLSecLibs/WSSESoap.php');
13 
33 {
38  protected $keyFile='';
39 
44  protected $passPhrase='';
45 
50  protected $certFile='';
51 
55  private $conTrazabilidadPAI = true;
56 
60  private $enableWSSecurity = true;
61 
65  protected $nsCert = null;
66 
70  protected $idApp = null;
71 
76  protected $mtom = false;
77 
78 
86  public function __construct($wsdl, $vOptions=null)
87  {
88 
89  $this->soapSent='';
90  $this->keyFile='';
91  $this->passPhrase='';
92  $this->certFile='';
93 
94  $this->conTrazabilidadPAI = true;
95  $this->enableWSSecurity = true;
96 
97  if (is_array($vOptions))
98  {
99  $vOptions['trace'] = true;
100  }
101  else
102  {
103  $vOptions = array('trace' => true);
104  }
105 
106  return parent::__construct($wsdl, $vOptions);
107  }//Fin __contruct
108 
109 
116  public function setKeyFile($pathKey)
117  {
118  $this->keyFile = $pathKey;
119  }//setKeyFile
120 
121 
128  public function getKeyFile()
129  {
130  return($this->keyFile);
131  }//getKeyFile
132 
133 
140  public function setPassPhrase($passphrase)
141  {
142  $this->passPhrase = $passphrase;
143  }//setPassPhrase
144 
145 
152  public function getPassPhrase()
153  {
154  return($this->passPhrase);
155  }//getPassPhrase
156 
157 
164  public function setCertFile($pathCert)
165  {
166  $this->certFile = $pathCert;
167  }//setCertFile
168 
175  public function getCertFile()
176  {
177  return($this->certFile);
178  }//getCertFile
179 
180 
187  public function loadCert($vCertData)
188  {
189  if (!is_array($vCertData))
190  throw new \Exception('La información debe venir como array asociativo');
191 
192  if (array_key_exists('certFile', $vCertData))
193  {
194  $this->certFile = $vCertData['certFile'];
195  }
196  else
197  {
198  throw new \Exception('El array asociativo debe contener la ruta al certificado');
199  }
200 
201  if (array_key_exists('keyFile', $vCertData))
202  {
203  $this->keyFile = $vCertData['keyFile'];
204  }
205  else
206  {
207  throw new \Exception('El array asociativo debe contener la ruta al fichero de clave');
208  }
209 
210  if (array_key_exists('passPhrase', $vCertData))
211  {
212  $this->passPhrase = $vCertData['passPhrase'];
213  }
214  }//loadCert
215 
216 
217 
224  public function isMTOM()
225  {
226  return($this->mtom);
227  }//isMTOM
228 
229 
230 
231  // ---------------------------------------------
232  // Métodos para el uso de trazabilidad de la PAI
233  // ---------------------------------------------
240  public function loadTracertPAI($vTrazabilidadPAI)
241  {
242  if (!is_array($vTrazabilidadPAI))
243  {
244  throw new \Exception('Las opciones de trazabilidad deben ser un array asociativo');
245  }
246 
247  if (array_key_exists('idApp', $vTrazabilidadPAI))
248  {
249  $this->idApp = $vTrazabilidadPAI['idApp'];
250  }
251  else
252  {
253  throw new \Exception('El array asociativo debe contener el ID de la aplicación que consume el WS');
254  }
255 
256  if ($this->enableWSSecurity)
257  {
258  $this->getCertificateSerial();
259  }
260  }//loadTracertPAI
261 
262 
269  public function enablePAITrace___($vTrazabilidadPAI = null)
270  {
271  if (empty ($vTrazabilidadPAI))
272  {
273  if (empty($this->idApp))
274  {
275  throw new \Exception(__CLASS__.":: Debe fijarse el idApp");
276  }
277 
278  if ($this->enableWSSecurity())
279  {
280  if(empty($this->nsCert))
281  {
282  $this->nsCert = $this->getCertificateSerial();
283  }
284  }
285  }
286  else
287  {
288  try
289  {
290  $this->loadTrazabilidad($vTrazabilidadPAI);
291  }
292  catch (\Exception $e)
293  {
294  throw $e;
295  }
296  }
297  $this->conTrazabilidadPAI = true;
298  }//enablePAITrace
299 
300 
305  public function disablePAITrace()
306  {
307  $this->conTrazabilidadPAI = false;
308  }//disablePAITrace
309 
310 
311 
316  public function enableWSSecurity()
317  {
318  $this->enableWSSecurity = true;
319  }//enableWSSecurity
320 
321 
326  public function disableWSSecurity()
327  {
328  $this->enableWSSecurity = false;
329  }//disableWSSecurity
330 
331 
332 
339  public function getCertificateSerial()
340  {
341  $certFile = realpath($this->certFile);
342  $cert = file_get_contents($certFile);
343  if ($cert === false)
344  {
345  throw new \Exception(__FILE__.'::'.__CLASS__." - No puedo leere el contenido de $certFile ");
346  }
347  $v_certData = openssl_x509_parse($cert, true);
348  $this->nsCert = strtoupper(self::numberBaseConvert($v_certData['serialNumber']));
349  return $this->nsCert;
350  }//getCertificateSerial
351 
352 
364  private static function numberBaseConvert($numstring, $frombase=10, $tobase=16)
365  {
366  $chars = "0123456789abcdefghijklmnopqrstuvwxyz";
367  $tostring = substr($chars, 0, $tobase);
368  $length = strlen($numstring);
369  $result = '';
370  $number = array();
371  for ($i = 0; $i < $length; $i++)
372  {
373  $number[$i] = strpos($chars, $numstring{$i});
374  }
375  do
376  {
377  $divide = 0;
378  $newlen = 0;
379  for ($i = 0; $i < $length; $i++)
380  {
381  $divide = $divide * $frombase + $number[$i];
382  if ($divide >= $tobase)
383  {
384  $number[$newlen++] = (int)($divide / $tobase);
385  $divide = $divide % $tobase;
386  } elseif ($newlen > 0)
387  {
388  $number[$newlen++] = 0;
389  }
390  }
391  $length = $newlen;
392  $result = $tostring{$divide} . $result;
393  } while ($newlen != 0);
394 
395  return $result;
396  }
397 
398 
406  private function getPAITraceToken()
407  {
408  $t = microtime(true);
409  $micro = sprintf("%06d",($t - floor($t)) * 1000000);
410  $date = new \DateTime( date('Y-m-d H:i:s.'.$micro, $t));
411  $token = $this->nsCert.'-'.$this->idApp.'-'.substr($date->format('YmdHisu'), 0, 17);
412 
413  return $token;
414  }//getPAITraceToken
415 
416 
417 
418 
427  public function __doRequest($newRequest, $location, $action, $version, $one_way = null)
428  {
429  if ($this->enableWSSecurity==true)//Si trabajamos con WSSecurity
430  {
431  //Creamos un DOMDocument
432  $doc = new \DOMDocument('1.0');
433 
434  //Cargamos el XML pasado por parámetro (WSDL)
435  $doc->loadXML($newRequest);
436 
437  //Creamos una instancia de WSSESoap con el documento, sin "mustUnderstand" ni "actor"
438  $objWSSE = new WSSESoap($doc, false, false);
439 
440  //Creamos una instacian de XMLSecurityKey con el RSA SHA1 y de tipo privado
441  $objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type'=>'private'));
442  //Pasamos el valor de passphrase
443  $objKey->passphrase = $this->getPassPhrase();
444  //Cargamos la clave privada con la ruta del fichero, que es fichero y que no es certificado
445  $objKey->loadKey($this->getKeyFile(), true);
446 
447  //Firmamos el mensaje
448  $objWSSE->signSoapDoc($objKey);
449 
450  //Añadimos el BinarySecurityToken, pasamos el contenido del certificado, le decimos que es formato PEM
451  $token = $objWSSE->addBinaryToken(file_get_contents($this->getCertFile()), true);
452  //Añadimos el KeyInfo
453  $objWSSE->attachTokentoSig($token);
454 
455  //Añadimos el Timestamp
456  $objWSSE->addTimestamp(3600);
457 
458  //Obtenemos el REQUEST modificado
459  $newRequest = $objWSSE->saveXML();
460  }
461 
462  if ($this->conTrazabilidadPAI)//Si trabajamos con la trazabilidad PAI
463  {
464  $dom = new \DOMDocument('1.0');
465  $dom->loadXML($newRequest);
466  $xpath = new \DOMXpath($dom);
467  $headers = $xpath->query("/*[local-name()='Envelope']/*[local-name()='Header']");
468 
469  if (($headers->length) > 0)
470  {
471  $header = $headers->item(0);//Localizamos la cabecera
472  }
473  else
474  {
475  $envelop = $dom->firstChild;
476  $prefijo = $dom->lookupPrefix ('http://schemas.xmlsoap.org/soap/envelope/');
477  $header = $dom->createElementNS ('http://schemas.xmlsoap.org/soap/envelope/',$prefijo.':Header','');
478  $body = $envelop->firstChild;
479  $header = $envelop->insertBefore($header, $body);
480  }
481  //Creamos el nodo traza
482  $nodoTraza = $dom->createElementNS('http://dgti.gva.es/interoperabilidad', 'Id_trazabilidad');
483  $nodoTraza->appendChild(new \DOMText( (string) $this->getPAITraceToken()));
484  $header->appendChild($nodoTraza);
485  unset($newRequest);$newRequest=null;gc_collect_cycles();
486  $newRequest = $dom->saveXML();
487  }
488 
489  //Tratamos la respuesta
490  $response = parent::__doRequest($newRequest, $location, $action, $version, $one_way);
491 
492  //Si la respuesta NO contiene MTOM la devolvemos
493  if (strpos($response, "Content-Type: application/xop+xml") === false)
494  {
495  $this->mtom = true;
496  }
497  return $response;
498  }
499 
500 
501 
502 }//Fin WSSSoapClient
503 ?>
loadTracertPAI($vTrazabilidadPAI)
enablePAITrace___($vTrazabilidadPAI=null)
__construct($wsdl, $vOptions=null)
__doRequest($newRequest, $location, $action, $version, $one_way=null)
setPassPhrase($passphrase)