
Compartilhar:
Ex-representante de desenvolvedores da Vonage, onde sua função era apoiar a comunidade tecnológica local em Londres. Ele é um experiente organizador de eventos, jogador de jogos de tabuleiro e pai de um cachorrinho fofo chamado Moo. Ele também é o principal organizador do You Got This — uma rede de eventos sobre as habilidades essenciais necessárias para uma vida profissional feliz e saudável.
Gerenciar um conjunto de números de telefone com o Node.js
Tempo de leitura: 7 minutos
Nem sempre você estará perto do telefone do escritório e, quando isso acontecer, os clientes podem ter dificuldade para entrar em contato com você. Neste tutorial, vamos criar um aplicativo que utiliza a API de Gerenciamento de Números as APIs da Vonage para gerenciar vários números de telefone mascarados. Cada número redirecionará as chamadas para outro número, como um celular particular que possa ser usado em casa.
Também garantiremos que os usuários do nosso aplicativo possam ver apenas os números adquiridos e gerenciados por ele, e não todos os números da sua Account da API da Vonage. Por fim, tomaremos algumas medidas para garantir que apenas usuários conhecidos por você tenham acesso e que o aplicativo não seja acessível pela internet pública sem uma senha.

Posso usar esse projeto agora?
O código finalizado deste projeto está no Glitch. Você pode acessar o projeto, clicar no botão “Remix to Edit” no canto superior direito e adicionar suas próprias credenciais ao 🔑.env arquivo. Você poderá então usar o projeto imediatamente clicando no Mostrar na parte superior da página.
Você também pode encontrar o código completo em GitHub.
Pré-requisitos
Observação: a Nexmo mudou recentemente sua marca para Vonage após ter sido adquirida em 2016. Você vai perceber que, neste tutorial, fazemos chamadas para uma URL da Nexmo; portanto, não se preocupe com isso.
Criação de um projeto base
Há um texto padrão projeto para você começar a trabalhar rapidamente. Esse aplicativo possui:
Instalamos e incluímos nossas dependências, o que você pode fazer em um novo projeto Express abrindo o terminal do Glitch e digitando
pnpm install express body-parser cors nedb-promises axios qs express-basic-auth.Criei um novo banco de dados no
.datapasta no Glitch. Essa pasta é específica para a sua versão do aplicativo e não pode ser visualizada por outras pessoas nem copiada.Inicializei um aplicativo Express básico e servi o
views/index.htmlarquivo quando os usuários acessam a URL do nosso projetoIncluí as bibliotecas Vue.js e Axios no
index.htmlarquivo, criei um novo aplicativo Vue.js e adicionei alguns estilos básicos nopublic/style.cssarquivo.
Faça login na sua conta do Glitch e, em seguida, clique neste link para remixar (copiar) nosso modelo para o seu Account.
Quer você comece do zero ou use nosso modelo, será necessário acessar o Painel de Controle da API da Vonage, obter sua chave e seu segredo da API e inseri-los no arquivo 🔑.env . Esses valores não são visíveis publicamente, mas podem ser acessados em seu aplicativo usando process.env.PROPERTY.
Criar um endpoint para comprar Numbers
Este endpoint exigirá que country seja fornecido, pois é isso que a API de Gerenciamento de Números exige.
Acima da última linha do seu aplicativo, inclua o seguinte código:
app.post('/numbers', async (req, res) => {
try {
const { NEXMO_API_KEY, NEXMO_API_SECRET } = process.env;
const availableNumbers = await axios.get(`https://rest.nexmo.com/number/search?api_key=${NEXMO_API_KEY}&api_secret=${NEXMO_API_SECRET}&country=${req.body.country}&features=SMS,VOICE`);
const msisdn = availableNumbers.data.numbers[0].msisdn;
res.send(msisdn);
} catch (err) {
res.send(err);
}
});
Ao enviar uma solicitação POST para /numbers, o aplicativo fará uma solicitação GET à API de Gerenciamento de Números para encontrar um MSISDN (número de telefone) disponível e retornará o primeiro encontrado.
Abra seu terminal e execute o seguinte comando para testar o novo endpoint da API: curl -H "Content-Type: application/json" -X POST -d '{"country": "GB"}' https://YOUR_GLITCH_PROJECT_NAME.glitch.me/numbers, certificando-se de substituir pelo nome do seu projeto no Glitch. Se for bem-sucedido, ele deve retornar um número de telefone disponível.
Substitua res.send(msisdn) pelo seguinte:
await axios({
method: 'POST',
url: `https://rest.nexmo.com/number/buy?api_key=${NEXMO_API_KEY}&api_secret=${NEXMO_API_SECRET}`,
data: qs.stringify({ country: req.body.country, msisdn }),
headers: { 'content-type': 'application/x-www-form-urlencoded' }
});
await db.insert({ msisdn });
res.send('Number successfully bought');
Isso seleciona o primeiro MSISDN dos resultados, efetua a compra utilizando o crédito disponível na Account e armazena um novo registro no banco de dados para esse MSISDN. O qs pacote formata os dados como uma x-www-form-encoded string, que é o que a API de Gerenciamento de Números exige.
Verificação! Repita a chamada à API do seu aplicativo a partir do terminal. Você deverá receber uma mensagem de sucesso, e um novo número deverá estar disponível na sua Account da API da Vonage.
Observação: há vários motivos pelos quais a chamada à API da Vonage pode falhar em seu aplicativo, que não têm nada a ver com o seu código. Verifique se você pode usar a API de Gerenciamento de Números para obter um número no seu país. Se ainda assim não funcionar, você talvez precise de um endereço , o que significa que você deverá obter o número por meio do Painel da API da Vonage
Criar uma interface para comprar Numbers
Seu endpoint de solicitação POST pode estar funcionando bem, mas é hora de criar uma interface mais intuitiva para utilizá-lo. Abra views/index.html e adicione o seguinte ao seu HTML:
<div id="app">
<h1>Number Manager</h1>
<section>
<h2>Buy New Number</h2>
<input type="text" v-model="country" placeholder="Country Code" />
<button @click="buyNumber">Buy new number</button>
</section>
</div>
Atualize o conteúdo do seu <script> da seguinte forma:
const app = new Vue({
el: '#app',
data: {
country: ''
},
methods: {
async buyNumber() {
try {
if(this.country && confirm('Are you sure you would like to buy a number?')) {
await axios.post('/numbers', {
country: this.form.country
})
alert('Successfully bought new number');
}
} catch(err) {
alert('Error buying new number', err);
}
}
}
})
Abra o aplicativo clicando em Mostrar na parte superior da janela do Glitch. Digite “GB” na caixa e clique em “Comprar novo número”. A confirm() função exibe uma caixa pop-up para o usuário e é uma boa prática para evitar compras acidentais. Embora este aplicativo use Vue.js, você pode criar qualquer aplicativo capaz de fazer solicitações HTTP.
Criar um endpoint para listar números
Crie um novo endpoint em sua aplicação Express antes da última linha de código:
app.get("/numbers", async (req, res) => {
try {
res.send('ok');
} catch (err) {
res.send(err);
}
});
No topo do try bloco, recupere todas as entradas do banco de dados local e todos os números da API de gerenciamento de números da Vonage para as APIs da Vonage.
const { NEXMO_API_KEY, NEXMO_API_SECRET } = process.env;
const dbNumbers = await db.find();
const vonageNumbers = await axios.get(`https://rest.nexmo.com/account/numbers?api_key=${NEXMO_API_KEY}&api_secret=${NEXMO_API_SECRET}`);
Em seguida, crie um novo array que filtre vonageNumbers apenas aqueles que também aparecem no banco de dados local. Isso garante que você retorne apenas os números desta Account da API da Vonage que são gerenciados por este aplicativo.
const numbersInBothResponses = vonageNumbers.data.numbers.filter(vonageNumber => {
return dbNumbers.map(dbNumber => dbNumber.msisdn).includes(vonageNumber.msisdn)
});
Em seguida, crie um objeto que combine ambas as fontes de dados para cada número:
const combinedResponses = numbersInBothResponses.map(vonageNumber => {
return {
...vonageNumber,
...dbNumbers.find(dbNumber => dbNumber.msisdn == vonageNumber.msisdn)
}
})
combinedResponses agora contém dados que podem ser enviados ao usuário; portanto, substitua res.send('ok'); por res.send(combinedResponses);.
Criar uma interface para listar Numbers
No seu index.html arquivo, crie um novo método para obter os Numbers do nosso endpoint do Express:
async getNumbers() {
const { data } = await axios.get('/numbers')
this.numbers = data;
}Atualize o data objeto da seguinte forma:
data: {
numbers: [],
country: ''
}Carregue esses dados adicionando uma created() função logo abaixo do seu data objeto:
created() {
this.getNumbers();
}Adicione o seguinte código HTML para exibir os Numbers:
<section>
<h2>Current Numbers</h2>
<div class="number" v-for="number in numbers" :key="number.msisdn">
<h3>{{number.msisdn}}</h3>
<label for="name">Friendly Name</label>
<input type="text" v-model="number.name" placeholder="New name">
<label for="forward">Forwarding Number</label>
<input type="text" v-model="number.voiceCallbackValue" placeholder="Update forwarding number">
</div>
</section>Ponto de verificação! Clique em “Mostrar” na parte superior do seu editor do Glitch e abra seu aplicativo front-end. Quando ele carregar, você deverá ver seus números de telefone gerenciados.
Para encerrar esta seção, atualize o buyNumber() método para incluir this.getNumbers(); após o sucesso alert(). Assim que você comprar um novo número, a lista será atualizada sem a necessidade de recarregar a página.
Criação de um endpoint e de um front-end para atualizar Numbers
Existem dois tipos de atualizações de números de telefone que este aplicativo suportará. Ao atualizar o nome descritivo de um número, você estará editando entradas no banco de dados local; e, ao atualizar o número de encaminhamento, estará atualizando o número por meio da API de Gerenciamento de Números. Nosso endpoint deve suportar ambos e utilizará os dados passados para decidir qual deles atualizar. Em server.js , adicione o seguinte:
app.patch("/numbers/:msisdn", async (req, res) => {
try {
const { NEXMO_API_KEY, NEXMO_API_SECRET } = process.env;
if(req.body.name) {
await db.update({ msisdn: req.params.msisdn }, { $set: { name: req.body.name } })
}
if(req.body.forward) {
await axios({
method: "POST",
url: `https://rest.nexmo.com/number/update?api_key=${NEXMO_API_KEY}&api_secret=${NEXMO_API_SECRET}`,
data: qs.stringify({
country: req.body.country,
msisdn: req.params.msisdn,
voiceCallbackType: 'tel',
voiceCallbackValue: req.body.forward
}),
headers: { "content-type": "application/x-www-form-urlencoded" }
})
}
res.send('Successfully updated')
} catch(err) {
res.send(err)
}
})
Este endpoint PATCH inclui o número de telefone que você está atualizando. Se o corpo da solicitação contiver uma name propriedade, o banco de dados local será atualizado; e, se contiver forward, as configurações do número serão atualizadas por meio da API de Gerenciamento de Números.
Em index.html, crie o seguinte método:
async updateNumber(number) {
try {
const { msisdn, country, name, voiceCallbackValue } = number
const payload = { country }
if(name) payload.name = name
if(voiceCallbackValue) payload.forward = voiceCallbackValue
await axios.patch(`/numbers/${msisdn}`, payload)
alert('Successfully updated number');
this.getNumbers();
} catch(err) {
alert('Error updating number', err);
}
}Você também deve chamar esse método a partir do modelo — o que ocorrerá quando um usuário pressionar a tecla Enter enquanto estiver com o foco em um dos campos de texto. Atualize os campos da seguinte forma:
<label for="name">Friendly Name</label>
<input type="text" v-model="number.name" @keyup.enter="updateNumber(number)" placeholder="New name">
<label for="forward">Forwarding Number</label>
<input type="text" v-model="number.voiceCallbackValue" @keyup.enter="updateNumber(number)" placeholder="Update forwarding number">Ponto de verificação! Atualize o nome descritivo de um número. Em seguida, tente atualizar o número de encaminhamento (lembre-se de que ele deve estar em um formato válido)
Criação de um endpoint e de um front-end para cancelar Numbers
Quando um número não for mais necessário, você pode optar por cancelá-lo, o que o libera imediatamente da sua Account. Essa é a etapa final e fundamental do gerenciamento do seu conjunto de números de telefone virtuais. Para server.js adicione o seguinte acima da última linha de código:
app.delete("/numbers/:msisdn", async (req, res) => {
try {
const { NEXMO_API_KEY, NEXMO_API_SECRET } = process.env;
await axios({
method: "POST",
url: `https://rest.nexmo.com/number/cancel?api_key=${NEXMO_API_KEY}&api_secret=${NEXMO_API_SECRET}`,
data: qs.stringify({
country: req.body.country,
msisdn: req.params.msisdn
}),
headers: { "content-type": "application/x-www-form-urlencoded" }
})
res.send('Successfully cancelled')
} catch(err) {
res.send(err)
}
})
Em index.html adicionar um deleteNumber() método:
async deleteNumber(number) {
try {
if(confirm('Are you sure you would like to delete this number?')) {
const { msisdn, country } = number
await axios.delete(`/numbers/${msisdn}`, { data: { country } })
alert('Successfully deleted number')
this.getNumbers()
}
} catch(err) {
alert('Error deleting number', err);
}
}Por fim, adicione um botão no modelo logo abaixo do campo de inserção do número de encaminhamento:
<button @click="deleteNumber(number)">Delete number</button>Ponto de verificação! Apague um número.
Você deve ter percebido que não está excluindo o número do banco de dados local. Você pode optar por implementar isso, mas como o endpoint GET de números retorna apenas os números que existem tanto na sua Account da API da Vonage quanto no banco de dados local, os números excluídos não serão retornados.
Serviço de limpeza
Esta aplicação está quase pronta, mas ainda faltam alguns detalhes de ajuste a serem resolvidos.
Permitir apenas chamadas de API a partir do nosso front-end
No momento, qualquer pessoa pode abrir seu terminal e gerenciar seus Numbers sem permissão. Perto do topo da server.js, logo abaixo das app.use() instruções, adicione o seguinte:
app.use(cors({ origin: `https://${process.env.PROJECT_NAME}.glitch.me` }));process.env.PROJECT_NAME é uma variável de ambiente fornecida pelo Glitch e corresponde ao nome deste projeto. Essa configuração permite apenas solicitações provenientes da nossa URL do Glitch.
Adicionando a autenticação básica
Mesmo que as pessoas não possam acessar sua API a partir de suas próprias Applications, elas ainda podem acabar encontrando seu site ativo. Felizmente, a configuração da autenticação HTTP básica envolve apenas duas etapas.
Primeiro, adicione uma senha no seu 🔑.env arquivo. Em seguida, adicione a seguinte linha ao final das app.use() instruções:
app.use(basicAuth({ users: { admin: process.env.ADMIN_PASSWORD }, challenge: true }));Agora, ao carregar seu aplicativo, você precisará inserir admin como nome de usuário e a senha que você forneceu.
E agora?
Esta aplicação simples atenderá à maioria das necessidades da equipe, mas certamente há algumas melhorias que você poderia fazer:
Permitir que apenas determinados usuários comprem Numbers
Confirmar o custo de cada número antes da compra
Adicionar mais dados a cada número em nosso banco de dados local
Melhor tratamento de erros
Lembre-se de que o código completo deste projeto também está no GitHub.
Você pode ler mais sobre a API de gerenciamento de números das APIs da Vonage por meio de nossa documentação; e, caso precise de suporte adicional, sinta-se à vontade para entrar em contato com nossa equipe pelo conta do Vonage Developer no Twitter Account or the Slack da Comunidade Vonage.
Compartilhar:
Ex-representante de desenvolvedores da Vonage, onde sua função era apoiar a comunidade tecnológica local em Londres. Ele é um experiente organizador de eventos, jogador de jogos de tabuleiro e pai de um cachorrinho fofo chamado Moo. Ele também é o principal organizador do You Got This — uma rede de eventos sobre as habilidades essenciais necessárias para uma vida profissional feliz e saudável.