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; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* Clase para acciones genéricas asociadas al SII de Chile |
28
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
29
|
|
|
* @version 2018-01-17 |
30
|
|
|
*/ |
31
|
|
|
class Sii |
32
|
|
|
{ |
33
|
|
|
|
34
|
|
|
private static $config = [ |
35
|
|
|
'wsdl' => [ |
36
|
|
|
'*' => 'https://{servidor}.sii.cl/DTEWS/{servicio}.jws?WSDL', |
37
|
|
|
'QueryEstDteAv' => 'https://{servidor}.sii.cl/DTEWS/services/{servicio}?WSDL', |
38
|
|
|
'wsDTECorreo' => 'https://{servidor}.sii.cl/DTEWS/services/{servicio}?WSDL', |
39
|
|
|
], |
40
|
|
|
'servidor' => ['palena', 'maullin'], ///< servidores 0: producción, 1: certificación |
41
|
|
|
'certs' => [300, 100], ///< certificados 0: producción, 1: certificación |
42
|
|
|
]; |
43
|
|
|
|
44
|
|
|
const PRODUCCION = 0; ///< Constante para indicar ambiente de producción |
45
|
|
|
const CERTIFICACION = 1; ///< Constante para indicar ambiente de desarrollo |
46
|
|
|
|
47
|
|
|
const IVA = 19; ///< Tasa de IVA |
48
|
|
|
|
49
|
|
|
private static $retry = 10; ///< Veces que se reintentará conectar a SII al usar el servicio web |
50
|
|
|
private static $verificar_ssl = true; ///< Indica si se deberá verificar o no el certificado SSL del SII |
51
|
|
|
private static $ambiente = self::PRODUCCION; ///< Ambiente que se utilizará |
52
|
|
|
|
53
|
|
|
private static $direcciones_regionales = [ |
54
|
|
|
'ARICA' => 'ARICA', |
55
|
|
|
'CAMARONES' => 'ARICA', |
56
|
|
|
'PUTRE' => 'ARICA', |
57
|
|
|
'GENERAL LAGOS' => 'ARICA', |
58
|
|
|
'IQUIQUE' => 'IQUIQUE', |
59
|
|
|
'PICA' => 'IQUIQUE', |
60
|
|
|
'POZO ALMONTE' => 'IQUIQUE', |
61
|
|
|
'HUARA' => 'IQUIQUE', |
62
|
|
|
'CAMIÑA' => 'IQUIQUE', |
63
|
|
|
'COLCHANE' => 'IQUIQUE', |
64
|
|
|
'ALTO HOSPICIO' => 'IQUIQUE', |
65
|
|
|
'ANTOFAGASTA' => 'ANTOFAGASTA', |
66
|
|
|
'MEJILLONES' => 'ANTOFAGASTA', |
67
|
|
|
'SIERRA GORDA' => 'ANTOFAGASTA', |
68
|
|
|
'CALAMA' => 'CALAMA', |
69
|
|
|
'SAN PEDRO DE ATACAMA' => 'CALAMA', |
70
|
|
|
'OLLAGUE' => 'CALAMA', |
71
|
|
|
'TOCOPILLA' => 'TOCOPILLA', |
72
|
|
|
'MARÍA ELENA' => 'TOCOPILLA', |
73
|
|
|
'TALTAL' => 'TALTAL', |
74
|
|
|
'COPIAPÓ' => 'COPIAPÓ', |
75
|
|
|
'CALDERA' => 'COPIAPÓ', |
76
|
|
|
'TIERRA AMARILLA' => 'COPIAPÓ', |
77
|
|
|
'CHAÑARAL' => 'CHAÑARAL', |
78
|
|
|
'DIEGO DE ALMAGRO' => 'CHAÑARAL', |
79
|
|
|
'VALLENAR' => 'VALLENAR', |
80
|
|
|
'FREIRINA' => 'VALLENAR', |
81
|
|
|
'HUASCO' => 'VALLENAR', |
82
|
|
|
'ALTO DEL CARMEN' => 'VALLENAR', |
83
|
|
|
'LA SERENA' => 'LA SERENA', |
84
|
|
|
'LA HIGUERA' => 'LA SERENA', |
85
|
|
|
'PAIHUANO' => 'LA SERENA', |
86
|
|
|
'ANDACOLLO' => 'LA SERENA', |
87
|
|
|
'VICUÑA' => 'LA SERENA', |
88
|
|
|
'OVALLE' => 'OVALLE', |
89
|
|
|
'MONTE PATRIA' => 'OVALLE', |
90
|
|
|
'PUNITAQUI' => 'OVALLE', |
91
|
|
|
'COMBARBALÁ' => 'OVALLE', |
92
|
|
|
'RÍO HURTADO' => 'OVALLE', |
93
|
|
|
'ILLAPEL' => 'ILLAPEL', |
94
|
|
|
'SALAMANCA' => 'ILLAPEL', |
95
|
|
|
'LOS VILOS' => 'ILLAPEL', |
96
|
|
|
'CANELA' => 'ILLAPEL', |
97
|
|
|
'COMQUIMBO' => 'COQUIMBO', |
98
|
|
|
'VALPARAÍSO' => 'VALPARAÍSO', |
99
|
|
|
'CASABLANCA' => 'VALPARAÍSO', |
100
|
|
|
'JUAN FERNÁNDEZ' => 'VALPARAÍSO', |
101
|
|
|
'ISLA DE PASCUA' => 'VALPARAÍSO', |
102
|
|
|
'CONCÓN' => 'VIÑA DEL MAR', |
103
|
|
|
'QUINTERO' => 'VIÑA DEL MAR', |
104
|
|
|
'PUCHUNCAVÍ' => 'VIÑA DEL MAR', |
105
|
|
|
'VIÑA DEL MAR' => 'VIÑA DEL MAR', |
106
|
|
|
'LA LIGUA' => 'LA LIGUA', |
107
|
|
|
'PETORCA' => 'LA LIGUA', |
108
|
|
|
'CABILDO' => 'LA LIGUA', |
109
|
|
|
'ZAPALLAR' => 'LA LIGUA', |
110
|
|
|
'PAPUDO' => 'LA LIGUA', |
111
|
|
|
'SAN ANTONIO' => 'SAN ANTONIO', |
112
|
|
|
'SANTO DOMINGO' => 'SAN ANTONIO', |
113
|
|
|
'CARTAGENA' => 'SAN ANTONIO', |
114
|
|
|
'EL TABO' => 'SAN ANTONIO', |
115
|
|
|
'EL QUISCO' => 'SAN ANTONIO', |
116
|
|
|
'ALGARROBO' => 'SAN ANTONIO', |
117
|
|
|
'QUILLOTA' => 'QUILLOTA', |
118
|
|
|
'NOGALES' => 'QUILLOTA', |
119
|
|
|
'HIJUELAS' => 'QUILLOTA', |
120
|
|
|
'LA CALERA' => 'QUILLOTA', |
121
|
|
|
'LA CRUZ' => 'QUILLOTA', |
122
|
|
|
'LIMACHE' => 'QUILLOTA', |
123
|
|
|
'OLMUÉ' => 'QUILLOTA', |
124
|
|
|
'SAN FELIPE' => 'SAN FELIPE', |
125
|
|
|
'PANQUEHUE' => 'SAN FELIPE', |
126
|
|
|
'CATEMU' => 'SAN FELIPE', |
127
|
|
|
'PUTAENDO' => 'SAN FELIPE', |
128
|
|
|
'SANTA MARÍA' => 'SAN FELIPE', |
129
|
|
|
'LLAY LLAY' => 'SAN FELIPE', |
130
|
|
|
'LOS ANDES' => 'LOS ANDES', |
131
|
|
|
'CALLE LARGA' => 'LOS ANDES', |
132
|
|
|
'SAN ESTEBAN' => 'LOS ANDES', |
133
|
|
|
'RINCONADA' => 'LOS ANDES', |
134
|
|
|
'VILLA ALEMANA' => 'VILLA ALEMANA', |
135
|
|
|
'QUILPUÉ' => 'VILLA ALEMANA', |
136
|
|
|
'RANCAGUA' => 'RANCAGUA', |
137
|
|
|
'MACHALÍ' => 'RANCAGUA', |
138
|
|
|
'GRANEROS' => 'RANCAGUA', |
139
|
|
|
'SAN FRANCISCO DE MOSTAZAL' => 'RANCAGUA', |
140
|
|
|
'DOÑIHUE' => 'RANCAGUA', |
141
|
|
|
'CODEGUA' => 'RANCAGUA', |
142
|
|
|
'RENGO' => 'RANCAGUA', |
143
|
|
|
'COLTAUCO' => 'RANCAGUA', |
144
|
|
|
'REQUINOA' => 'RANCAGUA', |
145
|
|
|
'OLIVAR' => 'RANCAGUA', |
146
|
|
|
'MALLOA' => 'RANCAGUA', |
147
|
|
|
'COINCO' => 'RANCAGUA', |
148
|
|
|
'QUINTA DE TILCOCO' => 'RANCAGUA', |
149
|
|
|
'SAN FERNANDO' => 'SAN FERNANDO', |
150
|
|
|
'CHIMBARONGO' => 'SAN FERNANDO', |
151
|
|
|
'NANCAGUA' => 'SAN FERNANDO', |
152
|
|
|
'PLACILLA' => 'SAN FERNANDO', |
153
|
|
|
'SANTA CRUZ' => 'SANTA CRUZ', |
154
|
|
|
'LOLOL' => 'SANTA CRUZ', |
155
|
|
|
'PALMILLA' => 'SANTA CRUZ', |
156
|
|
|
'PERALILLO' => 'SANTA CRUZ', |
157
|
|
|
'CHÉPICA' => 'SANTA CRUZ', |
158
|
|
|
'PUMANQUE' => 'SANTA CRUZ', |
159
|
|
|
'SAN VICENTE' => 'SAN VICENTE TAGUA TAGUA', |
160
|
|
|
'LAS CABRAS' => 'SAN VICENTE TAGUA TAGUA', |
161
|
|
|
'PEUMO' => 'SAN VICENTE TAGUA TAGUA', |
162
|
|
|
'PICHIDEGUA' => 'SAN VICENTE TAGUA TAGUA', |
163
|
|
|
'PICHILEMU' => 'PICHILEMU', |
164
|
|
|
'PAREDONES' => 'PICHILEMU', |
165
|
|
|
'MARCHIGUE' => 'PICHILEMU', |
166
|
|
|
'LITUECHE' => 'PICHILEMU', |
167
|
|
|
'LA ESTRELLA' => 'PICHILEMU', |
168
|
|
|
'TALCA' => 'TALCA', |
169
|
|
|
'SAN CLEMENTE' => 'TALCA', |
170
|
|
|
'PELARCO' => 'TALCA', |
171
|
|
|
'RÍO CLARO' => 'TALCA', |
172
|
|
|
'PENCAHUE' => 'TALCA', |
173
|
|
|
'MAULE' => 'TALCA', |
174
|
|
|
'CUREPTO' => 'TALCA', |
175
|
|
|
'SAN JAVIER' => 'TALCA', |
176
|
|
|
'LINARES' => 'LINARES', |
177
|
|
|
'YERBAS BUENAS' => 'LINARES', |
178
|
|
|
'COLBÚN' => 'LINARES', |
179
|
|
|
'LONGAVÍ' => 'LINARES', |
180
|
|
|
'VILLA ALEGRE' => 'LINARES', |
181
|
|
|
'CONSTITUCIÓN' => 'CONSTITUCIÓN', |
182
|
|
|
'EMPEDRADO' => 'CONSTITUCIÓN', |
183
|
|
|
'CAUQUENES' => 'CAUQUENES', |
184
|
|
|
'PELLUHUE' => 'CAUQUENES', |
185
|
|
|
'CHANCO' => 'CAUQUENES', |
186
|
|
|
'PARRAL' => 'PARRAL', |
187
|
|
|
'RETIRO' => 'PARRAL', |
188
|
|
|
'CURICÓ' => 'CURICÓ', |
189
|
|
|
'TENO' => 'CURICÓ', |
190
|
|
|
'ROMERAL' => 'CURICÓ', |
191
|
|
|
'MOLINA' => 'CURICÓ', |
192
|
|
|
'HUALAÑE' => 'CURICÓ', |
193
|
|
|
'SAGRADA FAMILIA' => 'CURICÓ', |
194
|
|
|
'LICANTÉN' => 'CURICÓ', |
195
|
|
|
'VICHUQUÉN' => 'CURICÓ', |
196
|
|
|
'RAUCO' => 'CURICÓ', |
197
|
|
|
'CONCEPCIÓN' => 'CONCEPCIÓN', |
198
|
|
|
'CHIGUAYANTE' => 'CONCEPCIÓN', |
199
|
|
|
'SAN PEDRO DE LA PAZ' => 'CONCEPCIÓN', |
200
|
|
|
'PENCO' => 'CONCEPCIÓN', |
201
|
|
|
'HUALQUI' => 'CONCEPCIÓN', |
202
|
|
|
'FLORIDA' => 'CONCEPCIÓN', |
203
|
|
|
'TOMÉ' => 'CONCEPCIÓN', |
204
|
|
|
'CORONEL' => 'CONCEPCIÓN', |
205
|
|
|
'LOTA' => 'CONCEPCIÓN', |
206
|
|
|
'SANTA JUANA' => 'CONCEPCIÓN', |
207
|
|
|
'ARAUCO' => 'CONCEPCIÓN', |
208
|
|
|
'CHILLÁN' => 'CHILLÁN', |
209
|
|
|
'PINTO' => 'CHILLÁN', |
210
|
|
|
'EL CARMEN' => 'CHILLÁN', |
211
|
|
|
'SAN IGNACIO' => 'CHILLÁN', |
212
|
|
|
'PEMUCO' => 'CHILLÁN', |
213
|
|
|
'YUNGAY' => 'CHILLÁN', |
214
|
|
|
'BULNES' => 'CHILLÁN', |
215
|
|
|
'QUILLÓN' => 'CHILLÁN', |
216
|
|
|
'RANQUIL' => 'CHILLÁN', |
217
|
|
|
'PORTEZUELO' => 'CHILLÁN', |
218
|
|
|
'COELEMU' => 'CHILLÁN', |
219
|
|
|
'TREHUACO' => 'CHILLÁN', |
220
|
|
|
'QUIRIHUE' => 'CHILLÁN', |
221
|
|
|
'COBQUECURA' => 'CHILLÁN', |
222
|
|
|
'NINHUE' => 'CHILLÁN', |
223
|
|
|
'CHILLÁN VIEJO' => 'CHILLÁN', |
224
|
|
|
'LOS ÁNGELES' => 'LOS ÁNGELES', |
225
|
|
|
'SANTA BARBARA' => 'LOS ÁNGELES', |
226
|
|
|
'LAJA' => 'LOS ÁNGELES', |
227
|
|
|
'QUILLECO' => 'LOS ÁNGELES', |
228
|
|
|
'NACIMIENTO' => 'LOS ÁNGELES', |
229
|
|
|
'NEGRETE' => 'LOS ÁNGELES', |
230
|
|
|
'MULCHÉN' => 'LOS ÁNGELES', |
231
|
|
|
'QUILACO' => 'LOS ÁNGELES', |
232
|
|
|
'YUMBEL' => 'LOS ÁNGELES', |
233
|
|
|
'CABRERO' => 'LOS ÁNGELES', |
234
|
|
|
'SAN ROSENDO' => 'LOS ÁNGELES', |
235
|
|
|
'TUCAPEL' => 'LOS ÁNGELES', |
236
|
|
|
'ANTUCO' => 'LOS ÁNGELES', |
237
|
|
|
'ALTO BÍO-BÍO' => 'LOS ÁNGELES', |
238
|
|
|
'SAN CARLOS' => 'SAN CARLOS', |
239
|
|
|
'SAN GREGORIO DE ÑINQUEN' => 'SAN CARLOS', |
240
|
|
|
'SAN NICOLÁS' => 'SAN CARLOS', |
241
|
|
|
'SAN FABIÁN DE ALICO' => 'SAN CARLOS', |
242
|
|
|
'TALCAHUANO' => 'TALCAHUANO', |
243
|
|
|
'HUALPÉN' => 'TALCAHUANO', |
244
|
|
|
'LEBU' => 'LEBU', |
245
|
|
|
'CURANILAHUE' => 'LEBU', |
246
|
|
|
'LOS ALAMOS' => 'LEBU', |
247
|
|
|
'CAÑETE' => 'LEBU', |
248
|
|
|
'CONTULMO' => 'LEBU', |
249
|
|
|
'TIRÚA' => 'LEBU', |
250
|
|
|
'TEMUCO' => 'TEMUCO', |
251
|
|
|
'VILCÚN' => 'TEMUCO', |
252
|
|
|
'FREIRE' => 'TEMUCO', |
253
|
|
|
'CUNCO' => 'TEMUCO', |
254
|
|
|
'LAUTARO' => 'TEMUCO', |
255
|
|
|
'PERQUENCO' => 'TEMUCO', |
256
|
|
|
'GALVARINO' => 'TEMUCO', |
257
|
|
|
'NUEVA IMPERIAL' => 'TEMUCO', |
258
|
|
|
'CARAHUE' => 'TEMUCO', |
259
|
|
|
'PUERTO SAAVEDRA' => 'TEMUCO', |
260
|
|
|
'PITRUFQUÉN' => 'TEMUCO', |
261
|
|
|
'GORBEA' => 'TEMUCO', |
262
|
|
|
'TOLTÉN' => 'TEMUCO', |
263
|
|
|
'LONCOCHE' => 'TEMUCO', |
264
|
|
|
'MELIPEUCO' => 'TEMUCO', |
265
|
|
|
'TEODORO SCHMIDT' => 'TEMUCO', |
266
|
|
|
'PADRE LAS CASAS' => 'TEMUCO', |
267
|
|
|
'CHOLCHOL' => 'TEMUCO', |
268
|
|
|
'ANGOL' => 'ANGOL', |
269
|
|
|
'PURÉN' => 'ANGOL', |
270
|
|
|
'LOS SAUCES' => 'ANGOL', |
271
|
|
|
'REINACO' => 'ANGOL', |
272
|
|
|
'COLLIPULLI' => 'ANGOL', |
273
|
|
|
'ERCILLA' => 'ANGOL', |
274
|
|
|
'VICTORIA' => 'VICTORIA', |
275
|
|
|
'TRAIGUÉN' => 'VICTORIA', |
276
|
|
|
'LUMACO' => 'VICTORIA', |
277
|
|
|
'CURACAUTÍN' => 'VICTORIA', |
278
|
|
|
'LONQUIMAY' => 'VICTORIA', |
279
|
|
|
'VILLARRICA' => 'VILLARRICA', |
280
|
|
|
'PUCÓN' => 'VILLARRICA', |
281
|
|
|
'CURARREHUE' => 'VILLARRICA', |
282
|
|
|
'VALDIVIA' => 'VALDIVIA', |
283
|
|
|
'MARIQUINA' => 'VALDIVIA', |
284
|
|
|
'LANCO' => 'LANCO', |
285
|
|
|
'MÁFIL' => 'VALDIVIA', |
286
|
|
|
'CORRAL' => 'VALDIVIA', |
287
|
|
|
'LOS LAGOS' => 'VALDIVIA', |
288
|
|
|
'PAILLACO' => 'VALDIVIA', |
289
|
|
|
'PANGUIPULLI' => 'PANGUIPULLI', |
290
|
|
|
'LA UNIÓN' => 'LA UNIÓN', |
291
|
|
|
'FUTRONO' => 'VALDIVIA', |
292
|
|
|
'RÍO BUENO' => 'LA UNIÓN', |
293
|
|
|
'LAGO RANCO' => 'LA UNIÓN', |
294
|
|
|
'PUERTO MONTT' => 'PUERTO MONTT', |
295
|
|
|
'CALBUCO' => 'PUERTO MONTT', |
296
|
|
|
'MAULLÍN' => 'PUERTO MONTT', |
297
|
|
|
'LOS MUERMOS' => 'PUERTO MONTT', |
298
|
|
|
'HUALAIHUÉ' => 'PUERTO MONTT', |
299
|
|
|
'PUERTO VARAS' => 'PUERTO VARAS', |
300
|
|
|
'COCHAMÓ' => 'PUERTO VARAS', |
301
|
|
|
'FRESIA' => 'PUERTO VARAS', |
302
|
|
|
'LLANQUIHUE' => 'PUERTO VARAS', |
303
|
|
|
'FRUTILLAR' => 'PUERTO VARAS', |
304
|
|
|
'ANCUD' => 'ANCUD', |
305
|
|
|
'QUEMCHI' => 'ANCUD', |
306
|
|
|
'OSORNO' => 'OSORNO', |
307
|
|
|
'PUYEHUE' => 'OSORNO', |
308
|
|
|
'PURRANQUE' => 'OSORNO', |
309
|
|
|
'RÍO NEGRO' => 'OSORNO', |
310
|
|
|
'SAN PABLO' => 'OSORNO', |
311
|
|
|
'SAN JUAN DE LA COSTA' => 'OSORNO', |
312
|
|
|
'PUERTO OCTAY' => 'OSORNO', |
313
|
|
|
'CASTRO' => 'CASTRO', |
314
|
|
|
'CURACO DE VÉLEZ' => 'CASTRO', |
315
|
|
|
'CHOCHI' => 'CASTRO', |
316
|
|
|
'DALCAHUE' => 'CASTRO', |
317
|
|
|
'PUQUELDÓN' => 'CASTRO', |
318
|
|
|
'QUEILÉN' => 'CASTRO', |
319
|
|
|
'QUELLÓN' => 'CASTRO', |
320
|
|
|
'CHAITÉN' => 'CHAITÉN', |
321
|
|
|
'PALENA' => 'CHAITÉN', |
322
|
|
|
'FUTALEUFÚ' => 'CHAITÉN', |
323
|
|
|
'COYHAIQUE' => 'COYHAIQUE', |
324
|
|
|
'RÍO IBAÑEZ' => 'COYHAIQUE', |
325
|
|
|
'O`HIGGINS' => 'COCHRANE', |
326
|
|
|
'TORTEL' => 'COCHRANE', |
327
|
|
|
'AYSÉN' => 'AYSÉN', |
328
|
|
|
'CISNES' => 'AYSÉN', |
329
|
|
|
'LAGO VERDE' => 'AYSÉN', |
330
|
|
|
'GUAITECAS' => 'AYSÉN', |
331
|
|
|
'CHILE CHICO' => 'CHILE CHICO', |
332
|
|
|
'COCHRANE' => 'COCHRANE', |
333
|
|
|
'GUADAL' => 'COCHRANE', |
334
|
|
|
'PUERTO BELTRAND' => 'COCHRANE', |
335
|
|
|
'PUNTA ARENAS' => 'PUNTA ARENAS', |
336
|
|
|
'RÍO VERDE' => 'PUNTA ARENAS', |
337
|
|
|
'SAN GREGORIO' => 'PUNTA ARENAS', |
338
|
|
|
'LAGUNA BLANCA' => 'PUNTA ARENAS', |
339
|
|
|
'CABO DE HORNOS' => 'PUNTA ARENAS', |
340
|
|
|
'PUERTO NATALES' => 'PUERTO NATALES', |
341
|
|
|
'TORRES DEL PAINE' => 'PUERTO NATALES', |
342
|
|
|
'PORVENIR' => 'PORVENIR', |
343
|
|
|
'PRIMAVERA' => 'PORVENIR', |
344
|
|
|
'TIMAUKEL' => 'PORVENIR', |
345
|
|
|
'INDEPENDENCIA' => 'SANTIAGO NORTE', |
346
|
|
|
'RECOLETA' => 'SANTIAGO NORTE', |
347
|
|
|
'HUECHURABA' => 'SANTIAGO NORTE', |
348
|
|
|
'CONCHALÍ' => 'SANTIAGO NORTE', |
349
|
|
|
'QUILICURA' => 'SANTIAGO NORTE', |
350
|
|
|
'COLINA' => 'SANTIAGO NORTE', |
351
|
|
|
'LAMPA' => 'SANTIAGO NORTE', |
352
|
|
|
'TILTIL' => 'SANTIAGO NORTE', |
353
|
|
|
'SANTIAGO' => 'SANTIAGO CENTRO', |
354
|
|
|
'CERRO NAVIA' => 'SANTIAGO PONIENTE', |
355
|
|
|
'CURACAVÍ' => 'SANTIAGO PONIENTE', |
356
|
|
|
'ESTACIÓN CENTRAL' => 'SANTIAGO PONIENTE', |
357
|
|
|
'LO PRADO' => 'SANTIAGO PONIENTE', |
358
|
|
|
'PUDAHUEL' => 'SANTIAGO PONIENTE', |
359
|
|
|
'QUINTA NORMAL' => 'SANTIAGO PONIENTE', |
360
|
|
|
'RENCA' => 'SANTIAGO PONIENTE', |
361
|
|
|
'MELIPILLA' => 'MELIPILLA', |
362
|
|
|
'SAN PEDRO' => 'MELIPILLA', |
363
|
|
|
'ALHUÉ' => 'MELIPILLA', |
364
|
|
|
'MARÍA PINTO' => 'MELIPILLA', |
365
|
|
|
'MAIPÚ' => 'MAIPÚ', |
366
|
|
|
'CERRILLOS' => 'MAIPÚ', |
367
|
|
|
'PADRE HURTADO' => 'MAIPÚ', |
368
|
|
|
'PEÑAFLOR' => 'MAIPÚ', |
369
|
|
|
'TALAGANTE' => 'MAIPÚ', |
370
|
|
|
'EL MONTE' => 'MAIPÚ', |
371
|
|
|
'ISLA DE MAIPO' => 'MAIPÚ', |
372
|
|
|
'LAS CONDES' => 'SANTIAGO ORIENTE', |
373
|
|
|
'VITACURA' => 'SANTIAGO ORIENTE', |
374
|
|
|
'LO BARNECHEA' => 'SANTIAGO ORIENTE', |
375
|
|
|
'ÑUÑOA' => 'ÑUÑOA', |
376
|
|
|
'LA REINA' => 'ÑUÑOA', |
377
|
|
|
'MACUL' => 'ÑUÑOA', |
378
|
|
|
'PEÑALOLÉN' => 'ÑUÑOA', |
379
|
|
|
'PROVIDENCIA' => 'PROVIDENCIA', |
380
|
|
|
'SAN MIGUEL' => 'SANTIAGO SUR', |
381
|
|
|
'LA CISTERNA' => 'SANTIAGO SUR', |
382
|
|
|
'SAN JOAQUÍN' => 'SANTIAGO SUR', |
383
|
|
|
'PEDRO AGUIRRE CERDA' => 'SANTIAGO SUR', |
384
|
|
|
'LO ESPEJO' => 'SANTIAGO SUR', |
385
|
|
|
'LA GRANJA' => 'SANTIAGO SUR', |
386
|
|
|
'LA PINTANA' => 'SANTIAGO SUR', |
387
|
|
|
'SAN RAMÓN' => 'SANTIAGO SUR', |
388
|
|
|
'LA FLORIDA' => 'LA FLORIDA', |
389
|
|
|
'PUENTE ALTO' => 'LA FLORIDA', |
390
|
|
|
'PIRQUE' => 'LA FLORIDA', |
391
|
|
|
'SAN JOSÉ DE MAIPO' => 'LA FLORIDA', |
392
|
|
|
'SAN BERNARDO' => 'SAN BERNARDO', |
393
|
|
|
'CALERA DE TANGO' => 'SAN BERNARDO', |
394
|
|
|
'EL BOSQUE' => 'SAN BERNARDO', |
395
|
|
|
'BUIN' => 'BUIN', |
396
|
|
|
'PAINE' => 'BUIN', |
397
|
|
|
]; /// Direcciones regionales del SII según la comuna |
398
|
|
|
|
399
|
|
|
/** |
400
|
|
|
* Método que permite asignar el nombre del servidor del SII que se |
401
|
|
|
* usará para las consultas al SII |
402
|
|
|
* @param servidor Servidor que se usará, si es https://maullin2.sii.cl, entonces se debe pasar como valor maullin2 |
403
|
|
|
* @param certificacion Permite definir si se está cambiando el servidor de certificación o el de producción |
404
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
405
|
|
|
* @version 2015-09-14 |
406
|
|
|
*/ |
407
|
|
|
public static function setServidor($servidor = 'maullin', $certificacion = Sii::CERTIFICACION) |
408
|
|
|
{ |
409
|
|
|
self::$config['servidor'][$certificacion] = $servidor; |
410
|
|
|
} |
411
|
|
|
|
412
|
|
|
/** |
413
|
|
|
* Método que entrega el nombre del servidor a usar según el ambiente |
414
|
|
|
* @param ambiente Ambiente que se desea obtener el servidor, si es null se autodetectará |
415
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
416
|
|
|
* @version 2016-08-01 |
417
|
|
|
*/ |
418
|
|
|
public static function getServidor($ambiente = null) |
419
|
|
|
{ |
420
|
|
|
return self::$config['servidor'][self::getAmbiente($ambiente)]; |
421
|
|
|
} |
422
|
|
|
|
423
|
|
|
/** |
424
|
|
|
* Método que entrega la URL de un recurso en el SII según el ambiente que se esté usando |
425
|
|
|
* @param recurso Recurso del sitio del SII que se desea obtener la URL |
426
|
|
|
* @param ambiente Ambiente que se desea obtener el servidor, si es null se autodetectará |
427
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
428
|
|
|
* @version 2017-09-11 |
429
|
|
|
*/ |
430
|
|
|
public static function getURL($recurso, $ambiente = null) |
431
|
|
|
{ |
432
|
|
|
return 'https://'.self::getServidor($ambiente).'.sii.cl'.$recurso; |
433
|
|
|
} |
434
|
|
|
|
435
|
|
|
/** |
436
|
|
|
* Método para obtener el WSDL |
437
|
|
|
* |
438
|
|
|
* \code{.php} |
439
|
|
|
* $wsdl = \sasco\LibreDTE\Sii::wsdl('CrSeed'); // WSDL para pedir semilla |
440
|
|
|
* \endcode |
441
|
|
|
* |
442
|
|
|
* Para forzar el uso del WSDL de certificación hay dos maneras, una es |
443
|
|
|
* pasando un segundo parámetro al método get con valor Sii::CERTIFICACION: |
444
|
|
|
* |
445
|
|
|
* \code{.php} |
446
|
|
|
* $wsdl = \sasco\LibreDTE\Sii::wsdl('CrSeed', \sasco\LibreDTE\Sii::CERTIFICACION); |
447
|
|
|
* \endcode |
448
|
|
|
* |
449
|
|
|
* La otra manera, para evitar este segundo parámetro, es asignar el valor a |
450
|
|
|
* través de la configuración: |
451
|
|
|
* |
452
|
|
|
* \code{.php} |
453
|
|
|
* \sasco\LibreDTE\Sii::setAmbiente(\sasco\LibreDTE\Sii::CERTIFICACION); |
454
|
|
|
* \endcode |
455
|
|
|
* |
456
|
|
|
* @param servicio Servicio por el cual se está solicitando su WSDL |
457
|
|
|
* @param ambiente Ambiente a usar: Sii::PRODUCCION o Sii::CERTIFICACION o null (para detección automática) |
458
|
|
|
* @return URL del WSDL del servicio según ambiente solicitado |
459
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
460
|
|
|
* @version 2016-06-11 |
461
|
|
|
*/ |
462
|
|
|
public static function wsdl($servicio, $ambiente = null) |
463
|
|
|
{ |
464
|
|
|
// determinar ambiente que se debe usar |
465
|
|
|
$ambiente = self::getAmbiente($ambiente); |
466
|
|
|
// entregar WSDL local (modificados para ambiente de certificación) |
467
|
|
|
if ($ambiente==self::CERTIFICACION) { |
468
|
|
|
$wsdl = dirname(dirname(__FILE__)).'/wsdl/'.self::$config['servidor'][$ambiente].'/'.$servicio.'.jws'; |
469
|
|
|
if (is_readable($wsdl)) |
470
|
|
|
return $wsdl; |
|
|
|
|
471
|
|
|
} |
472
|
|
|
// entregar WSDL oficial desde SII |
473
|
|
|
$location = isset(self::$config['wsdl'][$servicio]) ? self::$config['wsdl'][$servicio] : self::$config['wsdl']['*']; |
474
|
|
|
$wsdl = str_replace( |
475
|
|
|
['{servidor}', '{servicio}'], |
476
|
|
|
[self::$config['servidor'][$ambiente], $servicio], |
477
|
|
|
$location |
478
|
|
|
); |
479
|
|
|
// entregar wsdl |
480
|
|
|
return $wsdl; |
481
|
|
|
} |
482
|
|
|
|
483
|
|
|
/** |
484
|
|
|
* Método para realizar una solicitud al servicio web del SII |
485
|
|
|
* @param wsdl Nombre del WSDL que se usará |
486
|
|
|
* @param request Nombre de la función que se ejecutará en el servicio web |
487
|
|
|
* @param args Argumentos que se pasarán al servicio web |
488
|
|
|
* @param retry Intentos que se realizarán como máximo para obtener respuesta |
489
|
|
|
* @return Objeto SimpleXMLElement con la espuesta del servicio web consultado |
490
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
491
|
|
|
* @version 2016-08-28 |
492
|
|
|
*/ |
493
|
|
|
public static function request($wsdl, $request, $args = null, $retry = null) |
494
|
|
|
{ |
495
|
|
|
if (is_numeric($args)) { |
496
|
|
|
$retry = (int)$args; |
497
|
|
|
$args = null; |
498
|
|
|
} |
499
|
|
|
if (!$retry) |
500
|
|
|
$retry = self::$retry; |
501
|
|
|
if ($args and !is_array($args)) |
|
|
|
|
502
|
|
|
$args = [$args]; |
503
|
|
View Code Duplication |
if (!self::$verificar_ssl) { |
|
|
|
|
504
|
|
|
if (self::getAmbiente()==self::PRODUCCION) { |
505
|
|
|
$msg = Estado::get(Estado::ENVIO_SSL_SIN_VERIFICAR); |
506
|
|
|
\sasco\LibreDTE\Log::write(Estado::ENVIO_SSL_SIN_VERIFICAR, $msg, LOG_WARNING); |
|
|
|
|
507
|
|
|
} |
508
|
|
|
$options = ['stream_context' => stream_context_create([ |
509
|
|
|
'ssl' => [ |
510
|
|
|
'verify_peer' => false, |
511
|
|
|
'verify_peer_name' => false, |
512
|
|
|
'allow_self_signed' => true |
513
|
|
|
] |
514
|
|
|
])]; |
515
|
|
|
} else { |
516
|
|
|
$options = []; |
517
|
|
|
} |
518
|
|
|
try { |
519
|
|
|
$soap = new \SoapClient(self::wsdl($wsdl), $options); |
520
|
|
|
} catch (\Exception $e) { |
521
|
|
|
$msg = $e->getMessage(); |
522
|
|
View Code Duplication |
if (isset($e->getTrace()[0]['args'][1]) and is_string($e->getTrace()[0]['args'][1])) { |
|
|
|
|
523
|
|
|
$msg .= ': '.$e->getTrace()[0]['args'][1]; |
524
|
|
|
} |
525
|
|
|
\sasco\LibreDTE\Log::write(Estado::REQUEST_ERROR_SOAP, Estado::get(Estado::REQUEST_ERROR_SOAP, $msg)); |
|
|
|
|
526
|
|
|
return false; |
527
|
|
|
} |
528
|
|
|
for ($i=0; $i<$retry; $i++) { |
529
|
|
|
try { |
530
|
|
|
if ($args) { |
531
|
|
|
$body = call_user_func_array([$soap, $request], $args); |
532
|
|
|
} else { |
533
|
|
|
$body = $soap->$request(); |
534
|
|
|
} |
535
|
|
|
break; |
536
|
|
|
} catch (\Exception $e) { |
537
|
|
|
$msg = $e->getMessage(); |
538
|
|
View Code Duplication |
if (isset($e->getTrace()[0]['args'][1]) and is_string($e->getTrace()[0]['args'][1])) { |
|
|
|
|
539
|
|
|
$msg .= ': '.$e->getTrace()[0]['args'][1]; |
540
|
|
|
} |
541
|
|
|
\sasco\LibreDTE\Log::write(Estado::REQUEST_ERROR_SOAP, Estado::get(Estado::REQUEST_ERROR_SOAP, $msg)); |
|
|
|
|
542
|
|
|
$body = null; |
543
|
|
|
} |
544
|
|
|
} |
545
|
|
View Code Duplication |
if ($body===null) { |
|
|
|
|
546
|
|
|
\sasco\LibreDTE\Log::write(Estado::REQUEST_ERROR_BODY, Estado::get(Estado::REQUEST_ERROR_BODY, $wsdl, $retry)); |
|
|
|
|
547
|
|
|
return false; |
548
|
|
|
} |
549
|
|
|
return new \SimpleXMLElement($body, LIBXML_COMPACT); |
550
|
|
|
} |
551
|
|
|
|
552
|
|
|
/** |
553
|
|
|
* Método que permite indicar si se debe o no verificar el certificado SSL |
554
|
|
|
* del SII |
555
|
|
|
* @param verificar =true si se quiere verificar certificado, =false en caso que no (por defecto se verifica) |
556
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
557
|
|
|
* @version 2015-09-16 |
558
|
|
|
*/ |
559
|
|
|
public static function setVerificarSSL($verificar = true) |
560
|
|
|
{ |
561
|
|
|
self::$verificar_ssl = $verificar; |
562
|
|
|
} |
563
|
|
|
|
564
|
|
|
/** |
565
|
|
|
* Método que indica si se está o no verificando el SSL en las conexiones al SII |
566
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
567
|
|
|
* @version 2017-05-11 |
568
|
|
|
*/ |
569
|
|
|
public static function getVerificarSSL() |
570
|
|
|
{ |
571
|
|
|
return self::$verificar_ssl; |
572
|
|
|
} |
573
|
|
|
|
574
|
|
|
/** |
575
|
|
|
* Método que realiza el envío de un DTE al SII |
576
|
|
|
* Referencia: http://www.sii.cl/factura_electronica/factura_mercado/envio.pdf |
577
|
|
|
* @param usuario RUN del usuario que envía el DTE |
578
|
|
|
* @param empresa RUT de la empresa emisora del DTE |
579
|
|
|
* @param dte Documento XML con el DTE que se desea enviar a SII |
580
|
|
|
* @param token Token de autenticación automática ante el SII |
581
|
|
|
* @param gzip Permite enviar el archivo XML comprimido al servidor |
582
|
|
|
* @param retry Intentos que se realizarán como máximo para obtener respuesta |
583
|
|
|
* @return Respuesta XML desde SII o bien null si no se pudo obtener respuesta |
584
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
585
|
|
|
* @version 2017-10-23 |
586
|
|
|
*/ |
587
|
|
|
public static function enviar($usuario, $empresa, $dte, $token, $gzip = false, $retry = null) |
588
|
|
|
{ |
589
|
|
|
// definir datos que se usarán en el envío |
590
|
|
|
list($rutSender, $dvSender) = explode('-', str_replace('.', '', $usuario)); |
591
|
|
|
list($rutCompany, $dvCompany) = explode('-', str_replace('.', '', $empresa)); |
592
|
|
|
if (strpos($dte, '<?xml')===false) { |
593
|
|
|
$dte = '<?xml version="1.0" encoding="ISO-8859-1"?>'."\n".$dte; |
594
|
|
|
} |
595
|
|
View Code Duplication |
do { |
|
|
|
|
596
|
|
|
$file = sys_get_temp_dir().'/dte_'.md5(microtime().$token.$dte).'.'.($gzip?'gz':'xml'); |
597
|
|
|
} while (file_exists($file)); |
598
|
|
|
if ($gzip) { |
599
|
|
|
$dte = gzencode($dte); |
600
|
|
View Code Duplication |
if ($dte===false) { |
|
|
|
|
601
|
|
|
\sasco\LibreDTE\Log::write(Estado::ENVIO_ERROR_GZIP, Estado::get(Estado::ENVIO_ERROR_GZIP)); |
|
|
|
|
602
|
|
|
return false; |
603
|
|
|
} |
604
|
|
|
} |
605
|
|
|
file_put_contents($file, $dte); |
606
|
|
|
$data = [ |
607
|
|
|
'rutSender' => $rutSender, |
608
|
|
|
'dvSender' => $dvSender, |
609
|
|
|
'rutCompany' => $rutCompany, |
610
|
|
|
'dvCompany' => $dvCompany, |
611
|
|
|
'archivo' => curl_file_create( |
612
|
|
|
$file, |
613
|
|
|
$gzip ? 'application/gzip' : 'application/xml', |
614
|
|
|
basename($file) |
615
|
|
|
), |
616
|
|
|
]; |
617
|
|
|
// definir reintentos si no se pasaron |
618
|
|
|
if (!$retry) { |
619
|
|
|
$retry = self::$retry; |
620
|
|
|
} |
621
|
|
|
// crear sesión curl con sus opciones |
622
|
|
|
$curl = curl_init(); |
623
|
|
|
$header = [ |
624
|
|
|
'User-Agent: Mozilla/4.0 (compatible; PROG 1.0; LibreDTE)', |
625
|
|
|
'Referer: https://libredte.cl', |
626
|
|
|
'Cookie: TOKEN='.$token, |
627
|
|
|
]; |
628
|
|
|
$url = 'https://'.self::$config['servidor'][self::getAmbiente()].'.sii.cl/cgi_dte/UPL/DTEUpload'; |
629
|
|
|
curl_setopt($curl, CURLOPT_POST, true); |
630
|
|
|
curl_setopt($curl, CURLOPT_POSTFIELDS, $data); |
631
|
|
|
curl_setopt($curl, CURLOPT_HTTPHEADER, $header); |
632
|
|
|
curl_setopt($curl, CURLOPT_URL, $url); |
633
|
|
|
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); |
634
|
|
|
// si no se debe verificar el SSL se asigna opción a curl, además si |
635
|
|
|
// se está en el ambiente de producción y no se verifica SSL se |
636
|
|
|
// generará una entrada en el log |
637
|
|
View Code Duplication |
if (!self::$verificar_ssl) { |
|
|
|
|
638
|
|
|
if (self::getAmbiente()==self::PRODUCCION) { |
639
|
|
|
$msg = Estado::get(Estado::ENVIO_SSL_SIN_VERIFICAR); |
640
|
|
|
\sasco\LibreDTE\Log::write(Estado::ENVIO_SSL_SIN_VERIFICAR, $msg, LOG_WARNING); |
|
|
|
|
641
|
|
|
} |
642
|
|
|
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); |
643
|
|
|
} |
644
|
|
|
// enviar XML al SII |
645
|
|
View Code Duplication |
for ($i=0; $i<$retry; $i++) { |
|
|
|
|
646
|
|
|
$response = curl_exec($curl); |
647
|
|
|
if ($response and $response!='Error 500') { |
|
|
|
|
648
|
|
|
break; |
649
|
|
|
} |
650
|
|
|
} |
651
|
|
|
unlink($file); |
652
|
|
|
// verificar respuesta del envío y entregar error en caso que haya uno |
653
|
|
View Code Duplication |
if (!$response or $response=='Error 500') { |
|
|
|
|
654
|
|
|
if (!$response) { |
|
|
|
|
655
|
|
|
\sasco\LibreDTE\Log::write(Estado::ENVIO_ERROR_CURL, Estado::get(Estado::ENVIO_ERROR_CURL, curl_error($curl))); |
|
|
|
|
656
|
|
|
} |
657
|
|
|
if ($response=='Error 500') { |
658
|
|
|
\sasco\LibreDTE\Log::write(Estado::ENVIO_ERROR_500, Estado::get(Estado::ENVIO_ERROR_500)); |
|
|
|
|
659
|
|
|
} |
660
|
|
|
return false; |
661
|
|
|
} |
662
|
|
|
// cerrar sesión curl |
663
|
|
|
curl_close($curl); |
664
|
|
|
// crear XML con la respuesta y retornar |
665
|
|
|
try { |
666
|
|
|
$xml = new \SimpleXMLElement($response, LIBXML_COMPACT); |
667
|
|
|
} catch (Exception $e) { |
|
|
|
|
668
|
|
|
\sasco\LibreDTE\Log::write(Estado::ENVIO_ERROR_XML, Estado::get(Estado::ENVIO_ERROR_XML, $e->getMessage())); |
|
|
|
|
669
|
|
|
return false; |
670
|
|
|
} |
671
|
|
|
if ($xml->STATUS!=0) { |
672
|
|
|
\sasco\LibreDTE\Log::write( |
673
|
|
|
$xml->STATUS, |
674
|
|
|
Estado::get($xml->STATUS).(isset($xml->DETAIL)?'. '.implode("\n", (array)$xml->DETAIL->ERROR):'') |
|
|
|
|
675
|
|
|
); |
676
|
|
|
} |
677
|
|
|
return $xml; |
678
|
|
|
} |
679
|
|
|
|
680
|
|
|
/** |
681
|
|
|
* Método para obtener la clave pública (certificado X.509) del SII |
682
|
|
|
* |
683
|
|
|
* \code{.php} |
684
|
|
|
* $pub_key = \sasco\LibreDTE\Sii::cert(100); // Certificado IDK 100 (certificación) |
685
|
|
|
* \endcode |
686
|
|
|
* |
687
|
|
|
* @param idk IDK de la clave pública del SII. Si no se indica se tratará de determinar con el ambiente que se esté usando |
688
|
|
|
* @return Contenido del certificado |
689
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
690
|
|
|
* @version 2015-09-16 |
691
|
|
|
*/ |
692
|
|
|
public static function cert($idk = null) |
693
|
|
|
{ |
694
|
|
|
// si se pasó un idk y existe el archivo asociado se entrega |
695
|
|
|
if ($idk) { |
696
|
|
|
$cert = dirname(dirname(__FILE__)).'/certs/'.$idk.'.cer'; |
697
|
|
|
if (is_readable($cert)) |
698
|
|
|
return file_get_contents($cert); |
699
|
|
|
} |
700
|
|
|
// buscar certificado y entregar si existe o =false si no |
701
|
|
|
$ambiente = self::getAmbiente(); |
702
|
|
|
$cert = dirname(dirname(__FILE__)).'/certs/'.self::$config['certs'][$ambiente].'.cer'; |
703
|
|
|
if (!is_readable($cert)) { |
704
|
|
|
\sasco\LibreDTE\Log::write(Estado::SII_ERROR_CERTIFICADO, Estado::get(Estado::SII_ERROR_CERTIFICADO, self::$config['certs'][$ambiente])); |
|
|
|
|
705
|
|
|
return false; |
706
|
|
|
} |
707
|
|
|
return file_get_contents($cert); |
708
|
|
|
} |
709
|
|
|
|
710
|
|
|
/** |
711
|
|
|
* Método que asigna el ambiente que se usará por defecto (si no está |
712
|
|
|
* asignado con la constante _LibreDTE_CERTIFICACION_) |
713
|
|
|
* @param ambiente Ambiente a usar: Sii::PRODUCCION o Sii::CERTIFICACION |
714
|
|
|
* @warning No se está verificando SSL en ambiente de certificación |
715
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
716
|
|
|
* @version 2016-08-28 |
717
|
|
|
*/ |
718
|
|
|
public static function setAmbiente($ambiente = self::PRODUCCION) |
719
|
|
|
{ |
720
|
|
|
$ambiente = $ambiente ? self::CERTIFICACION : self::PRODUCCION; |
721
|
|
|
if ($ambiente==self::CERTIFICACION) { |
722
|
|
|
self::setVerificarSSL(false); |
723
|
|
|
} |
724
|
|
|
self::$ambiente = $ambiente; |
725
|
|
|
} |
726
|
|
|
|
727
|
|
|
/** |
728
|
|
|
* Método que determina el ambiente que se debe utilizar: producción o |
729
|
|
|
* certificación |
730
|
|
|
* @param ambiente Ambiente a usar: Sii::PRODUCCION o Sii::CERTIFICACION o null (para detección automática) |
731
|
|
|
* @return Ambiente que se debe utilizar |
732
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
733
|
|
|
* @version 2015-09-07 |
734
|
|
|
*/ |
735
|
|
|
public static function getAmbiente($ambiente = null) |
736
|
|
|
{ |
737
|
|
|
if ($ambiente===null) { |
738
|
|
|
if (defined('_LibreDTE_CERTIFICACION_')) |
739
|
|
|
$ambiente = (int)_LibreDTE_CERTIFICACION_; |
|
|
|
|
740
|
|
|
else |
741
|
|
|
$ambiente = self::$ambiente; |
|
|
|
|
742
|
|
|
} |
743
|
|
|
return $ambiente; |
744
|
|
|
} |
745
|
|
|
|
746
|
|
|
/** |
747
|
|
|
* Método que entrega la tasa de IVA vigente |
748
|
|
|
* @return Tasa de IVA vigente |
749
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
750
|
|
|
* @version 2015-09-03 |
751
|
|
|
*/ |
752
|
|
|
public static function getIVA() |
753
|
|
|
{ |
754
|
|
|
return self::IVA; |
755
|
|
|
} |
756
|
|
|
|
757
|
|
|
/** |
758
|
|
|
* Método que entrega un arreglo con todos los datos de los contribuyentes |
759
|
|
|
* que operan con factura electrónica descargados desde el SII |
760
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
761
|
|
|
* @version 2017-07-07 |
762
|
|
|
*/ |
763
|
|
|
public static function getContribuyentes(\sasco\LibreDTE\FirmaElectronica $Firma, $ambiente = null, $dia = null) |
764
|
|
|
{ |
765
|
|
|
// solicitar token |
766
|
|
|
$token = \sasco\LibreDTE\Sii\Autenticacion::getToken($Firma); |
|
|
|
|
767
|
|
|
if (!$token) |
|
|
|
|
768
|
|
|
return false; |
769
|
|
|
// definir ambiente y servidor |
770
|
|
|
$ambiente = self::getAmbiente($ambiente); |
771
|
|
|
$servidor = self::$config['servidor'][$ambiente]; |
772
|
|
|
// preparar consulta curl |
773
|
|
|
$curl = curl_init(); |
774
|
|
|
$header = [ |
775
|
|
|
'User-Agent: Mozilla/4.0 (compatible; PROG 1.0; LibreDTE)', |
776
|
|
|
'Referer: https://'.$servidor.'.sii.cl/cvc/dte/ee_empresas_dte.html', |
777
|
|
|
'Cookie: TOKEN='.$token, |
778
|
|
|
'Accept-Encoding' => 'gzip, deflate, sdch', |
779
|
|
|
]; |
780
|
|
|
$dia = $dia===null ? date('Ymd') : str_replace('-', '', $dia); |
781
|
|
|
$url = 'https://'.$servidor.'.sii.cl/cvc_cgi/dte/ce_empresas_dwnld?NOMBRE_ARCHIVO=ce_empresas_dwnld_'.$dia.'.csv'; |
782
|
|
|
curl_setopt($curl, CURLOPT_HTTPHEADER, $header); |
783
|
|
|
curl_setopt($curl, CURLOPT_URL, $url); |
784
|
|
|
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); |
785
|
|
|
// si no se debe verificar el SSL se asigna opción a curl, además si |
786
|
|
|
// se está en el ambiente de producción y no se verifica SSL se |
787
|
|
|
// generará un error de nivel E_USER_NOTICE |
788
|
|
View Code Duplication |
if (!self::$verificar_ssl) { |
|
|
|
|
789
|
|
|
if ($ambiente==self::PRODUCCION) { |
790
|
|
|
$msg = Estado::get(Estado::ENVIO_SSL_SIN_VERIFICAR); |
791
|
|
|
\sasco\LibreDTE\Log::write(Estado::ENVIO_SSL_SIN_VERIFICAR, $msg, LOG_WARNING); |
|
|
|
|
792
|
|
|
} |
793
|
|
|
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); |
794
|
|
|
} |
795
|
|
|
// realizar consulta curl |
796
|
|
|
$response = curl_exec($curl); |
797
|
|
|
if (!$response) |
798
|
|
|
return false; |
799
|
|
|
// cerrar sesión curl |
800
|
|
|
curl_close($curl); |
801
|
|
|
// entregar datos del archivo CSV |
802
|
|
|
ini_set('memory_limit', '1024M'); |
803
|
|
|
$lines = explode("\n", $response); |
804
|
|
|
$n_lines = count($lines); |
805
|
|
|
$data = []; |
806
|
|
|
for ($i=1; $i<$n_lines; $i++) { |
807
|
|
|
$row = str_getcsv($lines[$i], ';', ''); |
808
|
|
|
unset($lines[$i]); |
809
|
|
|
if (!isset($row[5])) |
810
|
|
|
continue; |
811
|
|
|
for ($j=0; $j<6; $j++) |
812
|
|
|
$row[$j] = trim($row[$j]); |
813
|
|
|
$row[1] = utf8_decode($row[1]); |
814
|
|
|
$row[4] = strtolower($row[4]); |
815
|
|
|
$row[5] = strtolower($row[5]); |
816
|
|
|
$data[] = $row; |
817
|
|
|
} |
818
|
|
|
return $data; |
819
|
|
|
} |
820
|
|
|
|
821
|
|
|
/** |
822
|
|
|
* Método que entrega la dirección regional según la comuna que se esté |
823
|
|
|
* consultando |
824
|
|
|
* @param comuna de la sucursal del emior o bien código de la sucursal del SII |
825
|
|
|
* @return Dirección regional del SII |
826
|
|
|
* @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) |
827
|
|
|
* @version 2017-11-07 |
828
|
|
|
*/ |
829
|
|
|
public static function getDireccionRegional($comuna) |
830
|
|
|
{ |
831
|
|
|
if (!$comuna) { |
832
|
|
|
return 'N.N.'; |
|
|
|
|
833
|
|
|
} |
834
|
|
|
if (!is_numeric($comuna)) { |
835
|
|
|
$direccion = mb_strtoupper($comuna, 'UTF-8'); |
836
|
|
|
return isset(self::$direcciones_regionales[$direccion]) ? self::$direcciones_regionales[$direccion] : $direccion; |
837
|
|
|
} |
838
|
|
|
return 'SUC '.$comuna; |
|
|
|
|
839
|
|
|
} |
840
|
|
|
|
841
|
|
|
} |
842
|
|
|
|
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.