/** * 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 EnvioRecibo_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 timbrado del DTE * @param Folios Objeto de los Folios con los que se desea timbrar * @return =true si se pudo timbrar o =false en caso de error * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-17 */ public function timbrar(Folios $Folios) { // verificar que el folio que se está usando para el DTE esté dentro // del rango de folios autorizados que se usarán para timbrar // Esta validación NO verifica si el folio ya fue usado, sólo si está // dentro del CAF que se está usando $folio = $this->xml->xpath('/DTE/' . $this->tipo_general . '/Encabezado/IdDoc/Folio')->item(0)->nodeValue; if ($folio < $Folios->getDesde() or $folio > $Folios->getHasta()) { \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::DTE_ERROR_RANGO_FOLIO, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::DTE_ERROR_RANGO_FOLIO, $this->getID())); return false; } // verificar que existan datos para el timbre if (!$this->xml->xpath('/DTE/' . $this->tipo_general . '/Encabezado/IdDoc/FchEmis')->item(0)) { \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::DTE_FALTA_FCHEMIS, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::DTE_FALTA_FCHEMIS, $this->getID())); \sasco\LibreDTE\Log::write('Falta FchEmis del DTE ' . $this->getID()); return false; } if (!$this->xml->xpath('/DTE/' . $this->tipo_general . '/Encabezado/Totales/MntTotal')->item(0)) { \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::DTE_FALTA_MNTTOTAL, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::DTE_FALTA_MNTTOTAL, $this->getID())); return false; } // timbrar $TED = new \sasco\LibreDTE\XML(); $TED->generate(['TED' => ['@attributes' => ['version' => '1.0'], 'DD' => ['RE' => $this->xml->xpath('/DTE/' . $this->tipo_general . '/Encabezado/Emisor/RUTEmisor')->item(0)->nodeValue, 'TD' => $this->xml->xpath('/DTE/' . $this->tipo_general . '/Encabezado/IdDoc/TipoDTE')->item(0)->nodeValue, 'F' => $folio, 'FE' => $this->xml->xpath('/DTE/' . $this->tipo_general . '/Encabezado/IdDoc/FchEmis')->item(0)->nodeValue, 'RR' => $this->xml->xpath('/DTE/' . $this->tipo_general . '/Encabezado/Receptor/RUTRecep')->item(0)->nodeValue, 'RSR' => substr($this->xml->xpath('/DTE/' . $this->tipo_general . '/Encabezado/Receptor/RznSocRecep')->item(0)->nodeValue, 0, 40), 'MNT' => $this->xml->xpath('/DTE/' . $this->tipo_general . '/Encabezado/Totales/MntTotal')->item(0)->nodeValue, 'IT1' => substr($this->xml->xpath('/DTE/' . $this->tipo_general . '/Detalle')->item(0)->getElementsByTagName('NmbItem')->item(0)->nodeValue, 0, 40), 'CAF' => $Folios->getCaf(), 'TSTED' => $this->timestamp], 'FRMT' => ['@attributes' => ['algoritmo' => 'SHA1withRSA']]]]); $DD = $TED->getFlattened('/TED/DD'); if (openssl_sign($DD, $timbre, $Folios->getPrivateKey(), OPENSSL_ALGO_SHA1) == false) { \sasco\LibreDTE\Log::write(\sasco\LibreDTE\Estado::DTE_ERROR_TIMBRE, \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::DTE_ERROR_TIMBRE, $this->getID())); return false; } $TED->getElementsByTagName('FRMT')->item(0)->nodeValue = base64_encode($timbre); $xml = str_replace('<TED/>', trim(str_replace('<?xml version="1.0" encoding="ISO-8859-1"?>', '', $TED->saveXML())), $this->saveXML()); $this->loadXML($xml); return true; }