1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* LibreDTE |
5
|
|
|
* Copyright (C) SASCO SpA (https://sasco.cl) |
6
|
|
|
* |
7
|
|
|
* Este programa es software libre: usted puede redistribuirlo y/o |
8
|
|
|
* modificarlo bajo los términos de la Licencia Pública General Affero de GNU |
9
|
|
|
* publicada por la Fundación para el Software Libre, ya sea la versión |
10
|
|
|
* 3 de la Licencia, o (a su elección) cualquier versión posterior de la |
11
|
|
|
* misma. |
12
|
|
|
* |
13
|
|
|
* Este programa se distribuye con la esperanza de que sea útil, pero |
14
|
|
|
* SIN GARANTÍA ALGUNA; ni siquiera la garantía implícita |
15
|
|
|
* MERCANTIL o de APTITUD PARA UN PROPÓSITO DETERMINADO. |
16
|
|
|
* Consulte los detalles de la Licencia Pública General Affero de GNU para |
17
|
|
|
* obtener una información más detallada. |
18
|
|
|
* |
19
|
|
|
* Debería haber recibido una copia de la Licencia Pública General Affero de GNU |
20
|
|
|
* junto a este programa. |
21
|
|
|
* En caso contrario, consulte <http://www.gnu.org/licenses/agpl.html>. |
22
|
|
|
*/ |
23
|
|
|
|
24
|
|
|
namespace sasco\LibreDTE\Sii; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* Clase que representa el envío de un DTE |
28
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
29
|
|
|
* @version 2016-08-10 |
30
|
|
|
*/ |
31
|
|
|
class EnvioDte extends \sasco\LibreDTE\Sii\Base\Envio |
32
|
|
|
{ |
33
|
|
|
|
34
|
|
|
private $dtes = []; ///< Objetos con los DTE que se enviarán |
35
|
|
|
private $config = [ // 0: DTE, 1: boleta |
|
|
|
|
36
|
|
|
'SubTotDTE_max' => [20, 2], ///< máxima cantidad de tipos de documentos en el envío |
37
|
|
|
'DTE_max' => [2000, 1000], ///< máxima cantidad de DTE en un envío |
38
|
|
|
'tipos' => ['EnvioDTE', 'EnvioBOLETA'], ///< Tag para el envío, según si son Boletas o no |
39
|
|
|
'schemas' => ['EnvioDTE_v10', 'EnvioBOLETA_v11'], ///< Schema (XSD) que se deberá usar para validar según si son boletas o no |
40
|
|
|
]; ///< Configuración/reglas para el documento XML |
41
|
|
|
private $tipo = null; ///< =0 DTE, =1 boleta |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* Método que agrega un DTE al listado que se enviará |
45
|
|
|
* @param DTE Objeto del DTE |
46
|
|
|
* @return =true si se pudo agregar el DTE o =false si no se agregó por exceder el límite de un envío |
|
|
|
|
47
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
48
|
|
|
* @version 2015-12-11 |
49
|
|
|
*/ |
50
|
|
|
public function agregar(Dte $DTE) |
51
|
|
|
{ |
52
|
|
|
// determinar el tipo del envío (DTE o boleta) |
53
|
|
|
if ($this->tipo === null) { |
54
|
|
|
$this->tipo = (int)$DTE->esBoleta(); |
55
|
|
|
} |
56
|
|
|
// validar que el tipo de documento sea del tipo que se espera |
57
|
|
|
else if ((int)$DTE->esBoleta() != $this->tipo) { |
58
|
|
|
return false; |
59
|
|
|
} |
60
|
|
|
// |
61
|
|
View Code Duplication |
if (isset($this->dtes[$this->config['DTE_max'][$this->tipo]-1])) { |
|
|
|
|
62
|
|
|
\sasco\LibreDTE\Log::write( |
63
|
|
|
\sasco\LibreDTE\Estado::ENVIODTE_DTE_MAX, |
64
|
|
|
\sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::ENVIODTE_DTE_MAX, $this->config['DTE_max'][$this->tipo]) |
|
|
|
|
65
|
|
|
); |
66
|
|
|
return false; |
67
|
|
|
} |
68
|
|
|
$this->dtes[] = $DTE; |
69
|
|
|
return true; |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* Método para asignar la caratula |
74
|
|
|
* @param caratula Arreglo con datos del envío: RutEnvia, FchResol y NroResol |
75
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
76
|
|
|
* @version 2015-12-11 |
77
|
|
|
*/ |
78
|
|
|
public function setCaratula(array $caratula) |
79
|
|
|
{ |
80
|
|
|
// si no hay DTEs para generar entregar falso |
81
|
|
|
if (!isset($this->dtes[0])) { |
82
|
|
|
\sasco\LibreDTE\Log::write( |
83
|
|
|
\sasco\LibreDTE\Estado::ENVIODTE_FALTA_DTE, |
84
|
|
|
\sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::ENVIODTE_FALTA_DTE) |
|
|
|
|
85
|
|
|
); |
86
|
|
|
return false; |
87
|
|
|
} |
88
|
|
|
// si se agregaron demasiados DTE error |
89
|
|
|
$SubTotDTE = $this->getSubTotDTE(); |
90
|
|
View Code Duplication |
if (isset($SubTotDTE[$this->config['SubTotDTE_max'][$this->tipo]])) { |
|
|
|
|
91
|
|
|
\sasco\LibreDTE\Log::write( |
92
|
|
|
\sasco\LibreDTE\Estado::ENVIODTE_TIPO_DTE_MAX, |
93
|
|
|
\sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::ENVIODTE_TIPO_DTE_MAX, $this->config['SubTotDTE_max'][$this->tipo]) |
|
|
|
|
94
|
|
|
); |
95
|
|
|
return false; |
96
|
|
|
} |
97
|
|
|
// generar caratula |
98
|
|
|
$this->caratula = array_merge([ |
99
|
|
|
'@attributes' => [ |
100
|
|
|
'version' => '1.0' |
101
|
|
|
], |
102
|
|
|
'RutEmisor' => $this->dtes[0]->getEmisor(), |
103
|
|
|
'RutEnvia' => isset($this->Firma) ? $this->Firma->getID() : false, |
104
|
|
|
'RutReceptor' => $this->dtes[0]->getReceptor(), |
105
|
|
|
'FchResol' => '', |
106
|
|
|
'NroResol' => '', |
107
|
|
|
'TmstFirmaEnv' => date('Y-m-d\TH:i:s'), |
108
|
|
|
'SubTotDTE' => $SubTotDTE, |
109
|
|
|
], $caratula); |
110
|
|
|
return true; |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* Método que realiza el envío del sobre con el o los DTEs al SII |
115
|
|
|
* @return Track ID del envío o =false si hubo algún problema al enviar el documento |
116
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
117
|
|
|
* @version 2015-12-15 |
118
|
|
|
*/ |
119
|
|
|
public function enviar() |
120
|
|
|
{ |
121
|
|
|
// si es boleta no se envía al SII |
122
|
|
|
if ($this->tipo) { |
123
|
|
|
return false; |
124
|
|
|
} |
125
|
|
|
// enviar al SII |
126
|
|
|
return parent::enviar(); |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
/** |
130
|
|
|
* Método que genera el XML para el envío del DTE al SII |
131
|
|
|
* @return XML con el envio del DTE firmado o =false si no se pudo generar o firmar el envío |
132
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
133
|
|
|
* @version 2016-08-06 |
134
|
|
|
*/ |
135
|
|
|
public function generar() |
136
|
|
|
{ |
137
|
|
|
// si ya se había generado se entrega directamente |
138
|
|
|
if ($this->xml_data) |
139
|
|
|
return $this->xml_data; |
140
|
|
|
// si no hay DTEs para generar entregar falso |
141
|
|
|
if (!isset($this->dtes[0])) { |
142
|
|
|
\sasco\LibreDTE\Log::write( |
143
|
|
|
\sasco\LibreDTE\Estado::ENVIODTE_FALTA_DTE, |
144
|
|
|
\sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::ENVIODTE_FALTA_DTE) |
|
|
|
|
145
|
|
|
); |
146
|
|
|
return false; |
|
|
|
|
147
|
|
|
} |
148
|
|
|
// genear XML del envío |
149
|
|
|
$xmlEnvio = (new \sasco\LibreDTE\XML())->generate([ |
150
|
|
|
$this->config['tipos'][$this->tipo] => [ |
151
|
|
|
'@attributes' => [ |
152
|
|
|
'xmlns' => 'http://www.sii.cl/SiiDte', |
153
|
|
|
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', |
154
|
|
|
'xsi:schemaLocation' => 'http://www.sii.cl/SiiDte '.$this->config['schemas'][$this->tipo].'.xsd', |
155
|
|
|
'version' => '1.0' |
156
|
|
|
], |
157
|
|
|
'SetDTE' => [ |
158
|
|
|
'@attributes' => [ |
159
|
|
|
'ID' => 'LibreDTE_SetDoc' |
160
|
|
|
], |
161
|
|
|
'Caratula' => $this->caratula, |
162
|
|
|
'DTE' => null, |
163
|
|
|
] |
164
|
|
|
] |
165
|
|
|
])->saveXML(); |
166
|
|
|
// generar XML de los DTE que se deberán incorporar |
167
|
|
|
$DTEs = []; |
168
|
|
|
foreach ($this->dtes as &$DTE) { |
169
|
|
|
$DTEs[] = trim(str_replace(['<?xml version="1.0" encoding="ISO-8859-1"?>', '<?xml version="1.0"?>'], '', $DTE->saveXML())); |
170
|
|
|
} |
171
|
|
|
// firmar XML del envío y entregar |
172
|
|
|
$xml = str_replace('<DTE/>', implode("\n", $DTEs), $xmlEnvio); |
173
|
|
|
$this->xml_data = $this->Firma ? $this->Firma->signXML($xml, '#LibreDTE_SetDoc', 'SetDTE', true) : $xml; |
|
|
|
|
174
|
|
|
return $this->xml_data; |
|
|
|
|
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* Método que obtiene los datos para generar los tags SubTotDTE |
179
|
|
|
* @return Arreglo con los datos para generar los tags SubTotDTE |
180
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
181
|
|
|
* @version 2015-09-02 |
182
|
|
|
*/ |
183
|
|
|
private function getSubTotDTE() |
184
|
|
|
{ |
185
|
|
|
$SubTotDTE = []; |
186
|
|
|
$subtotales = []; |
187
|
|
|
foreach ($this->dtes as &$DTE) { |
188
|
|
|
if (!isset($subtotales[$DTE->getTipo()])) |
189
|
|
|
$subtotales[$DTE->getTipo()] = 0; |
190
|
|
|
$subtotales[$DTE->getTipo()]++; |
191
|
|
|
} |
192
|
|
|
foreach ($subtotales as $tipo => $subtotal) { |
193
|
|
|
$SubTotDTE[] = [ |
194
|
|
|
'TpoDTE' => $tipo, |
195
|
|
|
'NroDTE' => $subtotal, |
196
|
|
|
]; |
197
|
|
|
} |
198
|
|
|
return $SubTotDTE; |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
/** |
202
|
|
|
* Método que carga un XML de EnvioDte y asigna el objeto XML correspondiente |
203
|
|
|
* para poder obtener los datos del envío |
204
|
|
|
* @return Objeto XML |
205
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
206
|
|
|
* @version 2016-11-21 |
207
|
|
|
*/ |
208
|
|
|
public function loadXML($xml_data) |
209
|
|
|
{ |
210
|
|
|
if (!parent::loadXML($xml_data)) { |
211
|
|
|
return false; |
212
|
|
|
} |
213
|
|
|
$tagName = $this->xml->documentElement->tagName; |
214
|
|
|
if ($tagName=='DTE') { |
215
|
|
|
$this->xml = null; |
216
|
|
|
$this->xml_data = null; |
217
|
|
|
$this->arreglo = null; |
218
|
|
|
$Dte = new Dte($xml_data, false); |
219
|
|
|
$this->agregar($Dte); |
220
|
|
|
$this->setCaratula([ |
221
|
|
|
'RutEnvia' => $Dte->getEmisor(), |
222
|
|
|
'RutReceptor' => $Dte->getReceptor(), |
223
|
|
|
'FchResol' => date('Y-m-d'), |
224
|
|
|
'NroResol' => ($Dte->getCertificacion()?'0':'').'9999', |
225
|
|
|
]); |
226
|
|
|
if (!parent::loadXML($this->generar())) { |
227
|
|
|
return false; |
228
|
|
|
} |
229
|
|
|
$tagName = $this->xml->documentElement->tagName; |
230
|
|
|
} |
231
|
|
|
if ($tagName=='EnvioDTE') { |
232
|
|
|
$this->tipo = 0; |
233
|
|
|
return $this->xml; |
234
|
|
|
} |
235
|
|
|
if ($tagName=='EnvioBOLETA') { |
236
|
|
|
$this->tipo = 1; |
237
|
|
|
return $this->xml; |
238
|
|
|
} |
239
|
|
|
return false; |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
/** |
243
|
|
|
* Método que entrega un arreglo con los datos de la carátula del envío |
244
|
|
|
* @return Arreglo con datos de carátula |
245
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
246
|
|
|
* @version 2015-12-11 |
247
|
|
|
*/ |
248
|
|
|
public function getCaratula() |
249
|
|
|
{ |
250
|
|
|
return isset($this->arreglo[$this->config['tipos'][$this->tipo]]['SetDTE']['Caratula']) ? $this->arreglo[$this->config['tipos'][$this->tipo]]['SetDTE']['Caratula'] : false; |
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
/** |
254
|
|
|
* Método que entrega el ID de SetDTE |
255
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
256
|
|
|
* @version 2015-12-11 |
257
|
|
|
*/ |
258
|
|
|
public function getID() |
259
|
|
|
{ |
260
|
|
|
return isset($this->arreglo[$this->config['tipos'][$this->tipo]]['SetDTE']['@attributes']['ID']) ? $this->arreglo[$this->config['tipos'][$this->tipo]]['SetDTE']['@attributes']['ID'] : false; |
261
|
|
|
} |
262
|
|
|
|
263
|
|
|
/** |
264
|
|
|
* Método que entrega el DigestValue de la firma del envío |
265
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
266
|
|
|
* @version 2015-12-11 |
267
|
|
|
*/ |
268
|
|
|
public function getDigest() |
269
|
|
|
{ |
270
|
|
|
return isset($this->arreglo[$this->config['tipos'][$this->tipo]]['Signature']['SignedInfo']['Reference']['DigestValue']) ? $this->arreglo[$this->config['tipos'][$this->tipo]]['Signature']['SignedInfo']['Reference']['DigestValue'] : false; |
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
/** |
274
|
|
|
* Método que entrega el rut del emisor del envío |
275
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
276
|
|
|
* @version 2015-09-07 |
277
|
|
|
*/ |
278
|
|
|
public function getEmisor() |
279
|
|
|
{ |
280
|
|
|
$Caratula = $this->getCaratula(); |
281
|
|
|
return $Caratula ? $Caratula['RutEmisor'] : false; |
282
|
|
|
} |
283
|
|
|
|
284
|
|
|
/** |
285
|
|
|
* Método que entrega el rut del receptor del envío |
286
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
287
|
|
|
* @version 2015-09-07 |
288
|
|
|
*/ |
289
|
|
|
public function getReceptor() |
290
|
|
|
{ |
291
|
|
|
$Caratula = $this->getCaratula(); |
292
|
|
|
return $Caratula ? $Caratula['RutReceptor'] : false; |
293
|
|
|
} |
294
|
|
|
|
295
|
|
|
/** |
296
|
|
|
* Método que entrega la fecha del DTE más antiguo del envio |
297
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
298
|
|
|
* @version 2015-12-12 |
299
|
|
|
*/ |
300
|
|
|
public function getFechaEmisionInicial() |
301
|
|
|
{ |
302
|
|
|
$fecha = '9999-12-31'; |
303
|
|
|
foreach ($this->getDocumentos() as $Dte) { |
|
|
|
|
304
|
|
|
if ($Dte->getFechaEmision() < $fecha) |
305
|
|
|
$fecha = $Dte->getFechaEmision(); |
306
|
|
|
} |
307
|
|
|
return $fecha; |
308
|
|
|
} |
309
|
|
|
|
310
|
|
|
/** |
311
|
|
|
* Método que entrega la fecha del DTE más nuevo del envio |
312
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
313
|
|
|
* @version 2015-12-12 |
314
|
|
|
*/ |
315
|
|
|
public function getFechaEmisionFinal() |
316
|
|
|
{ |
317
|
|
|
$fecha = '0000-01-01'; |
318
|
|
|
foreach ($this->getDocumentos() as $Dte) { |
|
|
|
|
319
|
|
|
if ($Dte->getFechaEmision() > $fecha) |
320
|
|
|
$fecha = $Dte->getFechaEmision(); |
321
|
|
|
} |
322
|
|
|
return $fecha; |
323
|
|
|
} |
324
|
|
|
|
325
|
|
|
/** |
326
|
|
|
* Método que entrega el arreglo con los objetos DTE del envío |
327
|
|
|
* @return Arreglo de objetos DTE |
328
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
329
|
|
|
* @version 2016-11-21 |
330
|
|
|
*/ |
331
|
|
|
public function getDocumentos($c14n = true) |
332
|
|
|
{ |
333
|
|
|
// si no hay documentos se deben crear |
334
|
|
|
if (!$this->dtes) { |
|
|
|
|
335
|
|
|
// si no hay XML no se pueden crear los documentos |
336
|
|
|
if (!$this->xml) { |
337
|
|
|
\sasco\LibreDTE\Log::write( |
338
|
|
|
\sasco\LibreDTE\Estado::ENVIODTE_GETDOCUMENTOS_FALTA_XML, |
339
|
|
|
\sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::ENVIODTE_GETDOCUMENTOS_FALTA_XML) |
|
|
|
|
340
|
|
|
); |
341
|
|
|
return false; |
342
|
|
|
} |
343
|
|
|
// crear documentos a partir del XML |
344
|
|
|
$DTEs = $this->xml->getElementsByTagName('DTE'); |
345
|
|
|
foreach ($DTEs as $nodo_dte) { |
346
|
|
|
$xml = $c14n ? $nodo_dte->C14N() : $this->xml->saveXML($nodo_dte); |
347
|
|
|
$this->dtes[] = new Dte($xml, false); // cargar DTE sin normalizar |
348
|
|
|
} |
349
|
|
|
} |
350
|
|
|
return $this->dtes; |
351
|
|
|
} |
352
|
|
|
|
353
|
|
|
/** |
354
|
|
|
* Método que entrega el objeto DTE solicitado del envío |
355
|
|
|
* @return Objeto DTE |
356
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
357
|
|
|
* @version 2016-11-21 |
358
|
|
|
*/ |
359
|
|
|
public function getDocumento($emisor, $dte, $folio) |
360
|
|
|
{ |
361
|
|
|
$emisor = str_replace('.', '', $emisor); |
362
|
|
|
// si no hay XML no se pueden crear los documentos |
363
|
|
|
if (!$this->xml) { |
364
|
|
|
\sasco\LibreDTE\Log::write( |
365
|
|
|
\sasco\LibreDTE\Estado::ENVIODTE_GETDOCUMENTOS_FALTA_XML, |
366
|
|
|
\sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::ENVIODTE_GETDOCUMENTOS_FALTA_XML) |
|
|
|
|
367
|
|
|
); |
368
|
|
|
return false; |
369
|
|
|
} |
370
|
|
|
// buscar documento |
371
|
|
|
$DTEs = $this->xml->getElementsByTagName('DTE'); |
372
|
|
|
foreach ($DTEs as $nodo_dte) { |
373
|
|
|
$e = $nodo_dte->getElementsByTagName('RUTEmisor')->item(0)->nodeValue; |
374
|
|
|
if (is_numeric($emisor)) |
375
|
|
|
$e = substr($e, 0, -2); |
376
|
|
|
$d = (int)$nodo_dte->getElementsByTagName('TipoDTE')->item(0)->nodeValue; |
377
|
|
|
$f = (int)$nodo_dte->getElementsByTagName('Folio')->item(0)->nodeValue; |
378
|
|
|
if ($folio == $f and $dte == $d and $emisor == $e) { |
|
|
|
|
379
|
|
|
return new Dte($nodo_dte->C14N(), false); // cargar DTE sin normalizar |
380
|
|
|
} |
381
|
|
|
} |
382
|
|
|
return false; |
383
|
|
|
} |
384
|
|
|
|
385
|
|
|
/** |
386
|
|
|
* Método que indica si es EnvioDTE o EnvioBOLETA |
387
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
388
|
|
|
* @version 2016-08-10 |
389
|
|
|
*/ |
390
|
|
|
public function esBoleta() |
391
|
|
|
{ |
392
|
|
|
return (bool)$this->tipo; |
393
|
|
|
} |
394
|
|
|
|
395
|
|
|
/** |
396
|
|
|
* Método que determina el estado de validación sobre el envío |
397
|
|
|
* @param datos Arreglo con datos para hacer las validaciones |
398
|
|
|
* @return Código del estado de la validación |
399
|
|
|
* @warning No se está validando la firma del EnvioDTE |
400
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
401
|
|
|
* @version 2015-09-07 |
402
|
|
|
*/ |
403
|
|
|
public function getEstadoValidacion(array $datos = null) |
404
|
|
|
{ |
405
|
|
|
if (!$this->schemaValidate()) |
|
|
|
|
406
|
|
|
return 1; |
407
|
|
|
/*if (!$this->checkFirma()) |
|
|
|
|
408
|
|
|
return 2;*/ |
409
|
|
|
if ($datos and $this->getReceptor()!=$datos['RutReceptor']) |
|
|
|
|
410
|
|
|
return 3; |
411
|
|
|
return 0; |
412
|
|
|
} |
413
|
|
|
|
414
|
|
|
/** |
415
|
|
|
* Método que indica si la firma del documento es o no válida |
416
|
|
|
* @return =true si la firma del documento del envío es válida, =null si no se pudo determinar |
|
|
|
|
417
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
418
|
|
|
* @version 2017-04-07 |
419
|
|
|
*/ |
420
|
|
|
public function checkFirma() |
421
|
|
|
{ |
422
|
|
|
if (!$this->xml) |
423
|
|
|
return null; |
424
|
|
|
// listado de firmas del XML |
425
|
|
|
$Signatures = $this->xml->documentElement->getElementsByTagName('Signature'); |
426
|
|
|
// verificar firma de SetDTE |
427
|
|
|
$SetDTE = $this->xml->documentElement->getElementsByTagName('SetDTE')->item(0)->C14N(); |
428
|
|
|
$SignedInfo = $Signatures->item($Signatures->length-1)->getElementsByTagName('SignedInfo')->item(0); |
429
|
|
|
$DigestValue = $Signatures->item($Signatures->length-1)->getElementsByTagName('DigestValue')->item(0)->nodeValue; |
430
|
|
|
$SignatureValue = $Signatures->item($Signatures->length-1)->getElementsByTagName('SignatureValue')->item(0)->nodeValue; |
431
|
|
|
$X509Certificate = $Signatures->item($Signatures->length-1)->getElementsByTagName('X509Certificate')->item(0)->nodeValue; |
432
|
|
|
if ($X509Certificate[1]==' ' or $X509Certificate[1]=="\t") { |
|
|
|
|
433
|
|
|
$lineas = explode("\n", $X509Certificate); |
434
|
|
|
$X509Certificate = ''; |
435
|
|
|
foreach($lineas as $l) { |
436
|
|
|
$X509Certificate .= trim($l); |
437
|
|
|
} |
438
|
|
|
} |
439
|
|
|
$X509Certificate = '-----BEGIN CERTIFICATE-----'."\n".wordwrap(trim($X509Certificate), 64, "\n", true)."\n".'-----END CERTIFICATE-----'; |
440
|
|
|
$valid = openssl_verify($SignedInfo->C14N(), base64_decode($SignatureValue), $X509Certificate) === 1 ? true : false; |
441
|
|
|
return $valid and $DigestValue===base64_encode(sha1($SetDTE, true)); |
|
|
|
|
442
|
|
|
} |
443
|
|
|
|
444
|
|
|
} |
445
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.