A Chamada do Mascarado

Este guia mostra como implementar a ideia descrita no Caso de uso de comunicação de voz privada. Ele ensina como criar um proxy de voz com o Vonage's SDK do Node Server, utilizando números virtuais para ocultar os números de telefone reais dos participantes. O código-fonte completo também está disponível em nosso Proxy de voz utilizando o repositório do GitHub da Voice API. Como alternativa, você pode acessar Code Hub para testar a API de chamadas com número oculto.

Visão geral

Em alguns casos, pode ser necessário que dois usuários se comuniquem sem revelar seus números de telefone pessoais. Por exemplo, em um serviço de carona compartilhada, os usuários precisam coordenar os horários de embarque sem divulgar seus dados de contato, o que também ajuda a evitar acordos diretos que poderiam prejudicar sua receita.

Com as APIs da Vonage, você pode fornecer aos participantes números temporários que ocultam seus números de telefone reais durante a ligação. Assim que a ligação termina, os números temporários são revogados, garantindo a privacidade.

Etapas

Este guia fornece instruções para a compilação do aplicativo, incluindo:

Pré-requisitos

Para trabalhar com este caso de uso, você precisa de:

Repositório de código

Existe um Repositório do GitHub que contém o código.

Configuração

Você precisa criar um .env arquivo que contém a configuração. As instruções para fazer isso estão explicadas no README do GitHub. À medida que for avançando neste guia, você poderá preencher seu arquivo de configuração com os valores necessários para variáveis como chave de API, segredo de API, ID do aplicativo, modo de depuração e números provisionados.

Criar um aplicativo da Voice API

Um aplicativo de Voice API é uma estrutura da Vonage. Não deve ser confundido com o aplicativo que você irá desenvolver. Trata-se, na verdade, de um “contêiner” para as configurações de autenticação e configuração necessárias para trabalhar com a API.

É possível criar uma Application de Voice API usando a CLI da Vonage. É necessário fornecer um nome para o aplicativo e as URLs de dois endpoints de webhook: o primeiro é o endpoint para o qual as APIs da Vonage enviarão uma solicitação quando você receber uma chamada recebida no seu número virtual, e o segundo é o endpoint para o qual a API pode enviar dados de eventos.

Substitua o nome de domínio no comando CLI da Vonage a seguir pelo seu nome de domínio do ngrok (para saber mais sobre como fazer isso, consulte o Como executar o ngrok (guia) e execute-o no diretório raiz do seu projeto:

vonage apps:create "Voice Proxy" --voice_answer_url=https://example.com/proxy-call --voice_event_url=https://example.com/event

Este comando cria um arquivo chamado voice_proxy.key que contém informações de autenticação e retorna um ID exclusivo do aplicativo. Anote esse ID, pois você precisará dele nas etapas seguintes.

Criar o aplicativo web

Este aplicativo utiliza o Expresso estrutura para o roteamento e o SDK do servidor Vonage Node para trabalhar com a Voice API. dotenv é usado para que o aplicativo possa ser configurado por meio de um .env arquivo de texto.

Em server.js, o código inicializa as dependências do aplicativo e inicia o servidor web. É implementado um manipulador de rota para a página inicial do aplicativo (/) para que você possa verificar se o servidor está em funcionamento, executando node server.js e visitar http://localhost:3000 no seu navegador:

"use strict";

const express = require('express');
const bodyParser = require('body-parser');

const app = express();
app.set('port', (process.env.PORT || 3000));
app.use(bodyParser.urlencoded({ extended: false }));

const config = require(__dirname + '/../config');

const VoiceProxy = require('./VoiceProxy');
const voiceProxy = new VoiceProxy(config);

app.listen(app.get('port'), function() {
  console.log('Voice Proxy App listening on port', app.get('port'));
});

Observe que o código instancia um objeto da VoiceProxy classe para lidar com o encaminhamento das mensagens enviadas ao seu número virtual para o número real do destinatário. O processo de proxy é descrito no Encaminhar a chamada capítulo deste guia. Por enquanto, saiba que essa classe inicializa o Vonage Server SDK usando a chave e o segredo da API que você configurará na próxima etapa. Essa configuração permite que seu aplicativo faça e receba chamadas de voz:

const VoiceProxy = function(config) {
  this.config = config;
  
  this.nexmo = new Nexmo({
      apiKey: this.config.VONAGE_API_KEY,
      apiSecret: this.config.VONAGE_API_SECRET
    },{
      debug: this.config.VONAGE_DEBUG
    });
  
  // Virtual Numbers to be assigned to UserA and UserB
  this.provisionedNumbers = [].concat(this.config.PROVISIONED_NUMBERS);
  
  // In progress conversations
  this.conversations = [];
};

Fornecimento de números virtuais

Os números virtuais são usados para ocultar os números de telefone reais dos usuários do seu aplicativo.

O diagrama de fluxo de trabalho a seguir mostra o processo de provisionamento e configuração de um número virtual:

Para provisionar um número virtual, você pesquisa entre os números disponíveis que atendem aos seus critérios. Por exemplo, um número de telefone em um país específico com capacidade para chamadas de voz:

const Nexmo = require('nexmo');

/**
 * Create a new VoiceProxy
 */
const VoiceProxy = function(config) {
  this.config = config;

  this.nexmo = new Nexmo({
    apiKey: this.config.NEXMO_API_KEY,
    apiSecret: this.config.NEXMO_API_SECRET
  },{
    debug: this.config.NEXMO_DEBUG
  });

  // Virtual Numbers to be assigned to UserA and UserB
  this.provisionedNumbers = [].concat(this.config.PROVISIONED_NUMBERS);

  // In progress conversations
  this.conversations = [];
};

/**
 * Provision two virtual numbers. Would provision more in a real app.
 */
VoiceProxy.prototype.provisionVirtualNumbers = function() {
  // Buy a UK number with VOICE capabilities.
  // For this example we'll also get SMS so we can send them a text notification
  this.nexmo.number.search('GB', {features: 'VOICE,SMS'}, function(err, res) {
    if(err) {
      console.error(err);
    }
    else {
      const numbers = res.numbers;

      // For demo purposes:
      // - Assume that at least two numbers will be available
      // - Rent just two virtual numbers: one for each conversation participant
      this.rentNumber(numbers[0]);
      this.rentNumber(numbers[1]);
    }
  }.bind(this));
};

Em seguida, alugue os números que desejar e associe-os ao seu aplicativo.

NOTA: Alguns tipos de números podem exigir que você forneça mais informações, como um endereço postal. Caso não consiga obter um número por meio de programação, você pode acessar o Painel do desenvolvedor para solicitar esses números. Lembre-se de que, para alguns números, pode ser necessário fornecer informações, e o processo não será totalmente automatizado.

Quando ocorrer um evento relacionado a qualquer número associado a um aplicativo, a Vonage enviará uma solicitação ao seu endpoint de webhook com informações sobre o evento. Após a configuração, certifique-se de salvar o número de telefone para uso posterior:

/**
 * Rent the given numbers
 */
VoiceProxy.prototype.rentNumber = function(number) {
  this.nexmo.number.buy(number.country, number.msisdn, function(err, res) {
    if(err) {
      console.error(err);
    }
    else {
      this.configureNumber(number);
    }
  }.bind(this));
};

/**
 * Configure the number to be associated with the Voice Proxy application.
 */
VoiceProxy.prototype.configureNumber = function(number) {
  const options = {
    voiceCallbackType: 'app',
    voiceCallbackValue: this.config.NEXMO_APP_ID,
  };
  this.nexmo.number.update(number.country, number.msisdn, options, function(err, res) {
    if(err) {
      console.error(err);
    }
    else {
      this.provisionedNumbers.push(number);
    }
  }.bind(this));
};

Para ativar números virtuais, acesse http://localhost:3000/numbers/provision no seu navegador.

Agora você dispõe dos números virtuais necessários para ocultar a comunicação entre seus usuários.

NOTA: Em um ambiente de produção, você escolherá entre um conjunto de números virtuais. No entanto, é importante manter essa funcionalidade ativa para poder alugar números adicionais a qualquer momento.

Criar uma chamada

O fluxo de trabalho para criar uma chamada é o apresentado no diagrama:

A chamada a seguir:

/**
 * Create a new tracked conversation so there is a real/virtual mapping of numbers.
 */
VoiceProxy.prototype.createConversation = function(userANumber, userBNumber, cb) {
  this.checkNumbers(userANumber, userBNumber)
    .then(this.saveConversation.bind(this))
    .then(this.sendSMS.bind(this))
    .then(function(conversation) {
      cb(null, conversation);
    })
    .catch(function(err) {
      cb(err);
    });
};

Validar os números de telefone

Quando os usuários do seu aplicativo fornecerem seus números de telefone, use o Number Insight para verificar se eles são válidos. Você também pode ver em qual país os números de telefone estão registrados:

/**
 * Ensure the given numbers are valid and which country they are associated with.
 */
VoiceProxy.prototype.checkNumbers = function(userANumber, userBNumber) {
  const niGetPromise = (number) => new Promise ((resolve) => {
    this.nexmo.numberInsight.get(number, (error, result) => {
      if(error) {
        console.error('error',error);
      }
      else {
        return resolve(result);
      }
    })
  });

  const userAGet = niGetPromise({level: 'basic', number: userANumber});
  const userBGet = niGetPromise({level: 'basic', number: userBNumber});

  return Promise.all([userAGet, userBGet]);
};

Mapeamento de números de telefone para números reais

Depois de ter certeza de que os números de telefone são válidos, associe cada número real a um número virtual e salve a chamada:

/**
 * Store the conversation information.
 */
VoiceProxy.prototype.saveConversation = function(results) {
  let userAResult = results[0];
  let userANumber = {
    msisdn: userAResult.international_format_number,
    country: userAResult.country_code
  };

  let userBResult = results[1];
  let userBNumber = {
    msisdn: userBResult.international_format_number,
    country: userBResult.country_code
  };

  // Create conversation object - for demo purposes:
  // - Use first indexed LVN for user A
  // - Use second indexed LVN for user B
  let conversation = {
    userA: {
      realNumber: userANumber,
      virtualNumber: this.provisionedNumbers[0]
    },
    userB: {
      realNumber: userBNumber,
      virtualNumber: this.provisionedNumbers[1]
    }
  };

  this.conversations.push(conversation);

  return conversation;
};

Enviar um SMS de confirmação

Em um sistema de comunicação privado, quando um usuário entra em contato com outro, o chamador liga para um número virtual a partir do seu telefone.

Envie um SMS para informar a cada participante da conversa o número virtual para o qual devem ligar:

/**
 * Send an SMS to each conversation participant so they know each other's
 * virtual number and can call either other via the proxy.
 */
VoiceProxy.prototype.sendSMS = function(conversation) {
  // Send UserA conversation information
  // From the UserB virtual number
  // To the UserA real number
  this.nexmo.message.sendSms(conversation.userB.virtualNumber.msisdn,
                             conversation.userA.realNumber.msisdn,
                             'Call this number to talk to UserB');

  // Send UserB conversation information
  // From the UserA virtual number
  // To the UserB real number
  this.nexmo.message.sendSms(conversation.userA.virtualNumber.msisdn,
                             conversation.userB.realNumber.msisdn,
                             'Call this number to talk to UserB');

  return conversation;
};

Os usuários não podem enviar SMS uns para os outros. Para ativar essa funcionalidade, é preciso configurar Comunicação privada por SMS.

Neste guia, cada usuário recebeu o número virtual por SMS. Em outros sistemas, esse número poderia ser fornecido por e-mail, notificações no aplicativo ou por meio de um número predefinido.

Atender chamadas recebidas

Quando a Vonage recebe uma chamada para o seu número virtual, ela envia uma solicitação para o endpoint do webhook que você configurou ao criou um aplicativo de Voice API:

Trecho to e from do webhook de entrada e repassá-los para a lógica de negócios do proxy de voz:

app.get('/proxy-call', function(req, res) {
  const from = req.query.from;
  const to = req.query.to;

  const ncco = voiceProxy.getProxyNCCO(from, to);
  res.json(ncco);
});

Converter números de telefone reais em números virtuais

Agora que você sabe o número de telefone de quem está ligando e o número virtual do destinatário, faça o mapeamento reverso do número virtual de entrada para o número de telefone real de origem:

A direção da chamada pode ser identificada como:

  • O from o número é um número real do UsuárioA e o to O número é o número do UserB na Vonage
  • O from o número é um número real UserB e o to O número é o número do UserA na Vonage
const fromUserAToUserB = function(from, to, conversation) {
  return (from === conversation.userA.realNumber.msisdn &&
          to === conversation.userB.virtualNumber.msisdn);
};
const fromUserBToUserA = function(from, to, conversation) {
  return (from === conversation.userB.realNumber.msisdn &&
          to === conversation.userA.virtualNumber.msisdn);
};

/**
 * Work out real number to virtual number mapping between users.
 */
VoiceProxy.prototype.getProxyRoute = function(from, to) {
  let proxyRoute = null;
  let conversation;
  for(let i = 0, l = this.conversations.length; i < l; ++i) {
    conversation = this.conversations[i];

    // Use to and from to determine the conversation
    const fromUserA = fromUserAToUserB(from, to, conversation);
    const fromUserB = fromUserBToUserA(from, to, conversation);

    if(fromUserA || fromUserB) {
      proxyRoute = {
        conversation: conversation,
        to: fromUserA? conversation.userB : conversation.userA,
        from: fromUserA? conversation.userA : conversation.userB
      };
      break;
    }
  }

  return proxyRoute;
};

Depois de realizada a consulta do número, tudo o que resta fazer é encaminhar a chamada.

Encaminhar a chamada

Encaminhar a chamada para o número de telefone ao qual o número virtual está associado. O from o número é sempre o número virtual, e o to é um número de telefone real.

Para isso, crie um NCCO (Objeto de Controle de Chamadas da Nexmo). Este NCCO utiliza um talk ação para ler um texto em voz alta. Quando o talk já foi concluído, um connect Essa ação encaminha a chamada para um número real.

/**
 * Build the NCCO response to instruct Nexmo how to handle the inbound call.
 */
VoiceProxy.prototype.getProxyNCCO = function(from, to) {
  // Determine how the call should be routed
  const proxyRoute = this.getProxyRoute(from, to);

  if(proxyRoute === null) {
    const errorText = 'No conversation found' +
                    ' from: ' + from +
                    ' to: ' + to;
    throw new Error(errorText);
  }

  // Build the NCCO
  let ncco = [];

  const textAction = {
    action: 'talk',
    text: 'Please wait whilst we connect your call'
  };
  ncco.push(textAction);

  const connectAction = {
    action: 'connect',
    from: proxyRoute.from.virtualNumber.msisdn,
    endpoint: [{
      type: 'phone',
      number: proxyRoute.to.realNumber.msisdn
    }]
  };
  ncco.push(connectAction);

  return ncco;
};

O NCCO é devolvido à Vonage pelo servidor web.

app.get('/proxy-call', function(req, res) {
  const from = req.query.from;
  const to = req.query.to;

  const ncco = voiceProxy.getProxyNCCO(from, to);
  res.json(ncco);
});

Conclusão

Você aprendeu a criar um proxy de voz para comunicação privada. Você provisionou e configurou números de telefone, realizou a análise de números, mapeou números reais para números virtuais a fim de garantir o anonimato, atendeu uma chamada recebida e redirecionou a chamada para outro usuário.

Mais informações