マスクド・コーリング

本ガイドは、「日本における プライベート音声通信の使用例.この本では、Vonageの音声プロキシを使用して音声プロキシを構築する方法を説明します。 ノードサーバーSDK参加者の実際の電話番号を隠すためにバーチャルナンバーを使用します。全ソースコードは Voice APIを使った音声プロキシ GitHub repo.または、以下のサイトもご参照ください。 コード・ハブでMasked Calling APIを試す.

概要

場合によっては、2人のユーザーが個人的な電話番号を明かすことなくコミュニケーションする必要があるかもしれません。例えば、ライドシェアサービスでは、ユーザーは連絡先を明かすことなくピックアップ時間を調整する必要がある。

VonageのAPIを使用すると、通話中に実際の電話番号を隠す一時的な番号を参加者に提供することができます。通話が終了すると、一時的な番号は取り消され、プライバシーが確保されます。

ステップ

このガイドでは、以下のようなアプリケーションの構築方法を説明します:

前提条件

このユースケースに取り組むには、以下のことが必要だ:

コード・リポジトリ

がある。 コードを含むGitHubリポジトリ.

構成

を作成する必要があります。 .env ファイルを作成します。その方法は GitHub README.このガイドを読みながら、APIキー、APIシークレット、アプリケーションID、デバッグモード、プロビジョニング番号などの変数に必要な値を設定ファイルに入力することができます。

Voice APIアプリケーションの作成

Voice API ApplicationsはVonageの構成要素です。あなたが書くアプリケーションと混同しないでください。その代わり、APIを使用するために必要な認証とコンフィギュレーション設定のための "コンテナ "です。

Voice API Applications は Vonage CLI で作成できます。アプリケーションの名前と2つのWebhookエンドポイントのNumbersを指定する必要があります。1つ目はバーチャル番号に着信があったときにVonageのAPIがリクエストを行うエンドポイント、2つ目はAPIがイベントデータをポストできるエンドポイントです。

以下の Vonage CLI コマンドのドメイン名を ngrok ドメイン名に置き換えます。 ngrokの動かし方 ガイドを参照)、プロジェクトのルート・ディレクトリで実行する:

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

このコマンドは voice_proxy.key には認証情報が含まれ、一意のアプリケーションIDが返されます。このIDは、以降のステップで必要になるので、メモしておくこと。

ウェブアプリケーションの作成

このアプリケーションでは エクスプレス ルーティングのフレームワークと Vonage Node Server SDK Voice API を使用します。 dotenv を使用してアプリケーションを設定できる。 .env テキストファイル。

server.jsコードはアプリケーションの依存関係を初期化し、ウェブサーバーを起動します。ルートハンドラはアプリケーションのホームページ(/を実行してサーバーが稼動していることをテストできる。 node server.js そして http://localhost:3000 をブラウザに追加する:

"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'));
});

のオブジェクトをインスタンス化していることに注意してください。 VoiceProxy クラスを使用して、あなたのバーチャル番号に送られたメッセージを、意図した受信者のリアル番号にルーティングする処理を行います。プロキシ処理は 電話の代理 の章を参照してください。とりあえず、このクラスは次のステップで設定する API キーとシークレットを使用して Vonage Server SDK を初期化することに注意してください。このセットアップにより、アプリケーションは音声通話の送受信が可能になります:

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 = [];
};

バーチャル番号の提供

仮想番号は、アプリケーションのユーザーから実際の電話番号を隠すために使用されます。

次のワークフロー図は、仮想番号のプロビジョニングと設定のプロセスを示している:

バーチャル番号をプロビジョニングするには、条件を満たす利用可能な Numbers を検索します。例えば、音声通話が可能な特定の国の電話番号などです:

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));
};

そして、必要なNumbersを借り、あなたのアプリケーションに関連付ける。

注: Numbersの種類によっては、郵送先住所など、より多くの情報を提供する必要がある場合があります。プログラム上で番号を取得できない場合は、以下のサイトをご覧ください。 開発者ダッシュボード までご連絡ください。番号によっては問い合わせが必要な場合があり、プロセスは完全には自動化されないことに留意してください。

アプリケーションに関連する電話番号に関連するイベントが発生すると、Vonageはそのイベントに関する情報をWebhookエンドポイントにリクエストを送信します。設定後、後で使用するために電話番号を保存してください:

/**
 * 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));
};

バーチャル・ナンバーのプロビジョニングは、以下をご覧ください。 http://localhost:3000/numbers/provision をブラウザに追加する。

これで、ユーザー間の通信をマスクするのに必要なバーチャルナンバーが揃ったことになる。

注: 本番アプリケーションでは、バーチャル番号のプールから選択することになります。しかし、その場で追加の番号をレンタルするために、この機能を維持することは重要です。

電話をかける

コールを作成するワークフローは、図のとおりである:

次のコール:

/**
 * 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);
    });
};

電話番号の確認

アプリケーションのユーザーが電話番号を提供する場合、Number Insightを使用して、その電話番号が有効であることを確認します。また、電話番号が登録されている国を確認することもできます:

/**
 * 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]);
};

電話番号を実際の番号にマップする

電話番号が有効であることを確認したら、それぞれの実番号を 仮想番号 で、通話を保存する:

/**
 * 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;
};

確認SMSの送信

プライベート・コミュニケーション・システムでは、あるユーザーが他のユーザーと連絡を取る際、発信者は自分の携帯電話からバーチャル・ナンバーに電話をかける。

SMSを送信し、会話参加者にバーチャル番号を通知します:

/**
 * 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;
};

ユーザー同士でSMSを送ることはできません。この機能を有効にするには、以下を設定する必要があります。 プライベートSMS通信.

このガイドでは、各ユーザーはSMSでバーチャル・ナンバーを受け取っている。他のシステムでは、電子メール、アプリ内通知、または事前に定義された番号を使用して提供される可能性があります。

インバウンドコールの処理

Vonageは、バーチャル番号への着信コールを受信すると、次のように設定したWebhookエンドポイントにリクエストを送信します。 Voice API Applicationsの作成:

抜粋 to そして from を受信 Webhook から取得し、音声プロキシのビジネスロジックに渡す:

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);
});

実際の電話番号をバーチャル番号に逆マッピング

発信側の電話番号と受信側のバーチャル番号がわかったので、着信側のバーチャル番号を発信側のリアル電話番号にリバースマップする:

通話方向は次のように特定できる:

  • について from はユーザーAの実数であり to 番号はユーザーBのVonage番号です。
  • について from はユーザーBの実数である。 to の番号はユーザーAの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;
};

番号検索が実行されたので、あとは通話をプロキシするだけだ。

電話の代理

バーチャル番号に関連付けられた電話番号にコールをプロキシする。その from 番号は常にバーチャル番号であり to は実際の電話番号である。

これを行うには NCCO(ネクスモ・コール・コントロール・オブジェクト).このNCCOは talk アクションでテキストを読み上げる。そのとき talk を完了した。 connect アクションは、実際の番号に電話を転送する。

/**
 * 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;
};

NCCOはウェブサーバーから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);
});

結論

あなたは、プライベート通信用の音声プロキシを構築する方法を学んだ。電話番号のプロビジョニングと設定を行い、番号インサイトを実行し、匿名性を確保するために実際の番号を仮想番号にマッピングし、着信コールを処理し、コールを別のユーザーにプロキシしました。

詳細情報