interface AbacatePayConfig { apiKey: string; baseUrl?: string; } interface CreateBillingParams { amount: number; metadata?: { donorName?: string; donorEmail?: string; message?: string; }; returnUrl?: string; completionUrl?: string; } interface BillingResponse { id: string; amount: number; status: "PENDING" | "PAID" | "EXPIRED" | "CANCELLED"; brCode?: string; // Código PIX copia-e-cola brCodeBase64?: string; // QR Code em Base64 expiresAt?: string; createdAt: string; } interface CreatePixParams { amount: number; // em centavos description: string; expiresIn?: number; // em segundos, padrão 600 (10 min) customer?: { name: string; email?: string; cellphone?: string; taxId?: string; }; } class AbacatePayClient { private config: AbacatePayConfig; constructor(config: AbacatePayConfig) { this.config = { ...config, baseUrl: config.baseUrl || "https://api.abacatepay.com/v1", }; } async createPixQrCode(params: CreatePixParams): Promise { const requestBody: any = { amount: params.amount, expiresIn: params.expiresIn || 600, // 10 minutos por padrão description: params.description, }; if (params.customer) { requestBody.customer = params.customer; } // Request body logging removido para segurança LGPD // Dados sensíveis não devem aparecer em logs const response = await fetch(`${this.config.baseUrl}/pixQrCode/create`, { method: "POST", headers: { Authorization: `Bearer ${this.config.apiKey}`, "Content-Type": "application/json", }, body: JSON.stringify(requestBody), }); if (!response.ok) { const errorData = await response.json().catch(() => ({})); console.error("PIX Error:", errorData); throw new Error(`Failed to create PIX: ${JSON.stringify(errorData)}`); } const result = await response.json(); if (result.error) { throw new Error(result.error); } return result.data; } async createBilling(params: CreateBillingParams): Promise { const response = await fetch(`${this.config.baseUrl}/billing`, { method: "POST", headers: { Authorization: `Bearer ${this.config.apiKey}`, "Content-Type": "application/json", }, body: JSON.stringify({ amount: params.amount * 100, // centavos metadata: params.metadata, return_url: params.returnUrl, completion_url: params.completionUrl, }), }); if (!response.ok) { const errorData = await response.json().catch(() => ({})); throw new Error( `Failed to create billing: ${errorData.message || response.statusText}`, ); } return response.json(); } async getBillingStatus(billingId: string): Promise { const response = await fetch( `${this.config.baseUrl}/billing/${billingId}`, { headers: { Authorization: `Bearer ${this.config.apiKey}`, }, }, ); if (!response.ok) { const errorData = await response.json().catch(() => ({})); throw new Error( `Failed to get billing status: ${ errorData.message || response.statusText }`, ); } const result = await response.json(); // AbacatePay retorna { error: null, data: { ... } } if (result.error) { throw new Error(result.error); } // Retornar apenas o data return result.data; } async getPixStatus(pixId: string): Promise { // AbacatePay usa o endpoint /billing/{id} para todos os tipos de billing const response = await fetch(`${this.config.baseUrl}/billing/${pixId}`, { headers: { Authorization: `Bearer ${this.config.apiKey}`, }, }); if (!response.ok) { const errorData = await response.json().catch(() => ({})); throw new Error( `Failed to get PIX status: ${errorData.message || response.statusText}`, ); } const result = await response.json(); if (result.error) { throw new Error(result.error); } return result.data; } verifyWebhookSignature(_payload: string, _signature: string): boolean { // Método mantido para compatibilidade, mas validação agora é feita via query param return true; } } // 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 das variáveis de ambiente (sem expor valores sensíveis) console.log("\n🔧 Configuração do AbacatePay:"); console.log(`📊 Environment: ${isProduction ? "PRODUCTION" : "TEST"}`); console.log(`📊 API Key: ${apiKey ? "✅ Configurada" : "❌ NÃO CONFIGURADA"}`); console.log( `📊 Webhook Secret: ${ process.env.ABACATEPAY_WEBHOOK_SECRET ? "✅ Configurada" : "❌ NÃO CONFIGURADA" }`, ); console.log("🔧 ==========================================\n"); export const abacatePay = new AbacatePayClient({ apiKey, }); export type { CreateBillingParams, BillingResponse };