La génération de factures de paiement est un aspect crucial de toute entreprise, et la facturation numérique est devenue une pratique courante dans divers secteurs. Dans ce contexte, les développeurs d'applications Web sont souvent confrontés à la tâche de générer et d'envoyer par programmation des factures PDF.
Que vous automatisez le processus de génération et de notification des factures ou que vous développiez une interface utilisateur graphique (GUI) pour rappeler de manière proactive aux clients les factures impayées, le défi technique initial consiste à générer des factures PDF. Bien que vous puissiez développer un script personnalisé pour la génération de PDF, ce serait une entreprise importante. Bien que les services Web soient pratiques, ils peuvent ne pas convenir si vous avez des accords de confidentialité avec vos clients, car l'envoi de données à un service tiers sur Internet peut poser des problèmes.
Heureusement, Foxit
Ce didacticiel vous guidera tout au long du processus de création d'un
Dans ce didacticiel, nous vous guiderons tout au long du processus de création d'une application Web permettant à votre service de facturation de gérer efficacement les factures impayées. Vous créerez diverses fonctionnalités, dont un outil interne de suivi, une page affichant les factures impayées et une page de prévisualisation pour chaque facture. Les utilisateurs auront la possibilité d'envoyer des rappels par e-mail aux clients avec la facture jointe.
Pour ce projet, nous utiliserons le
Conditions préalables:
Pour créer une nouvelle application Web standard Express, vous devez utiliser le générateur d'application :
npx express-generator --git --view=hbs
Cela créera une application Web avec un fichier .gitignore
et
Ensuite, vous devez ajouter le package Nodemailer npm et installer les dépendances d'Express :
npm i nodemailer && npm i
L'application par défaut générée par Express vous fournit deux fichiers de route : /routes/index.js
et /routes/users.js
. Supprimez la route users.js
et créez un nouveau fichier de route appelé invoices.js
. Ajoutez cette nouvelle route à votre fichier app.js
et supprimez la usersRoute
:
... var indexRouter = require('./routes/index'); var invoicesRouter = require('./routes/invoices'); var app = express(); ... app.use('/', indexRouter); app.use('/invoices', invoicesRouter); ...
La majeure partie du travail dans cette application se trouve dans le routeur des factures.
Avant de créer l'itinéraire, vous aurez besoin de certaines données que vous pourrez utiliser. Dans une application réelle, vous vous connecterez probablement à une base de données, mais à des fins de démonstration, ajoutez vos données de facturation à un fichier JSON.
Créez un nouveau fichier dans /data/invoices.json
et ajoutez ce qui suit :
[ { "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 } ]
Les trois factures que vous pouvez voir ci-dessus contiennent des données de client, de forfait et de facturation qui vous aideront à générer une facture dans la section suivante.
Le fichier routes/invoices.js
créera trois nouvelles routes dans votre application :
/invoices
– Une liste de toutes les factures du fichier de données plat ci-dessus./invoices/:id
– Un aperçu de la facture permettant aux utilisateurs de voir à quoi ressemblera la facture avant de l'envoyer au client./invoices/:id/email
– Un point de terminaison qui génère et envoie la facture PDF à l'e-mail de contact enregistré.
Ouvrez le fichier invoices.js
et ajoutez l'extrait de code suivant pour définir les deux premières routes :
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;
Votre application est presque prête à être testée, mais vous devez d'abord créer les deux fichiers de vue.
Express sépare la logique et la présentation en routes/
et views/
. Ajoutez maintenant deux nouveaux fichiers dans le répertoire views/
: invoice-list.hbs
et invoice-single.hbs
.
Ajoutez également ce qui suit à votre fichier 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}}
Ouvrez le fichier invoice-single.hbs
et ajoutez ceci :
<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>
Pour ajouter des styles à la feuille de style de votre application et incorporer lesviews/layout.hbs
et remplacer son contenu par l'extrait de code suivant. Cela importera Pure et créera une disposition de grille à colonne unique :
<!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>
Ouvrez public/style.css file
de votre application et ajoutez l'extrait de code CSS suivant :
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; }
Bien que ce ne soit pas obligatoire, l'ajout de styles à vos factures peut améliorer leur apparence professionnelle, car Foxit capture tout le style de votre document HTML lors de la génération de PDF.
Vous êtes maintenant prêt à tester votre application. Veuillez run npm
start dans votre interface de ligne de commande et ouvrez votre navigateur Web sur localhost:3000/invoices
Une liste de factures semblable à celle-ci vous sera présentée :
Cliquez sur "Voir" pour prévisualiser chaque facture.
Au cours des deux dernières étapes, vous utiliserez l' outil Foxit__ HTML vers PDF __ pour générer des factures PDF. Une fois les factures générées, vous devrez ensuite les joindre à un e-mail à l'aide de Nodemailer avant de les envoyer.
Le SDK de Foxit offre une gamme de fonctionnalités pour la création et la manipulation de PDF, y compris la possibilité de générer un fichier PDF à partir d'un document HTML ou d'une URL. Le processus de téléchargement et de compilation de l'exécutable HTML vers PDF est disponible
La bibliothèque child_process
de Node inclut une fonction appelée exec()
qui vous permet d'exécuter des fonctions de ligne de commande. Cette méthode est utile pour exécuter des exécutables C++ à partir de Foxit. Pour exécuter l'exécutable HTML vers PDF, veuillez mettre à jour votre route /:id/email
avec le code suivant :
... 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'); } }); });
Avant d'exécuter ce code, assurez-vous de mettre à jour la variable htmlToPdfPath
pour refléter le chemin correct vers votre exécutable htmltopdf
.
Pour envoyer un rappel par e-mail pour une facture, veuillez revenir à votre liste de factures et cliquer sur "Rappel par e-mail" pour une facture spécifique. Cette action déclenchera l'application Node pour appeler l'exécutable htmltopdf
. L'exécutable, à son tour, convertira la facture du document HTML servi par Express en un fichier PDF. Vous pouvez localiser le fichier PDF résultant dans le répertoire invoices/
de votre application Web.
Maintenant que vous avez la possibilité de générer des factures PDF, la dernière étape consiste à envoyer ces factures à vos clients.
sendmail
de votre serveur comme alternatives.
Pour tester Nodemailer, vous pouvez utiliser leconsole.log
"PDF généré et enregistré dans..." dans votre route /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'); } }); ...
Veuillez actualiser votre application Node et cliquer sur "Email Reminder" pour l'une des factures. Cette fois, vous observerez l'objet de données de messagerie complet affiché au format JSON dans votre console.
{ "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 chaîne attachments.content
représente le fichier PDF encodé. Par souci de brièveté, je l'ai tronqué dans l'exemple ci-dessus.
Pour tester l'e-mail à l'aide d'un vraicreateTransport({jsonTransport: true})
par l'extrait de code suivant :
createTransport({ host: "smtp.mailtrap.io", port: 2525, auth: { user: "<YOUR_MAILTRAP_USERID>", pass: "<YOUR_MAILTRAP_PASS>" } })
Lors de l'envoi de la facture par e-mail, Mailtrap capturera le résultat et vous offrira la possibilité de télécharger la pièce jointe au format PDF. Si vous accédez à votre compte Mailtrap, vous trouverez un e-mail similaire à l'exemple ci-dessous :
Une fois que vous êtes prêt à déployer votre application en production, remplacez les informations d'identification SMTP Mailtrap par un serveur de messagerie de production. Notre application Web offre désormais la possibilité de générer et d'envoyer automatiquement des factures PDF aux clients à la demande de notre équipe de facturation.
Si vous avez besoin d'une solution pour présenter des factures en ligne et les envoyer au format PDF, notre application fournit une base fiable. Bien que l'outil HTML vers PDF de Foxit soit une option pratique et efficace pour générer des PDF, il est important de noter qu'il propose également diverses autres solutions. Avec leur
Également publié ici .