Twilioブログ

クラウドコンタクトセンターをスモールスタートする際のコード例

こんにちは、Twilio Championsの西口です。
前回は、クラウドコンタクトセンターをスモールスタートする際にあたり必要なモノについて記載しました。

そして、今回はクラウドコンタクトセンターをスモールスタートするときのコード例についてご紹介していきます。

この記事の技術構成について

私が得意な技術だけでまとめました。

  • PHP
  • PHPのTwilio SDK
  • Twilio Client(JavaScript)
  • Chromeブラウザ
  • CentOSサーバ

今回、PHPインストールとCentOSセットアップについては触れませんが、なるべく最新バージョンでWebサーバを使用する状態にしてください。

Twilio SDKの準備

https://jp.twilio.com/docs/libraries/php

このドキュメントを参照にインストールをしてください。
composerさえあれば、すぐに利用可能な状態にできると思います。

不明な場合は、KDDIウェブコミュニケーションズ社にこちらからお問い合わせください。

Twilio Clientの準備

https://jp.twilio.com/docs/voice/client/javascript

Twilio Clientはブラウザで動作するライブラリです。

そのため、電話機としての操作をするためのインターフェイスは作る必要がありますが、架電や受電などの通話部分に関することは、このライブラリを利用するだけでとても簡単に完成します。
 
CDNが用意されているため、CDNを利用すると、自動でClientのバージョンアップが行われます。

ただし、Clientバージョンアップに伴う不具合も少なからず起きているため、ブラウザ側の自動テストなどが用意できていない場合、突然不具合が発生する場合もあるためご注意ください。

開発時点の最新バージョンをダウンロードし、それをテストした後、利用することを個人的にはおすすめしています。

各仕様の要件とコード例

架電

架電については、下記のドキュメントとGithubリポジトリが参考になります。
 
Twilio Clientクイックスタートドキュメント(JavaScript):https://jp.twilio.com/docs/voice/client/javascript/quickstart

Twilio Clientクイックスタートドキュメント(PHP):https://github.com/TwilioDevEd/client-quickstart-php

 
クイックスタートには特に記載ありませんが、様々なユーザに利用してもらうにあたり、電話番号の入力チェックを実装してください。

入力チェックを実装する理由として、架電にあたり数字以外も利用するためです。

通常の電話機などに対しては、電話番号を用いて架電しますが、他ブラウザのTwilio Client同士の通話する際、Identityを用いた架電を行います。
 
Identityというのは、Twilio Clientで保持するIDのことで、同じアカウント内の他ブラウザのTwilio Clientと通話するために利用します。

下記要件を満たす入力チェックをJavaScriptの正規表現で実装しておき、実際にサーバに架電リクエストを行う前にチェックします。
 
* 0始まりのすべて数字の電話番号フォーマット
* アルファベットから始まるクライアント名のフォーマット
 
電話番号は正式には「+国番号」から始まる番号形式ですが、スモールスタートでは利用可能な国は日本限定とし、上記のような正規表現を利用します。
 
Identityのドキュメント:https://jp.twilio.com/docs/voice/client/tutorials/calls-between-devices
 
Identityは同じアカウント内での通話を行ういわゆる内線をする際や、通話ログから誰がどこと通話したかなどの分析で利用します。
そのため、一意で特定のユーザと紐づけできるようにしておいてください。

受電

受電については、前回の記事で書いた通り、特定のIdentityの人達のClientを同時に鳴らすことにします。

同時に鳴らせる人数は10人までです。
 
複数のClientを同時に鳴らすには、「ClientというTwiml」を使用します。
PHPで下記のように書くことで、複数Clientを同時に指定し、電話を鳴らすことができます。
 

require_once './vendor/autoload.php';
use Twilio\TwiML\VoiceResponse;

$response = new VoiceResponse();
$dial = $response->dial('', ['callerId' => '+815012345678']);
$dial->client('alice');
$dial->client('bob');
// 必要なだけ増やす

echo $response;

 
このコードをTwilioで購入した電話番号のIncoming Webhookに設定します。

詳しくはこちらのドキュメントを参照してください。

このコードは簡易的な仕様のため、受電者のaliceとbobを変えたり、増やしたりするにはコードの修正が必要ですし、aliceとbobが受電可能かどうか、そもそも存在するのかどうかの確認もしていません。

プロダクトで使用するには心もとないですが、期間限定のスモールスタートで使用してもらう分には問題ありませんでした。

Client側はこちらのドキュメントも参考になります。
 
ただし、ドキュメントのコードだと、受電したら即座に通話が始まってしまうため、「電話を取るボタン」を用意する必要があります。

Notificationを使って、受電していることの通知と通知クリックで通話が始まるように修正しました。
 

Twilio.Device.incoming(function(inbound_connection) {
const inbound_notification = new Notification('受電中');
inbound_notification.onclick = () => {
inbound_connection.accept();
inbound_notification.close();
};
});

 
これだけだと、どこの番号からどこの番号へ受電したのか不明のため、こちらのドキュメントを参照に、customParametersを利用するのが良さそうです。

 
Parameterにfromとtoの番号をもたせて、customParametersから取得した情報をNotificationに渡すことでどこからどこへの受電なのか表示が可能です。是非、試してみてください。

保留

一般的な電話機同様、実装が可能です。

保留にあたり、サーバ側でQueueと呼ばれる、通話を待機させる場所に通話を入れることで実現ができます。

ドキュメントのこちらのコードが参考になります。
 
また、このEnqueueの呼び出しにあたり、通話相手の通話を更新する必要があります。
詳しくはこちらのドキュメントを参考にしてください。

ドキュメントの通りだと、すべての保留はsampleというQueueに入ってしまうため、取次時に困ることになります。
というのもQueueに入っている通話は、最初に入った通話から順次取り出されて通話するため、指定した通話を取り次ぐためにはQueueの状態を見ながら指定の通話が次に取り出されるタイミングまで待つ必要があるからです。
この仕様だと、とても使いづらいかと思います。

そこでQueueの名前はTwilioが自動で割り振りするCallSidを使用するのをおすすめします。
下記のようなコードになります。
 

require_once './vendor/autoload.php';
use Twilio\TwiML\VoiceResponse;

$response = new VoiceResponse();
$response->enqueue($_REQUEST['call_sid'], ['waitUrl' => 'wait-music.xml']);

echo $response;

 
Clientでは、上記のURLに対して、通話中のCallSidを付与して、呼び出すようにしましょう。
通話中のCallSidTwilio.DeviceのactiveConnection()を呼び出し、Connectionオブジェクトを取得します。
Connectionオブジェクトにparametersというプロパティがあり、その中でCallSidを保持しています。

説明すると長いですが、コードだと下記のようになります。
 

const call_sid = Twilio.Device.activeConnection().parameters.CallSid;

 
このCallSidをサーバに渡し、Queueの名前にすることで、
必ず一意な名前を持つQueueが作成できます。
またここで取得したcall_sidは次の取次でも利用します。

取次

Twilioにおいて「取次」とは、指定のQueueに対して、電話をかけることに該当します。
そのため、コードとしてはシンプルで架電とほぼ同じ実装です。
 

require_once './vendor/autoload.php';
use Twilio\TwiML\VoiceResponse;

$response = new VoiceResponse();
$dial = $response->dial('');
$dial->queue($_REQUEST['call_sid'], ['url' => 'about_to_connect.xml']);

echo $response;

 
取次の難しいところは、上で指定したCallSidの受け渡しが難しいことです。

私の場合は、受け渡しはTwilio Syncというリアルタイムデータベースを用いて、同じアカウント内のClientはすべて保留一覧が同期された状態で見れるようにしています。

ユーザにとって、CallSidは意味のわからない文字列なのでこれは見せず、通話相手の電話番号と保留した人の情報が見れるようになっています。

コードは公開していないのですが、システム構成図自体は下記スライドの29ページ目が参考になると思います。
https://www.slideshare.net/ssuser4d37c8/twilio-104443847
 
ただし、Syncは実装やテストが大変なので、ひとまずは保留したらユーザのブラウザなどにログを残し、手動でCallSidをチャットツールなどで受け渡すなどの方法でも大丈夫だと考えています。

こちらは締切との兼ね合いになるため、どれくらい保留取次が発生するかなどの要件をすり合わせた上で、どの実装方法を選択するかエンジニアの腕の見せ所になります。

DTMFトーン

宅配便などの再配達で、「再配達の依頼は1を、配達状況の確認は2を、それ以外は3を押してください」というようなアナウンスを聞いて、用件に合わせて指定された番号を押したことがあると思います。
この番号ボタンを押した際に発生する音が「DTMFトーン」です。

DTMFトーンの実装をしておかないと、「架電したのにトーンを送る方法がなくて通話ができなかった」ということが起こりえます。
実装自体は簡単なので、必ず実装しておくようにしてください。

下記ドキュメントにあるsendDigitsを使用するだけです。
https://jp.twilio.com/docs/voice/client/javascript/connection#sendDigits
 
保留でも使用したactiveConnectionからConnectionオブジェクトを参照し、押された数字を引数に呼び出すだけです。
簡単なコード例ですが、下記をそのまま使用できると思います。
 

const sendDigit = (digit) => {
// 通話中以外もボタンを押せるUIの場合は通話中チェックをします
// https://jp.twilio.com/docs/voice/client/javascript/device#status
const device_status = Twilio.Device.status();
if (device_status === 'busy') {
Twilio.Device.activeConnection().sendDigits(digit);
}
};

まとめ

今回はドキュメントをベースに実際にスモールスタートでコンタクトセンターを運用した際に使ったコードを抜粋しつつ、起きた問題を改修したサンプルコードを挙げました。
サーバとクライアントの連携が必須で、覚えることもたくさんありますが、サンプルコードを参考に、ぜひスモールスタートなコンタクトセンターを実現してみてください。

次回は本格的なコールセンター移行にあたり考慮が必要な仕様や要件の洗い出しについてまとめますので乞うご期待ください。

Webエンジニア 西口瑛一
Webエンジニア 西口瑛一

前職でTwilioを用いた国内最大規模のコンタクトセンターを1から開発。 その経歴が認められ、日本では5人しかいないTwilio Championsに選ばれる。

CTA_まずはtwilioを使ってみる。

Share!!

  • お役立ち情報
  • イベント情報
  • 相談会申込
  • 導入事例