/** * Método que verifica el código de autorización de folios * @return =true si está ok el XML cargado * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-10-30 */ public function check() { // validar firma del SII sobre los folios $firma = $this->getFirma(); $idk = $this->getIDK(); if (!$firma or !$idk) { return false; } $pub_key = \sasco\LibreDTE\Sii::cert($idk); if (!$pub_key or openssl_verify($this->xml->getFlattened('/AUTORIZACION/CAF/DA'), base64_decode($firma), $pub_key) !== 1) { \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::FOLIOS_ERROR_FIRMA, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::FOLIOS_ERROR_FIRMA)); return false; } // validar clave privada y pública proporcionada por el SII $private_key = $this->getPrivateKey(); if (!$private_key) { return false; } $plain = md5(date('U')); if (!openssl_private_encrypt($plain, $crypt, $private_key)) { \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::FOLIOS_ERROR_ENCRIPTAR, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::FOLIOS_ERROR_ENCRIPTAR)); return false; } $public_key = $this->getPublicKey(); if (!$public_key) { return false; } if (!openssl_public_decrypt($crypt, $plain_firmado, $public_key)) { \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::FOLIOS_ERROR_DESENCRIPTAR, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::FOLIOS_ERROR_DESENCRIPTAR)); return false; } return $plain === $plain_firmado; }
public function caso3() { \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::ENVIO_USUARIO_INCORRECTO, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::ENVIO_USUARIO_INCORRECTO)); \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::ENVIO_ERROR_XML, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::ENVIO_ERROR_XML, 'No hay XML')); \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::REQUEST_ERROR_BODY, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::REQUEST_ERROR_BODY, 'getToken', 10)); \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::ENVIO_NO_AUTENTICADO, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::ENVIO_NO_AUTENTICADO)); }
/** * Método que genera el XML para el envío de la respuesta al SII * @param caratula Arreglo con la carátula de la respuesta * @param Firma Objeto con la firma electrónica * @return XML con la respuesta firmada o =false si no se pudo generar o firmar la respuesta * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-17 */ public function generar() { // si ya se había generado se entrega directamente if ($this->xml_data) { return $this->xml_data; } // si no hay respuestas para generar entregar falso if (!isset($this->recibos[0])) { \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::ENVIORECIBOS_FALTA_RECIBO, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::ENVIORECIBOS_FALTA_RECIBO)); return false; } // si no hay carátula error if (!$this->caratula) { \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::ENVIORECIBOS_FALTA_CARATULA, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::ENVIORECIBOS_FALTA_CARATULA)); return false; } // crear arreglo de lo que se enviará $xmlEnvio = (new \sasco\LibreDTE\XML())->generate(['EnvioRecibos' => ['@attributes' => ['xmlns' => 'http://www.sii.cl/SiiDte', 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:schemaLocation' => 'http://www.sii.cl/SiiDte EnvioRecibos_v10.xsd', 'version' => '1.0'], 'SetRecibos' => ['@attributes' => ['ID' => 'SetDteRecibidos'], 'Caratula' => $this->caratula, 'Recibo' => null]]])->saveXML(); // generar cada recibo y firmar $Recibos = []; foreach ($this->recibos as &$recibo) { $recibo_xml = new \sasco\LibreDTE\XML(); $recibo_xml->generate(['Recibo' => $recibo]); $recibo_firmado = $this->Firma ? $this->Firma->signXML($recibo_xml->saveXML(), '#' . $recibo['DocumentoRecibo']['@attributes']['ID'], 'DocumentoRecibo', true) : $recibo_xml->saveXML(); $Recibos[] = trim(str_replace('<?xml version="1.0" encoding="ISO-8859-1"?>', '', $recibo_firmado)); } // firmar XML del envío y entregar $xml = str_replace('<Recibo/>', implode("\n", $Recibos), $xmlEnvio); $this->xml_data = $this->Firma ? $this->Firma->signXML($xml, '#SetDteRecibidos', 'SetRecibos', true) : $xml; return $this->xml_data; }
/** * Método que realiza el envío del documento al SII * @return Track ID del envío o =false si hubo algún problema al enviar el documento * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-12-14 */ public function enviar() { // generar XML que se enviará if (!$this->xml_data) { $this->xml_data = $this->generar(); } if (!$this->xml_data) { \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::DOCUMENTO_ERROR_GENERAR_XML, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::DOCUMENTO_ERROR_GENERAR_XML, substr(get_class($this), strrpos(get_class($this), '\\') + 1))); return false; } // validar schema del documento antes de enviar if (!$this->schemaValidate()) { return false; } // solicitar token $token = \sasco\LibreDTE\Sii\Autenticacion::getToken($this->Firma); if (!$token) { return false; } // enviar DTE $envia = $this->caratula['RutEnvia']; $emisor = !empty($this->caratula['RutEmisor']) ? $this->caratula['RutEmisor'] : $this->caratula['RutEmisorLibro']; $result = \sasco\LibreDTE\Sii::enviar($envia, $emisor, $this->xml_data, $token); if ($result === false) { return false; } if (!is_numeric((string) $result->TRACKID)) { return false; } return (int) (string) $result->TRACKID; }
/** * Método que valida el XML que se genera para la respuesta del envío * @return =true si el schema del documento del envío es válido, =null si no se pudo determinar * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-17 */ public function schemaValidate() { if (!$this->xml_data) { return null; } $xsd = dirname(dirname(dirname(__FILE__))) . '/schemas/EnvioRecibos_v10.xsd'; $this->xml = new \sasco\LibreDTE\XML(); $this->xml->loadXML($this->xml_data); $result = $this->xml->schemaValidate($xsd); if (!$result) { \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::ENVIORECIBOS_ERROR_SCHEMA, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::ENVIORECIBOS_ERROR_SCHEMA, implode("\n", libxml_get_errors()))); } return $result; }
/** * Método para obtener la clave pública (certificado X.509) del SII * * \code{.php} * $pub_key = \sasco\LibreDTE\Sii::cert(100); // Certificado IDK 100 (certificación) * \endcode * * @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 * @return Contenido del certificado * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-16 */ public static function cert($idk = null) { // si se pasó un idk y existe el archivo asociado se entrega if ($idk) { $cert = dirname(dirname(__FILE__)) . '/certs/' . $idk . '.cer'; if (is_readable($cert)) { return file_get_contents($cert); } } // buscar certificado y entregar si existe o =false si no $ambiente = self::getAmbiente(); $cert = dirname(dirname(__FILE__)) . '/certs/' . self::$config['certs'][$ambiente] . '.cer'; if (!is_readable($cert)) { \sasco\LibreDTE\Log::write(Estado::SII_ERROR_CERTIFICADO, Estado::get(Estado::SII_ERROR_CERTIFICADO, self::$config['certs'][$ambiente])); return false; } return file_get_contents($cert); }
/** * Método para generar un error usando una excepción de SowerPHP o terminar * el script si no se está usando el framework * @param msg Mensaje del error * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-17 */ private function error($msg) { $msg = Estado::get(Estado::FIRMA_ERROR, $msg); if (class_exists('\\sowerphp\\core\\Exception')) { throw new \sowerphp\core\Exception($msg); } else { \sasco\LibreDTE\Log::write(Estado::FIRMA_ERROR, $msg); } return false; }
/** * Método para obtener el token de la sesión a través de una semilla * previamente firmada * * WSDL producción: https://palena.sii.cl/DTEWS/GetTokenFromSeed.jws?WSDL * WSDL certificación: https://maullin.sii.cl/DTEWS/GetTokenFromSeed.jws?WSDL * * @param Firma objeto de la Firma electrónica o arreglo con configuración de la misma * @return Token para autenticación en SII o =false si no se pudo obtener * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-17 */ public static function getToken($Firma = []) { $semilla = self::getSeed(); if (!$semilla) { return false; } $requestFirmado = self::getTokenRequest($semilla, $Firma); if (!$requestFirmado) { return false; } $xml = \sasco\LibreDTE\Sii::request('GetTokenFromSeed', 'getToken', $requestFirmado); if ($xml === false or (string) $xml->xpath('/SII:RESPUESTA/SII:RESP_HDR/ESTADO')[0] !== '00') { \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::AUTH_ERROR_TOKEN, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::AUTH_ERROR_TOKEN)); return false; } return (string) $xml->xpath('/SII:RESPUESTA/SII:RESP_BODY/TOKEN')[0]; }
/** * Método que realiza la firma del DTE * @param Firma objeto que representa la Firma Electrónca * @return =true si el DTE pudo ser fimado o =false si no se pudo firmar * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-17 */ public function firmar(\sasco\LibreDTE\FirmaElectronica $Firma) { $parent = $this->xml->getElementsByTagName($this->tipo_general)->item(0); $this->xml->generate(['TmstFirma' => $this->timestamp], $parent); $xml = $Firma->signXML($this->xml->saveXML(), '#' . $this->id, $this->tipo_general); if (!$xml) { \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::DTE_ERROR_FIRMA, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::DTE_ERROR_FIRMA, $this->getID())); return false; } $this->loadXML($xml); return true; }
/** * Método que valida el XML que se genera para la respuesta del envío * @return =true si el schema del documento del envío es válido, =null si no se pudo determinar * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-18 */ public function schemaValidate() { if (!$this->xml_data) { \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::LIBROCOMPRAVENTA_FALTA_XML, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::LIBROCOMPRAVENTA_FALTA_XML)); return null; } $xsd = dirname(dirname(dirname(__FILE__))) . '/schemas/LibroCVS_v10.xsd'; $this->xml = new \sasco\LibreDTE\XML(); $this->xml->loadXML($this->xml_data); $result = $this->xml->schemaValidate($xsd); if (!$result) { \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::LIBROCOMPRAVENTA_ERROR_SCHEMA, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::LIBROCOMPRAVENTA_ERROR_SCHEMA, implode("\n", $this->xml->getErrors()))); } return $result; }
/** * Método que entrega un arreglo con todos los datos de los contribuyentes * que operan con factura electrónica descargados desde el SII * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-30 */ public static function getContribuyentes(\sasco\LibreDTE\FirmaElectronica $Firma, $ambiente = null) { // solicitar token $token = \sasco\LibreDTE\Sii\Autenticacion::getToken($Firma); if (!$token) { return false; } // definir ambiente y servidor $ambiente = self::getAmbiente($ambiente); $servidor = self::$config['servidor'][$ambiente]; // preparar consulta curl $curl = curl_init(); $header = ['User-Agent: Mozilla/4.0 (compatible; PROG 1.0; Windows NT 5.0; YComp 5.0.2.4)', 'Referer: https://' . $servidor . '.sii.cl/cvc/dte/ee_empresas_dte.html', 'Cookie: TOKEN=' . $token, 'Accept-Encoding' => 'gzip, deflate, sdch']; $url = 'https://' . $servidor . '.sii.cl/cvc_cgi/dte/ee_consulta_empresas_dwnld?NOMBRE_ARCHIVO=ce_empresas_dwnld_' . date('Ymd') . '.csv'; curl_setopt($curl, CURLOPT_HTTPHEADER, $header); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // si no se debe verificar el SSL se asigna opción a curl, además si // se está en el ambiente de producción y no se verifica SSL se // generará un error de nivel E_USER_NOTICE if (!self::$verificar_ssl) { if ($ambiente == self::PRODUCCION) { $msg = Estado::get(Estado::ENVIO_SSL_SIN_VERIFICAR); trigger_error($msg, E_USER_NOTICE); \sasco\LibreDTE\Log::write(Estado::ENVIO_SSL_SIN_VERIFICAR, $msg, LOG_WARNING); } curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); } // realizar consulta curl $response = curl_exec($curl); if (!$response) { return false; } // cerrar sesión curl curl_close($curl); // entregar datos del archivo CSV ini_set('memory_limit', '1024M'); $lines = explode("\n", $response); $n_lines = count($lines); $data = []; for ($i = 1; $i < $n_lines; $i++) { $row = str_getcsv($lines[$i], ';', ''); unset($lines[$i]); if (!isset($row[5])) { continue; } for ($j = 0; $j < 6; $j++) { $row[$j] = trim($row[$j]); } $row[1] = utf8_decode($row[1]); $row[4] = strtolower($row[4]); $row[5] = strtolower($row[5]); $data[] = $row; } return $data; }
/** * Método que empaqueta y comprime archivos (uno o varios, o directorios). * Si se pide usar formato zip entonces se usará ZipArchive de PHP para * comprimir * @param filepath Directorio (o archivo) que se desea comprimir * @param options Arreglo con opciones para comprmir (format, download, delete) * @todo Preparar datos si se pasa un arreglo * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]delaf.cl) * @version 2015-11-03 */ public static function compress($file, $options = []) { // definir opciones por defecto $options = array_merge(['format' => 'gz', 'delete' => false, 'download' => true, 'commands' => ['gz' => 'gzip --keep :in', 'tar.gz' => 'tar czf :in.tar.gz :in', 'tar' => 'tar cf :in.tar :in', 'bz2' => 'bzip2 --keep :in', 'tar.bz2' => 'tar cjf :in.tar.bz2 :in', 'zip' => 'zip -r :in.zip :in']], $options); // si el archivo no se puede leer se entrega =false if (!is_readable($file)) { \sasco\LibreDTE\Log::write(Estado::COMPRESS_ERROR_READ, Estado::get(Estado::COMPRESS_ERROR_READ)); return false; } // si es formato gz y es directorio se cambia a tgz if (is_dir($file)) { if ($options['format'] == 'gz') { $options['format'] = 'tar.gz'; } else { if ($options['format'] == 'bz2') { $options['format'] = 'tar.bz2'; } } } // obtener directorio que contiene al archivo/directorio y el nombre de este $filepath = $file; $dir = dirname($file); $file = basename($file); $file_compressed = $file . '.' . $options['format']; // empaquetar/comprimir directorio/archivo if ($options['format'] == 'zip') { // crear archivo zip $zip = new \ZipArchive(); if ($zip->open($dir . DIRECTORY_SEPARATOR . $file . '.zip', \ZipArchive::CREATE) !== true) { \sasco\LibreDTE\Log::write(Estado::COMPRESS_ERROR_ZIP, Estado::get(Estado::COMPRESS_ERROR_ZIP)); return false; } // agregar un único archivo al zip if (!is_dir($filepath)) { $zip->addFile($filepath, $file); } else { if (is_dir($filepath)) { $Iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($filepath)); foreach ($Iterator as $f) { if (!$f->isDir()) { $path = $f->getPath() . DIRECTORY_SEPARATOR . $f->getFilename(); $zip->addFile($path, str_replace($filepath, '', $file . DIRECTORY_SEPARATOR . $path)); } } } } // escribir en el sistema de archivos y cerrar archivo file_put_contents($dir . DIRECTORY_SEPARATOR . $file_compressed, $zip->getStream(md5($filepath))); $zip->close(); } else { exec('cd ' . $dir . ' && ' . str_replace(':in', $file, $options['commands'][$options['format']])); } // enviar archivo if ($options['download']) { ob_clean(); header('Content-Disposition: attachment; filename=' . $file_compressed); $mimetype = self::mimetype($dir . DIRECTORY_SEPARATOR . $file_compressed); if ($mimetype) { header('Content-Type: ' . $mimetype); } header('Content-Length: ' . filesize($dir . DIRECTORY_SEPARATOR . $file_compressed)); readfile($dir . DIRECTORY_SEPARATOR . $file_compressed); unlink($dir . DIRECTORY_SEPARATOR . $file_compressed); } // borrar directorio o archivo que se está comprimiendo si así se ha // solicitado if ($options['delete']) { if (is_dir($filepath)) { self::rmdir($filepath); } else { unlink($filepath); } } }
/** * Método que valida el XML del documento * @return =true si el schema del documento del envío es válido, =null si no se pudo determinar * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-12-14 */ public function schemaValidate() { if (!$this->xml_data) { \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::DOCUMENTO_FALTA_XML, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::DOCUMENTO_FALTA_XML, substr(get_class($this), strrpos(get_class($this), '\\') + 1))); return null; } $this->xml = new \sasco\LibreDTE\XML(); $this->xml->loadXML($this->xml_data); $xsd = dirname(dirname(dirname(dirname(__FILE__)))) . '/schemas/' . $this->xml->getSchema(); if (!is_readable($xsd)) { return null; } $result = $this->xml->schemaValidate($xsd); if (!$result) { \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::DOCUMENTO_ERROR_SCHEMA, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::DOCUMENTO_ERROR_SCHEMA, substr(get_class($this), strrpos(get_class($this), '\\') + 1), implode("\n", $this->xml->getErrors()))); } return $result; }
/** * Método que valida el XML que se genera para la respuesta del envío * @return =true si el schema del documento del envío es válido, =null si no se pudo determinar * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-18 */ public function schemaValidate() { if (!$this->xml_data) { return null; } $xsd = dirname(dirname(dirname(__FILE__))) . '/schemas/RespuestaEnvioDTE_v10.xsd'; $this->xml = new \sasco\LibreDTE\XML(); $this->xml->loadXML($this->xml_data); $result = $this->xml->schemaValidate($xsd); if (!$result) { \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::RESPUESTAENVIO_ERROR_SCHEMA, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::RESPUESTAENVIO_ERROR_SCHEMA, implode("\n", $this->xml->getErrors()))); } return $result; }
/** * Método que entrega el arreglo con los objetos DTE del envío * @return Arreglo de objetos DTE * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-17 */ public function getDocumentos() { // si no hay documentos se deben crear if (!$this->dtes) { // si no hay XML no se pueden crear los documentos if (!$this->xml) { \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::ENVIODTE_GETDOCUMENTOS_FALTA_XML, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::ENVIODTE_GETDOCUMENTOS_FALTA_XML)); return false; } // crear documentos a partir del XML $DTEs = $this->xml->getElementsByTagName('DTE'); foreach ($DTEs as $nodo_dte) { $this->dtes[] = new Dte($nodo_dte->C14N(), false); // cargar DTE sin normalizar } } return $this->dtes; }
/** * Método que genera el XML para el envío de la respuesta al SII * @param caratula Arreglo con la carátula de la respuesta * @param Firma Objeto con la firma electrónica * @return XML con la respuesta firmada o =false si no se pudo generar o firmar la respuesta * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-17 */ public function generar() { // si ya se había generado se entrega directamente if ($this->xml_data) { return $this->xml_data; } // si no hay respuestas para generar entregar falso if (!isset($this->respuesta_envios[0]) and !isset($this->respuesta_documentos[0])) { \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::RESPUESTAENVIO_FALTA_RESPUESTA, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::RESPUESTAENVIO_FALTA_RESPUESTA)); return false; } // si no hay carátula error if (!$this->caratula) { \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::RESPUESTAENVIO_FALTA_CARATULA, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::RESPUESTAENVIO_FALTA_CARATULA)); return false; } // crear arreglo de lo que se enviará $arreglo = ['RespuestaDTE' => ['@attributes' => ['xmlns' => 'http://www.sii.cl/SiiDte', 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:schemaLocation' => 'http://www.sii.cl/SiiDte RespuestaEnvioDTE_v10.xsd', 'version' => '1.0'], 'Resultado' => ['@attributes' => ['ID' => 'ResultadoEnvio'], 'Caratula' => $this->caratula]]]; if (isset($this->respuesta_envios[0])) { $arreglo['RespuestaDTE']['Resultado']['RecepcionEnvio'] = $this->respuesta_envios; } else { $arreglo['RespuestaDTE']['Resultado']['ResultadoDTE'] = $this->respuesta_documentos; } // generar XML del envío $xmlEnvio = (new \sasco\LibreDTE\XML())->generate($arreglo)->saveXML(); // firmar XML del envío y entregar $this->xml_data = $this->Firma ? $this->Firma->signXML($xmlEnvio, '#ResultadoEnvio', 'Resultado', true) : $xmlEnvio; return $this->xml_data; }