Skip to content

Exemplos Node.js

Exemplos práticos de como usar a API ZapFlare com Node.js.

Instalação

bash
npm install axios dotenv

Configuração Inicial

javascript
// config.js
require('dotenv').config();

const config = {
  apiKey: process.env.ZAPFLARE_API_KEY,
  apiUrl: 'https://api.zapflare.io',
  instanceId: process.env.ZAPFLARE_INSTANCE_ID
};

module.exports = config;

Cliente da API

javascript
// zapflare-client.js
const axios = require('axios');
const config = require('./config');

class ZapFlareClient {
  constructor(apiKey) {
    this.api = axios.create({
      baseURL: config.apiUrl,
      headers: {
        'Authorization': `Bearer ${apiKey}`,
        'Content-Type': 'application/json'
      }
    });
  }

  // Listar instâncias
  async listInstances() {
    const response = await this.api.get('/whatsapp/instances');
    return response.data;
  }

  // Criar instância
  async createInstance(name, webhookUrl) {
    const response = await this.api.post('/whatsapp/instances', {
      name,
      webhookUrl,
      webhookEvents: ['message', 'status']
    });
    return response.data;
  }

  // Enviar mensagem de texto
  async sendText(instanceId, to, message) {
    const response = await this.api.post(
      `/whatsapp/instances/${instanceId}/send-text`,
      { to, message }
    );
    return response.data;
  }

  // Enviar mídia
  async sendMedia(instanceId, to, mediaType, mediaUrl, caption) {
    const response = await this.api.post(
      `/whatsapp/instances/${instanceId}/send-media`,
      { to, mediaType, mediaUrl, caption }
    );
    return response.data;
  }
}

module.exports = ZapFlareClient;

Enviando Mensagens

javascript
// send-message.js
const ZapFlareClient = require('./zapflare-client');
const config = require('./config');

async function sendWelcomeMessage(phoneNumber) {
  const client = new ZapFlareClient(config.apiKey);
  
  try {
    const result = await client.sendText(
      config.instanceId,
      phoneNumber,
      '👋 Olá! Bem-vindo ao nosso atendimento.\n\n' +
      'Como posso ajudá-lo hoje?'
    );
    
    console.log('Mensagem enviada:', result);
  } catch (error) {
    console.error('Erro ao enviar mensagem:', error.response?.data || error.message);
  }
}

// Uso
sendWelcomeMessage('5511999999999');

Processando Webhooks

javascript
// webhook-server.js
const express = require('express');
const crypto = require('crypto');

const app = express();
app.use(express.json());

// Verificar assinatura do webhook
function verifyWebhookSignature(payload, signature, secret) {
  const hash = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  
  return hash === signature;
}

// Processar webhook
app.post('/webhook', (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  const payload = JSON.stringify(req.body);
  
  // Verificar autenticidade (se configurado)
  if (signature && !verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }
  
  const { event, instanceId, data } = req.body;
  
  switch (event) {
    case 'message':
      console.log(`Nova mensagem de ${data.from}: ${data.message}`);
      // Processar mensagem recebida
      handleIncomingMessage(instanceId, data);
      break;
      
    case 'status':
      console.log(`Status da instância ${instanceId}: ${data.status}`);
      break;
      
    case 'connection':
      console.log(`Evento de conexão: ${data.type}`);
      break;
  }
  
  res.json({ success: true });
});

async function handleIncomingMessage(instanceId, data) {
  // Lógica para processar mensagens recebidas
  const { from, message, type } = data;
  
  if (type === 'text' && message.toLowerCase() === 'oi') {
    // Responder automaticamente
    const client = new ZapFlareClient(config.apiKey);
    await client.sendText(instanceId, from, 'Olá! Como posso ajudar?');
  }
}

app.listen(3000, () => {
  console.log('Webhook server rodando na porta 3000');
});

Gerenciando Instâncias

javascript
// instance-manager.js
const ZapFlareClient = require('./zapflare-client');
const config = require('./config');

class InstanceManager {
  constructor(apiKey) {
    this.client = new ZapFlareClient(apiKey);
  }

  async checkInstanceStatus(instanceId) {
    const response = await this.client.api.get(
      `/whatsapp/instances/${instanceId}`
    );
    return response.data.data;
  }

  async waitForConnection(instanceId, maxAttempts = 60) {
    for (let i = 0; i < maxAttempts; i++) {
      const instance = await this.checkInstanceStatus(instanceId);
      
      if (instance.status === 'connected') {
        console.log('✅ Instância conectada!');
        return instance;
      }
      
      if (instance.status === 'error') {
        throw new Error('Erro ao conectar instância');
      }
      
      if (instance.qrCode) {
        console.log('📱 Escaneie o QR Code:');
        console.log(instance.qrCode);
      }
      
      // Aguardar 2 segundos antes de verificar novamente
      await new Promise(resolve => setTimeout(resolve, 2000));
    }
    
    throw new Error('Timeout ao aguardar conexão');
  }

  async setupNewInstance(name) {
    console.log('Criando nova instância...');
    const result = await this.client.createInstance(
      name,
      'https://meuapp.com/webhook'
    );
    
    const instanceId = result.data.id;
    console.log(`Instância criada: ${instanceId}`);
    
    console.log('Aguardando conexão...');
    await this.waitForConnection(instanceId);
    
    return instanceId;
  }
}

// Uso
async function main() {
  const manager = new InstanceManager(config.apiKey);
  
  try {
    const instanceId = await manager.setupNewInstance('Minha Instância');
    console.log(`Instância pronta para uso: ${instanceId}`);
  } catch (error) {
    console.error('Erro:', error.message);
  }
}

main();

Sistema de Notificações em Lote

javascript
// batch-notifier.js
const ZapFlareClient = require('./zapflare-client');
const config = require('./config');

class BatchNotifier {
  constructor(apiKey, instanceId) {
    this.client = new ZapFlareClient(apiKey);
    this.instanceId = instanceId;
    this.queue = [];
    this.processing = false;
  }

  addToQueue(phoneNumber, message) {
    this.queue.push({ phoneNumber, message });
    
    if (!this.processing) {
      this.processQueue();
    }
  }

  async processQueue() {
    this.processing = true;
    
    while (this.queue.length > 0) {
      const batch = this.queue.splice(0, 10); // Processar 10 por vez
      
      await Promise.all(
        batch.map(async ({ phoneNumber, message }) => {
          try {
            await this.client.sendText(this.instanceId, phoneNumber, message);
            console.log(`✅ Enviado para ${phoneNumber}`);
          } catch (error) {
            console.error(`❌ Erro ao enviar para ${phoneNumber}:`, error.message);
            // Recolocar na fila para retry
            this.queue.push({ phoneNumber, message });
          }
        })
      );
      
      // Aguardar entre lotes para evitar rate limiting
      if (this.queue.length > 0) {
        await new Promise(resolve => setTimeout(resolve, 1000));
      }
    }
    
    this.processing = false;
  }
}

// Uso
const notifier = new BatchNotifier(config.apiKey, config.instanceId);

// Enviar notificações em massa
const customers = [
  { phone: '5511999999999', name: 'João' },
  { phone: '5511888888888', name: 'Maria' },
  // ... mais clientes
];

customers.forEach(customer => {
  notifier.addToQueue(
    customer.phone,
    `Olá ${customer.name}! Temos novidades para você.`
  );
});

Tratamento de Erros

javascript
// error-handler.js
class APIErrorHandler {
  static handle(error) {
    if (error.response) {
      // Erro da API
      const { status, data } = error.response;
      
      switch (status) {
        case 401:
          console.error('Erro de autenticação. Verifique sua API key.');
          break;
        case 403:
          console.error('Acesso negado:', data.error?.message);
          break;
        case 404:
          console.error('Recurso não encontrado:', data.error?.message);
          break;
        case 429:
          console.error('Rate limit excedido. Aguarde antes de tentar novamente.');
          break;
        default:
          console.error(`Erro ${status}:`, data.error?.message || 'Erro desconhecido');
      }
    } else if (error.request) {
      // Erro de rede
      console.error('Erro de rede. Verifique sua conexão.');
    } else {
      // Outro erro
      console.error('Erro:', error.message);
    }
  }
}

// Uso com interceptor
const client = new ZapFlareClient(config.apiKey);

client.api.interceptors.response.use(
  response => response,
  error => {
    APIErrorHandler.handle(error);
    return Promise.reject(error);
  }
);

Próximos Passos

Desenvolvido com ❤️ pela equipe ZapFlare