Adicionar a API do Vonage Verify ao backend
Como usar o SDK do servidor da Vonage
A Vonage disponibiliza uma API HTTP padrão nos bastidores. Isso significa que, em teoria, você poderia integrar o Verify enviando solicitações HTTP brutas você mesmo (por exemplo, com fetch, axios, etc.).
Então, por que usar o SDK do Vonage Node?
O uso do SDK é útil porque:
-
A autenticação é mais fácil e segura: o Verify utiliza autenticação baseada em JWT com uma chave privada. O SDK lida com o fluxo de assinatura corretamente, o que reduz a probabilidade de você cometer erros.
-
Código mais limpo: em vez de construir manualmente URLs e cabeçalhos e analisar formatos de resposta, você chama métodos como
newRequest()echeckCode(). -
Melhor manutenção: quando a Vonage atualiza a API ou adiciona recursos, o SDK geralmente é atualizado para acompanhar essas mudanças.
-
Menos “armadilhas”: aspectos como a formatação das solicitações e os campos esperados são tratados de maneira consistente.
Vamos adicionar o SDK ao nosso app.js arquivo:
require("dotenv").config();
const fs = require("fs");
const express = require("express");
const cors = require("cors");
const { Auth } = require("@vonage/auth");
const { Verify2 } = require("@vonage/verify2");
const app = express();
const port = process.env.PORT || 3000;
app.use(cors());
app.use(express.json());
// Create Vonage credentials (JWT auth)
const credentials = new Auth({
applicationId: process.env.VONAGE_APPLICATION_ID,
privateKey: process.env.VONAGE_PRIVATE_KEY_PATH,
});
// Verify client (Verify API v2)
const verifyClient = new Verify2(credentials);
// Health check endpoint
app.get('/health', (req, res) => {
res.json({ status: 'ok' });
});
// Run the server
app.listen(port, () => {
console.log(`Backend listening on port ${port}`);
});
O que está acontecendo aqui?
- O backend precisa comprovar à Vonage: “Tenho permissão para chamar essa API.”
- A Vonage utiliza JWT (JSON Web Tokens) assinados pela sua chave privada para essa comprovação.
- O SDK gera e anexa o JWT automaticamente sempre que faz uma chamada para a Vonage.
Iniciar verificação: POST /verification
Este endpoint inicia o processo de verificação. O aplicativo móvel envia uma solicitação ao seu backend com um número de telefone. Em seguida, o seu backend solicita à Vonage que inicie uma solicitação de verificação.
O que acontece neste endpoint?
- O usuário insere seu número de telefone no aplicativo móvel.
- O aplicativo móvel envia o número de telefone para o seu backend.
- Seu backend inicia uma solicitação de Verify:
- primeiras tentativas Autenticação silenciosa
- se isso não puder ser concluído, recorre a SMS
app.post("/verification", async (req, res) => {
const { phone } = req.body || {};
if (!phone) {
return res.status(400).json({ error: "Phone number is required." });
}
try {
const result = await verifyClient.newRequest({
brand: "DemoApp",
workflow: [
{ channel: "silent_auth", to: phone },
{ channel: "sms", to: phone },
],
});
return res.json({
request_id: result.requestId,
check_url: result.checkUrl,
});
} catch (error) {
const status = error?.response?.status || 500;
const details = error?.response?.data || error?.message;
console.error("Vonage Verify newRequest failed:", details);
return res.status(status).json({
error: "Failed to start verification",
details: typeof details === "string" ? details : undefined,
});
}
});
Compreensão request_id e check_url:
-
request_id: um identificador único para esta tentativa de verificação. Pense nisso como um “número de recibo” para a verificação. -
check_url: usado para autenticação silenciosa. Seu backend retorna essa URL para o aplicativo móvel. O aplicativo móvel a acessa para comprovar que “essa solicitação está vindo da rede móvel do número de telefone”.
Verifique o código de verificação: POST /check-code
Se a autenticação silenciosa falhar ou não estiver disponível, a Vonage recorrerá ao SMS e o usuário receberá um código. O aplicativo móvel envia o código para o seu backend juntamente com o request_id.
app.post("/check-code", async (req, res) => {
const { request_id, code } = req.body || {};
if (!request_id || !code) {
return res.status(400).json({ error: "request_id and code are required." });
}
try {
const status = await verifyClient.checkCode(request_id, code);
return res.json({
verified: status === "completed",
status,
});
} catch (error) {
const status = error?.response?.status || 400;
const details = error?.response?.data || error?.message;
return res.status(status).json({
error: "Failed to check code",
details: typeof details === "string" ? details : undefined,
});
}
});
Callbacks
Um callback (também chamado de webhook) é uma URL no seu backend que um serviço externo (Vonage) pode acessar para notificá-lo sobre eventos.
Em vez de seu backend ficar constantemente consultando a Vonage: “O Silent Auth já terminou? E agora? E agora?”
A Vonage pode enviar o resultado para você: “A autenticação silenciosa foi concluída. Aqui está o status final.”
Essa notificação push é o callback.
Por que os callbacks são úteis neste caso? A autenticação silenciosa pode demorar e ser concluída de forma assíncrona. Usar um callback significa:
- Seu backend não precisa consultar o Vonage repetidamente
- Você recebe um evento definitivo quando a verificação muda de estado
- Ele se adapta melhor a sistemas reais
Para configurar a URL de retorno de chamada no Painel, abra o Painel da Vonage:
- Acessar Applications
- Selecione seu aplicativo → Editar
- Encontrar o Registro de Rede
- Ativar Verify (SA)
- Defina a URL de retorno de chamada (onde seu servidor fica à espera), por exemplo:
https://your-domain.com/callback
Nota: Se você estiver executando o programa localmente, a Vonage não conseguirá acessá-lo http://localhost:3000. Você precisará de uma URL pública (geralmente um túnel como ngrok).
Para implementar o callback, adicione um novo método à sua aplicação Express da seguinte maneira:
app.post("/callback", (req, res) => {
console.log("Callback received:", req.body);
return res.status(200).json({ ok: true });
});
Por enquanto, registramos o evento para que você possa ver o que a Vonage envia. Na próxima seção, vamos ampliar essa funcionalidade para armazenar o estado e fazer com que o aplicativo móvel reaja a essas atualizações.
Adicionar um estado na memória
Um fluxo de verificação não se resume a “uma solicitação e pronto”. Ele possui um ciclo de vida:
- começou
- em espera (autenticação silenciosa / SMS)
- concluído ou reprovado/vencido
Se você não armazenar o estado em lugar algum, seu backend não terá registro do que aconteceu, e:
/callbacksó consegue registrar dados (o que não é muito útil)- O aplicativo não consegue determinar com precisão o status atual
- A depuração se torna um tormento (“funcionou uma vez, depois não funcionou mais…”)
Uma loja oferece a você uma única fonte de informação confiável.
Em ambiente de produção, você usaria um banco de dados (por exemplo, Postgres/Redis), mas, para o tutorial, podemos simplesmente usar um Map.
Passo 1: Crie a loja com um Map
No Node.js, um Map é uma maneira fácil de armazenar pares chave/valor na memória.
Adicione isso perto do início do seu app.js:
// In-memory store for tutorial purposes:
// request_id -> verification state
const verificationStore = new Map();
Adicione uma função auxiliar para validar os campos obrigatórios do corpo da solicitação. Adicione-a logo abaixo do verificationStore declaração:
function requireFields(obj, fields) {
for (const f of fields) {
if (!obj || obj[f] == null || obj[f] === "") return f;
}
return null;
}
Isso retorna o nome do primeiro campo ausente, ou null se todos os campos estiverem presentes.
Cada entrada será identificada por request_id.
Uma entrada típica poderia ser assim:
{
"phone": "+34600111222",
"status": "started",
"createdAt": "2026-02-02T11:22:00.000Z",
"updatedAt": "2026-02-02T11:22:00.000Z"
}
Etapa 2: Salvar o estado inicial ao criar uma verificação
Quando você ligar verifyClient.newRequest(...) em /verification, você recebe um request_id.
Essa é a chave perfeita para armazenar o estado inicial.
Dentro do seu /verification ponto final, logo depois de obter result:
verificationStore.set(result.requestId, {
phone,
status: "started",
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
});
Agora, o backend “lembra” que uma verificação foi iniciada.
Etapa 3: Atualizar o estado quando a função de retorno de chamada receber eventos
Um callback (webhook) é quando a Vonage informa ao seu backend: “Algo mudou. Aqui está a nova situação.”
Em vez de apenas registrar a carga útil, atualizamos o estado armazenado:
app.post("/callback", (req, res) => {
const { request_id, status } = req.body || {};
if (!request_id) return res.status(400).json({ error: "Missing request_id" });
const current = verificationStore.get(request_id) || {
phone: null,
status: "unknown",
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
lastEvent: null,
};
const updated = {
...current,
status: status || current.status,
updatedAt: new Date().toISOString(),
lastEvent: req.body,
};
verificationStore.set(request_id, updated);
return res.status(200).json({ ok: true });
});
As entregas de webhooks podem ser repetidas, o que significa que você pode receber o mesmo evento várias vezes. Atualizar a loja dessa forma é, naturalmente, idempotente: definir o mesmo status novamente não causa nenhum problema.
Etapa 4: Adicionar um endpoint de status para o aplicativo móvel
Agora podemos disponibilizar um endpoint simples que o aplicativo possa chamar para verificar o estado atual:
app.get("/status/:request_id", (req, res) => {
const { request_id } = req.params;
const entry = verificationStore.get(request_id);
if (!entry) return res.status(404).json({ error: "Unknown request_id" });
return res.json({
request_id,
status: entry.status,
updated_at: entry.updatedAt,
});
});
Isso é especialmente útil para a autenticação silenciosa, pois o aplicativo pode fazer consultas a cada 1–2 segundos por um curto período, em vez de ficar esperando sem saber o que vai acontecer.
Etapa 5: Adicionar POST /next
O /next O endpoint instrui a Vonage a pular o canal atual do fluxo de trabalho e passar para o próximo. No nosso caso, isso significa pular a autenticação silenciosa e enviar um SMS imediatamente.
Isso é útil no aplicativo para Android quando a solicitação de autenticação silenciosa falha (problemas de rede, erro no SDK etc.) — em vez de esperar cerca de 20 segundos até que o tempo limite da Vonage expire naturalmente, o aplicativo chama a função /next e o usuário recebe um SMS imediatamente.
app.post("/next", async (req, res) => {
try {
const missing = requireFields(req.body, ["requestId"]);
if (missing) {
return res.status(400).json({ error: `Field '${missing}' is required.` });
}
const { requestId } = req.body;
const entry = verificationStore.get(requestId);
if (!entry) {
return res.status(404).json({ error: "Unknown request_id" });
}
console.log("Moving to next workflow (SMS) for:", requestId);
// Call Vonage to move to next workflow
const result = await verifyClient.nextWorkflow(requestId);
console.log("Vonage nextWorkflow result:", result);
// Update last event
const updated = {
...entry,
updatedAt: new Date().toISOString(),
lastEvent: { source: "next_workflow", result },
};
verificationStore.set(requestId, updated);
return res.status(200).json({ ok: true });
} catch (error) {
const status = error?.response?.status || 500;
const details = error?.response?.data || error?.message;
console.error("Error /next:", details);
return res.status(status).json({
error: "Failed to move workflow",
details: typeof details === "string" ? details : undefined,
});
}
});
Observação: Se a opção /next falhar, isso não é grave. A Vonage voltará automaticamente para o SMS após o tempo limite da autenticação silenciosa. O aplicativo para Android deve exibir a tela de inserção de SMS, independentemente de essa chamada ter sido bem-sucedida ou não.
Introdução à autenticação silenciosa
A autenticação silenciosa leva um bom tempo para ser compreendida. Este tutorial mostra como criar uma integração do zero usando Node.js e Kotlin