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 para realizar operaciones con lo Folios autorizados por el SII |
28
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
29
|
|
|
* @version 2018-03-20 |
30
|
|
|
*/ |
31
|
|
|
class Folios |
32
|
|
|
{ |
33
|
|
|
|
34
|
|
|
private $xml; ///< Objeto XML que representa el CAF |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* Constructor de la clase |
38
|
|
|
* @param xml Datos XML del código de autorización de folios (CAF) |
39
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
40
|
|
|
* @version 2016-11-21 |
41
|
|
|
*/ |
42
|
|
|
public function __construct($xml) |
43
|
|
|
{ |
44
|
|
|
$this->xml = new \sasco\LibreDTE\XML(); |
45
|
|
|
$this->xml->loadXML(utf8_encode($xml)); |
46
|
|
View Code Duplication |
if (!$this->check()) { |
|
|
|
|
47
|
|
|
\sasco\LibreDTE\Log::write( |
48
|
|
|
\sasco\LibreDTE\Estado::FOLIOS_ERROR_CHECK, |
49
|
|
|
\sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::FOLIOS_ERROR_CHECK) |
|
|
|
|
50
|
|
|
); |
51
|
|
|
$this->xml = null; |
52
|
|
|
} |
53
|
|
|
} |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* Método que verifica el código de autorización de folios |
57
|
|
|
* @return =true si está ok el XML cargado |
|
|
|
|
58
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
59
|
|
|
* @version 2015-10-30 |
60
|
|
|
*/ |
61
|
|
|
public function check() |
62
|
|
|
{ |
63
|
|
|
// validar firma del SII sobre los folios |
64
|
|
|
$firma = $this->getFirma(); |
65
|
|
|
$idk = $this->getIDK(); |
66
|
|
|
if (!$firma || !$idk) { |
|
|
|
|
67
|
|
|
return false; |
68
|
|
|
} |
69
|
|
|
$pub_key = \sasco\LibreDTE\Sii::cert($idk); |
|
|
|
|
70
|
|
|
if (!$pub_key || openssl_verify($this->xml->getFlattened('/AUTORIZACION/CAF/DA'), base64_decode($firma), $pub_key)!==1) { |
|
|
|
|
71
|
|
|
\sasco\LibreDTE\Log::write( |
72
|
|
|
\sasco\LibreDTE\Estado::FOLIOS_ERROR_FIRMA, |
73
|
|
|
\sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::FOLIOS_ERROR_FIRMA) |
|
|
|
|
74
|
|
|
); |
75
|
|
|
return false; |
76
|
|
|
} |
77
|
|
|
// validar clave privada y pública proporcionada por el SII |
78
|
|
|
$private_key = $this->getPrivateKey(); |
79
|
|
|
if (!$private_key) { |
|
|
|
|
80
|
|
|
return false; |
81
|
|
|
} |
82
|
|
|
$plain = md5(date('U')); |
83
|
|
|
if (!openssl_private_encrypt($plain, $crypt, $private_key)) { |
84
|
|
|
\sasco\LibreDTE\Log::write( |
85
|
|
|
\sasco\LibreDTE\Estado::FOLIOS_ERROR_ENCRIPTAR, |
86
|
|
|
\sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::FOLIOS_ERROR_ENCRIPTAR) |
|
|
|
|
87
|
|
|
); |
88
|
|
|
return false; |
89
|
|
|
} |
90
|
|
|
$public_key = $this->getPublicKey(); |
91
|
|
|
if (!$public_key) { |
|
|
|
|
92
|
|
|
return false; |
93
|
|
|
} |
94
|
|
|
if (!openssl_public_decrypt($crypt, $plain_firmado, $public_key)) { |
95
|
|
|
\sasco\LibreDTE\Log::write( |
96
|
|
|
\sasco\LibreDTE\Estado::FOLIOS_ERROR_DESENCRIPTAR, |
97
|
|
|
\sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::FOLIOS_ERROR_DESENCRIPTAR) |
|
|
|
|
98
|
|
|
); |
99
|
|
|
return false; |
100
|
|
|
} |
101
|
|
|
return $plain === $plain_firmado; |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* Método que entrega el nodo CAF |
106
|
|
|
* @return DomElement |
107
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
108
|
|
|
* @version 2015-10-30 |
109
|
|
|
*/ |
110
|
|
|
public function getCaf() |
111
|
|
|
{ |
112
|
|
|
if (!$this->xml) { |
113
|
|
|
return false; |
114
|
|
|
} |
115
|
|
|
$CAF = $this->xml->getElementsByTagName('CAF')->item(0); |
116
|
|
|
return $CAF ? $CAF : false; |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* Método que entrega el RUT de a quién se está autorizando el CAF |
121
|
|
|
* @return Rut del emisor del CAF |
122
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
123
|
|
|
* @version 2015-10-30 |
124
|
|
|
*/ |
125
|
|
|
public function getEmisor() |
126
|
|
|
{ |
127
|
|
|
if (!$this->xml) { |
128
|
|
|
return false; |
129
|
|
|
} |
130
|
|
|
$RE = $this->xml->getElementsByTagName('RE')->item(0); |
131
|
|
|
return $RE ? $RE->nodeValue : false; |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
/** |
135
|
|
|
* Método que entrega el primer folio autorizado en el CAF |
136
|
|
|
* @return Número del primer folio |
137
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
138
|
|
|
* @version 2015-10-30 |
139
|
|
|
*/ |
140
|
|
|
public function getDesde() |
141
|
|
|
{ |
142
|
|
|
if (!$this->xml) { |
143
|
|
|
return false; |
144
|
|
|
} |
145
|
|
|
$D = $this->xml->getElementsByTagName('D')->item(0); |
146
|
|
|
return $D ? (int)$D->nodeValue : false; |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
/** |
150
|
|
|
* Método que entrega el últimmo folio autorizado en el CAF |
151
|
|
|
* @return Número del último folio |
152
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
153
|
|
|
* @version 2015-10-30 |
154
|
|
|
*/ |
155
|
|
|
public function getHasta() |
156
|
|
|
{ |
157
|
|
|
if (!$this->xml) { |
158
|
|
|
return false; |
159
|
|
|
} |
160
|
|
|
$H = $this->xml->getElementsByTagName('H')->item(0); |
161
|
|
|
return $H ? (int)$H->nodeValue : false; |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
/** |
165
|
|
|
* Método que entrega la firma del SII sobre el nodo DA |
166
|
|
|
* @return Firma en base64 |
167
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
168
|
|
|
* @version 2015-10-30 |
169
|
|
|
*/ |
170
|
|
View Code Duplication |
private function getFirma() |
|
|
|
|
171
|
|
|
{ |
172
|
|
|
if (!$this->xml) { |
173
|
|
|
return false; |
174
|
|
|
} |
175
|
|
|
$FRMA = $this->xml->getElementsByTagName('FRMA')->item(0); |
176
|
|
|
return $FRMA ? $FRMA->nodeValue : false; |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
/** |
180
|
|
|
* Método que entrega el IDK (serial number) de la clave pública del SII |
181
|
|
|
* utilizada para firmar el CAF |
182
|
|
|
* @return Serial number |
183
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
184
|
|
|
* @version 2015-10-30 |
185
|
|
|
*/ |
186
|
|
View Code Duplication |
private function getIDK() |
|
|
|
|
187
|
|
|
{ |
188
|
|
|
if (!$this->xml) { |
189
|
|
|
return false; |
190
|
|
|
} |
191
|
|
|
$IDK = $this->xml->getElementsByTagName('IDK')->item(0); |
192
|
|
|
return $IDK ? (int)$IDK->nodeValue : false; |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
/** |
196
|
|
|
* Método que entrega la clave privada proporcionada por el SII para el CAF |
197
|
|
|
* @return Clave privada en base64 |
198
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
199
|
|
|
* @version 2015-10-30 |
200
|
|
|
*/ |
201
|
|
|
public function getPrivateKey() |
202
|
|
|
{ |
203
|
|
|
if (!$this->xml) { |
204
|
|
|
return false; |
205
|
|
|
} |
206
|
|
|
$RSASK = $this->xml->getElementsByTagName('RSASK')->item(0); |
207
|
|
|
return $RSASK ? $RSASK->nodeValue : false; |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
/** |
211
|
|
|
* Método que entrega la clave pública proporcionada por el SII para el CAF |
212
|
|
|
* @return Clave pública en base64 |
213
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
214
|
|
|
* @version 2015-10-30 |
215
|
|
|
*/ |
216
|
|
|
public function getPublicKey() |
217
|
|
|
{ |
218
|
|
|
if (!$this->xml) { |
219
|
|
|
return false; |
220
|
|
|
} |
221
|
|
|
$RSAPUBK = $this->xml->getElementsByTagName('RSAPUBK')->item(0); |
222
|
|
|
return $RSAPUBK ? $RSAPUBK->nodeValue : false; |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
/** |
226
|
|
|
* Método que entrega el tipo de DTE para el cual se emitió el CAF |
227
|
|
|
* @return Código de tipo de DTE |
228
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
229
|
|
|
* @version 2015-10-30 |
230
|
|
|
*/ |
231
|
|
|
public function getTipo() |
232
|
|
|
{ |
233
|
|
|
if (!$this->xml) { |
234
|
|
|
return false; |
235
|
|
|
} |
236
|
|
|
$TD = $this->xml->getElementsByTagName('TD')->item(0); |
237
|
|
|
return $TD ? (int)$TD->nodeValue : false; |
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
/** |
241
|
|
|
* Método que entrega la fecha de autorización con la que se emitió el CAF |
242
|
|
|
* @return Fecha de autorización del CAF |
243
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
244
|
|
|
* @version 2017-07-19 |
245
|
|
|
*/ |
246
|
|
|
public function getFechaAutorizacion() |
247
|
|
|
{ |
248
|
|
|
if (!$this->xml) { |
249
|
|
|
return false; |
250
|
|
|
} |
251
|
|
|
$FA = $this->xml->getElementsByTagName('FA')->item(0); |
252
|
|
|
return $FA ? $FA->nodeValue : false; |
253
|
|
|
} |
254
|
|
|
|
255
|
|
|
/** |
256
|
|
|
* Método que indica si el CAF es de certificación o no |
257
|
|
|
* @return =true si los folios son del ambiente de certificación, =null si no se pudo determinar |
|
|
|
|
258
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
259
|
|
|
* @version 2015-10-30 |
260
|
|
|
*/ |
261
|
|
|
public function getCertificacion() |
262
|
|
|
{ |
263
|
|
|
$idk = $this->getIDK(); |
264
|
|
|
return $idk ? $idk === 100 : null; |
265
|
|
|
} |
266
|
|
|
|
267
|
|
|
/** |
268
|
|
|
* Método que indica si el CAF está o no vigente |
269
|
|
|
* @return =true si el CAF está vigente, =false si no está vigente |
|
|
|
|
270
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
271
|
|
|
* @version 2018-03-20 |
272
|
|
|
*/ |
273
|
|
|
public function vigente() |
274
|
|
|
{ |
275
|
|
|
if (!in_array($this->getTipo(), [33, 46, 61])) { |
276
|
|
|
return true; |
277
|
|
|
} |
278
|
|
|
$d1 = new \DateTime($this->getFechaAutorizacion()); |
279
|
|
|
$d2 = new \DateTime(date('Y-m-d')); |
280
|
|
|
$meses = $d1->diff($d2)->m + ($d1->diff($d2)->y*12); |
281
|
|
|
return $meses <= 18; |
282
|
|
|
} |
283
|
|
|
|
284
|
|
|
/** |
285
|
|
|
* Método que entrega el XML completo del archivo CAF |
286
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
287
|
|
|
* @version 2016-08-24 |
288
|
|
|
*/ |
289
|
|
|
public function saveXML() |
290
|
|
|
{ |
291
|
|
|
return $this->xml->saveXML(); |
292
|
|
|
} |
293
|
|
|
|
294
|
|
|
} |
295
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.