diff --git a/ABACATEPAY_SETUP.md b/ABACATEPAY_SETUP.md new file mode 100644 index 0000000..13d68fb --- /dev/null +++ b/ABACATEPAY_SETUP.md @@ -0,0 +1,43 @@ +# Variáveis de Ambiente - AbacatePay + +## Configuração para Desenvolvimento/Teste + +```env +# Chave de API para ambiente de teste +ABACATE_TEST_APIKEY=your_test_api_key_here + +# ID da conta AbacatePay +ABACATEPAY_ACCOUNT_ID=your_account_id_here + +# URLs da aplicação +NEXT_PUBLIC_BASE_URL=http://localhost:3000 +NEXT_PUBLIC_ABACATEPAY_WEBHOOK_URL=http://localhost:3000/api/webhooks/abacatepay +``` + +## Configuração para Produção + +```env +# Chave de API para ambiente de produção (usado automaticamente quando NODE_ENV=production) +ABACATE_APIKEY=your_production_api_key_here + +# ID da conta AbacatePay +ABACATEPAY_ACCOUNT_ID=your_account_id_here + +# URLs da aplicação +NEXT_PUBLIC_BASE_URL=https://seudominio.com +NEXT_PUBLIC_ABACATEPAY_WEBHOOK_URL=https://seudominio.com/api/webhooks/abacatepay +``` + +## Como Funciona + +O sistema automaticamente escolhe a chave correta baseado no ambiente: + +- **Desenvolvimento/Teste**: Usa `ABACATE_TEST_APIKEY` +- **Produção**: Usa `ABACATE_APIKEY` (quando `NODE_ENV=production`) + +## Obtenção das Chaves + +1. Acesse o painel do AbacatePay +2. Vá em "Configurações" > "API Keys" +3. Gere uma chave para teste e outra para produção +4. Configure as URLs de webhook no painel do AbacatePay diff --git a/app/[locale]/apoiar/page.tsx b/app/[locale]/apoiar/page.tsx index 1dccefd..9bcef60 100644 --- a/app/[locale]/apoiar/page.tsx +++ b/app/[locale]/apoiar/page.tsx @@ -10,7 +10,7 @@ import { AccordionItem, AccordionTrigger, } from "@/components/ui/accordion"; -import { Heart, Server, Code, Shield, AlertTriangle } from "lucide-react"; +import { Heart } from "lucide-react"; import { getTranslations } from "next-intl/server"; import Link from "next/link"; import { ShareButton } from "@/components/share-button"; @@ -36,44 +36,19 @@ export default async function SupportPage({ const { locale } = await params; const t = await getTranslations({ locale, namespace: "donation" }); - // Dados mockados para demonstração + // Dados REAIS para demonstração const stats = { - totalSupporters: 1247, - totalRaised: 18542, - monthsOnline: 12, - uptime: 99.8, + monthsOnline: 1, + uptime: 100, }; - const transparencyData = [ - { - icon: Server, - title: t("transparency.hosting"), - percentage: 40, - description: t("transparency.hostingDesc"), - color: "text-blue-500", - }, - { - icon: Code, - title: t("transparency.development"), - percentage: 35, - description: t("transparency.developmentDesc"), - color: "text-green-500", - }, - { - icon: Shield, - title: t("transparency.support"), - percentage: 15, - description: t("transparency.supportDesc"), - color: "text-purple-500", - }, - { - icon: AlertTriangle, - title: t("transparency.emergency"), - percentage: 10, - description: t("transparency.emergencyDesc"), - color: "text-orange-500", - }, - ]; + // Custos mensais REAIS + const monthlyCosts = { + vps: 69, // R$ 69/mês + devHours: 40, // média horas/mês + devRate: 50, // R$ 50/hora + total: 2069, // R$ 69 + (40 * 50) + }; const faqItems = [ { @@ -136,58 +111,39 @@ export default async function SupportPage({ - {/* Transparência */} + {/* Custos Reais */}

- {t("transparency.title")} + {t("costs.title")}

-
- {transparencyData.map((item, idx) => ( -
-
-
- -
-
-
-

{item.title}

- {item.percentage}% -
-

- {item.description} -

-
-
-
- ))} +
+
+ {t("costs.vps")} + + {t("costs.vpsValue")} + +
+
+ {t("costs.dev")} + + {t("costs.devValue")} + +
+
+ {t("costs.total")} + + {t("costs.totalValue")} + +
- {/* Prova Social */} + {/* Estatísticas Simplificadas */}
-
-
-

- -

-

- {t("social.supporters")} -

-
-
-

- R$ -

-

- {t("social.raised")} -

-
+

diff --git a/app/api/donations/create/route.ts b/app/api/donations/create/route.ts index f7ec4b0..faa1434 100644 --- a/app/api/donations/create/route.ts +++ b/app/api/donations/create/route.ts @@ -17,22 +17,24 @@ export async function POST(request: NextRequest) { ); } - const billing = await abacatePay.createBilling({ + const billing = await abacatePay.createDonationBilling({ amount: body.amount, - metadata: { - donorName: body.donorName, - donorEmail: body.donorEmail, - message: body.message, - }, - returnUrl: `${process.env.NEXT_PUBLIC_BASE_URL}/apoiar/obrigado`, - completionUrl: `${process.env.NEXT_PUBLIC_BASE_URL}/api/donations/verify`, + donorEmail: body.donorEmail, + donorName: body.donorName, + message: body.message, }); + // AbacatePay pode retornar diferentes formatos + const pixCode = billing.pixCode || billing.qrCode; + const pixQrCode = billing.pixQrCode || billing.qrCode; + const paymentUrl = billing.url || billing.paymentUrl; + return NextResponse.json({ success: true, billingId: billing.id, - pixCode: billing.pixCode, - pixQrCode: billing.pixQrCode, + paymentUrl, // URL para redirecionar + pixCode, + pixQrCode, expiresAt: billing.expiresAt, }); } catch (error) { diff --git a/components/donation-card.tsx b/components/donation-card.tsx index 270390e..3e5334a 100644 --- a/components/donation-card.tsx +++ b/components/donation-card.tsx @@ -52,7 +52,11 @@ export function DonationCard({ const data: DonationResponse = await response.json(); - if (data.success && data.pixCode && data.pixQrCode) { + if (data.success && data.paymentUrl) { + // Redirecionar para página de pagamento do AbacatePay + window.location.href = data.paymentUrl; + } else if (data.success && data.pixCode && data.pixQrCode) { + // Fallback: mostrar modal com QR Code se disponível setPixData({ code: data.pixCode, qrCode: data.pixQrCode, diff --git a/lib/abacatepay.ts b/lib/abacatepay.ts index 92010ed..6f3384e 100644 --- a/lib/abacatepay.ts +++ b/lib/abacatepay.ts @@ -19,10 +19,13 @@ interface BillingResponse { id: string; amount: number; status: "PENDING" | "PAID" | "EXPIRED" | "CANCELLED"; - pixCode: string; - pixQrCode: string; - expiresAt: string; + pixCode?: string; + pixQrCode?: string; + qrCode?: string; + expiresAt?: string; createdAt: string; + url?: string; // URL para redirecionamento + paymentUrl?: string; // URL alternativa de pagamento } class AbacatePayClient { @@ -61,6 +64,56 @@ class AbacatePayClient { return response.json(); } + async createDonationBilling(params: { + amount: number; + donorEmail?: string; + donorName?: string; + message?: string; + }): Promise { + const requestBody = { + products: [ + { + external_id: `donation-${Date.now()}`, + name: "Doação - Tibia Trade Pagodera", + quantity: 1, + price: Math.round(params.amount * 100), // R$ para centavos + }, + ], + return_url: `${process.env.NEXT_PUBLIC_BASE_URL}/apoiar/obrigado`, + completion_url: `${process.env.NEXT_PUBLIC_BASE_URL}/api/donations/verify`, + }; + + console.log("🔍 AbacatePay Request URL:", `${this.config.baseUrl}/billing`); + console.log( + "🔍 AbacatePay Request Body:", + JSON.stringify(requestBody, null, 2) + ); + + const response = await fetch(`${this.config.baseUrl}/billing`, { + method: "POST", + headers: { + Authorization: `Bearer ${this.config.apiKey}`, + "Content-Type": "application/json", + }, + body: JSON.stringify(requestBody), + }); + + console.log("🔍 AbacatePay Response Status:", response.status); + console.log("🔍 AbacatePay Response OK:", response.ok); + + if (!response.ok) { + const errorData = await response.json().catch(() => ({})); + console.error("🔍 AbacatePay Error Response:", errorData); + throw new Error( + `Failed to create billing: ${errorData.message || response.statusText}` + ); + } + + const result = await response.json(); + console.log("🔍 AbacatePay Success Response:", result); + return result; + } + async getBillingStatus(billingId: string): Promise { const response = await fetch( `${this.config.baseUrl}/billing/${billingId}`, @@ -92,8 +145,20 @@ class AbacatePayClient { } // Instância do cliente (será configurada com variáveis de ambiente) +const isProduction = process.env.NODE_ENV === "production"; +const apiKey = isProduction + ? process.env.ABACATE_APIKEY || "demo_key" + : process.env.ABACATE_TEST_APIKEY || "demo_key"; + +// Log para debug (apenas em desenvolvimento) +if (process.env.NODE_ENV !== "production") { + console.log( + `🔧 AbacatePay: Using ${isProduction ? "PRODUCTION" : "TEST"} environment` + ); +} + export const abacatePay = new AbacatePayClient({ - apiKey: process.env.ABACATEPAY_API_KEY || "demo_key", + apiKey, accountId: process.env.ABACATEPAY_ACCOUNT_ID || "demo_account", }); diff --git a/messages/en.json b/messages/en.json index 85ced38..08d73cf 100644 --- a/messages/en.json +++ b/messages/en.json @@ -189,63 +189,70 @@ } }, "donation": { - "title": "Support Tibia Trade Pagodera", - "subtitle": "We keep the project free with help from people like you", + "title": "Support Project Development", + "subtitle": "Your voluntary donation helps maintain and evolve the platform", "story": { "title": "Our Project, Our Community", - "text": "Tibia Trade Pagodera was born from the passion to create a safer and more efficient trading experience for our community. We started as a small project, but with big dreams of revolutionizing how players trade items on the Pagodera server.\n\nOver the months, we faced technical challenges, learned from our community, and constantly evolved. Every line of code was written thinking of you, players who trust our platform for their trades.\n\nToday, we are more than a trading platform - we are a community united by passion for Tibia and mutual trust." + "text": "Tibia Trade Pagodera is developed with dedication to create the best trading experience for our community. Each voluntary donation helps us continue evolving and maintaining service quality.\n\nWe are not a company, we are developers passionate about Tibia who believe in total transparency. Every penny is invested directly in the project.\n\nYour trust and support make all the difference." }, "transparency": { - "title": "How We Use Your Donations", - "hosting": "Hosting & Infrastructure", - "development": "Development & Improvements", - "support": "Support & Moderation", + "title": "Total Cost Transparency", + "hosting": "VPS Infrastructure", + "development": "Development", + "support": "Maintenance & Support", "emergency": "Emergency Reserve", - "hostingDesc": "Servers, CDN and infrastructure to keep the platform always online", - "developmentDesc": "New features, fixes and improvements to user experience", - "supportDesc": "Support team and moderation to keep the community safe", - "emergencyDesc": "Reserve for emergencies and critical improvements" + "hostingDesc": "R$ 69/month - Dedicated server to ensure performance", + "developmentDesc": "R$ 50/hour - Real cost of development and improvements", + "supportDesc": "Monitoring, bug fixes and customer service", + "emergencyDesc": "Buffer for unforeseen situations and scalability" + }, + "costs": { + "title": "Estimated Monthly Costs", + "vps": "VPS (Server)", + "dev": "Development (average 40h/month)", + "total": "Total Monthly Estimate", + "vpsValue": "R$ 69/month", + "devValue": "R$ 2,000/month", + "totalValue": "R$ 2,069/month" }, "social": { - "supporters": "supporters", - "raised": "raised", - "months": "months online", + "months": "month online", "uptime": "uptime" }, "tiers": { "coffee": { "title": "A Coffee", - "description": "Helps with basic costs", + "description": "Equals ~10 minutes of development", "badge": "Popular" }, "lunch": { "title": "Team Lunch", - "description": "Keeps the server running for 1 day", + "description": "Equals ~30 minutes of development", "badge": "Recommended" }, "custom": { "title": "Custom Amount", - "description": "You choose how much you want to support" + "description": "You choose how much you want to contribute" } }, "cta": { - "support": "Support with PIX", + "support": "Make Donation", "share": "Share Project", - "final": "Every help makes a difference", - "subtitle": "Even $5 helps us keep the project alive and free for everyone" + "final": "Every contribution matters", + "subtitle": "Each donation helps us dedicate more time to the project and keep the infrastructure running" }, "faq": { "title": "Frequently Asked Questions", - "q1": "Where does my money go?", - "a1": "All donations are used exclusively to maintain and improve the platform. We publish quarterly reports showing exactly how the money was spent.", - "q2": "Do I get anything in return?", - "a2": "The project remains 100% free for everyone. Your reward is knowing you're helping maintain a tool that benefits the entire community.", + "q1": "Is the project free?", + "a1": "The project charges transaction fees to sustain itself. Donations are voluntary for those who want to contribute beyond normal usage fees.", + "q2": "Where does my donation go?", + "a2": "100% invested in the project: server cost (R$ 69/month) and development hours (R$ 50/hour). We maintain total transparency of expenses.", "q3": "How does PIX payment work?", - "a3": "You scan the QR Code or copy the PIX code and make the payment through your banking app. Payment is instant and secure.", - "q4": "Can I cancel my donation?", - "a4": "Donations are one-time and non-recurring. No cancellation needed - you pay only once for the chosen amount.", + "a3": "You choose the amount, we generate a QR Code or PIX code, you pay through your banking app. Instant and secure payment.", + "q4": "Do I get anything in return?", + "a4": "We don't offer direct benefits. Your donation is voluntary and helps the project evolve for everyone.", "q5": "Are you a company?", - "a5": "We are an independent project created by players for players. We are not a commercial company, just Tibia enthusiasts." + "a5": "No. We are independent developers passionate about Tibia. Transparency and community are our values." }, "supporters": { "title": "Our Amazing Supporters", diff --git a/messages/pt.json b/messages/pt.json index dd1c3cc..e75c509 100644 --- a/messages/pt.json +++ b/messages/pt.json @@ -189,63 +189,70 @@ } }, "donation": { - "title": "Apoie o Tibia Trade Pagodera", - "subtitle": "Mantemos o projeto gratuito com a ajuda de pessoas como você", + "title": "Apoie o Desenvolvimento do Projeto", + "subtitle": "Sua doação voluntária ajuda a manter e evoluir a plataforma", "story": { "title": "Nosso Projeto, Nossa Comunidade", - "text": "O Tibia Trade Pagodera nasceu da paixão por criar uma experiência de trading mais segura e eficiente para nossa comunidade. Começamos como um projeto pequeno, mas com grandes sonhos de revolucionar como os jogadores negociam itens no servidor Pagodera.\n\nAo longo dos meses, enfrentamos desafios técnicos, aprendemos com nossa comunidade e evoluímos constantemente. Cada linha de código foi escrita pensando em vocês, jogadores que confiam em nossa plataforma para suas negociações.\n\nHoje, somos mais que uma plataforma de trading - somos uma comunidade unida pela paixão pelo Tibia e pela confiança mútua." + "text": "O Tibia Trade Pagodera é desenvolvido com dedicação para criar a melhor experiência de trading para nossa comunidade. Cada doação voluntária nos ajuda a continuar evoluindo e mantendo a qualidade do serviço.\n\nNão somos uma empresa, somos desenvolvedores apaixonados por Tibia que acreditam em transparência total. Todo centavo é investido diretamente no projeto.\n\nSua confiança e apoio fazem toda a diferença." }, "transparency": { - "title": "Como Usamos Suas Doações", - "hosting": "Hospedagem & Infraestrutura", - "development": "Desenvolvimento & Melhorias", - "support": "Suporte & Moderação", - "emergency": "Reserva de Emergência", - "hostingDesc": "Servidores, CDN e infraestrutura para manter a plataforma sempre online", - "developmentDesc": "Novas funcionalidades, correções e melhorias na experiência do usuário", - "supportDesc": "Equipe de suporte e moderação para manter a comunidade segura", - "emergencyDesc": "Reserva para emergências e melhorias críticas" + "title": "Transparência Total de Custos", + "hosting": "Infraestrutura VPS", + "development": "Desenvolvimento", + "support": "Manutenção & Suporte", + "emergency": "Reserva para Emergências", + "hostingDesc": "R$ 69/mês - Servidor dedicado para garantir performance", + "developmentDesc": "R$ 50/hora - Custo real de desenvolvimento e melhorias", + "supportDesc": "Monitoramento, correções de bugs e atendimento", + "emergencyDesc": "Buffer para situações imprevistas e escalabilidade" + }, + "costs": { + "title": "Custos Mensais Estimados", + "vps": "VPS (Servidor)", + "dev": "Desenvolvimento (média 40h/mês)", + "total": "Total Mensal Estimado", + "vpsValue": "R$ 69/mês", + "devValue": "R$ 2.000/mês", + "totalValue": "R$ 2.069/mês" }, "social": { - "supporters": "apoiadores", - "raised": "arrecadados", - "months": "meses online", + "months": "mês online", "uptime": "uptime" }, "tiers": { "coffee": { "title": "Um Café", - "description": "Ajuda com custos básicos", + "description": "Equivale a ~10 minutos de desenvolvimento", "badge": "Popular" }, "lunch": { "title": "Almoço da Equipe", - "description": "Mantém o servidor rodando por 1 dia", + "description": "Equivale a ~30 minutos de desenvolvimento", "badge": "Recomendado" }, "custom": { "title": "Valor Livre", - "description": "Você escolhe quanto quer apoiar" + "description": "Você escolhe quanto quer contribuir" } }, "cta": { - "support": "Apoiar com PIX", + "support": "Fazer Doação", "share": "Compartilhar Projeto", - "final": "Toda ajuda faz diferença", - "subtitle": "Mesmo R$ 5 nos ajuda a manter o projeto vivo e gratuito para todos" + "final": "Toda contribuição é importante", + "subtitle": "Cada doação nos ajuda a dedicar mais tempo ao projeto e manter a infraestrutura funcionando" }, "faq": { "title": "Perguntas Frequentes", - "q1": "Para onde vai meu dinheiro?", - "a1": "Todas as doações são usadas exclusivamente para manter e melhorar a plataforma. Publicamos relatórios trimestrais mostrando exatamente como o dinheiro foi gasto.", - "q2": "Recebo algo em troca?", - "a2": "O projeto continua 100% gratuito para todos. Sua recompensa é saber que está ajudando a manter uma ferramenta que beneficia toda a comunidade.", + "q1": "O projeto é gratuito?", + "a1": "O projeto cobra taxas de transação para se manter. As doações são voluntárias para quem deseja contribuir além das taxas normais de uso.", + "q2": "Para onde vai minha doação?", + "a2": "100% investido no projeto: custo de servidor (R$ 69/mês) e horas de desenvolvimento (R$ 50/hora). Mantemos transparência total dos gastos.", "q3": "Como funciona o pagamento PIX?", - "a3": "Você escaneia o QR Code ou copia o código PIX e faz o pagamento pelo seu app bancário. O pagamento é instantâneo e seguro.", - "q4": "Posso cancelar minha doação?", - "a4": "As doações são únicas e não recorrentes. Não há cancelamento necessário - você paga apenas uma vez pelo valor escolhido.", + "a3": "Você escolhe o valor, geramos um QR Code ou código PIX, você paga pelo seu app bancário. Pagamento instantâneo e seguro.", + "q4": "Recebo algo em troca?", + "a4": "Não oferecemos benefícios diretos. Sua doação é voluntária e ajuda o projeto a evoluir para todos.", "q5": "Vocês são uma empresa?", - "a5": "Somos um projeto independente criado por jogadores para jogadores. Não somos uma empresa comercial, apenas apaixonados por Tibia." + "a5": "Não. Somos desenvolvedores independentes apaixonados por Tibia. Transparência e comunidade são nossos valores." }, "supporters": { "title": "Nossos Incríveis Apoiadores", diff --git a/types/donation.ts b/types/donation.ts index 5450cad..1807420 100644 --- a/types/donation.ts +++ b/types/donation.ts @@ -18,6 +18,7 @@ export interface DonationData { export interface DonationResponse { success: boolean; billingId?: string; + paymentUrl?: string; pixCode?: string; pixQrCode?: string; expiresAt?: string;