/** * 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; }
/** * Recurso de la API que permite validar el TED (timbre electrónico) * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-19 */ public function _api_verificar_ted_POST() { // verificar si se pasaron credenciales de un usuario $User = $this->Api->getAuthUser(); if (is_string($User)) { $this->Api->send($User, 401); } // obtener TED $TED = base64_decode($this->Api->data); if (strpos($TED, '<?xml') !== 0) { $TED = '<?xml version="1.0" encoding="ISO-8859-1"?>' . "\n" . $TED; } // crear xml con el ted y obtener datos en arreglo $xml = new \sasco\LibreDTE\XML(); $xml->loadXML($TED); $datos = $xml->toArray(); // verificar firma del ted $DD = $xml->getFlattened('/TED/DD'); $FRMT = $datos['TED']['FRMT']; $pub_key = \sasco\LibreDTE\FirmaElectronica::getFromModulusExponent($datos['TED']['DD']['CAF']['DA']['RSAPK']['M'], $datos['TED']['DD']['CAF']['DA']['RSAPK']['E']); if (openssl_verify($DD, base64_decode($FRMT), $pub_key, OPENSSL_ALGO_SHA1) !== 1) { $this->Api->send('Firma del timbre incorrecta', 500); } // verificar que datos del timbre correspondan con datos del CAF if ($datos['TED']['DD']['RE'] != $datos['TED']['DD']['CAF']['DA']['RE']) { $this->Api->send('RUT del timbre no corresponde con RUT del CAF', 500); } if ($datos['TED']['DD']['TD'] != $datos['TED']['DD']['CAF']['DA']['TD']) { $this->Api->send('Tipo de DTE del timbre no corresponde con tipo de DTE del CAF', 500); } if ($datos['TED']['DD']['F'] < $datos['TED']['DD']['CAF']['DA']['RNG']['D'] or $datos['TED']['DD']['F'] > $datos['TED']['DD']['CAF']['DA']['RNG']['H']) { $this->Api->send('Folio del DTE del timbre fuera del rango del CAF', 500); } // definir si se consultará en certificación o producción define('_LibreDTE_CERTIFICACION_', $datos['TED']['DD']['CAF']['DA']['IDK'] == 100); // crear objeto firma $Firma = new \sasco\LibreDTE\FirmaElectronica(); // obtener token $token = \sasco\LibreDTE\Sii\Autenticacion::getToken($Firma); if (!$token) { return $this->Api->send(\sasco\LibreDTE\Log::readAll(), 500); } // verificar estado del DTE con el SII list($RutConsultante, $DvConsultante) = explode('-', $Firma->getID()); list($RutCompania, $DvCompania) = explode('-', $datos['TED']['DD']['RE']); list($RutReceptor, $DvReceptor) = explode('-', $datos['TED']['DD']['RR']); list($a, $m, $d) = explode('-', $datos['TED']['DD']['FE']); $xml = \sasco\LibreDTE\Sii::request('QueryEstDte', 'getEstDte', ['RutConsultante' => $RutConsultante, 'DvConsultante' => $DvConsultante, 'RutCompania' => $RutCompania, 'DvCompania' => $DvCompania, 'RutReceptor' => $RutReceptor, 'DvReceptor' => $DvReceptor, 'TipoDte' => $datos['TED']['DD']['TD'], 'FolioDte' => $datos['TED']['DD']['F'], 'FechaEmisionDte' => $d . $m . $a, 'MontoDte' => $datos['TED']['DD']['MNT'], 'token' => $token]); if ($xml === false) { return $this->Api->send(\sasco\LibreDTE\Log::readAll(), 500); } return (array) $xml->xpath('/SII:RESPUESTA/SII:RESP_HDR')[0]; }