paint-brush
Cómo crear una aplicación web de facturación en PDF usando NodeJS y Foxit PDF SDKpor@foxitsoftware
8,604 lecturas
8,604 lecturas

Cómo crear una aplicación web de facturación en PDF usando NodeJS y Foxit PDF SDK

por Foxit Software9m2023/06/23
Read on Terminal Reader

Demasiado Largo; Para Leer

La facturación digital se ha convertido en una práctica común en varias industrias. Los desarrolladores de aplicaciones web a menudo se enfrentan a la tarea de generar y enviar facturas en PDF mediante programación. La biblioteca __PDF de Foxit proporciona una solución rápida y segura para generar archivos PDF. En este tutorial, lo guiaremos a través del proceso de creación de una aplicación web que le permita a su departamento de facturación administrar las facturas impagas de manera efectiva.
featured image - Cómo crear una aplicación web de facturación en PDF usando NodeJS y Foxit PDF SDK
Foxit Software HackerNoon profile picture
0-item
1-item


La generación de facturas de pago es un aspecto crucial de cualquier negocio, y la facturación digital se ha convertido en una práctica común en varias industrias. En este contexto, los desarrolladores de aplicaciones web a menudo se enfrentan a la tarea de generar y enviar facturas en PDF mediante programación.


Ya sea que esté automatizando el proceso de notificación y generación de facturas o desarrollando una interfaz gráfica de usuario (GUI) para recordar de manera proactiva a los clientes las facturas pendientes, el desafío técnico inicial radica en generar facturas en PDF. Si bien podría desarrollar un script personalizado para la generación de PDF, sería una tarea importante. Si bien los servicios basados en la web son convenientes, es posible que no sean adecuados si tiene acuerdos de confidencialidad con sus clientes, ya que enviar datos a un servicio de terceros a través de Internet puede generar preocupaciones.


Afortunadamente, Foxit biblioteca PDF proporciona una solución rápida y segura para generar archivos PDF. Al utilizar su Conversor de HTML a PDF , puede convertir cualquier documento HTML, incluidas las facturas, en un archivo PDF que puede adjuntarse a un correo electrónico o ponerse a disposición de los clientes para que lo descarguen desde su aplicación web.


Este tutorial lo guiará a través del proceso de creación de un Nodo.js aplicación que aprovecha la SDK PDF de Foxit para generar facturas en PDF a partir de facturas en HTML dentro de una aplicación web. Una vez generado, utilizará Nodemailer para enviar la Factura vía SMTP a la dirección de correo electrónico del cliente. Puede seguir los pasos que se describen a continuación o acceda al código base completo en el repositorio GitHub de Foxit .


Creación de una aplicación web para crear y enviar facturas en PDF

En este tutorial, lo guiaremos a través del proceso de creación de una aplicación web que le permita a su departamento de facturación administrar las facturas impagas de manera efectiva. Creará varias funciones, incluida una herramienta interna para el seguimiento, una página que muestra las facturas pendientes y una página de vista previa para cada Factura. Los usuarios tendrán la opción de enviar recordatorios por correo electrónico a los clientes con la factura adjunta.


Para este proyecto, utilizaremos el Expresar marco web, CSS puro para peinar y Nodemailer para la funcionalidad de correo electrónico.


requisitos previos:


Creación de una nueva aplicación Express

Para crear una nueva aplicación web repetitiva Express, debe usar el generador de aplicaciones :


 npx express-generator --git --view=hbs


Esto creará una aplicación web con un archivo .gitignore y Bigote daliniano archivos de plantilla.

A continuación, debe agregar el paquete Nodemailer npm e instalar las dependencias de Express:


 npm i nodemailer && npm i


La aplicación predeterminada generada por Express le proporciona dos archivos de ruta: /routes/index.js y /routes/users.js . Elimine la ruta users.js y cree un nuevo archivo de ruta invoices.js . Agregue esta nueva ruta a su archivo app.js y elimine la usersRoute :


 ... var indexRouter = require('./routes/index'); var invoicesRouter = require('./routes/invoices'); var app = express(); ... app.use('/', indexRouter); app.use('/invoices', invoicesRouter); ...


La mayor parte del trabajo en esta aplicación está dentro del enrutador de facturas.


Antes de crear la ruta, necesitará algunos datos que pueda usar. En una aplicación real, probablemente se conectará a una base de datos, pero para fines de demostración, agregue los datos de su factura a un archivo JSON.


Cree un nuevo archivo en /data/invoices.json y agregue lo siguiente:


 [ { "id": "47427759-9362-4f8e-bfe4-2d3733534e83", "customer": "Bins and Sons", "contact_name": "Verne McKim", "contact_email": "[email protected]", "address": "3 Burning Wood Street", "city_state": "Memphis, TN 38118", "plan_id": "41595-5514", "plan_name": "Starter", "subtotal": 499.99, "fee": 50.00, "total": 549.99 }, { "id": "1afdd2fa-6353-437c-a923-e43baac506f4", customer": "Koepp Group", "contact_name": "Junia Pretious", "contact_email": "[email protected]", "address": "7170 Fairfield Hill", "city_state": "Los Angeles, CA 90026", "plan_id": "43419-355", "plan_name": "Professional", "amount": 999.99, "fee": 50.00, "total": 1049.99 }, { "id": "59c216f8-7471-4ec2-a527-ab3641dc49aa", "customer": "Lynch-Bednar", "contact_name": "Evelin Stollenberg", "contact_email": "[email protected]", "address": "9951 Erie Place", "city_state": "Chicago, IL 60605", "plan_id": "63323-714", "plan_name": "Starter", "amount": 499.99, "fee": 50.00, "total": 549.99 } ]


Las tres facturas que puede ver arriba contienen datos de clientes, planes y facturación que lo ayudarán a generar una factura en la siguiente sección.


Creando las Rutas de Facturas

El archivo routes/invoices.js creará tres nuevas rutas dentro de su aplicación:

  • /invoices : una lista de todas las facturas del archivo de datos planos anterior.
  • /invoices/:id : una vista previa de la factura para que los usuarios puedan ver cómo se verá la factura antes de enviarla al cliente.
  • /invoices/:id/email : un punto final que genera y envía la factura en PDF al correo electrónico de contacto que está en el archivo.


Abra el archivo invoices.js y agregue el siguiente fragmento de código para definir las dos primeras rutas:


 const express = require('express'); const router = express.Router(); const invoices = require('../data/invoices.json'); // Import exec to run the Foxit HTML to PDF executable const { exec } = require('child_process'); // Import nodemailer to send emails const nodemailer = require('nodemailer'); router.get('/', function(req, res) { res.render('invoice-list', { invoices: invoices, // Accepts errors and successes as query string arguments success: req.query['success'], error: req.query['error'], }); }); router.get('/:id', function(req, res) { const invoice = invoices.find(invoice => invoice.id === req.params['id']); // If the invoice doesn't exist, redirect the user back to the list page if (!invoice) { res.redirect('/invoices'); } // Make the date format pretty const date = new Date().toLocaleDateString("en", { year:"numeric", day:"2-digit", month:"2-digit", }); res.render('invoice-single', { invoice, date }); }); router.get('/:id/email', function(req, res) { // Coming soon. }); module.exports = router;


Su aplicación está casi lista para probarse, pero primero debe crear los dos archivos de vista.


Adición de vistas y estilos

Express separa la lógica y la presentación en routes/ y views/ . Ahora agregue dos nuevos archivos al directorio views/ : invoice-list.hbs y invoice-single.hbs .


Además, agregue lo siguiente a su archivo invoice-list.hbs :


 <h1><a href="/invoices">Unpaid Invoices</a></h1> {{#if success}} <p class="success"><strong>Success!</strong> The invoice has been sent to the client.</p> {{/if}} {{#if error}} <p class="error"><strong>Whoops!</strong> Something went wrong and your invoice could not be sent.</p> {{/if}} {{#each invoices}} <h3>{{this.customer}}</h3> <p>ID: {{this.id}} <br/> <a href="/invoices/{{this.id}}">View</a> | <a href="/invoices/{{this.id}}/email">Email Reminder</a> </p> {{/each}}


Abra el archivo invoice-single.hbs y agregue esto:


 <div class="pure-g"> <div class="pure-u-1-2"> <h1>Invoice</h1> </div> <div class="pure-u-1-2" style="text-align: right;"> <p class="muted">Issued on {{ date }}</p> </div> </div> <div class="pure-g"> <div class="pure-u-1-2"> <h3>Provider</h3> <p> <strong>Tiller, Inc.</strong><br/> 1255 S. Clark<br/> Chicago, IL 60608 </p> </div> <div class="pure-u-1-2" style="text-align: right;"> <h3>Billed to</h3> <p> <strong>{{invoice.customer}}</strong><br/> {{invoice.contact_name}}<br/> {{invoice.address}}<br/> {{invoice.city_state}} </p> </div> </div> <table class="pure-table pure-table-horizontal"> <thead> <tr> <th>ID</th> <th>Plan Name</th> <th class="text-right">Amount</th> </tr> </thead> <tbody> <tr> <td>{{invoice.plan_id}}</td> <td>{{invoice.plan_name}}</td> <td class="text-right">${{invoice.subtotal}}</td> </tr> <tr> <td></td> <td class="text-right">Subtotal:</td> <td class="text-right">${{invoice.subtotal}}</td> </tr> <tr> <td></td> <td class="text-right">Taxes and Fees:</td> <td class="text-right">${{invoice.fee}}</td> </tr> <tr class="bold"> <td></td> <td class="text-right">Total:</td> <td class="text-right">${{invoice.total}}</td> </tr> </tbody> </table> <div class="footer"> <p>Please make checks payable to <strong>Tiller, Inc</strong>. Invoices are due 30 days after date issued.</p> <p>Thank you for your business!</p> </div>


Para agregar estilos a la hoja de estilo de su aplicación e incorporar el Módulo CSS puro para una apariencia visualmente atractiva, abra el archivo views/layout.hbs y reemplace su contenido con el siguiente fragmento de código. Esto importará Pure y creará un diseño de cuadrícula de una sola columna:


 <!DOCTYPE html> <html> <head> <title>{{title}}</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://unpkg.com/[email protected]/build/pure-min.css" integrity="sha384-cg6SkqEOCV1NbJoCu11+bm0NvBRc8IYLRGXkmNrqUBfTjmMYwNKPWBTIKyw9mHNJ" crossorigin="anonymous"> <link rel='stylesheet' href='/stylesheets/style.css' /> </head> <body> <div class="container"> <div class="pure-g"> <div class="pure-u-1"> {{{body}}} </div> </div> </div> </body> </html>


Abra public/style.css file de su aplicación y agregue el siguiente fragmento de código CSS:


 body { background-color: #f7f7f7; color: #333333; } a { color: #156d6a; } h1 a, h2 a, h3 a { text-decoration: none; } table { width: 100%; } .container { background-color: #ffffff; max-width: 700px; margin: 0 auto; padding: 30px; } .muted { color: #999999; } .bold { font-weight: bold; } .text-right { text-align: right; } .footer p { margin-top: 30px; } .success { background-color: #c0f5f3; color: #0d928d; padding: 10px; } .error { background-color: #f5c0c0; color: #792525; padding: 10px; }


Si bien no es obligatorio, agregar estilos a sus facturas puede mejorar su apariencia profesional, ya que Foxit captura todo el estilo de su documento HTML al generar archivos PDF.

Ahora, está listo para probar su aplicación. run npm start en su interfaz de línea de comandos y abra su navegador web en localhost:3000/invoices Se le presentará una lista de facturas similar a la siguiente:


Haga clic en "Ver" para obtener una vista previa de cada factura.



En los últimos dos pasos, utilizará la herramienta Foxit__ HTML to PDF __ para generar facturas en PDF. Una vez generadas las facturas, procederás a adjuntarlas a un correo electrónico mediante Nodemailer antes de enviarlas.


Generación de PDF con Foxit

El SDK de Foxit ofrece una gama de funcionalidades para la creación y manipulación de PDF, incluida la capacidad de generar un archivo PDF a partir de un documento HTML o una URL. El proceso de descarga y compilación del ejecutable de HTML a PDF está disponible aquí . Una vez que haya ejecutado con éxito la demostración desde su línea de comando, puede continuar con los siguientes pasos.


La biblioteca child_process de Node incluye una función llamada exec() que le permite ejecutar funciones de línea de comandos. Este método es útil para ejecutar ejecutables de C++ desde Foxit. Para ejecutar el ejecutable de HTML a PDF, actualice su ruta /:id/email con el siguiente código:


 ... router.get('/:id/email', function(req, res) { // Set the executable path and output folder const htmlToPdfPath = '/path/to/foxit/html2pdf'; const outputFolder = __dirname + '/../invoices/'; // Get the invoice const invoice = invoices.find(invoice => invoice.id === req.params['id']); if (!invoice) { res.redirect('/invoices?error=1'); } // Convert the HTML to PDF exec( `${htmlToPdfPath} -html /invoices/${req.params['id']} -o ${outputFolder}${req.params['id']}.pdf`, (err, stdout, stderr) => { if (err || stderr) { console.error(err, stderr); res.redirect('/invoices?error=1'); } else { // For now: log the output file path console.log(`PDF generated and saved to ${outputFolder}${req.params['id']}.pdf`); res.redirect('/invoices?success=1'); } }); });


Antes de ejecutar este código, asegúrese de actualizar la variable htmlToPdfPath para reflejar la ruta correcta a su ejecutable htmltopdf .


Para enviar un recordatorio por correo electrónico de una factura, vuelva a su lista de facturas y haga clic en "Recordatorio por correo electrónico" para cualquier factura específica. Esta acción activará la aplicación Node para llamar al ejecutable htmltopdf . El ejecutable, a su vez, convertirá la factura del documento HTML servido por Express en un archivo PDF. Puede ubicar el archivo PDF resultante en el directorio invoices/ de su aplicación web.


Ahora que tiene la capacidad de generar facturas en PDF, el paso final es enviar estas facturas a sus clientes.

Envío de correos electrónicos con Nodemailer

Nodemailer ofrece una interfaz conveniente que le permite acceder a varias capas de transporte de correo electrónico. SMTP es una de las opciones más utilizadas, pero también puede utilizar servicios como Amazon SES o el comando sendmail de su servidor como alternativas.


Para probar Nodemailer, puede utilizar el opción JSON del transporte de flujo , que le permite registrar el mensaje en su consola. Para configurar su mensaje y enviarlo usando Nodemailer, agregue el siguiente fragmento de código justo debajo de la instrucción "PDF generado y guardado en..." console.log en su ruta /invoices/:id/email :


 ... // Construct the message const message = { from: '[email protected]', to: invoice.contact_email, subject: 'Reminder: Your Invoice from Tiller, Inc. is Due', html: `<p>Hey ${invoice.contact_name},</p><p>I just wanted to remind you that your invoice for last month's services is now due. I've attached it here for your convenience.</p><p>Thanks for your business!</p>`, attachments: [ { filename: 'invoice.pdf', path: `${outputFolder}${req.params['id']}.pdf`, } ] }; // Use mailer to send invoice nodemailer .createTransport({jsonTransport: true}) .sendMail(message, function (err, info) { if (err) { res.redirect('/invoices?error=1'); } else { console.log(info.message); res.redirect('/invoices?success=1'); } }); ...


Actualice su aplicación Node y haga clic en "Recordatorio por correo electrónico" para cualquiera de las facturas. Esta vez, observará el objeto de datos de correo electrónico completo que se muestra como JSON en su consola.


 { "from": { "address": "[email protected]", "name": "" }, "to": [ { "address": "[email protected]", "name": "" } ], "subject": "Reminder: Your Invoice from Tiller, Inc. is Due", "html": "<p>Hey Junia Pretious,</p><p>I just wanted to remind you that your invoice for last month's services is now due. I've attached it here for your convenience.</p><p>Thanks for your business!</p>", "attachments": [ { "content": "JVBERi0xLjMKJcTl8uXrp...", "filename": "invoice.pdf", "contentType": "application/pdf", "encoding": "base64" } ], "headers": {}, "messageId": "<[email protected]>" }


La cadena de attachments.content representa el archivo PDF codificado. En aras de la brevedad, lo he truncado en el ejemplo anterior.


Para probar el correo electrónico utilizando un servidor SMTP , puedes usar Trampa de correo . Suponiendo que tiene una cuenta con Mailtrap, reemplace la llamada createTransport({jsonTransport: true}) con el siguiente fragmento de código:


 createTransport({ host: "smtp.mailtrap.io", port: 2525, auth: { user: "<YOUR_MAILTRAP_USERID>", pass: "<YOUR_MAILTRAP_PASS>" } })


Al enviar la factura por correo electrónico, Mailtrap capturará el resultado y le brindará la opción de descargar el archivo PDF adjunto. Si accede a su cuenta de Mailtrap, encontrará un correo electrónico similar al ejemplo a continuación:



Una vez que esté listo para implementar su aplicación en producción, reemplace las credenciales SMTP de Mailtrap con un servidor de correo de producción. Nuestra aplicación web ahora ofrece la capacidad de generar y enviar automáticamente facturas en PDF a los clientes a pedido de nuestro equipo de facturación.


Si necesita una solución para presentar facturas en línea y enviarlas en formato PDF, nuestra aplicación proporciona una base confiable. Si bien la herramienta HTML a PDF de Foxit es una opción conveniente y eficiente para generar archivos PDF, es importante tener en cuenta que también ofrecen otras soluciones. Con su kits de desarrollo de software (SDK) disponibles para múltiples plataformas , Foxit se destaca como la opción ideal al integrar la funcionalidad de PDF en sus aplicaciones web, móviles o de escritorio.


También publicado aquí .