NextJS Templates
Tutorial de Aplicativo de Faturamento com Next.js, Vercel e Back4app
26 min
neste tutorial, construiremos um aplicativo de faturamento usando next js como frontend, back4app como backend, e serviços adicionais como clerk para autenticação, stripe para pagamentos, e resend para notificações por e mail este guia irá orientar sobre como configurar autenticação, gerenciamento de faturas, processamento de pagamentos e implantação no vercel 1\ pré requisitos antes de começar, certifique se de ter o seguinte uma conta back4app ( https //www back4app com/ ) uma conta clerk ( https //clerk dev/ ) para autenticação uma conta stripe ( https //stripe com/ ) para processamento de pagamentos uma conta resend ( https //resend io/ ) para notificações por e mail node js e npm instalados ( https //nodejs org/ ) 2\ configurando o backend (back4app) 2 1 criar um novo projeto no back4app faça login no back4app e crie um novo projeto navegue até o data browser e crie as seguintes classes 2 2 modelos de dados (classes) 2 2 1 usuário (gerenciado automaticamente pelo clerk) objectid nome de usuário email 2 2 2 organização crie uma classe chamada organização adicione as seguintes colunas nome (string) o nome da organização ownerid (pointer< user>) aponta para a classe user (criada automaticamente pelo clerk) membros (array\<pointer< user>>) um array de usuários que pertencem a esta organização 2 2 3 cliente crie uma classe chamada cliente adicione estas colunas nome (string) nome do cliente email (string) email do cliente organizationid (pointer) organização à qual este cliente pertence 2 2 4 fatura crie uma classe chamada fatura adicione estas colunas numerofatura (string) identificador único da fatura idcliente (pointer) links para o cliente idorganizacao (pointer) links para a organização valor (number) valor total da fatura status (string) as opções incluem 'rascunho', 'enviado', 'pago' e 'atrasado' datavencimento (date) a data de vencimento da fatura itens (array) a lista de itens na fatura 2 2 5 pagamento crie uma classe chamada pagamento adicione estas colunas idfatura (pointer) links para a fatura relacionada valor (number) valor do pagamento idsessaostripe (string) o id da sessão do stripe status (string) status do pagamento (por exemplo, 'pendente', 'bem sucedido', 'falhou') 3\ configurando o frontend (next js) 3 1 criar um projeto next js comece configurando seu projeto next js com typescript, tailwind css e componentes shadcn/ui npx create next app\@latest invoicing app typescript cd invoicing app npm install tailwindcss postcss autoprefixer npx tailwindcss init 3 2 configurar o tailwind css configure o tailwind atualizando o tailwind config js e adicionando os estilos ao globals css em tailwind config js module exports = { content \[ ' /pages/ / {js,ts,jsx,tsx}', ' /components/ / {js,ts,jsx,tsx}', ], theme { extend {}, }, plugins \[], }; em styles/globals css @tailwind base; @tailwind components; @tailwind utilities; 3 3 instalar o sdk do parse e serviços adicionais instale as dependências necessárias para parse, clerk, stripe e resend npm install parse @clerk/clerk next stripe resend 3 4 inicializar o sdk do parse no next js em pages/ app tsx , inicialize o sdk do parse com suas credenciais do 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; substitua 'your app id' e 'your javascript key' pelas suas credenciais do back4app 4\ implementando a autenticação de usuário 4 1 integração do clerk para autenticação configure clerk para autenticação vá para o painel do clerk, crie um aplicativo e pegue suas chaves de api atualize seu env local arquivo com as chaves do clerk next public clerk frontend api=your clerk frontend api clerk api key=your clerk api key agora crie pages/sign in tsx e pages/sign up tsx para funcionalidade de login e cadastro usando os componentes do clerk em pages/sign in tsx import { signin } from '@clerk/clerk react'; export default function signinpage() { return \<signin />; } em pages/sign up tsx import { signup } from '@clerk/clerk react'; export default function signuppage() { return \<signup />; } 5\ organização e gestão de clientes 5 1 criar organizações os usuários podem criar organizações que possuem crie uma página pages/organizations/new\ tsx para criar novas organizações 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 gerenciando clientes crie uma página de gerenciamento de clientes pages/customers/new\ tsx para adicionar novos clientes 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\ gerenciamento de faturas 6 1 criar faturas crie uma página de criação de faturas pages/invoices/new\ tsx para gerar novas faturas 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 visualizando faturas crie uma página pages/invoices/index tsx para visualizar todas as faturas com opções de ordenação e filtragem 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\ processamento de pagamentos (integração com stripe) 7 1 configurar o stripe checkout para processar pagamentos, integre o stripe em pages/invoices/\[id] tsx , implemente a criação do link de pagamento usando o 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\ notificações por email (integração de reenvio) 8 1 enviando emails de fatura configure resend para enviar emails de fatura para os clientes 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\ implantação no vercel para implantar o aplicativo no vercel, instale o vercel cli e implante npm install g vercel vercel configure as variáveis de ambiente para clerk, stripe, resend e back4app no painel do vercel antes da implantação 10\ conclusão neste tutorial, construímos um completo aplicativo de faturamento com next js, integrado ao back4app para o backend, clerk para autenticação, stripe para pagamentos, e resend para notificações por email abordamos gerenciamento de usuários e organizações, criação de faturas, processamento de pagamentos e implantação