Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like Sii often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Sii, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
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) |
||
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) |
||
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) |
||
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) |
||
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() |
||
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) |
||
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) |
||
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) |
||
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() |
||
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) |
||
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) |
||
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.