/** * Acción que permite mostrar los documentos recibidos por el contribuyente * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2016-01-04 */ public function listar($pagina = 1) { if (!is_numeric($pagina)) { $this->redirect('/dte/' . $this->request->params['controller'] . '/listar'); } $Emisor = $this->getContribuyente(); $filtros = []; if (isset($_GET['search'])) { foreach (explode(',', $_GET['search']) as $filtro) { list($var, $val) = explode(':', $filtro); $filtros[$var] = $val; } } $searchUrl = isset($_GET['search']) ? '?search=' . $_GET['search'] : ''; try { $documentos_total = $Emisor->countDocumentosRecibidos($filtros); $documentos = $Emisor->getDocumentosRecibidos($filtros); } catch (\sowerphp\core\Exception_Model_Datasource_Database $e) { \sowerphp\core\Model_Datasource_Session::message('Error al recuperar los documentos:<br/>' . $e->getMessage(), 'error'); $documentos_total = 0; $documentos = []; } if (!empty($pagina)) { $filtros['limit'] = \sowerphp\core\Configure::read('app.registers_per_page'); $filtros['offset'] = ($pagina - 1) * $filtros['limit']; $paginas = ceil($documentos_total / $filtros['limit']); if ($pagina != 1 && $pagina > $paginas) { $this->redirect('/dte/' . $this->request->params['controller'] . '/listar' . $searchUrl); } } else { $paginas = 1; } $this->set(['Emisor' => $Emisor, 'documentos' => $documentos, 'documentos_total' => $documentos_total, 'paginas' => $paginas, 'pagina' => $pagina, 'search' => $filtros, 'tipos_dte' => (new \website\Dte\Admin\Model_DteTipos())->getList(true), 'usuarios' => $Emisor->getListUsuarios(), 'searchUrl' => $searchUrl]); }
/** * Constructor para la clase: crea configuración y carga certificado digital * * Si se desea pasar una configuración específica para la firma electrónica * se debe hacer a través de un arreglo con los índices file y pass, donde * file es la ruta hacia el archivo .p12 que contiene tanto la clave privada * como la pública y pass es la contraseña para abrir dicho archivo. * Ejemplo: * * \code{.php} * $firma_config = ['file'=>'/ruta/al/certificado.p12', 'pass'=>'contraseña']; * $firma = new \sasco\LibreDTE\FirmaElectronica($firma_config); * \endcode * * También se permite que en vez de pasar la ruta al certificado p12 se pase * el contenido del certificado, esto servirá por ejemplo si los datos del * archivo están almacenados en una base de datos. Ejemplo: * * \code{.php} * $firma_config = ['data'=>file_get_contents('/ruta/al/certificado.p12'), 'pass'=>'contraseña']; * $firma = new \sasco\LibreDTE\FirmaElectronica($firma_config); * \endcode * * @param config Configuración para la clase, si no se especifica se tratará de determinar * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-15 */ public function __construct(array $config = []) { // crear configuración if (!$config) { if (class_exists('\\sowerphp\\core\\Configure')) { $config = (array) \sowerphp\core\Configure::read('firma_electronica.default'); } else { $config = []; } } $this->config = array_merge(['file' => null, 'pass' => null, 'data' => null, 'wordwrap' => 64], $config); // cargar firma electrónica desde el contenido del archivo .p12 si no // se pasaron como datos del arreglo de configuración if (!$this->config['data'] and $this->config['file']) { if (is_readable($this->config['file'])) { $this->config['data'] = file_get_contents($this->config['file']); } else { return $this->error('Archivo de la firma electrónica ' . basename($this->config['file']) . ' no puede ser leído'); } } // leer datos de la firma electrónica if ($this->config['data'] and openssl_pkcs12_read($this->config['data'], $this->certs, $this->config['pass']) === false) { return $this->error('No fue posible leer los datos de la firma electrónica (verificar la contraseña)'); } $this->data = openssl_x509_parse($this->certs['cert']); // quitar datos del contenido del archivo de la firma unset($this->config['data']); }
/** * Constructor de la clase * @param config Configuración del correo electrónico que se usará * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]delaf.cl) * @version 2016-04-20 */ public function __construct($config = 'default') { // Si es un arreglo, se asume es la configuración directamente if (is_array($config)) { $this->_config = $config; } else { $this->_config = \SowerPHP\core\Configure::read('email.' . $config); } // se ponen valores por defecto $this->_config = array_merge(['type' => 'smtp', 'host' => 'localhost', 'port' => 25], $this->_config); // extraer puerto si se pasó en el host $url = parse_url($this->_config['host']); if (isset($url['port'])) { $this->_config['host'] = str_replace(':' . $url['port'], '', $this->_config['host']); $this->_config['port'] = $url['port']; } // si no están los campos mínimos necesarios error if (empty($this->_config['type']) || empty($this->_config['host']) || empty($this->_config['port']) || empty($this->_config['user']) || empty($this->_config['pass'])) { throw new Exception('Configuración del correo electrónico incompleta'); } // determinar from if (isset($this->_config['from'])) { if (is_array($this->_config['from'])) { $this->_config['from'] = $this->_config['from']['name'] . ' <' . $this->_config['from']['email'] . '>'; } else { $this->_config['from'] = $this->_config['from']; } } else { $this->_config['from'] = $this->_config['user']; } }
/** * Método que desencripta un texto encriptado * @param $ciphertext_base64 Texto encriptado en base64 a desencriptar * @param key Índice en la configuración para obtener la clave a usar * @return Texto plano * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2016-01-02 */ public static function decrypt($ciphertext_base64, $key = 'dte.pkey') { if (empty($ciphertext_base64)) { return $ciphertext_base64; } $ciphertext_dec = base64_decode($ciphertext_base64); $key = \sowerphp\core\Configure::read($key); if (!$key) { return $ciphertext_dec; } $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC); $iv_dec = substr($ciphertext_dec, 0, $iv_size); $ciphertext_dec = substr($ciphertext_dec, $iv_size); $plaintext_dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec); return $plaintext_dec; }
/** * Constructor para la clase: crea configuración y carga certificado digital * * Si se desea pasar una configuración específica para la firma electrónica * se debe hacer a través de un arreglo con los índices file y pass, donde * file es la ruta hacia el archivo .p12 que contiene tanto la clave privada * como la pública y pass es la contraseña para abrir dicho archivo. * Ejemplo: * * \code{.php} * $firma_config = ['file'=>'/ruta/al/certificado.p12', 'pass'=>'contraseña']; * $firma = new \sasco\LibreDTE\FirmaElectronica($firma_config); * \endcode * * @param config Configuración para la cllase, si no se especifica se trarará de determinar * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2014-12-08 */ public function __construct($config = []) { // crear configuración if (!$config and class_exists('\\sowerphp\\core\\Configure')) { $config = (array) \sowerphp\core\Configure::read('firma_electronica.default'); } $this->config = array_merge(['file' => (defined('DIR_PROJECT') ? DIR_PROJECT . '/data/firma_electronica/' : '') . 'default.p12', 'pass' => '', 'wordwrap' => 64], $config); // cargar certificado digital if (file_exists($this->config['file'])) { $pkcs12 = file_get_contents($this->config['file']); if (openssl_pkcs12_read($pkcs12, $this->certs, $this->config['pass']) === false) { $this->error('Contraseña incorrecta para la firma electrónica ' . basename($this->config['file'])); } } else { $this->error('Archivo de la firma electrónica ' . basename($this->config['file']) . ' no existe'); } }
/** * Método que guarda en memoria un valor a ser cacheado * @param host Hostname del servidor que corre Memcached * @param port Puerto donde Memcached está escuchando * @param prefix Prefijo que se utilizará en las claves de los elementos del caché * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]delaf.cl) * @version 2016-04-13 */ public function __construct($host = null, $port = null, $prefix = false) { if (class_exists('\\Memcached')) { // definir host y puerto if (!$host or !$port) { $cache = \sowerphp\core\Configure::read('cache.default'); if (!$host) { $host = isset($cache['host']) ? $cache['host'] : '127.0.0.1'; } if (!$port) { $port = isset($cache['port']) ? $cache['port'] : 11211; } } // conectar a Memcached $this->_cache = new \Memcached(); $this->_cache->addServer($host, $port); $this->_prefix = $prefix ? $prefix : defined('DIR_PROJECT') ? DIR_PROJECT . ':' : ''; } }
/** * Método que genera la previsualización del PDF del DTE * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]delaf.cl) * @version 2015-09-24 */ public function pdf($receptor, $dte, $codigo) { $Emisor = $this->getContribuyente(); // obtener datos JSON del DTE $DteTmp = new Model_DteTmp($Emisor->rut, $receptor, $dte, $codigo); if (!$DteTmp->exists()) { \sowerphp\core\Model_Datasource_Session::message('No existe el DTE temporal solicitado', 'error'); $this->redirect('/dte/dte_tmps'); } // armar xml a partir de datos del dte temporal $xml = $DteTmp->getEnvioDte()->generar(); if (!$xml) { \sowerphp\core\Model_Datasource_Session::message('No fue posible crear el PDF para previsualización:<br/>' . implode('<br/>', \sasco\LibreDTE\Log::readAll()), 'error'); $this->redirect('/dte/dte_tmps'); } // armar datos con archivo XML y flag para indicar si es cedible o no $data = ['xml' => base64_encode($xml), 'cedible' => false, 'compress' => false]; // si hay un logo para la empresa se usa $logo = \sowerphp\core\Configure::read('dte.logos.dir') . '/' . $Emisor->rut . '.png'; if (is_readable($logo)) { $data['logo'] = base64_encode(file_get_contents($logo)); } // realizar consulta a la API $rest = new \sowerphp\core\Network_Http_Rest(); $rest->setAuth($this->Auth->User ? $this->Auth->User->hash : $this->token); $response = $rest->post($this->request->url . '/api/dte/documentos/generar_pdf', $data); if ($response['status']['code'] != 200) { \sowerphp\core\Model_Datasource_Session::message($response['body'], 'error'); return; } // si dió código 200 se entrega la respuesta del servicio web foreach (['Content-Disposition', 'Content-Length', 'Content-Type'] as $header) { if (isset($response['header'][$header])) { header($header . ': ' . $response['header'][$header]); } } echo $response['body']; exit; }
/** * Acción para mostrar el PDF de un EnvioDTE de un intercambio de DTE * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-27 */ public function pdf($codigo, $cedible = false) { $Emisor = $this->getContribuyente(); // obtener DTE intercambiado $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'); } // armar datos con archivo XML y flag para indicar si es cedible o no $data = ['xml' => $DteIntercambio->archivo_xml, 'cedible' => $cedible, 'compress' => $DteIntercambio->documentos == 1 ? false : true]; // si hay un logo para la empresa se usa $logo = \sowerphp\core\Configure::read('dte.logos.dir') . '/' . $DteIntercambio->emisor . '.png'; if (is_readable($logo)) { $data['logo'] = base64_encode(file_get_contents($logo)); } // realizar consulta a la API $rest = new \sowerphp\core\Network_Http_Rest(); $rest->setAuth($this->Auth->User ? $this->Auth->User->hash : $this->token); $response = $rest->post($this->request->url . '/api/dte/documentos/generar_pdf', $data); if ($response['status']['code'] != 200) { \sowerphp\core\Model_Datasource_Session::message($response['body'], 'error'); return; } // si dió código 200 se entrega la respuesta del servicio web foreach (['Content-Disposition', 'Content-Length', 'Content-Type'] as $header) { if (isset($response['header'][$header])) { header($header . ': ' . $response['header'][$header]); } } echo $response['body']; exit; }
<?php /** * LibreDTE * Copyright (C) SASCO SpA (https://sasco.cl) * * Este programa es software libre: usted puede redistribuirlo y/o * modificarlo bajo los términos de la Licencia Pública General GNU * publicada por la Fundación para el Software Libre, ya sea la versión * 3 de la Licencia, o (a su elección) cualquier versión posterior de la * misma. * * Este programa se distribuye con la esperanza de que sea útil, pero * SIN GARANTÍA ALGUNA; ni siquiera la garantía implícita * MERCANTIL o de APTITUD PARA UN PROPÓSITO DETERMINADO. * Consulte los detalles de la Licencia Pública General GNU para obtener * una información más detallada. * * Debería haber recibido una copia de la Licencia Pública General GNU * junto a este programa. * En caso contrario, consulte <http://www.gnu.org/licenses/gpl.html>. */ // Menú para el módulo \sowerphp\core\Configure::write('nav.module', ['/dte_folios' => ['name' => 'Folios', 'desc' => 'Mantenedor de códigos de autorización de folios', 'icon' => 'fa fa-cube'], '/firma_electronicas' => ['name' => 'Firma electrónica', 'desc' => 'Mantenedor para poder cargar la firma electrónica del usuario', 'icon' => 'fa fa-certificate'], '/contribuyente_dtes/listar/1/contribuyente/A' => ['name' => 'DTEs autorizados por contribuyente', 'desc' => 'DTEs que los contribuyentes de LibreDTE tienen autorizado emitir en la aplicación', 'icon' => 'fa fa-list'], '/dte_tipos/listar/1/codigo/A' => ['name' => 'Documentos tributarios', 'desc' => 'Tipos de documentos tributarios (electrónicos y no electrónicos)', 'icon' => 'fa fa-list-alt'], '/iva_no_recuperables/listar/1/codigo/A' => ['name' => 'IVA no recuperable', 'icon' => 'fa fa-dollar'], '/impuesto_adicionales/listar/1/codigo/A' => ['name' => 'Impuestos adicionales', 'icon' => 'fa fa-dollar']]);
/** * Acción que entrega el logo del contribuyente * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-29 */ public function logo($rut) { $Contribuyente = new Model_Contribuyente(substr($rut, 0, -4)); if (!$Contribuyente->exists()) { \sowerphp\core\Model_Datasource_Session::message('Contribuyente solicitado no existe'); $this->redirect('/'); } $dir = \sowerphp\core\Configure::read('dte.logos.dir'); $logo = $dir . '/' . $Contribuyente->rut . '.png'; if (!is_readable($logo)) { $logo = $dir . '/default.png'; } header('Content-Type: image/png'); header('Content-Length: ' . filesize($logo)); header('Content-Disposition: inline; filename="' . $Contribuyente->rut . '.png"'); print file_get_contents($logo); exit; }
* junto a este programa. * En caso contrario, consulte <http://www.gnu.org/licenses/agpl.html>. */ /** * @file core.php * Configuración propia de cada proyecto * @version 2014-12-11 */ // Tema de la página (diseño) \sowerphp\core\Configure::write('page.layout', 'Bootstrap'); // Textos de la página \sowerphp\core\Configure::write('page.header.title', 'Proyecto web'); \sowerphp\core\Configure::write('page.body.title', 'Proyecto web'); \sowerphp\core\Configure::write('page.footer', ['left' => '<span>Página web generada utilizando el framework <a href="http://sowerphp.org">SowerPHP</a></span>', 'right' => '']); // Menú principal del sitio web \sowerphp\core\Configure::write('nav.website', []); // Configuración para el correo electrónico /*\sowerphp\core\Configure::write('email.default', [ 'type' => 'smtp', 'host' => 'ssl://smtp.gmail.com', 'port' => 465, 'user' => '', 'pass' => '', 'from' => ['email'=>'', 'name'=>''], 'to' => '', ]);*/ // Configuración para la base de datos /*\sowerphp\core\Configure::write('database.default', [ 'type' => 'PostgreSQL', 'user' => '', 'pass' => '',
define('DIR_WEBSITE', DIR_PROJECT . '/website'); // Iniciar buffer ob_start(); // Incluir archivo de funciones básicas y clase para autoload include DIR_FRAMEWORK . '/lib/sowerphp/core/basics.php'; include DIR_FRAMEWORK . '/lib/sowerphp/core/App.php'; // Asociar el método que cargará las clases spl_autoload_register('\\sowerphp\\core\\App::loadClass'); // Crear capas de la aplicación (se registrarán extensiones) \sowerphp\core\App::createLayers($_EXTENSIONS); unset($_EXTENSIONS); // Definir si la aplicación se ejecuta en ambiente de desarrollo // Si estamos en Apache se debe definir en /etc/httpd/conf/httpd.conf: // SetEnv APPLICATION_ENV "dev". // Si estamos en una terminal se debe pasar el flas: --dev global $argv; if (isset($_SERVER['APPLICATION_ENV']) and $_SERVER['APPLICATION_ENV'] == 'dev') { define('ENVIRONMENT_DEV', true); } else { if (is_array($argv) and in_array('--dev', $argv)) { define('ENVIRONMENT_DEV', true); // se quita flasg --dev de los argumentos unset($argv[array_search('--dev', $argv)]); } } // Iniciar sesión y configurar el sitio \sowerphp\core\Configure::bootstrap(); \sowerphp\core\Model_Datasource_Session::start(\sowerphp\core\Configure::read('session.expires')); \sowerphp\core\Model_Datasource_Session::configure(); // autocarga de composer require 'Vendor/autoload.php';
<?php /** * LibreDTE * Copyright (C) SASCO SpA (https://sasco.cl) * * Este programa es software libre: usted puede redistribuirlo y/o * modificarlo bajo los términos de la Licencia Pública General GNU * publicada por la Fundación para el Software Libre, ya sea la versión * 3 de la Licencia, o (a su elección) cualquier versión posterior de la * misma. * * Este programa se distribuye con la esperanza de que sea útil, pero * SIN GARANTÍA ALGUNA; ni siquiera la garantía implícita * MERCANTIL o de APTITUD PARA UN PROPÓSITO DETERMINADO. * Consulte los detalles de la Licencia Pública General GNU para obtener * una información más detallada. * * Debería haber recibido una copia de la Licencia Pública General GNU * junto a este programa. * En caso contrario, consulte <http://www.gnu.org/licenses/gpl.html>. */ // Menú para el módulo \sowerphp\core\Configure::write('nav.module', ['/documentos/emitir' => ['name' => 'Emitir documento', 'desc' => 'Emitir documento tributario electrónico (DTE)', 'icon' => 'fa fa-file-text'], '/dte_tmps' => ['name' => 'Documentos temporales', 'desc' => 'Revisar documentos temporales', 'icon' => 'fa fa-list'], '/dte_emitidos/listar' => ['name' => 'Documentos emitidos', 'desc' => 'Revisar documentos emitidos', 'icon' => 'fa fa-sign-out'], '/dte_recibidos/listar' => ['name' => 'Documentos recibidos', 'desc' => 'Revisar documentos recibidos', 'icon' => 'fa fa-sign-in'], '/dte_intercambios' => ['name' => 'Intercambio entre contribuyentes', 'desc' => 'Menú de intercambio de DTE entre contribuyentes', 'icon' => 'fa fa-exchange'], '/dte_compras' => ['name' => 'Libro de compras', 'desc' => 'Acceder al Libro de Compras', 'icon' => 'fa fa-book'], '/dte_ventas' => ['name' => 'Libro de ventas', 'desc' => 'Acceder al Libro de Ventas', 'icon' => 'fa fa-book'], '/dte_guias' => ['name' => 'Libro de guías', 'desc' => 'Acceder al Libro de Guías de despacho', 'icon' => 'fa fa-book'], '/admin' => ['name' => 'Administración', 'desc' => 'Administración del módulo DTE', 'icon' => 'fa fa-cogs']]);
/** * Acción que permite la generación del PDF con los DTEs contenidos en un * XML de EnvioDTE * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-12-12 */ public function generar_pdf() { if (isset($_POST['submit'])) { // si hubo problemas al subir el archivo error if (!isset($_FILES['xml']) or $_FILES['xml']['error']) { \sowerphp\core\Model_Datasource_Session::message('Hubo algún problema al recibir el archivo XML con el EnvioDTE', 'error'); return; } // armar datos con archivo XML y flag para indicar si es cedible o no $data = ['xml' => base64_encode(file_get_contents($_FILES['xml']['tmp_name'])), 'cedible' => isset($_POST['cedible']), 'papelContinuo' => $_POST['papelContinuo'], 'webVerificacion' => $_POST['webVerificacion']]; // si se pasó un logo se agrega el archivo a los datos que se enviarán if (isset($_FILES['logo']) and !$_FILES['logo']['error']) { $data['logo'] = base64_encode(file_get_contents($_FILES['logo']['tmp_name'])); } // realizar consulta a la API $rest = new \sowerphp\core\Network_Http_Rest(); $rest->setAuth($this->Auth->User ? $this->Auth->User->hash : \sowerphp\core\Configure::read('api.default.token')); $response = $rest->post($this->request->url . '/api/dte/documentos/generar_pdf', $data); if ($response['status']['code'] != 200) { \sowerphp\core\Model_Datasource_Session::message($response['body'], 'error'); return; } // si dió código 200 se entrega la respuesta del servicio web foreach (['Content-Disposition', 'Content-Length', 'Content-Type'] as $header) { if (isset($response['header'][$header])) { header($header . ': ' . $response['header'][$header]); } } echo $response['body']; exit; } }
'name' => 'Latch', 'url' => 'https://latch.elevenpaths.com', 'app_id' => '', 'app_key' => '', 'default' => false, ]);*/ // Configuración para reCAPTCHA (extensión: sowerphp/app) /*\sowerphp\core\Configure::write('recaptcha', [ 'public_key' => '', 'private_key' => '', ]);*/ // Configuración para auto registro de usuarios (extensión: sowerphp/app) \sowerphp\core\Configure::write('app.self_register', ['groups' => ['usuarios', 'usuarios_dte']]); // Configuración para Telegram /*\sowerphp\core\Configure::write('telegram', [ 'LibreDTE_bot' => [ 'bot' => 'LibreDTE_bot', 'token' => '', ], 'LibreDTEbot' => [ 'bot' => 'LibreDTEbot', 'token' => '', ], ]);*/ // configuración general del módulo DTE \sowerphp\core\Configure::write('dte', ['pkey' => '', 'logos' => ['dir' => DIR_PROJECT . '/data/logos', 'width' => 150, 'height' => 100], 'dtes' => [33, 56, 61]]); // configuración para firma electrónica \sowerphp\core\Configure::write('firma_electronica.default', ['file' => DIR_PROJECT . '/data/firma_electronica/default.p12', 'pass' => '']); // configuración para autenticación en API a usuarios no logueados \sowerphp\core\Configure::write('api.default', ['token' => '']);
/** * Comando que procesa el envío del timbre como fotografía * @param photo ID de la fotografía que envió el usuario * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]delaf.cl) * @version 2015-10-13 */ protected function _bot_photo($file_id) { $this->Bot->sendChatAction(); $n_sizes = count($this->Bot->getMessage()->photo); $file_id = $this->Bot->getMessage()->photo[$n_sizes - 1]->file_id; $file = $this->Bot->downloadFile($file_id); if (!$file) { $this->Bot->send('No fue posible recuperar el archivo que envíaste'); return; } $rest = new \sowerphp\core\Network_Http_Rest(); $rest->setAuth(\sowerphp\core\Configure::read('api.default.token')); $response = $rest->post($this->request->url . '/api/dte/documentos/get_ted', base64_encode($file['data'])); if ($response['status']['code'] != 200) { $this->Bot->send($response['body']); return; } $this->_bot_timbre(base64_decode($response['body'])); }
/** * Acción que envía por email el PDF y el XML del DTE * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-12-12 */ public function enviar_email($dte, $folio) { $Emisor = $this->getContribuyente(); // obtener DTE emitido $DteEmitido = new Model_DteEmitido($Emisor->rut, $dte, $folio, (int) $Emisor->certificacion); if (!$DteEmitido->exists()) { \sowerphp\core\Model_Datasource_Session::message('No existe el DTE solicitado', 'error'); $this->redirect('/dte/dte_emitidos/listar'); } // se verifican datos mínimos foreach (['emails', 'asunto', 'mensaje'] as $attr) { if (empty($_POST[$attr])) { \sowerphp\core\Model_Datasource_Session::message('Debe especificar el campo: ' . $attr, 'error'); $this->redirect(str_replace('enviar_email', 'ver', $this->request->request) . '#email'); } } // crear email $email = $Emisor->getEmailSmtp(); $email->to($_POST['emails']); $email->subject($_POST['asunto']); // adjuntar PDF $data = ['xml' => $DteEmitido->xml, 'cedible' => isset($_POST['cedible']), 'compress' => false]; $logo = \sowerphp\core\Configure::read('dte.logos.dir') . '/' . $Emisor->rut . '.png'; if (is_readable($logo)) { $data['logo'] = base64_encode(file_get_contents($logo)); } $rest = new \sowerphp\core\Network_Http_Rest(); $rest->setAuth($this->Auth->User->hash); $response = $rest->post($this->request->url . '/api/dte/documentos/generar_pdf', $data); if ($response['status']['code'] != 200) { \sowerphp\core\Model_Datasource_Session::message($response['body'], 'error'); $this->redirect(str_replace('enviar_email', 'ver', $this->request->request) . '#email'); } $email->attach(['data' => $response['body'], 'name' => 'dte_' . $Emisor->rut . '-' . $Emisor->dv . '_T' . $DteEmitido->dte . 'F' . $DteEmitido->folio . '.pdf', 'type' => 'application/pdf']); // adjuntar XML $email->attach(['data' => base64_decode($DteEmitido->xml), 'name' => 'dte_' . $Emisor->rut . '-' . $Emisor->dv . '_T' . $DteEmitido->dte . 'F' . $DteEmitido->folio . '.xml', 'type' => 'application/xml']); // enviar email $status = $email->send($_POST['mensaje']); if ($status === true) { \sowerphp\core\Model_Datasource_Session::message('Se envió el DTE a: ' . implode(', ', $_POST['emails']), 'ok'); $this->redirect(str_replace('enviar_email', 'ver', $this->request->request)); } else { \sowerphp\core\Model_Datasource_Session::message('No fue posible enviar el email, por favor intente nuevamente.<br /><em>' . $status['message'] . '</em>', 'error'); $this->redirect(str_replace('enviar_email', 'ver', $this->request->request) . '#email'); } }