NextJS Templates
Tutorial on Billing App with Next.js, Vercel and Back4app
26 min
in questo tutorial, costruiremo un completo invoicing app utilizzando next js come frontend, back4app come backend, e servizi aggiuntivi come clerk per l'autenticazione, stripe per i pagamenti, e resend per le notifiche email questa guida passerà attraverso la configurazione dell'autenticazione, la gestione delle fatture, l'elaborazione dei pagamenti e il deployment su vercel 1\ requisiti prima di iniziare, assicurati di avere i seguenti un account back4app ( registrati qui https //www back4app com/ ) un account clerk ( clerk io https //clerk dev/ ) per l'autenticazione un account stripe ( stripe com https //stripe com/ ) per l'elaborazione dei pagamenti un account resend ( resend io https //resend io/ ) per le notifiche email node js e npm installati ( installazione di node js https //nodejs org/ ) 2\ configurazione del backend (back4app) 2 1 crea un nuovo progetto in back4app accedi a back4app e crea un nuovo progetto naviga nel data browser e crea le seguenti classi 2 2 modelli di dati (classi) 2 2 1 utente (gestito automaticamente da clerk) idoggetto nomeutente email 2 2 2 organizzazione crea una classe chiamata organizzazione aggiungi le seguenti colonne nome (string) il nome dell'organizzazione idproprietario (puntatore< user>) punta alla classe utente (creata automaticamente da clerk) membri (array\<puntatore< user>>) un array di utenti che appartengono a questa organizzazione 2 2 3 cliente crea una classe chiamata cliente aggiungi queste colonne nome (string) nome del cliente email (string) email del cliente idorganizzazione (puntatore) organizzazione a cui appartiene questo cliente 2 2 4 fattura crea una classe chiamata fattura aggiungi queste colonne numerofattura (string) identificatore unico della fattura idcliente (puntatore) collega al cliente idorganizzazione (puntatore) collega all'organizzazione importo (numero) importo totale per la fattura stato (string) le opzioni includono 'bozza', 'inviata', 'pagata' e 'scaduta' datascadenza (data) la data di scadenza della fattura articoli (array) l'elenco degli articoli nella fattura 2 2 5 pagamento crea una classe chiamata pagamento aggiungi queste colonne idfattura (puntatore) collega alla fattura correlata importo (numero) importo del pagamento idsessionestripe (string) l'id della sessione stripe stato (string) stato del pagamento (ad es , 'in attesa', 'riuscito', 'fallito') 3\ configurazione del frontend (next js) 3 1 crea un progetto next js inizia configurando il tuo progetto next js con typescript, tailwind css e i componenti shadcn/ui npx create next app\@latest invoicing app typescript cd invoicing app npm install tailwindcss postcss autoprefixer npx tailwindcss init 3 2 configura tailwind css configura tailwind aggiornando il tailwind config js e aggiungendo gli stili a globals css in tailwind config js module exports = { content \[ ' /pages/ / {js,ts,jsx,tsx}', ' /components/ / {js,ts,jsx,tsx}', ], theme { extend {}, }, plugins \[], }; in styles/globals css @tailwind base; @tailwind components; @tailwind utilities; 3 3 installa parse sdk e servizi aggiuntivi installa le dipendenze necessarie per parse, clerk, stripe e resend npm install parse @clerk/clerk next stripe resend 3 4 inizializza parse sdk in next js in pages/ app tsx , inizializza il parse sdk con le tue credenziali back4app import { clerkprovider } from '@clerk/clerk react'; import parse from 'parse'; parse initialize('your app id', 'your javascript key'); parse serverurl = 'https //parseapi back4app com'; function myapp({ component, pageprops }) { return ( \<clerkprovider> \<component { pageprops} /> \</clerkprovider> ); } export default myapp; sostituisci 'your app id' e 'your javascript key' con le tue credenziali back4app 4\ implementazione dell'autenticazione utente 4 1 integrazione di clerk per l'autenticazione imposta clerk per l'autenticazione vai alla dashboard di clerk, crea un'applicazione e prendi le tue chiavi api aggiorna il tuo env local file con le chiavi di clerk next public clerk frontend api=your clerk frontend api clerk api key=your clerk api key ora crea pages/sign in tsx e pages/sign up tsx per la funzionalità di accesso e registrazione utilizzando i componenti di clerk in pages/sign in tsx import { signin } from '@clerk/clerk react'; export default function signinpage() { return \<signin />; } in pages/sign up tsx import { signup } from '@clerk/clerk react'; export default function signuppage() { return \<signup />; } 5\ gestione dell'organizzazione e dei clienti 5 1 crea organizzazioni gli utenti possono creare organizzazioni di cui sono proprietari crea una pagina pages/organizations/new\ tsx per creare nuove organizzazioni import { usestate } from 'react'; import parse from 'parse'; export default function neworganization() { const \[name, setname] = usestate(''); const handlecreateorganization = async () => { const organization = parse object extend('organization'); const organization = new organization(); organization set('name', name); organization set('ownerid', parse user current()); try { await organization save(); alert('organization created successfully!'); } catch (error) { console error('error creating organization ', error); } }; return ( \<div> \<h1>create new organization\</h1> \<input type="text" value={name} onchange={(e) => setname(e target value)} placeholder="organization name" /> \<button onclick={handlecreateorganization}>create\</button> \</div> ); } 5 2 gestire i clienti crea una pagina di gestione dei clienti pages/customers/new\ tsx per aggiungere nuovi clienti import { usestate } from 'react'; import parse from 'parse'; export default function newcustomer() { const \[name, setname] = usestate(''); const \[email, setemail] = usestate(''); const handlecreatecustomer = async () => { const customer = parse object extend('customer'); const customer = new customer(); customer set('name', name); customer set('email', email); customer set('organizationid', parse user current() get('organizationid')); try { await customer save(); alert('customer created successfully!'); } catch (error) { console error('error creating customer ', error); } }; return ( \<div> \<h1>create new customer\</h1> \<input type="text" value={name} onchange={(e) => setname(e target value)} placeholder="customer name" /> \<input type="email" value={email} onchange={(e) => setemail(e target value)} placeholder="customer email" /> \<button onclick={handlecreatecustomer}>create\</button> \</div> ); } 6\ gestione fatture 6 1 crea fatture crea una pagina di creazione delle fatture pages/invoices/new\ tsx per generare nuove fatture import { usestate } from 'react'; import parse from 'parse'; export default function newinvoice() { const \[invoicenumber, setinvoicenumber] = usestate(''); const \[amount, setamount] = usestate(0); const handlecreateinvoice = async () => { const invoice = parse object extend('invoice'); const invoice = new invoice(); invoice set('invoicenumber', invoicenumber); invoice set('amount', amount); invoice set('organizationid', parse user current() get('organizationid')); try { await invoice save(); alert('invoice created successfully!'); } catch (error) { console error('error creating invoice ', error); } }; return ( \<div> \<h1>create new invoice\</h1> \<input type="text" value={invoicenumber} onchange={(e) => setinvoicenumber(e target value)} placeholder="invoice number" /> \<input type="number" value={amount} onchange={(e) => setamount(parsefloat(e target value))} placeholder="amount" /> \<button onclick={handlecreateinvoice}>create\</button> \</div> ); } 6 2 visualizzazione fatture crea una pagina pages/invoices/index tsx per visualizzare tutte le fatture con opzioni di ordinamento e filtraggio import { useeffect, usestate } from 'react'; import parse from 'parse'; export default function invoiceslist() { const \[invoices, setinvoices] = usestate(\[]); useeffect(() => { const fetchinvoices = async () => { const invoice = parse object extend('invoice'); const query = new parse query(invoice); const results = await query find(); setinvoices(results); }; fetchinvoices(); }, \[]); return ( \<div> \<h1>invoices\</h1> {invoices map(invoice => ( \<div key={invoice id}> \<h2>invoice #{invoice get('invoicenumber')}\</h2> \<p>amount ${invoice get('amount')}\</p> \<p>status {invoice get('status')}\</p> \</div> ))} \</div> ); } 7\ elaborazione dei pagamenti (integrazione stripe) 7 1 configurare stripe checkout per elaborare i pagamenti, integra stripe in pages/invoices/\[id] tsx , implementa la creazione del link di pagamento utilizzando stripe checkout import { userouter } from 'next/router'; import { useeffect, usestate } from 'react'; import stripe from 'stripe'; export default function invoicedetail() { const router = userouter(); const { id } = router query; const \[invoice, setinvoice] = usestate(null); useeffect(() => { if (!id) return; const fetchinvoice = async () => { const invoice = parse object extend('invoice'); const query = new parse query(invoice); query equalto('objectid', id); const result = await query first(); setinvoice(result); }; fetchinvoice(); }, \[id]); const handlepayinvoice = async () => { const stripe = new stripe(process env stripe secret key); const session = await stripe checkout sessions create({ payment method types \['card'], line items \[ { price data { currency 'usd', product data { name `invoice #${invoice get('invoicenumber')}` }, unit amount invoice get('amount') 100, }, quantity 1, }, ], mode 'payment', success url window\ location origin + '/success', cancel url window\ location origin + '/cancel', }); window\ location href = session url; }; if (!invoice) return \<div>loading \</div>; return ( \<div> \<h1>invoice #{invoice get('invoicenumber')}\</h1> \<p>amount ${invoice get('amount')}\</p> \<button onclick={handlepayinvoice}>pay now\</button> \</div> ); } 8\ notifiche email (integrazione di rinvio) 8 1 inviare email di fattura imposta resend per inviare email di fattura ai clienti import { resend } from 'resend'; export default async function sendinvoiceemail(invoiceid) { const resend = new resend(process env resend api key); const invoice = await fetchinvoicedetails(invoiceid); // function to fetch invoice details const customer = await fetchcustomerdetails(invoice customerid); await resend sendemail({ from 'no reply\@invoicingapp com', to customer email, subject `invoice #${invoice invoicenumber}`, html `\<h1>invoice #${invoice invoicenumber}\</h1>\<p>amount ${invoice amount}\</p>`, }); } 9\ distribuzione su vercel per distribuire l'app su vercel, installa il vercel cli e distribuisci npm install g vercel vercel configura le variabili d'ambiente per clerk, stripe, resend e back4app nel dashboard di vercel prima della distribuzione 10\ conclusione in questo tutorial, abbiamo costruito un completo invoicing app con next js, integrato back4app per il backend, clerk per l'autenticazione, stripe per i pagamenti, e resend per le notifiche email abbiamo trattato la gestione degli utenti e delle organizzazioni, la creazione di fatture, l'elaborazione dei pagamenti e la distribuzione