Invoice-Generator / invoice-generator-api

A free API for generating invoice PDFs and e-Invoices.
https://invoice-generator.com/developers
407 stars 54 forks source link

inplementation with Next.js #80

Open ZuritaKelvin opened 1 week ago

ZuritaKelvin commented 1 week ago

I m trying to build and proyect with Next.js and this invoice generator api but i cant found any example of an inplementation with Next.js or other framework.

syedmaazsaeed commented 6 days ago

Can I fix this Issue? I am a Full-Stack Software Developer and work with various Tech Stack like MERN , NEXT , REACT , FLUTTER, C#.

ZuritaKelvin commented 6 days ago

Of course! Below I will give more details about what I am trying to do and how I have been doing it. First in app/api/createInvoice/route.ts create the following endpoint to make the request to the API: `import axios from 'axios';

export async function POST(req: Request) { const apiKey = process.env.INVOICE_GENERATOR_API_KEY; if (!apiKey) { return Response.json({ error: 'Missing API key' }, { status: 401 }); }

try { const invoiceData = await req.json(); if (!invoiceData) { return Response.json({ error: 'Missing invoice data' }, { status: 400 }); }

const response = await axios.post('https://invoice-generator.com', invoiceData, {
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
});

if (!response || !response.data) {
  return Response.json({ error: 'Failed to generate invoice' }, { status: 500 });
}

return Response.json({ blob: response.data });

} catch (error) { return Response.json({ error: 'Failed to generate invoice' }, { status: 500 }); } } I make the request from the function that is responsible for calling this endpoint, obtaining the response and converting it to a File: axios .post('http://localhost:3000/api/createInvoice', invoice, { headers: { 'Content-Type': 'application/json', }, }) .then((response) => { if (!response.data) return; if (!data.crm) return; const crm = data.crm as File; const { blob } = response.data; if (!blob) return; const pdf = new File([blob], CRM_${invoice.number}_${invoice.date}.${fileTypeByUrl(crm.name)}, { type: 'application/pdf', }); Then I send this file along with more data to another endpoint that is responsible for sending an email with the files: formData.append('crm', data.crm); formData.append('crmName', CRM_${invoice.number}_${invoice.date}.${fileTypeByUrl(crm.name)}); formData.append('inv', pdf); formData.append('invName', Factura_${invoice.number}_${invoice.date}.pdf); formData.append('clientName', data.clientName); formData.append('dealerName', data.dealerName); formData.append('destination', data.destination); formData.append('date', data.date); formData.append('invoiceNumber', invoice.number); axios .post('http://localhost:3000/api/send', formData, { headers: { 'Content-Type': 'multipart/form-data', }, }) .then((response) => { console.log(response.data); setNotify(alert.successAlert('Factura enviada con exito', setNotify)); }) .catch((error) => { console.error(error); setNotify(alert.errorAlert('Error al enviar la factura', setNotify)); });` that endpoint use Resend. The main problem is that when receiving the email, the generated PDF shows a blank page without information. I made this issue here assuming that the problem is when generating the pdf file or when obtaining it. any help is welcome.thx

syedmaazsaeed commented 6 days ago

Open this Issue I will solve this

ZuritaKelvin commented 6 days ago

Is this issue not already open? The status is open. What exactly do you mean? This is the first time I've made an issue. Could you explain?

syedmaazsaeed commented 6 days ago

okay let me check again. I was having a network glitch not refreshing the Page But All is ok

syedmaazsaeed commented 6 days ago

Your Issue : This issue is likely related to how the PDF is being generated or how the data is being fetched and sent. Issue: The generated PDF file is showing a blank page when received via email. let me fix this

syedmaazsaeed commented 6 days ago
                                            Code with fixes for generating the PDF and sending it via email. 

createInvoice/route.ts (Invoice Generation Endpoint) :

import axios from 'axios';

export async function POST(req: Request) { const apiKey = process.env.INVOICE_GENERATOR_API_KEY; if (!apiKey) { return new Response(JSON.stringify({ error: 'Missing API key' }), { status: 401 }); }

try { const invoiceData = await req.json();

console.log('Invoice Data:', invoiceData);

if (!invoiceData) {
  return new Response(JSON.stringify({ error: 'Missing invoice data' }), { status: 400 });
}

const response = await axios.post('https://invoice-generator.com', invoiceData, {
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
});

console.log('API Response:', response.data);

if (!response || !response.data) {
  return new Response(JSON.stringify({ error: 'Failed to generate invoice' }), { status: 500 });
}

return new Response(JSON.stringify({ blob: response.data }), { status: 200 });

} catch (error) { console.error('Error generating invoice:', error); return new Response(JSON.stringify({ error: 'Failed to generate invoice' }), { status: 500 }); } }

  1. Frontend Call to Generate Invoice and Convert to File:

axios .post('http://localhost:3000/api/createInvoice', invoice, { headers: { 'Content-Type': 'application/json', }, }) .then((response) => { if (!response.data) return;

const { blob } = response.data;

console.log('Received Blob:', blob);

if (!blob) return;

const pdf = new File([blob], `CRM_${invoice.number}_${invoice.date}.pdf`, {
  type: 'application/pdf',
});

sendEmailWithInvoice(pdf);

}) .catch((error) => { console.error('Error generating PDF:', error); });

Email Sending Function:

function sendEmailWithInvoice(pdf) { const formData = new FormData(); formData.append('crm', data.crm);
formData.append('crmName', CRM_${invoice.number}_${invoice.date}.pdf); formData.append('inv', pdf);
formData.append('invName', Factura_${invoice.number}_${invoice.date}.pdf); formData.append('clientName', data.clientName); formData.append('dealerName', data.dealerName); formData.append('destination', data.destination); formData.append('date', data.date); formData.append('invoiceNumber', invoice.number);

axios .post('http://localhost:3000/api/send', formData, { headers: { 'Content-Type': 'multipart/form-data', }, }) .then((response) => { console.log('Invoice sent successfully:', response.data); setNotify(alert.successAlert('Factura enviada con exito', setNotify)); }) .catch((error) => { console.error('Error sending the invoice:', error); setNotify(alert.errorAlert('Error al enviar la factura', setNotify)); }); }

I have made the necessary fixes based on your requirements for generating the PDF and sending it via email. Check this and run this In Your Coding Environment. Copy this code and run it in your project. Let me know if this resolves the issue, or if you encounter any other problems.

ZuritaKelvin commented 6 days ago

Thank you very much for your contribution. I just found the solution on my own but I will check if this way works and I will let you know. In the meantime this has been the solution that worked for me to receive and be able to view the pdf correctly:

First the endpoint returns the file encrypted on base63 string: `import axios from 'axios';

export async function POST(req: Request) { const apiKey = process.env.INVOICE_GENERATOR_API_KEY; if (!apiKey) { return Response.json({ error: 'Missing API key' }, { status: 401 }); }

try { const invoiceData = await req.json(); if (!invoiceData) { return Response.json({ error: 'Missing invoice data' }, { status: 400 }); }

const response = await axios.post('https://invoice-generator.com', invoiceData, {
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
    'Content-Disposition': 'attachment; filename="invoice.pdf"',
  },
  responseType: 'arraybuffer',
});

if (!response || !response.data) {
  return Response.json({ error: 'Failed to generate invoice' }, { status: 500 });
}

const invoiceBuffer = Buffer.from(response.data);
const invoiceBase64 = invoiceBuffer.toString('base64');

return Response.json(invoiceBase64);

} catch (error) { return Response.json({ error: 'Failed to generate invoice' }, { status: 500 }); } } ` I directly pass the response to the other endpoint:

const file = response.data; formData.append('inv', file); Finally i convert the stringBase64 to a Buffer and send it in the POST request: const invoiceFile = formData.get('inv') as string; const pdfFile = Buffer.from(invoiceFile, 'base64'); I'm surprised that someone helped me so quickly after creating the issue. Many thanks to @syedmaazsaeed.