Tạo hóa đơn thanh toán là một khía cạnh quan trọng của bất kỳ doanh nghiệp nào và lập hóa đơn kỹ thuật số đã trở thành một thông lệ phổ biến trong các ngành khác nhau. Trong bối cảnh này, các nhà phát triển ứng dụng web thường phải đối mặt với nhiệm vụ tạo và gửi hóa đơn PDF theo chương trình. Cho dù bạn đang tự động hóa quy trình tạo và thông báo Hóa đơn hay phát triển Giao diện người dùng đồ họa (GUI) để chủ động nhắc nhở khách hàng về các Hóa đơn chưa thanh toán, thách thức kỹ thuật ban đầu nằm ở việc tạo Hóa đơn PDF. Mặc dù bạn có thể phát triển tập lệnh tùy chỉnh để tạo PDF, nhưng đó sẽ là một công việc quan trọng. Mặc dù các dịch vụ dựa trên web thuận tiện nhưng chúng có thể không phù hợp nếu bạn có thỏa thuận bảo mật với khách hàng của mình vì việc gửi dữ liệu đến dịch vụ của bên thứ ba qua internet có thể gây ra mối lo ngại. May mắn thay, Foxit's cung cấp một giải pháp nhanh chóng và an toàn để tạo các tệp PDF. Bằng cách sử dụng của họ , bạn có thể chuyển đổi bất kỳ tài liệu HTML nào, kể cả Hóa đơn, thành tệp PDF có thể được đính kèm vào email hoặc cung cấp cho khách hàng tải xuống từ ứng dụng web của bạn. thư viện PDF Trình chuyển đổi HTML sang PDF Hướng dẫn này sẽ hướng dẫn bạn qua quá trình tạo một ứng dụng tận dụng để tạo Hóa đơn PDF từ Hóa đơn HTML trong ứng dụng web. Sau khi được tạo, bạn sẽ sử dụng để gửi Hóa đơn qua SMTP đến địa chỉ email của khách hàng. Bạn có thể làm theo các bước được nêu dưới đây hoặc . Node.js Foxit PDF SDK Nodemailer truy cập cơ sở mã hoàn chỉnh trên kho lưu trữ GitHub của Foxit Xây dựng ứng dụng web để tạo và gửi hóa đơn PDF Trong hướng dẫn này, chúng tôi sẽ hướng dẫn bạn quy trình xây dựng một ứng dụng web cho phép bộ phận thanh toán của bạn quản lý các hóa đơn chưa thanh toán một cách hiệu quả. Bạn sẽ tạo nhiều tính năng khác nhau, bao gồm công cụ nội bộ để theo dõi, trang hiển thị hóa đơn chưa thanh toán và trang xem trước cho từng Hóa đơn. Người dùng sẽ có tùy chọn gửi email nhắc nhở cho khách hàng bằng Hóa đơn đính kèm. Đối với dự án này, chúng tôi sẽ sử dụng khung web, để tạo kiểu, và cho chức năng email. Thể hiện CSS thuần túy Nodemailer điều kiện tiên quyết: phiên bản 8+ và phiên bản 5+ Node.js NPM Foxit SDK (bạn có thể phiên bản từ trang web của họ) tải xuống bản dùng thử miễn phí Tiện ích chuyển đổi Foxit HTML sang PDF (tùy chọn, để kiểm tra vận chuyển email SMTP) bẫy thư Tạo ứng dụng Express mới Để tạo một ứng dụng web bản soạn sẵn Express mới, bạn cần sử dụng : trình tạo ứng dụng npx express-generator --git --view=hbs Thao tác này sẽ tạo một ứng dụng web có tệp và tập tin mẫu. .gitignore tay lái Tiếp theo, bạn cần thêm gói npm Nodemailer và cài đặt các phụ thuộc Express': npm i nodemailer && npm i Ứng dụng mặc định do Express tạo ra cung cấp cho bạn hai tệp định tuyến: và . Xóa định tuyến và tạo một tệp định tuyến mới có tên là . Thêm route mới này vào tệp của bạn và xóa : /routes/index.js /routes/users.js users.js invoices.js app.js usersRoute ... var indexRouter = require('./routes/index'); var invoicesRouter = require('./routes/invoices'); var app = express(); ... app.use('/', indexRouter); app.use('/invoices', invoicesRouter); ... Phần lớn công việc trong ứng dụng này nằm trong bộ định tuyến hóa đơn. Trước khi tạo tuyến đường, bạn sẽ cần một số dữ liệu có thể sử dụng. Trong ứng dụng thực tế, bạn có thể sẽ kết nối với cơ sở dữ liệu, nhưng với mục đích minh họa, hãy thêm dữ liệu hóa đơn của bạn vào tệp JSON. Tạo một tệp mới tại và thêm vào bên dưới: /data/invoices.json [ { "id": "47427759-9362-4f8e-bfe4-2d3733534e83", "customer": "Bins and Sons", "contact_name": "Verne McKim", "contact_email": "vmckim0@example.com", "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": "jpretious1@example.com", "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": "estollenberg2@example.com", "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 } ] Ba hóa đơn bạn có thể thấy ở trên chứa dữ liệu khách hàng, gói và thanh toán sẽ giúp bạn tạo hóa đơn trong phần tiếp theo. Tạo các tuyến hóa đơn Tệp sẽ tạo ba tuyến mới trong ứng dụng của bạn: routes/invoices.js – Danh sách tất cả các hóa đơn từ tệp dữ liệu phẳng ở trên. /invoices – Bản xem trước hóa đơn để người dùng có thể xem hóa đơn trông như thế nào trước khi gửi cho khách hàng. /invoices/:id – Điểm cuối tạo và gửi hóa đơn PDF tới email liên hệ có trong hồ sơ. /invoices/:id/email Mở tệp hóa và thêm đoạn mã sau để xác định hai tuyến đường đầu tiên: invoices.js 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; Ứng dụng của bạn gần như đã sẵn sàng để thử nghiệm, nhưng trước tiên bạn cần tạo hai tệp dạng xem. Thêm Chế độ xem và Kiểu Express tách biệt logic và cách trình bày thành và . Bây giờ thêm hai tệp mới vào thư mục : vàvoice . routes/ views/ views/ invoice-list.hbs invoice-single.hbs Ngoài ra, hãy thêm phần sau vào của bạn: 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}} Mở tệp hóa đơn và thêm tệp này: điện invoice-single.hbs <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> Để thêm kiểu vào biểu định kiểu ứng dụng của bạn và kết hợp để có giao diện hấp dẫn trực quan, vui lòng mở tệp và thay thế nội dung của tệp bằng đoạn mã sau. Thao tác này sẽ nhập Pure và tạo bố cục lưới cột đơn: Mô-đun CSS thuần túy views/layout.hbs <!DOCTYPE html> <html> <head> <title>{{title}}</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://unpkg.com/purecss@2.0.3/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> Mở của ứng dụng của bạn và thêm đoạn mã CSS sau: public/style.css file 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; } Mặc dù không bắt buộc nhưng việc thêm kiểu dáng vào hóa đơn của bạn có thể nâng cao vẻ ngoài chuyên nghiệp của chúng, vì Foxit nắm bắt tất cả kiểu dáng từ tài liệu HTML của bạn khi tạo tệp PDF. Bây giờ, bạn đã sẵn sàng để kiểm tra ứng dụng của mình. Vui lòng start trong giao diện dòng lệnh của bạn và mở trình duyệt web của bạn tới Bạn sẽ thấy một danh sách các hóa đơn tương tự như sau: run npm localhost:3000/invoices Nhấp vào “Xem” để xem trước từng hóa đơn. Trong hai bước cuối cùng, bạn sẽ sử dụng __ để tạo hóa đơn PDF. Sau khi hóa đơn được tạo, bạn sẽ tiến hành đính kèm chúng vào email bằng Nodemailer trước khi gửi chúng. công cụ Foxit__ HTML to PDF Tạo tệp PDF với Foxit SDK của Foxit cung cấp nhiều chức năng để tạo và thao tác PDF, bao gồm khả năng tạo tệp PDF từ tài liệu HTML hoặc URL. Quá trình tải xuống và biên dịch tệp thực thi HTML sang PDF có sẵn . Khi bạn đã thực hiện thành công bản demo từ dòng lệnh của mình, bạn có thể tiến hành các bước tiếp theo. đây Thư viện của nút bao gồm một hàm gọi là cho phép bạn thực thi các hàm dòng lệnh. Phương pháp này rất hữu ích để chạy các tệp thực thi C++ từ Foxit. Để thực thi tệp thực thi HTML sang PDF, vui lòng cập nhật tuyến đường của bạn bằng mã sau: child_process exec() /:id/email ... 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'); } }); }); Trước khi chạy mã này, vui lòng đảm bảo rằng bạn cập nhật biến để phản ánh đúng đường dẫn tới tệp thực thi của bạn. htmlToPdfPath htmltopdf Để gửi lời nhắc qua email cho hóa đơn, vui lòng quay lại danh sách hóa đơn của bạn và nhấp vào “Lời nhắc qua email” cho bất kỳ hóa đơn cụ thể nào. Hành động này sẽ kích hoạt ứng dụng Node gọi tệp thực thi . Đổi lại, tệp thực thi sẽ chuyển đổi hóa đơn từ tài liệu HTML do Express cung cấp thành tệp PDF. Bạn có thể định vị tệp PDF kết quả trong thư mục của ứng dụng web của mình. htmltopdf invoices/ Bây giờ bạn đã có khả năng tạo Hóa đơn PDF, bước cuối cùng là gửi các hóa đơn này cho khách hàng của bạn. Gửi email với Nodemailer cung cấp một giao diện thuận tiện cho phép bạn truy cập các lớp vận chuyển email khác nhau. SMTP là một trong những tùy chọn được sử dụng phổ biến nhất, nhưng bạn cũng có thể sử dụng các dịch vụ như Amazon SES hoặc lệnh của máy chủ làm các tùy chọn thay thế. Nodemailer sendmail Để kiểm tra Nodemailer, bạn có thể sử dụng , cho phép bạn ghi thông báo vào bảng điều khiển của mình. Để thiết lập và gửi thư của bạn bằng Nodemailer, hãy thêm đoạn mã sau ngay bên dưới câu lệnh “PDF được tạo và lưu vào…” trong định tuyến của bạn: tùy chọn JSON của luồng truyền tải console.log /invoices/:id/email ... // Construct the message const message = { from: 'accounting@example.com', 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'); } }); ... Vui lòng làm mới ứng dụng Node của bạn và nhấp vào “Lời nhắc qua email” cho bất kỳ hóa đơn nào. Lần này, bạn sẽ quan sát đối tượng dữ liệu email hoàn chỉnh được hiển thị dưới dạng JSON trong bảng điều khiển của mình. { "from": { "address": "accounting@example.com", "name": "" }, "to": [ { "address": "jpretious1@example.com", "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": "<65ea9109-8d5a-295e-9295-8e98e1b2c667@example.com>" } Chuỗi đại diện cho tệp PDF được mã hóa. Để cho ngắn gọn, tôi đã cắt bớt nó trong ví dụ trên. attachments.content Để kiểm tra email bằng cách sử dụng thực tế , bạn có thể dùng . Giả sử bạn có tài khoản với Mailtrap, hãy thay thế lệnh gọi bằng đoạn mã sau: máy chủ SMTP bẫy thư createTransport({jsonTransport: true}) createTransport({ host: "smtp.mailtrap.io", port: 2525, auth: { user: "<YOUR_MAILTRAP_USERID>", pass: "<YOUR_MAILTRAP_PASS>" } }) Khi gửi Hóa đơn qua email, Mailtrap sẽ chụp đầu ra và cung cấp cho bạn tùy chọn tải xuống tệp đính kèm PDF. Nếu bạn truy cập vào tài khoản Mailtrap của mình, bạn sẽ tìm thấy một email tương tự như ví dụ bên dưới: Khi bạn đã sẵn sàng triển khai ứng dụng của mình vào sản xuất, hãy thay thế thông tin đăng nhập SMTP của Mailtrap bằng máy chủ thư sản xuất. Ứng dụng web của chúng tôi hiện cung cấp khả năng tạo và tự động gửi Hóa đơn PDF cho khách hàng theo yêu cầu từ nhóm thanh toán của chúng tôi. Nếu bạn yêu cầu một giải pháp để trình bày Hóa đơn trực tuyến và gửi chúng dưới dạng PDF, ứng dụng của chúng tôi sẽ cung cấp một nền tảng đáng tin cậy. Mặc dù công cụ HTML to PDF của Foxit là một tùy chọn thuận tiện và hiệu quả để tạo tệp PDF, nhưng điều quan trọng cần lưu ý là họ cũng cung cấp nhiều giải pháp khác. Với họ , Foxit nổi bật là lựa chọn lý tưởng khi tích hợp chức năng PDF vào các ứng dụng web, thiết bị di động hoặc máy tính để bàn của bạn. bộ công cụ phát triển phần mềm (SDK) có sẵn cho nhiều nền tảng Cũng được xuất bản . ở đây