Llamada enmascarada
Esta guía le muestra cómo poner en práctica la idea descrita en el Caso práctico de comunicación de voz privada. Te enseña a crear un proxy de voz con el software de Vonage SDK de servidor de nodosutilizando números virtuales para ocultar los números de teléfono reales de los participantes. El código fuente completo también está disponible en nuestra Proxy de voz mediante el repositorio GitHub de Voice API. También puede dirigirse a Code Hub para probar la API de llamadas enmascaradas.
Visión general
En algunos casos, puede que necesites que dos usuarios se comuniquen sin revelar sus números de teléfono personales. Por ejemplo, en un servicio de viajes compartidos, los usuarios necesitan coordinar las horas de recogida sin revelar sus datos de contacto, lo que también ayuda a evitar acuerdos directos que podrían mermar tus ingresos.
Con las API de Vonage, puedes proporcionar a los participantes números temporales que enmascaren sus números de teléfono reales durante la llamada. Una vez que finaliza la llamada, los números temporales se revocan, lo que garantiza la privacidad.
Pasos
Esta guía proporciona instrucciones para construir la aplicación, incluyendo:
- Requisitos previos
- Repositorio de código
- Configuración
- Crear una aplicación Voice API
- Crear la aplicación web
- Provisión de Numbers virtuales
- Crear una convocatoria
- Gestión de llamadas entrantes
- Reverse Map Números de teléfono reales a los números virtuales
- Delegar la llamada
- Conclusión
- Más información
Requisitos previos
Para trabajar con este caso de uso necesitas:
- A Account de Vonage
- En CLI de Vonage instalado y configurado
Repositorio de código
Hay un Repositorio GitHub que contiene el código.
Configuración
Debe crear un .env que contiene la configuración. Las instrucciones para hacerlo se explican en la sección LÉEME de GitHub. A medida que avanza en esta guía, puede rellenar el archivo de configuración con los valores necesarios para variables como la clave de API, el secreto de API, el ID de aplicación, el modo de depuración y los números aprovisionados.
Crear una aplicación Voice API
Una aplicación Voice API es una construcción de Vonage. No debe confundirse con la aplicación que escribirás. En cambio, es un "contenedor" para los ajustes de autenticación y configuración que necesitas para trabajar con la API.
Puedes crear una aplicación Voice API con la CLI de Vonage. Debes proporcionar un nombre para la aplicación y las URL de dos puntos finales de webhook: el primero es el punto final al que las API de Vonage harán una solicitud cuando recibas una llamada entrante en tu número virtual, y el segundo es el punto final donde la API puede publicar datos de eventos.
Sustituye el nombre de dominio en el siguiente comando de la CLI de Vonage por tu nombre de dominio ngrok (para obtener más información sobre cómo hacerlo, consulta la sección Cómo ejecutar ngrok ) y ejecútelo en el directorio raíz de su proyecto:
Este comando crea un archivo llamado voice_proxy.key que contiene información de autenticación y devuelve un ID de aplicación único. Anote este ID porque lo necesitará en los pasos siguientes.
Crear la aplicación web
Esta aplicación utiliza el Express marco para el enrutamiento y la SDK de servidor de nodo de Vonage para trabajar con la Voice API. dotenv para que la aplicación pueda configurarse mediante un archivo .env archivo de texto.
En server.jsEl código inicializa las dependencias de la aplicación e inicia el servidor web. Se implementa un manejador de rutas para la página de inicio de la aplicación (/) para que pueda comprobar que el servidor está funcionando ejecutando node server.js y visitando http://localhost:3000 en tu 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'));
});
Obsérvese que el código instancia un objeto del tipo VoiceProxy para enrutar los mensajes enviados a su número virtual al número real del destinatario. El proceso de proxy se describe en la sección Delegar la llamada de esta guía. Por ahora, ten en cuenta que esta clase inicializa el SDK del servidor de Vonage utilizando la clave y el secreto de la API que configurarás en el próximo paso. Esta configuración permite que tu aplicación realice y reciba llamadas 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 = [];
};
Provisión de Numbers virtuales
Los números virtuales se utilizan para ocultar los números de teléfono reales a los usuarios de sus aplicaciones.
El siguiente diagrama de flujo de trabajo muestra el proceso de aprovisionamiento y configuración de un número virtual:
Para aprovisionar un número virtual, busque entre los números disponibles que cumplan sus criterios. Por ejemplo, un número de teléfono de un país concreto con capacidad 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));
};
A continuación, alquile los números que desee y asócielos a su solicitud.
NOTA: Algunos tipos de Numbers pueden requerir que proporcione más información, como una dirección postal. Si no puede obtener un número mediante programación, puede visitar la página Panel de control para desarrolladores para solicitar dichos Numbers. Tenga en cuenta que algunos Numbers pueden requerir que se solicite información y que el proceso no estará totalmente automatizado.
Cuando se produzca un evento relacionado con cualquier número asociado con una aplicación, Vonage enviará una solicitud a tu punto final de webhook con información sobre el evento. Después de la configuración, asegúrate de almacenar el número de teléfono para su 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 aprovisionar números virtuales, visite http://localhost:3000/numbers/provision en tu navegador.
Ya dispone de los números virtuales necesarios para enmascarar la comunicación entre sus usuarios.
NOTA: En una aplicación de producción, elegirá entre un conjunto de números virtuales. Sin embargo, es importante mantener esta funcionalidad para alquilar números adicionales sobre la marcha.
Crear una convocatoria
El flujo de trabajo para crear una convocatoria es el que se presenta en el diagrama:
La siguiente llamada:
- Validar los Numbers de teléfono
- Asignar números de teléfono a números reales
- Enviar un SMS de confirmación
/**
* 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 los Numbers de teléfono
Cuando los usuarios de su aplicación faciliten sus números de teléfono, utilice Number Insight para asegurarse de que son válidos. También puedes ver en qué país están registrados los números de teléfono:
/**
* 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]);
};
Asignar números de teléfono a números reales
Una vez que esté seguro de que los números de teléfono son válidos, asigne cada número real a un campo número virtual y guarda la llamada:
/**
* 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 un SMS de confirmación
En un sistema de comunicación privada, cuando un usuario se pone en contacto con otro, el interlocutor llama a un número virtual desde su teléfono.
Envía un SMS para notificar a cada participante en la conversación el número virtual al que debe llamar:
/**
* 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;
};
Los usuarios no pueden enviarse SMS entre sí. Para habilitar esta funcionalidad, debe configurar Comunicación SMS privada.
En esta guía, cada usuario ha recibido el número virtual en un SMS. En otros sistemas, podría suministrarse mediante correo electrónico, notificaciones in-app o un número predefinido.
Gestión de llamadas entrantes
Cuando Vonage recibe una llamada entrante a tu número virtual, realiza una solicitud al punto final de webhook que configuraste cuando creó una aplicación Voice API:
Extracto to y from del webhook entrante y pasarlos a la lógica de negocio del 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);
});
Reverse Map Números de teléfono reales a los números virtuales
Ahora que conoce el número de teléfono que realiza la llamada y el número virtual del destinatario, realice una asignación inversa del número virtual de entrada al número de teléfono real de salida:
La dirección de la llamada puede identificarse como:
- En
fromes un número real UserA y el númerotoes el número de Vonage de UserB - En
fromes un número real UserB y el númerotoes el número de Vonage de UserA
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;
};
Una vez realizada la búsqueda del número, sólo queda proxy la llamada.
Delegar la llamada
Proxy de la llamada al número de teléfono al que está asociado el número virtual. La dirección from es siempre el número virtual, y el número to es un número de teléfono real.
Para ello, cree un NCCO (Objeto de control de llamadas Nexmo). Esta OCN utiliza un talk para leer un texto. Cuando la talk ha completado, un connect desvía la llamada a un 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;
};
El servidor web devuelve la NCCO a Vonage.
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);
});
Conclusión
Has aprendido a crear un proxy de voz para comunicaciones privadas. Se han aprovisionado y configurado números de teléfono, se ha realizado el análisis de números, se han asignado números reales a números virtuales para garantizar el anonimato, se ha gestionado una llamada entrante y se ha transferido la llamada a otro usuario.