Capítulo 4 de 15
Receber a mensagem: o webhook, com o código pronto
O endereço que escuta o WhatsApp, com código.
- Leitura: 1 min
- Custo para acompanhar: R$ 0
- Cadastro: nenhum
Manual gratuito de Certu · Atualizado em 15 de setembro de 2026 · ver o manual inteiro
Como receber mensagens do WhatsApp no meu servidor?
Resposta curta
Um endereço https que responde a duas chamadas: a verificação por GET, devolvendo o desafio da Meta, e as mensagens por POST. Ele confere a assinatura e responde 200 rápido.
O código
Salve como src/index.js.
src/index.jsjavascript
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (url.pathname !== '/webhook') return new Response('no ar');
// Verificacao: a Meta chama uma vez, quando voce cadastra o endereco.
if (request.method === 'GET') {
const ok = url.searchParams.get('hub.mode') === 'subscribe'
&& url.searchParams.get('hub.verify_token') === env.VERIFY_TOKEN;
return ok
? new Response(url.searchParams.get('hub.challenge'))
: new Response('token errado', { status: 403 });
}
if (request.method !== 'POST') return new Response('metodo nao permitido', { status: 405 });
const corpo = await request.text();
const assinatura = request.headers.get('x-hub-signature-256');
if (!(await assinaturaConfere(corpo, assinatura, env.APP_SECRET))) {
return new Response('assinatura invalida', { status: 401 });
}
// Confirmacao de entrega chega aqui tambem, sem messages. Ignore.
const valor = JSON.parse(corpo)?.entry?.[0]?.changes?.[0]?.value;
const mensagem = valor?.messages?.[0];
if (mensagem) console.log('mensagem de', mensagem.from, mensagem.text?.body);
return new Response('ok');
},
};
// Sem esta conferencia, qualquer um manda mensagem falsa pro seu endereco.
async function assinaturaConfere(corpo, cabecalho, segredo) {
if (!cabecalho || !segredo) return false;
const chave = await crypto.subtle.importKey(
'raw', new TextEncoder().encode(segredo),
{ name: 'HMAC', hash: 'SHA-256' }, false, ['sign'],
);
const assinado = await crypto.subtle.sign('HMAC', chave, new TextEncoder().encode(corpo));
const esperado = 'sha256=' + [...new Uint8Array(assinado)]
.map((b) => b.toString(16).padStart(2, '0')).join('');
// Comparacao de tempo constante.
if (esperado.length !== cabecalho.length) return false;
let diferenca = 0;
for (let i = 0; i < esperado.length; i += 1) {
diferenca |= esperado.charCodeAt(i) ^ cabecalho.charCodeAt(i);
}
return diferenca === 0;
}Publicar
VERIFY_TOKEN é uma senha sua. APP_SECRET fica em Configurações, Básico, no portal de desenvolvedores.
terminalbash
npm create cloudflare@latest atendente -- --type=hello-world
cd atendente
npx wrangler secret put VERIFY_TOKEN
npx wrangler secret put APP_SECRET
npx wrangler deployCadastrar na Meta
- Passo 1
Cole o endereço
Com /webhook no fim e a senha de VERIFY_TOKEN.
- Passo 2
Assine o campo messages
Sem isso nenhuma mensagem chega.
- Passo 3
Teste
Mande uma mensagem e veja com npx wrangler tail.
Pergunta frequente
Preciso mesmo conferir a assinatura?
Sim. Sem ela qualquer um manda mensagem falsa e você paga a IA.
E onde entra Certu
Em Certu esta parte é invisível e cuidada todo mês.
Montar um agente e testar sem cartão