Recebendo Mensagens
Aprenda como receber e processar mensagens através de webhooks.
Como Funciona
Quando alguém envia uma mensagem para seu número conectado:
- WhatsApp envia para o ZapFlare
- ZapFlare processa e valida
- ZapFlare envia para seu webhook
- Você processa e responde (opcional)
Configurando Webhook
Durante Criação da Instância
javascript
const instance = await createInstance({
name: "Atendimento",
webhookUrl: "https://meu-site.com/webhook/whatsapp"
});Atualizando Webhook Existente
bash
PUT /whatsapp/instances/{instanceId}
Content-Type: application/json
{
"webhookUrl": "https://novo-webhook.com/whatsapp"
}Estrutura do Webhook
Mensagem de Texto
json
{
"event": "messages.upsert",
"instance": {
"instanceName": "Atendimento",
"instanceId": "inst_abc123"
},
"data": {
"key": {
"remoteJid": "5511999999999@s.whatsapp.net",
"fromMe": false,
"id": "BAE5C8F9A2B4E231"
},
"message": {
"conversation": "Olá, preciso de ajuda!",
"messageTimestamp": "1704456789"
},
"messageType": "conversation",
"pushName": "João Silva",
"phone": "5511999999999"
}
}Mensagem com Mídia
json
{
"event": "messages.upsert",
"instance": {
"instanceName": "Atendimento",
"instanceId": "inst_abc123"
},
"data": {
"key": {
"remoteJid": "5511999999999@s.whatsapp.net",
"fromMe": false,
"id": "BAE5C8F9A2B4E232"
},
"message": {
"imageMessage": {
"url": "https://mmg.whatsapp.net/...",
"mimetype": "image/jpeg",
"caption": "Veja esta imagem",
"fileLength": "43234",
"mediaKey": "..."
}
},
"messageType": "imageMessage",
"pushName": "João Silva",
"phone": "5511999999999"
}
}Implementando o Webhook
Node.js com Express
javascript
const express = require('express');
const crypto = require('crypto');
const app = express();
// Middleware para receber o body raw
app.use(express.raw({ type: 'application/json' }));
// Validar assinatura HMAC
function validateSignature(body, signature, secret) {
const hash = crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return `sha256=${hash}` === signature;
}
// Endpoint do webhook
app.post('/webhook/whatsapp', async (req, res) => {
// Validar assinatura
const signature = req.headers['x-hub-signature-256'];
const secret = process.env.WEBHOOK_SECRET;
if (!validateSignature(req.body, signature, secret)) {
return res.status(401).send('Invalid signature');
}
// Parse do evento
const event = JSON.parse(req.body);
// Processar diferentes tipos de eventos
switch (event.event) {
case 'messages.upsert':
await handleNewMessage(event.data);
break;
case 'messages.update':
await handleMessageUpdate(event.data);
break;
case 'connection.update':
await handleConnectionUpdate(event.data);
break;
}
// Sempre retornar 200 rapidamente
res.status(200).send('OK');
});
async function handleNewMessage(data) {
// Ignorar mensagens enviadas por nós
if (data.key.fromMe) return;
const from = data.phone;
const message = data.message.conversation ||
data.message.extendedTextMessage?.text ||
'';
console.log(`Nova mensagem de ${from}: ${message}`);
// Responder automaticamente
if (message.toLowerCase().includes('ajuda')) {
await sendMessage(from, 'Olá! Como posso ajudar você?');
}
}
app.listen(3000, () => {
console.log('Webhook rodando na porta 3000');
});Python com Flask
python
from flask import Flask, request, abort
import hmac
import hashlib
import json
app = Flask(__name__)
def validate_signature(body, signature, secret):
expected = hmac.new(
secret.encode(),
body,
hashlib.sha256
).hexdigest()
return f'sha256={expected}' == signature
@app.route('/webhook/whatsapp', methods=['POST'])
def webhook():
# Validar assinatura
signature = request.headers.get('X-Hub-Signature-256')
secret = 'seu_webhook_secret'
if not validate_signature(request.data, signature, secret):
abort(401)
# Processar evento
event = request.json
if event['event'] == 'messages.upsert':
handle_new_message(event['data'])
return 'OK', 200
def handle_new_message(data):
if data['key']['fromMe']:
return
phone = data['phone']
message = data['message'].get('conversation', '')
print(f'Nova mensagem de {phone}: {message}')
if __name__ == '__main__':
app.run(port=3000)Tipos de Eventos
messages.upsert
Nova mensagem recebida ou enviada
messages.update
Atualização de status (entregue, lido)
connection.update
Mudança no status da conexão
groups.update
Eventos de grupos (adição, remoção)
presence.update
Status online/digitando
Processamento Assíncrono
Para não bloquear o webhook:
javascript
const Queue = require('bull');
const messageQueue = new Queue('messages');
// No webhook
app.post('/webhook/whatsapp', async (req, res) => {
const event = JSON.parse(req.body);
// Adicionar à fila
await messageQueue.add('process', event);
// Responder imediatamente
res.send('OK');
});
// Processador
messageQueue.process('process', async (job) => {
const event = job.data;
// Processamento demorado aqui
await processEvent(event);
});Boas Práticas
- Responda Rápido - Retorne 200 em menos de 5 segundos
- Valide Assinaturas - Sempre verifique a autenticidade
- Idempotência - Trate mensagens duplicadas
- Logs - Registre todos os eventos
- Retry - Implemente reprocessamento para falhas
Testando Webhooks
Desenvolvimento Local
Use ngrok para expor seu servidor local:
bash
ngrok http 3000Configure o webhook com a URL do ngrok:
https://abc123.ngrok.io/webhook/whatsappTeste Manual
bash
POST /whatsapp/instances/{instanceId}/webhook/test