/** * Método principal del comando * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-12-15 */ public function main() { // cargar XML y extraer arreglo con datos de carátula y DTEs $EnvioDte = new \sasco\LibreDTE\Sii\EnvioDte(); $EnvioDte->loadXML(file_get_contents($this->args['xml'])); $Caratula = $EnvioDte->getCaratula(); $Documentos = $EnvioDte->getDocumentos(); // procesar cada DTEs e ir creando los archivos PDF foreach ($Documentos as $DTE) { if (!$DTE->getDatos()) { $this->error('No se pudieron obtener los datos de uno de los DTE del XML'); } $this->out('Generando PDF para DTE ' . $DTE->getID()); $pdf = new \sasco\LibreDTE\Sii\PDF\Dte($this->args['papel']); $pdf->setFooterText(); if ($this->args['logo']) { $pdf->setLogo($this->args['logo']); } $pdf->setResolucion(['FchResol' => $Caratula['FchResol'], 'NroResol' => $Caratula['NroResol']]); $pdf->setWebVerificacion($this->args['web']); $pdf->agregar($DTE->getDatos(), $DTE->getTED()); if (isset($this->args['cedible'])) { $pdf->setCedible(true); $pdf->agregar($DTE->getDatos(), $DTE->getTED()); } $pdf->Output($this->args['dir'] . '/dte_' . $Caratula['RutEmisor'] . '_' . $DTE->getID() . '.pdf', 'F'); } return 0; }
* * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-16 */ // respuesta en texto plano header('Content-type: text/plain; charset=ISO-8859-1'); // incluir archivos php de la biblioteca y configuraciones include 'inc.php'; // datos para validar $archivo_recibido = 'xml/intercambio/ENVIO_DTE_420328.xml'; $RutReceptor_esperado = '76192083-9'; $RutEmisor_esperado = '88888888-8'; // Cargar EnvioDTE y extraer arreglo con datos de carátula y DTEs $EnvioDte = new \sasco\LibreDTE\Sii\EnvioDte(); $EnvioDte->loadXML(file_get_contents($archivo_recibido)); $Caratula = $EnvioDte->getCaratula(); $Documentos = $EnvioDte->getDocumentos(); // caratula $caratula = ['RutResponde' => $RutReceptor_esperado, 'RutRecibe' => $Caratula['RutEmisor'], 'IdRespuesta' => 1]; // objeto para la respuesta $RespuestaEnvio = new \sasco\LibreDTE\Sii\RespuestaEnvio(); // procesar cada DTE $i = 1; foreach ($Documentos as $DTE) { $estado = !$DTE->getEstadoValidacion(['RUTEmisor' => $RutEmisor_esperado, 'RUTRecep' => $RutReceptor_esperado]) ? 0 : 2; $RespuestaEnvio->agregarRespuestaDocumento(['TipoDTE' => $DTE->getTipo(), 'Folio' => $DTE->getFolio(), 'FchEmis' => $DTE->getFechaEmision(), 'RUTEmisor' => $DTE->getEmisor(), 'RUTRecep' => $DTE->getReceptor(), 'MntTotal' => $DTE->getMontoTotal(), 'CodEnvio' => $i++, 'EstadoDTE' => $estado, 'EstadoDTEGlosa' => \sasco\LibreDTE\Sii\RespuestaEnvio::$estados['respuesta_documento'][$estado]]); } // asignar carátula y Firma $RespuestaEnvio->setCaratula($caratula); $RespuestaEnvio->setFirma(new \sasco\LibreDTE\FirmaElectronica($config['firma'])); // generar XML
/** * Acción para la etapa de certificación de intercambio de DTEs * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-11 */ public function intercambio() { $this->set(['nav' => $this->nav]); if (!isset($_POST['submit'])) { return; } // verificar que se hayan pasado los datos requeridos if (!isset($_FILES['xml']) or $_FILES['xml']['error']) { \sowerphp\core\Model_Datasource_Session::message('Hubo algún problema al subir el XML EnvioDTE', 'error'); return; } if (empty($_POST['emisor'])) { \sowerphp\core\Model_Datasource_Session::message('RUT emisor esperado no puede estar en blanco', 'error'); return; } if (empty($_POST['receptor'])) { \sowerphp\core\Model_Datasource_Session::message('RUT receptor esperado no puede estar en blanco', 'error'); return; } if (!isset($_FILES['firma']) or $_FILES['firma']['error']) { \sowerphp\core\Model_Datasource_Session::message('Hubo algún problema al subir la firma electrónica', 'error'); return; } // Cargar EnvioDTE y extraer arreglo con datos de carátula y DTEs $EnvioDte = new \sasco\LibreDTE\Sii\EnvioDte(); $EnvioDte->loadXML(file_get_contents($_FILES['xml']['tmp_name'])); $Caratula = $EnvioDte->getCaratula(); // objeto firma electrónica try { $Firma = new \sasco\LibreDTE\FirmaElectronica(['data' => file_get_contents($_FILES['firma']['tmp_name']), 'pass' => $_POST['contrasenia']]); } catch (\Exception $e) { \sowerphp\core\Model_Datasource_Session::message('No fue posible abrir la firma digital, quizás contraseña incorrecta', 'error'); return; } // generar XML RecepcionDTE.xml $RecepcionDTE = $this->intercambio_RecepcionDTE($EnvioDte, $_POST['emisor'], $_POST['receptor'], ['RutResponde' => $_POST['receptor'], 'RutRecibe' => $Caratula['RutEmisor'], 'IdRespuesta' => 1, 'NmbContacto' => $Firma->getName(), 'MailContacto' => $Firma->getEmail()], $Firma); if (!$RecepcionDTE) { \sowerphp\core\Model_Datasource_Session::message('No fue posible generar RecepcionDTE.xml', 'error'); return; } // generar XML EnvioRecibos.xml $EnvioRecibos = $this->intercambio_EnvioRecibos($EnvioDte, ['RutResponde' => $_POST['receptor'], 'RutRecibe' => $Caratula['RutEmisor'], 'NmbContacto' => $Firma->getName(), 'MailContacto' => $Firma->getEmail()], $Firma); if (!$EnvioRecibos) { \sowerphp\core\Model_Datasource_Session::message('No fue posible generar EnvioRecibos.xml', 'error'); return; } // generar XML ResultadoDTE.xml $ResultadoDTE = $this->intercambio_ResultadoDTE($EnvioDte, $_POST['emisor'], $_POST['receptor'], ['RutResponde' => $_POST['receptor'], 'RutRecibe' => $Caratula['RutEmisor'], 'IdRespuesta' => 1, 'NmbContacto' => $Firma->getName(), 'MailContacto' => $Firma->getEmail()], $Firma); if (!$ResultadoDTE) { \sowerphp\core\Model_Datasource_Session::message('No fue posible generar ResultadoDTE.xml', 'error'); return; } // aquí se tienen los 3 XML, se guardan en un único directorio $dir = TMP . '/intercambio_' . $Caratula['RutEmisor'] . '_' . date('U'); if (!mkdir($dir)) { \sowerphp\core\Model_Datasource_Session::message('No fue posible generar el archivo comprimido con los XML', 'error'); return; } file_put_contents($dir . '/1_RecepcionDTE.xml', $RecepcionDTE); file_put_contents($dir . '/2_EnvioRecibos.xml', $EnvioRecibos); file_put_contents($dir . '/3_ResultadoDTE.xml', $ResultadoDTE); unset($RecepcionDTE, $EnvioRecibos, $ResultadoDTE); // entregar archivos XML comprimidos al usuario \sasco\LibreDTE\File::compress($dir, ['format' => 'zip', 'delete' => true]); }
/** * Recurso de la API que genera el PDF de los DTEs contenidos en un EnvioDTE * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2016-01-15 */ public function _api_generar_pdf_POST() { // verificar si se pasaron credenciales de un usuario $User = $this->Api->getAuthUser(); if (is_string($User)) { $this->Api->send($User, 401); } // si hubo problemas al subir el archivo error if (!isset($this->Api->data['xml']) and (!isset($_FILES['xml']) or $_FILES['xml']['error'])) { $this->Api->send('Hubo algún problema al recibir el archivo XML con el EnvioDTE', 500); } // recuperar contenido del archivo xml if (isset($this->Api->data['xml'])) { $xml = base64_decode($this->Api->data['xml']); } else { $xml = file_get_contents($_FILES['xml']['tmp_name']); } // recuperar contenido del logo (si existe) if (isset($this->Api->data['logo'])) { $logo = base64_decode($this->Api->data['logo']); } else { if (isset($_FILES['logo']) and !$_FILES['logo']['error']) { $logo = file_get_contents($_FILES['logo']['tmp_name']); } } // crear flag cedible $cedible = !empty($this->Api->data['cedible']) ? $this->Api->data['cedible'] : false; // crear flag papel continuo $papelContinuo = !empty($this->Api->data['papelContinuo']) ? $this->Api->data['papelContinuo'] : false; // crear opción para web de verificación $webVerificacion = !empty($this->Api->data['webVerificacion']) ? $this->Api->data['webVerificacion'] : false; // sin límite de tiempo para generar documentos set_time_limit(0); // Cargar EnvioDTE y extraer arreglo con datos de carátula y DTEs $EnvioDte = new \sasco\LibreDTE\Sii\EnvioDte(); $EnvioDte->loadXML($xml); $Caratula = $EnvioDte->getCaratula(); $Documentos = $EnvioDte->getDocumentos(); // directorio temporal para guardar los PDF $dir = sys_get_temp_dir() . '/dte_' . $Caratula['RutEmisor'] . '_' . $Caratula['RutReceptor'] . '_' . str_replace(['-', ':', 'T'], '', $Caratula['TmstFirmaEnv']); if (is_dir($dir)) { \sasco\LibreDTE\File::rmdir($dir); } if (!mkdir($dir)) { $this->Api->send('No fue posible crear directorio temporal para DTEs', 500); } // procesar cada DTEs e ir agregándolo al PDF foreach ($Documentos as $DTE) { if (!$DTE->getDatos()) { $this->Api->send('No se pudieron obtener los datos de un DTE', 500); } // generar PDF $pdf = new \sasco\LibreDTE\Sii\PDF\Dte($papelContinuo); $pdf->setFooterText(); if (isset($logo)) { $pdf->setLogo('@' . $logo); } $pdf->setResolucion(['FchResol' => $Caratula['FchResol'], 'NroResol' => $Caratula['NroResol']]); if ($webVerificacion) { $pdf->setWebVerificacion($webVerificacion); } $pdf->agregar($DTE->getDatos(), $DTE->getTED()); if ($cedible and $DTE->esCedible()) { $pdf->setCedible(true); $pdf->agregar($DTE->getDatos(), $DTE->getTED()); } $file = $dir . '/dte_' . $Caratula['RutEmisor'] . '_' . $DTE->getID() . '.pdf'; $pdf->Output($file, 'F'); } // si solo es un archivo y se pidió no comprimir se entrega directamente if (isset($this->Api->data['compress']) and !$this->Api->data['compress'] and !isset($Documentos[1])) { $this->response->sendFile($file, ['disposition' => 'attachement', 'exit' => false]); \sowerphp\general\Utility_File::rmdir($dir); exit(0); } else { \sasco\LibreDTE\File::compress($dir, ['format' => 'zip', 'delete' => true]); } }
// cargar XML boletas y notas $EnvioBOLETA = new \sasco\LibreDTE\Sii\EnvioDte(); $EnvioBOLETA->loadXML(file_get_contents($boletas)); $EnvioDTE = new \sasco\LibreDTE\Sii\EnvioDte(); $EnvioDTE->loadXML(file_get_contents($notas_credito)); // crear objeto para consumo de folios $ConsumoFolio = new \sasco\LibreDTE\Sii\ConsumoFolio(); $ConsumoFolio->setFirma(new \sasco\LibreDTE\FirmaElectronica($config['firma'])); // agregar detalle de boletas foreach ($EnvioBOLETA->getDocumentos() as $Dte) { $ConsumoFolio->agregar($Dte->getResumen()); } // agregar detalle de notas de crédito foreach ($EnvioDTE->getDocumentos() as $Dte) { $ConsumoFolio->agregar($Dte->getResumen()); } // crear carátula para el envío (se hace después de agregar los detalles ya que // así se obtiene automáticamente la fecha inicial y final de los documentos) $CaratulaEnvioBOLETA = $EnvioBOLETA->getCaratula(); $ConsumoFolio->setCaratula(['RutEmisor' => $CaratulaEnvioBOLETA['RutEmisor'], 'FchResol' => $CaratulaEnvioBOLETA['FchResol'], 'NroResol' => $CaratulaEnvioBOLETA['NroResol']]); // generar, validar schema y mostrar XML $ConsumoFolio->generar(); if ($ConsumoFolio->schemaValidate()) { //echo $ConsumoFolio->generar(); $track_id = $ConsumoFolio->enviar(); var_dump($track_id); } // si hubo errores mostrar foreach (\sasco\LibreDTE\Log::readAll() as $error) { echo $error, "\n"; }
/** * Acción que procesa y responde al intercambio recibido * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-10-08 */ public function responder($codigo) { $Emisor = $this->getContribuyente(); // si no se viene por post error if (!isset($_POST['submit'])) { \sowerphp\core\Model_Datasource_Session::message('No puede acceder de forma directa a ' . $this->request->request, 'error'); $this->redirect(str_replace('responder', 'ver', $this->request->request)); } // obtener DTE emitido $DteIntercambio = new Model_DteIntercambio($Emisor->rut, $codigo, (int) $Emisor->certificacion); if (!$DteIntercambio->exists()) { \sowerphp\core\Model_Datasource_Session::message('No existe el intercambio solicitado', 'error'); $this->redirect('/dte/dte_intercambios'); } // obtener firma $Firma = $Emisor->getFirma($this->Auth->User->id); if (!$Firma) { \sowerphp\core\Model_Datasource_Session::message('No hay firma electrónica asociada a la empresa (o bien no se pudo cargar), debe agregar su firma antes de generar DTE', 'error'); $this->redirect('/dte/admin/firma_electronicas'); } // // construir RecepcionDTE // $RecepcionDTE = []; $n_dtes = count($_POST['TipoDTE']); for ($i = 0; $i < $n_dtes; $i++) { $RecepcionDTE[] = ['TipoDTE' => $_POST['TipoDTE'][$i], 'Folio' => $_POST['Folio'][$i], 'FchEmis' => $_POST['FchEmis'][$i], 'RUTEmisor' => $_POST['RUTEmisor'][$i], 'RUTRecep' => $_POST['RUTRecep'][$i], 'MntTotal' => $_POST['MntTotal'][$i], 'EstadoRecepDTE' => $_POST['EstadoRecepDTE'][$i], 'RecepDTEGlosa' => $_POST['RecepDTEGlosa'][$i]]; } // armar respuesta de envío $EnvioDte = new \sasco\LibreDTE\Sii\EnvioDte(); $EnvioDte->loadXML(base64_decode($DteIntercambio->archivo_xml)); $Caratula = $EnvioDte->getCaratula(); $RespuestaEnvio = new \sasco\LibreDTE\Sii\RespuestaEnvio(); $RespuestaEnvio->agregarRespuestaEnvio(['NmbEnvio' => $DteIntercambio->archivo, 'CodEnvio' => $DteIntercambio->codigo, 'EnvioDTEID' => $EnvioDte->getID(), 'Digest' => $EnvioDte->getDigest(), 'RutEmisor' => $EnvioDte->getEmisor(), 'RutReceptor' => $EnvioDte->getReceptor(), 'EstadoRecepEnv' => $_POST['EstadoRecepEnv'], 'RecepEnvGlosa' => $_POST['RecepEnvGlosa'], 'NroDTE' => count($RecepcionDTE), 'RecepcionDTE' => $RecepcionDTE]); // asignar carátula y Firma $RespuestaEnvio->setCaratula(['RutResponde' => $Emisor->rut . '-' . $Emisor->dv, 'RutRecibe' => $Caratula['RutEmisor'], 'IdRespuesta' => $DteIntercambio->codigo, 'NmbContacto' => $_POST['NmbContacto'], 'MailContacto' => $_POST['MailContacto']]); $RespuestaEnvio->setFirma($Firma); // generar y validar XML $RecepcionDTE_xml = $RespuestaEnvio->generar(); if (!$RespuestaEnvio->schemaValidate()) { \sowerphp\core\Model_Datasource_Session::message('No fue posible generar RecepcionDTE.<br/>' . implode('<br/>', \sasco\LibreDTE\Log::readAll()), 'error'); $this->redirect(str_replace('responder', 'ver', $this->request->request)); } // // generar EnvioRecibos // $EnvioRecibos = new \sasco\LibreDTE\Sii\EnvioRecibos(); $EnvioRecibos->setCaratula(['RutResponde' => $Emisor->rut . '-' . $Emisor->dv, 'RutRecibe' => $Caratula['RutEmisor'], 'NmbContacto' => $_POST['NmbContacto'], 'MailContacto' => $_POST['MailContacto']]); $EnvioRecibos->setFirma($Firma); // procesar cada DTE $EnvioRecibos_r = []; for ($i = 0; $i < $n_dtes; $i++) { if ($_POST['acuse'][$i]) { $EnvioRecibos->agregar(['TipoDoc' => $_POST['TipoDTE'][$i], 'Folio' => $_POST['Folio'][$i], 'FchEmis' => $_POST['FchEmis'][$i], 'RUTEmisor' => $_POST['RUTEmisor'][$i], 'RUTRecep' => $_POST['RUTRecep'][$i], 'MntTotal' => $_POST['MntTotal'][$i], 'Recinto' => $_POST['Recinto'], 'RutFirma' => $Firma->getID()]); $EnvioRecibos_r[] = 'T' . $_POST['TipoDTE'][$i] . 'F' . $_POST['Folio'][$i]; } } // generar y validar XML if ($EnvioRecibos_r) { $EnvioRecibos_xml = $EnvioRecibos->generar(); if (!$EnvioRecibos->schemaValidate()) { \sowerphp\core\Model_Datasource_Session::message('No fue posible generar EnvioRecibos.<br/>' . implode('<br/>', \sasco\LibreDTE\Log::readAll()), 'error'); $this->redirect(str_replace('responder', 'ver', $this->request->request)); } } // // generar ResultadoDTE // // objeto para la respuesta $RespuestaEnvio = new \sasco\LibreDTE\Sii\RespuestaEnvio(); // procesar cada DTE for ($i = 0; $i < $n_dtes; $i++) { $estado = !$_POST['EstadoRecepDTE'][$i] ? 0 : 2; $RespuestaEnvio->agregarRespuestaDocumento(['TipoDTE' => $_POST['TipoDTE'][$i], 'Folio' => $_POST['Folio'][$i], 'FchEmis' => $_POST['FchEmis'][$i], 'RUTEmisor' => $_POST['RUTEmisor'][$i], 'RUTRecep' => $_POST['RUTRecep'][$i], 'MntTotal' => $_POST['MntTotal'][$i], 'CodEnvio' => $i + 1, 'EstadoDTE' => $estado, 'EstadoDTEGlosa' => \sasco\LibreDTE\Sii\RespuestaEnvio::$estados['respuesta_documento'][$estado]]); } // asignar carátula y Firma $RespuestaEnvio->setCaratula(['RutResponde' => $Emisor->rut . '-' . $Emisor->dv, 'RutRecibe' => $Caratula['RutEmisor'], 'IdRespuesta' => $DteIntercambio->codigo, 'NmbContacto' => $_POST['NmbContacto'], 'MailContacto' => $_POST['MailContacto']]); $RespuestaEnvio->setFirma($Firma); // generar y validar XML $ResultadoDTE_xml = $RespuestaEnvio->generar(); if (!$RespuestaEnvio->schemaValidate()) { \sowerphp\core\Model_Datasource_Session::message('No fue posible generar ResultadoDTE.<br/>' . implode('<br/>', \sasco\LibreDTE\Log::readAll()), 'error'); $this->redirect(str_replace('responder', 'ver', $this->request->request)); } // // guardar estado del intercambio y usuario que lo procesó // $DteIntercambio->estado = (int) $_POST['EstadoRecepEnv']; $DteIntercambio->recepcion_xml = base64_encode($RecepcionDTE_xml); if (isset($EnvioRecibos_xml)) { $DteIntercambio->recibos_xml = base64_encode($EnvioRecibos_xml); } $DteIntercambio->resultado_xml = base64_encode($ResultadoDTE_xml); $DteIntercambio->fecha_hora_respuesta = date('Y-m-d H:i:s'); $DteIntercambio->usuario = $this->Auth->User->id; $DteIntercambio->save(); // // guardar documentos que han sido aceptados con acuse de recibo // if (isset($EnvioRecibos_xml)) { // actualizar datos del emisor si no tine usuario asociado $EmisorIntercambio = $DteIntercambio->getEmisor(); if (!$EmisorIntercambio->usuario) { $emisor = $DteIntercambio->getDocumentos()[0]->getDatos()['Encabezado']['Emisor']; $EmisorIntercambio->razon_social = $emisor['RznSoc']; if (!empty($emisor['GiroEmis'])) { $EmisorIntercambio->giro = $emisor['GiroEmis']; } if (!empty($emisor['CorreoEmisor'])) { $EmisorIntercambio->email = $emisor['CorreoEmisor']; } if (!empty($emisor['Acteco'])) { $actividad_economica = $EmisorIntercambio->actividad_economica; $EmisorIntercambio->actividad_economica = $emisor['Acteco']; if (!$EmisorIntercambio->getActividadEconomica()->exists()) { $EmisorIntercambio->actividad_economica = $actividad_economica; } } $comuna = (new \sowerphp\app\Sistema\General\DivisionGeopolitica\Model_Comunas())->getComunaByName($emisor['CmnaOrigen']); if ($comuna) { $EmisorIntercambio->direccion = $emisor['DirOrigen']; $EmisorIntercambio->comuna = $comuna; } if (!empty($emisor['CdgSIISucur'])) { $EmisorIntercambio->sucursal_sii = (int) $emisor['CdgSIISucur']; } $EmisorIntercambio->modificado = date('Y-m-d H:i:s'); $EmisorIntercambio->save(); } // guardar documentos que tienen acuse de recibo como dte recibidos $Documentos = $DteIntercambio->getDocumentos(); foreach ($Documentos as $Dte) { if (in_array($Dte->getID(), $EnvioRecibos_r)) { $resumen = $Dte->getResumen(); $DteRecibido = new Model_DteRecibido(); $DteRecibido->emisor = $DteIntercambio->getEmisor()->rut; $DteRecibido->dte = $resumen['TpoDoc']; $DteRecibido->folio = $resumen['NroDoc']; $DteRecibido->certificacion = (int) $DteIntercambio->certificacion; if (!$DteRecibido->exists()) { $DteRecibido->receptor = $Emisor->rut; $DteRecibido->tasa = (int) $resumen['TasaImp']; $DteRecibido->fecha = $resumen['FchDoc']; $DteRecibido->sucursal_sii = (int) $resumen['CdgSIISucur']; if ($resumen['MntExe']) { $DteRecibido->exento = $resumen['MntExe']; } if ($resumen['MntNeto']) { $DteRecibido->neto = $resumen['MntNeto']; } $DteRecibido->iva = (int) $resumen['MntIVA']; $DteRecibido->total = (int) $resumen['MntTotal']; $DteRecibido->usuario = $this->Auth->User->id; $DteRecibido->intercambio = $DteIntercambio->codigo; $DteRecibido->save(); } } } } // // enviar los 3 XML de respuesta por email // $email = $Emisor->getEmailSmtp(); $email->to($_POST['responder_a']); $email->subject($Emisor->rut . '-' . $Emisor->dv . ' - Respuesta intercambio N° ' . $DteIntercambio->codigo); foreach (['RecepcionDTE', 'EnvioRecibos', 'ResultadoDTE'] as $xml) { if (isset(${$xml . '_xml'})) { $email->attach(['data' => ${$xml . '_xml'}, 'name' => $xml . '_' . $Emisor->rut . '-' . $Emisor->dv . '_' . $DteIntercambio->codigo . '.xml', 'type' => 'application/xml']); } } // enviar email $status = $email->send('Se adjuntan XMLs de respuesta a intercambio de DTE.'); if ($status === true) { \sowerphp\core\Model_Datasource_Session::message('Se procesaron DTEs de intercambio y se envió la respuesta a: ' . $_POST['responder_a'], 'ok'); } else { \sowerphp\core\Model_Datasource_Session::message('Se procesaron DTEs de intercambio, pero no fue posible enviar el email, por favor intente nuevamente.<br /><em>' . $status['message'] . '</em>', 'error'); } $this->redirect(str_replace('responder', 'ver', $this->request->request)); }