Pular para o conteúdo principal

Visão Geral

Esta página consolida as melhores práticas para integração com a API FireBanking, baseadas na experiência de milhares de integrações bem-sucedidas. Seguir estas recomendações garante integrações mais robustas, seguras e eficientes.

Tratamento de Erros

Implemente retry inteligente e fallbacks adequados

Performance

Otimize requisições e monitore latência

Monitoramento

Configure logs estruturados e alertas

Produção

Checklist completo para deploy seguro

Tratamento de Erros e Retry

Estratégia de Retry

Retry com Exponential Backoff

class FireBankingClient {
  constructor(apiKey, options = {}) {
    this.apiKey = apiKey;
    this.maxRetries = options.maxRetries || 3;
    this.baseDelay = options.baseDelay || 1000; // 1 segundo
  }

  async makeRequest(url, options, attempt = 1) {
    try {
      const response = await fetch(url, {
        ...options,
        headers: {
          'x-api-key': this.apiKey,
          'Content-Type': 'application/json',
          ...options.headers
        }
      });

      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
      }

      return await response.json();

    } catch (error) {
      // Erros que devem ser retentados
      const retryableErrors = [408, 429, 500, 502, 503, 504];
      const shouldRetry = retryableErrors.includes(error.status) ||
                         error.code === 'ECONNRESET' ||
                         error.code === 'ETIMEDOUT';

      if (shouldRetry && attempt <= this.maxRetries) {
        const delay = this.baseDelay * Math.pow(2, attempt - 1);
        console.log(`Retry ${attempt}/${this.maxRetries} after ${delay}ms`);

        await new Promise(resolve => setTimeout(resolve, delay));
        return this.makeRequest(url, options, attempt + 1);
      }

      throw error;
    }
  }
}

Classificação de Erros

Erros que NÃO devem ser retentados:
{
  "400": "Bad Request - Dados inválidos",
  "401": "Unauthorized - Chave de API inválida",
  "403": "Forbidden - Operação não permitida",
  "404": "Not Found - Recurso não encontrado",
  "422": "Unprocessable Entity - Validação falhou"
}
Ação recomendada: Corrigir dados e tentar novamente
Erros que devem ser retentados:
{
  "500": "Internal Server Error - Erro interno",
  "502": "Bad Gateway - Problema de gateway",
  "503": "Service Unavailable - Serviço indisponível",
  "504": "Gateway Timeout - Timeout do gateway"
}
Ação recomendada: Retry com exponential backoff
// Tratamento especial para rate limiting
if (error.status === 429) {
  const retryAfter = error.headers['retry-after'] || 60;
  console.log(`Rate limited. Retrying after ${retryAfter}s`);
  await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
  return this.makeRequest(url, options, attempt);
}

Performance e Otimização

Pool de Conexões

const https = require('https');

// Agent com pool de conexões
const agent = new https.Agent({
  keepAlive: true,
  keepAliveMsecs: 30000,
  maxSockets: 50,
  maxFreeSockets: 10,
  timeout: 60000
});

// Uso com fetch ou axios
const response = await fetch(url, {
  agent: agent,
  headers: { 'x-api-key': apiKey }
});

Cache de Consultas

Cache Inteligente
class PaymentCache {
  constructor(ttl = 300000) { // 5 minutos
    this.cache = new Map();
    this.ttl = ttl;
  }

  get(key) {
    const item = this.cache.get(key);
    if (!item) return null;

    if (Date.now() > item.expiry) {
      this.cache.delete(key);
      return null;
    }

    return item.data;
  }

  set(key, data) {
    this.cache.set(key, {
      data,
      expiry: Date.now() + this.ttl
    });
  }

  // Cache para consultas de status
  async getPaymentStatus(transactionId) {
    const cacheKey = `payment_status_${transactionId}`;
    let status = this.get(cacheKey);

    if (!status) {
      status = await this.apiClient.getPayment(transactionId);

      // Cache apenas status finais
      if (['APPROVED', 'DENIED', 'CANCELLED'].includes(status.status)) {
        this.set(cacheKey, status);
      }
    }

    return status;
  }
}

Timeout Adequados

Configuração de Timeouts
const timeoutConfig = {
  // Operações de consulta
  read: 10000,    // 10 segundos

  // Criação de transações
  create: 30000,  // 30 segundos

  // Operações críticas (captura, cancelamento)
  critical: 60000 // 60 segundos
};

async function createPayment(paymentData) {
  return await makeRequest(
    '/credit-card/v1/payment',
    {
      method: 'POST',
      body: JSON.stringify(paymentData),
      signal: AbortSignal.timeout(timeoutConfig.create)
    }
  );
}

Monitoramento e Observabilidade

Logs Estruturados

const winston = require('winston');

const logger = winston.createLogger({
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.errors({ stack: true }),
    winston.format.json()
  )
});

// Log de transação
function logTransaction(event, data) {
  logger.info('firebanking_transaction', {
    event,
    transaction_id: data.transactionId,
    external_id: data.externalId,
    amount: data.amount,
    payment_method: data.payment_method,
    status: data.status,
    processing_time_ms: data.processing_time,
    api_version: 'v1',
    timestamp: new Date().toISOString()
  });
}

// Uso
logTransaction('payment_created', {
  transactionId: 'txn_123',
  externalId: 'order_456',
  amount: 100.00,
  payment_method: 'credit_card',
  status: 'processing',
  processing_time: 1250
});

Métricas Importantes

Métricas de Performance

Métricas com Prometheus
const promClient = require('prom-client');

// Contador de transações
const transactionCounter = new promClient.Counter({
  name: 'firebanking_transactions_total',
  help: 'Total de transações processadas',
  labelNames: ['method', 'status']
});

// Histograma de latência
const requestDuration = new promClient.Histogram({
  name: 'firebanking_request_duration_seconds',
  help: 'Duração das requisições para FireBanking',
  labelNames: ['endpoint', 'method'],
  buckets: [0.1, 0.5, 1, 2, 5, 10]
});

// Gauge para taxa de sucesso
const successRate = new promClient.Gauge({
  name: 'firebanking_success_rate',
  help: 'Taxa de sucesso das transações'
});

// Middleware para medir performance
function measurePerformance(endpoint) {
  const end = requestDuration.startTimer({ endpoint });

  return {
    success: () => {
      end();
      transactionCounter.inc({ method: endpoint, status: 'success' });
    },
    error: () => {
      end();
      transactionCounter.inc({ method: endpoint, status: 'error' });
    }
  };
}

Alertas Recomendados

Configure alertas para:
  • Taxa de erro > 5% em 5 minutos
  • Latência P95 > 3 segundos
  • Taxa de timeout > 1%
  • Queda na taxa de sucesso > 10%
# Exemplo Prometheus Alert
- alert: HighErrorRate
  expr: rate(firebanking_transactions_total{status="error"}[5m]) > 0.05
  for: 2m
  labels:
    severity: warning
  annotations:
    summary: "Alta taxa de erro na API FireBanking"
Monitore:
  • Volume anormal de transações
  • Spike em transações negadas
  • Webhooks falhando consecutivamente
  • Tentativas de pagamento sem sucesso

Implementação por Ambiente

Desenvolvimento

version: '3.8'
services:
  app:
    build: .
    environment:
      - NODE_ENV=development
      - FIREBANKING_API_KEY=SUA_CHAVE_DE_API
      - FIREBANKING_BASE_URL=https://api-gateway.firebanking.dev
      - LOG_LEVEL=debug
    ports:
      - "3000:3000"

  # Mock para webhooks em desenvolvimento
  webhook-mock:
    image: mockserver/mockserver
    ports:
      - "1080:1080"

Staging/Homologação

Testes de Carga

Teste de Performance com Artillery
// artillery.yml
config:
  target: 'https://api-gateway.firebanking.dev/v1'
  phases:
    - duration: 60
      arrivalRate: 10
  defaults:
    headers:
      x-api-key: 'SUA_CHAVE_DE_API'

scenarios:
  - name: "Criar pagamento"
    weight: 70
    flow:
      - post:
          url: "/credit-card/v1/payment"
          json:
            purchaseValue: 100
            installments: 1
            externalId: "perf_test_{{ $randomString() }}"

  - name: "Consultar status"
    weight: 30
    flow:
      - get:
          url: "/credit-card/v1/payment/{{ transactionId }}"

Produção

Health Checks

Health Check Endpoint
app.get('/health', async (req, res) => {
  const checks = {
    timestamp: new Date().toISOString(),
    status: 'ok',
    checks: {}
  };

  try {
    // Verificar conectividade com FireBanking
    const start = Date.now();
    await firebankingClient.getAccountBalance();
    checks.checks.firebanking = {
      status: 'healthy',
      responseTime: Date.now() - start
    };

  } catch (error) {
    checks.status = 'error';
    checks.checks.firebanking = {
      status: 'unhealthy',
      error: error.message
    };
  }

  const httpStatus = checks.status === 'ok' ? 200 : 503;
  res.status(httpStatus).json(checks);
});

Checklist de Produção

Pré-Deploy

  • Credenciais
    • Chaves de produção configuradas
    • Secrets em serviço seguro
    • Rotação de chaves agendada
  • Configuração
    • URLs de produção validadas
    • Timeouts adequados configurados
    • Pool de conexões otimizado
    • Rate limiting implementado
  • Monitoramento
    • Logs estruturados ativos
    • Métricas sendo coletadas
    • Alertas configurados
    • Health checks funcionando

Pós-Deploy

  • Validação
    • Transação de teste executada
    • Webhooks recebidos corretamente
    • Métricas sendo reportadas
    • Logs estruturados visíveis
  • Monitoramento
    • Dashboard de monitoramento ativo
    • Alertas testados
    • On-call configurado
    • Runbook documentado

Manutenção Contínua

  • Segurança
    • Chaves rotacionadas periodicamente
    • Logs de segurança analisados
    • Vulnerabilidades verificadas
    • Compliance validado
  • Performance
    • Métricas analisadas semanalmente
    • Otimizações implementadas
    • Capacity planning atualizado
    • SLAs monitorados

Padrões de Integração

Padrão Singleton para Cliente

Client Singleton
class FireBankingClientSingleton {
  constructor() {
    if (FireBankingClientSingleton.instance) {
      return FireBankingClientSingleton.instance;
    }

    this.client = new FireBankingClient({
      apiKey: process.env.FIREBANKING_API_KEY,
      baseUrl: process.env.FIREBANKING_BASE_URL,
      timeout: 30000,
      retries: 3
    });

    FireBankingClientSingleton.instance = this;
    return this;
  }

  getClient() {
    return this.client;
  }
}

// Uso
const client = new FireBankingClientSingleton().getClient();

Padrão Circuit Breaker

Circuit Breaker
class CircuitBreaker {
  constructor(threshold = 5, timeout = 60000) {
    this.failureThreshold = threshold;
    this.timeout = timeout;
    this.failureCount = 0;
    this.state = 'CLOSED'; // CLOSED, OPEN, HALF_OPEN
    this.lastFailureTime = null;
  }

  async execute(operation) {
    if (this.state === 'OPEN') {
      if (Date.now() - this.lastFailureTime > this.timeout) {
        this.state = 'HALF_OPEN';
      } else {
        throw new Error('Circuit breaker is OPEN');
      }
    }

    try {
      const result = await operation();

      if (this.state === 'HALF_OPEN') {
        this.state = 'CLOSED';
        this.failureCount = 0;
      }

      return result;

    } catch (error) {
      this.failureCount++;
      this.lastFailureTime = Date.now();

      if (this.failureCount >= this.failureThreshold) {
        this.state = 'OPEN';
      }

      throw error;
    }
  }
}

// Uso
const circuitBreaker = new CircuitBreaker();

async function createPayment(paymentData) {
  return circuitBreaker.execute(() =>
    firebankingClient.createPayment(paymentData)
  );
}

Troubleshooting Comum

Problemas Frequentes

Sintomas: Requisições falhando por timeoutDiagnóstico:
# Verificar latência de rede
curl -w "@curl-format.txt" -o /dev/null -s "https://api-gateway.firebanking.com.br/v1/account/balance"

# curl-format.txt
time_namelookup:  %{time_namelookup}\n
time_connect:     %{time_connect}\n
time_appconnect:  %{time_appconnect}\n
time_pretransfer: %{time_pretransfer}\n
time_total:       %{time_total}\n
Soluções:
  1. Aumentar timeout para 30-60 segundos
  2. Implementar retry com exponential backoff
  3. Usar pool de conexões keep-alive
Sintomas: Erro 429 em baixo volumeDiagnóstico:
  • Verificar se múltiplas instâncias compartilham mesma chave
  • Analisar padrão de requisições (burst vs distribuído)
  • Confirmar se retry está implementado corretamente
Soluções:
  1. Implementar jitter no retry
  2. Distribuir requisições ao longo do tempo
  3. Usar diferentes chaves por ambiente/serviço

🎯 Resultado: Seguindo estas práticas, você terá uma integração robusta, monitorada e pronta para escalar em produção.