Category Archives: Twilio

PHPマイクロフレームワークSlimで作るTwilioコールセンターシステム(2.環境設定:1.ライブラリインストール編)

こちらのページでも紹介していますが、Twilioを使ったアプリケーション(Webクライアント+コールフロー)を作成しました。

以下の本を読みまして、PHPマイクロフレームワークSlim、テンプレートエンジンTwig、ORマッパーilluminate/Eloquentを使って開発しています。入力値検証用にRespect/Validationも試用しています。

あとはフロントエンドにJQueryとBootstrap/Bootswatchを使っています。もちろん、Twilio-phpも使っています。

フォルダ構造は以下の通りとしました。詳細は別途。ルートは/var/www/html/runa-cca/というフォルダとします。

/var/www/html/runa-cca/
 |-composer.json ... Composer定義ファイル
 |-composer.lock ... Composerバージョンロックファイル
 |-create_table_for_Runa-CCA.sql ...テーブル定義・初期データ投入SQLファイル
 |
 |-htdocs ... 公開用ディレクトリ
 |   |-vendor ... 外部のライブラリ
 |       |-bootstrap ... bootstrap
 |
 |-lib ... 作成したクラスライブラリ
 |   |-Base ... 設定クラス置き場
 |   | 
 |   |-Controller ... コントローラクラス置き場
 |   |   |-CallFlow ... コールフロー毎のコントローラクラス置き場
 |   |
 |   |-Model ... モデルクラス置き場
 |   |   |-CallFlow ... コールフロー毎のモデルクラス置き場
 |   |
 |   |-Model ... ビュークラス置き場
 |
 |-templates ... 作成したテンプレートファイル
 |
 |-vendor ... ライブラリ(Composerでインストール)

まずは環境設定です。

そもそもの環境ですが、Macbook Pro Retina ME865J/AMAMPを動かしています。バージョンは3.0.3を使いました。なので、Apacheは2.2.26、PHPは5.5.10、MySQLは5.5.34になります。

その上で、PHPのパッケージマネージャであるComposerを使って、必要なライブラリをインストールします。
Composerの定義ファイルcomposer.jsonは以下の通り。

{
    "require": {
        
        "slim/slim" : "2.*",
        "slim/views" : "0.1.*",
        "slim/extras" : "2.0.*",
        "twig/twig" : "1.*",
        "illuminate/database" : "4.0.*",
        "Respect/Validation" : "0.5.*",
        "twilio/sdk": "dev-master"
        
    },
    "autoload": {
        "psr-0": {"": "lib/"}
    }
}

参照書籍の記載の通り、以下のようにしてComposerをダウンロードします。

$ cd /var/www/html/runa-cca/
$ php -r "eval('?>'.file_get_contents('https://getcomposer.org/installer'));"
#!/usr/bin/env php
All settings correct for using Composer
Downloading...

Composer successfully installed to: /var/www/html/runa-cca/composer.phar
Use it: php composer.phar

composer.jsonをアップロードしておきます。Runa-CCAをディレクトリごとアップしておけばよいかと。
で、以下のコマンドを実行します。
composer.lockがある場合は、引数をinstallにすると、lockの内容を再現するようにインストールされます。

$ php composer.phar update
Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Installing respect/validation (0.5.0)
    Downloading: 100%         

  - Installing slim/slim (2.4.3)
    Downloading: 100%         

  - Installing slim/views (0.1.2)
    Downloading: 100%         

  - Installing slim/extras (2.0.3)
    Downloading: 100%         

  - Installing twig/twig (v1.15.1)
    Downloading: 100%         

  - Installing nesbot/carbon (1.8.0)
    Downloading: 100%         

  - Installing illuminate/support (v4.0.10)
    Downloading: 100%         

  - Installing illuminate/container (v4.0.10)
    Downloading: 100%         

  - Installing illuminate/events (v4.0.10)
    Downloading: 100%         

  - Installing illuminate/database (v4.0.10)
    Downloading: 100%         

slim/slim suggests installing ext-mcrypt (Required for HTTP cookie encryption)
slim/views suggests installing smarty/smarty (Smarty templating system)
Writing lock file
Generating autoload files

#twilio/sdkは省略

これで、ライブラリがvendor配下にダウンロードされます。
続きはまた別途。

PHPマイクロフレームワークSlimで作るTwilioコールセンターシステム(1.アプリ紹介編)

PHPマイクロフレームワークSlimを使って、Twilioコールセンターシステムを作成しました。
まだいろいろとわからないところ、足りないところも多く、作成中の段階です。

技術的な内容は別途として、まずはアプリの説明からなのですが、こちらのページに書いてみました。よろしければご覧ください。

Twilioコールセンターシステムにヒストリカルレポート機能を搭載した

Twilioコールセンターシステム(Twilio-MiniCC)にヒストリカルレポート機能を搭載しました。MySQLにデータを貯めるので、レポート参照はいろいろなツールを使えばいいでしょう、というのを言い訳にして、データ収集機能までの実装になります。

アプリケーションなんだから、適当なところでデータベースにデータ入力しておけばいいだろう、くらいのノリだったのですが、結構大変でありました。さんざん調べたり、考えたりして、とりあえず以下の3ポイントで、取れるデータをすべて取ってみたつもりです。さすがに不要なので、標準リクエストパラメータからAccountSidは抜きました。
これからの記述でおかしなところやもっとカイゼンするべき点があったら、ぜひご指摘ください。

データ取得のポイントは以下の3つ。本当はIVRの分岐点でもログを取って、お客様がどのようなルートを通っているのかを把握するべきなのですが、今回は割愛しました。

  1. キューのお客様側(Enqueue)から出た時
  2. キューのオペレータ側(Queue)から出た時
  3. 通話終了時

Twilioのキューの考え方はこちらが参考になります。お客様とオペレータとで同じQueueに入ります。入り方が異なっていて、お客様はTwiMLのEnqueueタグ(動詞)で、オペレータはDialタグ(動詞)のQueueタグ(動詞)で入ります。

まずはじめに、キューのお客様側(Enqueue)から出た時のデータ取得方法です。
Enqueue動詞ではaction属性が設定できます。ややこしいのですが、Enqueueのaction属性は、以下の動きになります。日本語サイトはやや怪しい(一部しか翻訳されていないところがある)ので、英語のサイトから引用します。

In the case where a call is dequeued due to a REST API request or the verb, the action URL is requested right away. In the case where a call is dequeued via the verb, the action URL is hit once when the bridged parties disconnect. If no ‘action’ is provided, Twilio will fall through to the next verb in the document, if any.

Twilio-MiniCCでは、今のところDial動詞のQueue動詞を使って呼をキューから出しますので、Enqueueのaction属性に指定されたURLは、接続された相手同士が切断されたときに、一度実行されることになります。
(キューから出たときではありません)

Enqueue動詞のaction属性でデータを取る意味は、「放棄呼」の情報を取ることができる点にあります。
一般的にコールセンターにおいて、お客様がキューに入って自分から切断した場合、その呼は「放棄呼」とされます。放棄呼が発生した場合には、actionに指定してあるURLが実行されます。そのURLで、データベースにデータを登録するプログラムを書いておけば、放棄呼の情報を取得することが出来ます。具体的には、QueueResultカラムでhangupが記録されることになります。放棄呼はコールセンターにとっては良くないことです。本来受け付けるべき呼を受け付けられなかったわけですから。放棄呼のデータを収集し、対策を打つことが極めて重要です。

なお、特に記載はないのですが、Enqueueのaction属性は、おそらく非同期で実行されています。Basic認証を使用している場合、以下のように書くとエラーが発生します。TwilioのAPPモニターに「11200 – HTTP 復帰エラー」が出て、内容を見ると、「401 Authorization Required」が出ます。

$response->enqueue('キュー名', array('waitUrl' => 'wait.php',
                                    'action' => 'action.php');

そのため、以下のように修正する必要があります。

$response->enqueue('キュー名', array('waitUrl' => 'wait.php',
                                    'action' => 'http://A:B@C/D/action.php');

A: Basic認証のユーザ名
B: Basic認証のパスワード
C: Webサーバのドメイン名
D: action.phpを置いた場所

あと、Twilio-MiniCCにおいて、本機能はexit_enqueue.phpで実装されているのですが、何もレスポンスが無いとオペレータから切断したときエラーメッセージになるため、空のTwiMLを出力するようにしています。

続いて、キューのオペレータ側(Queue)から出た時のデータ取得方法です。
Queue動詞においては、url属性を指定できます。英語のサイトから引用します。

The ‘url’ attribute takes an absolute or relative URL as a value. The url points to a Twiml document that will be executed on the queued caller’s end before the two parties are connected. This is typically used to be able to notify the queued caller that he or she is about to be connected to an agent or that the call may be recorded. The allowed verbs in this TwiML document are Play, Say, Pause and Redirect.

Queue動詞はオペレータが使うものなのですが、Queue動詞のurl属性には「お客様側」で実行したいことを書きます。ややこしい。オペレータとの接続前に、録音することをアナウンスするとか、そういうために使うそうです。お客様にアナウンスを流しつつ、裏でデータベースにデータを格納すれば、Queueのデータを取得できます。

最後に通話終了時のデータ取得方法です。
How To Track and Report Your Twilio Usage」という記事に書いてありました。通話終了後にStatusCallback Requestを投げることが出来、そこでレポートを取得します。

StatusCallback occurs asynchronously and after a call has completed, this is an opportune time to update properties of your local call record. Your application also has more flexibility at this time to process database updates or compile larger reports without impacting user experience.

非同期処理なので負担もかからずオススメということらしい。
デフォルトではオフ。Twilioのページから、「電話番号」をクリックした後、 「Optional Voice Settings」をクリック。表示される「Status Callback URL」に、プログラムへのURLを書けばオッケー。通話終了後に実行されます。Basic認証を使っている場合は、先ほどのEnqueueのときと同様の書式にする必要があります。

最後に、データベース構造なのですが、まず型がわかりませんでした。Twilioのサンプルをいくつか見ましたが、全部SQLiteのTEXT型になっているし。
REST APIの資料とか見て、MySQLの型を決めましたが、これでいいのかどうかはわかりません。そもそも正規化とかしてないので、まだまだ検討が必要そうです。

ともあれ、Twilio-MiniCCのVersion 2が完成しました。
ヒストリカルレポート収集機能の追加と同時に、データベースアクセスをPDOにしたり、設定共通クラスを作ったりと、ソースコードをカイゼンしています。
Webクライアントも作成済みなのですが、まだ公開するまでのレベルではないので、次のバージョンとします。

Twilioでコールセンターシステムを作ってみた

Twilioでコールセンターシステムを作ってみました。

※続編は「Twilioコールセンターシステムにヒストリカルレポート機能を搭載した」です。

※今は「Runa-CCA」を鋭意開発中になります。

何で作ろうかなあと考えました。
Rubyで作ろうかとも思ったのですが、Webアプリですし、フレームワーク上に構築するまでの規模でもなかったので、手軽なPHPにしました。

まず以下の本を買ってお勉強。
私がプログラマーだったとき、PHPはPHP3でありまして、今やPHP5.5です。もはやわかりません。ということで一から勉強し直してみました。PHP、MySQL、JavaScriptとCSSの基礎を学べる、非常にいい本です。オススメします。

コールセンターの機能としては、

音声自動応答(IVR)
音声ガイダンス
キューイング(待ち順番アナウンス付き)

の3つを搭載しようと考えました。基本的なフローは以下の通り。

Twilio-MiniCC Sequence

実装を考えます。

IVRが出来るということは、Twilioのブログにも書いてあったので、それほどハードルは高くないだろうと考えていました。コールセンターシステムで必要なのはキューです。オペレータに着信させなければならないのですが、オペレータがすべて電話業務(よく「受電」とか言います)をしているとき、お客様を待たせる必要があります。オペレータが忙しいからって、すぐに電話を切ってしまうのは良いセンターとは言えませんよね。その待たせる機能である「キュー」がTwilioにあるのかなあ・・・と思って探してみたら、ありました。こちらに紹介されています。

うーん、簡単すぎるぞ。オペレータはQueueタグで、お客様はEnqueueタグを使うのか。それだけでいいのかなあ・・・と思いましたが、まあ作ってみることにしました。

Twilioには、PHP用のHelperライブラリがあります。それを使うと実装は簡単です。今回のような、“着信”を処理する場合は、TwiMLというXMLライクなマークアップ言語を用いてTwilioに命令する形になるので、Helperライブラリ無しでも作れてしまいます。が、Responseタグの閉じ忘れとかなんとか、いろいろと発生しましたので、素直にHelperライブラリに頼るのが良いでしょう。

久々のPHP言語に不慣れだったので、PHPでのデータベースアクセス処理とか、クラスの定義方法とかに時間がかかりました。また、実行しても結果が無い(白いページが表示される)のにも悩まされました。白いページになる場合は、php.iniでエラーが出力される設定になっていない可能性があります。iniファイルの設定を変更するか、ini_set( ‘display_errors’, 1 );を書く必要があります。エラー出力される設定になっていても、白いページになることがあります。その場合は、php.iniに指定されているログを見ると、エラー内容を確認することが出来ます。当たり前かもしれませんが、なにぶん不慣れなので、こういったところに時間がかかってしまいました。

Twilioの部分は極めて簡単です。PHPを知っている人だったら、すぐに作れちゃうと思います。キューの実装もブログにある通り、超簡単でした。

完成したものをGitHubに公開しております。勉強用に、細かいところまでコメントを書いたつもりですので、よろしければご覧ください。

RubyでTwilio使って電話してみた

池澤あやかさんがTwilio使って電話しているのを見まして(MacPeople)、面白そうだなあと思ったので、私もやってみました。前に「Zabbix Conference Japan 2013」で「Zabbix × Twilio でサーバー監視電話連絡の自動化」という発表を聞いたことがあって、Twilioが気になってはいたんですよね。けけけ、けっして、池澤あやかさんがやってたから真似した訳ではないです。

そもそもTwilioとは何か?
公式ページから引用しましょう。

「Twilio を使えば、標準的なウェブ言語を使用して、簡単に、インテリジェントな音声通話アプリケーションを構築できます。 Twilio は従来のテレコム サービスの世界と IPコミュニケーションの橋渡しをします。」

自由かつオープンにテレコムサービスを利用できる。素晴らしいです。本来はNGN(Next Generation Network)にこのような役割が期待されていたと思うんですけどね。残念ながら、いまだNGNは自由でもオープンでもないですからねえ。残念なことです。

利用するにはまず登録が必要です。Twilioのサイトに行く。
日本だとKDDIのグループ会社であるKDDIウェブコミュニケーションズが事業として運営しているようです。うーん、通信キャリアの色が付くのは微妙だなあ。
ともあれ、登録。利用登録ボタンから登録するだけです。テストコールもかかってきます。トライアル中は無料。ただ、いつトライアル終わるのかが不明瞭です。使用量が一定量に達したら使えなくなるみたいです。

Rubyから電話をかける方法は、Twilioのブログに載っていますし、ログイン後の「Api Explorer」というコーナーでサンプルスクリプトを見ることもできます。サンプルは、なんと、Curl/Ruby/PHP/Python/Node.js/Java/C#が用意されています。好きな言語で書けるのはいいですなあ。

Twilioはマークアップ言語TwiMLを使います。TwiMLでTwilioにしゃべらす内容などを書きます。TwiMLはTwilioが読める場所に無いといけません。つまりインターネット公開する必要があります。私は自分のWebサーバを使いました。持っていない人は、TwiML用のホスティングサービスなどがありますので、そちらを使うといいかも。

日本語も話せますが、とりあえず英語にしてみました。

このwelcome.xmlをWebサーバに置きます。
ここでは仮にhttp://hogehoge/welcome.xmlとしておきます。

続いて、Rubyでコードを書きます。Ruby 2.1.1を使用。
まずはtwilio-rubyを入れます。

# gem install twilio-ruby

サンプルを参考に(というかそのまま)書く。

これで準備完了。

$ ruby call.rb

と実行すると、電話がかかってきました!
試用期間中はTwilioの宣伝文言が入りますが、その後、男性の声で「Welcome to Twilio!」と話してくれました。

TwilioのWebサイトを見てみると、IVRとかも作れちゃうようです。
これは色々な可能性があるなあ。