Files
pagodera/lib/abacatepay.ts
T
Evandro Fonseca Junior ad62dd0de2 feat(abacatepay): enhance environment variable logging
Replace simple debug log with comprehensive logging of environment variables, including NODE_ENV, API key (masked), webhook secret, and base URL, to improve debugging and visibility in both development and production environments.
2025-10-26 21:59:39 -03:00

211 lines
5.6 KiB
TypeScript

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<BillingResponse> {
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;
}
console.log("🔍 PIX Request:", JSON.stringify(requestBody, null, 2));
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),
});
console.log("🔍 PIX Response Status:", response.status);
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();
console.log("🔍 PIX Success:", result);
if (result.error) {
throw new Error(result.error);
}
return result.data;
}
async createBilling(params: CreateBillingParams): Promise<BillingResponse> {
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<BillingResponse> {
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<BillingResponse> {
// 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 completo das variáveis de ambiente configuradas
console.log("\n🔧 ==========================================");
console.log("🔧 VARIÁVEIS DE AMBIENTE DO ABACATEPAY");
console.log("🔧 ==========================================");
console.log(`📊 NODE_ENV: ${process.env.NODE_ENV || "não definido"}`);
console.log(`📊 Environment: ${isProduction ? "PRODUCTION" : "TEST"}`);
console.log(
`📊 API Key: ${apiKey ? "✅ Configurada (masqueada)" : "❌ NÃO CONFIGURADA"}`
);
console.log(
`📊 API Key preview: ${
apiKey ? apiKey.substring(0, 10) + "..." : "não definida"
}`
);
console.log(
`📊 Webhook Secret: ${
process.env.ABACATEPAY_WEBHOOK_SECRET
? "✅ Configurada"
: "❌ NÃO CONFIGURADA"
}`
);
console.log(
`📊 Base URL: ${process.env.NEXT_PUBLIC_BASE_URL || "não definido"}`
);
console.log("🔧 ==========================================\n");
export const abacatePay = new AbacatePayClient({
apiKey,
});
export type { CreateBillingParams, BillingResponse };