ふと思い立って、”たった4行で電話が作れる API” の Twilio で遊んでみることにした。まずは電話を受けて、発信者情報を取得してみよう。
Twilio とは?
Twilio とは、Web アプリケーションに対して電話の発着信や SMS の送受信機能を実装できるクラウド電話 API で、「トゥイリオ」と読むらしい。日本では KDDI なんちゃらかんちゃらって会社が提供しているようだ。
登録すると自分専用の電話番号 (050-XXXX-XXXX) が発行される。色んなとこに紹介記事があがってるので、詳細はググって欲しい。
TwiML
Twilio に着信があったときの挙動は、TwiML (トぅぃむる) で定義する。TwiML とは「通話や SMS を受信した時の動作を Twilio に指示するための命令のセット」とのことだが、実体はただの XML なので何も難しくない。
Twilio に着信があると、あらかじめ指定した URL (Voice Request URL) に対して、Twilio のサーバが http(s) 通信で TwiML を読みに来る。その際、アプリ側では各種メタデータ (発信者の電話番号など) を POST 値として取得できる。そしてアプリは Twilio に TwiML を返し、Twilio はその記述 (TwiML 動詞) に従って電話の発信者に応答する。シーケンス図にすると以下のような感じ。
あとから気づいたが、公式のブログでわかりやすくまとめられていた。
それで今回は TwiML 動詞の “Reject” を使って、着信を拒否してみる (なぜなら課金されないらしいから)。ちなみに Reject 以外の挙動だと、発信者には通常の通話料が、着信者 (つまり Web アプリ側) には1円/回が課金される模様。
話がそれるが web sequence diagrams 便利だな。以下のような記述で、簡単にシーケンス図を作成できる。
title Twilio's Incoming Flow
発信者->Twilio: 電話を発信
Twilio->Web アプリ: メタデータを添えて、\nTwiML を http(s) で要求
note right of "Web アプリ": TwiML を生成
Web アプリ->Twilio: TwiML を出力
Twilio->発信者: TwiML に従って応答
サンプルアプリケーション
Twilio に対して TwiML を返すプログラムを作成する。言語は何でも良くて、極端な話 static な XML ファイルでも OK だが、今回は POST 値を手軽に取得したいので PHP を使う。
で、作成したのが以下のコード。日時と POST 値をログに残しつつ、TwiML を出力するプログラムだ。なお、xml の宣言が PHP のショートタグとコンフリクトするので echo で出力している。
<?php
$log = "./reject.log";
error_log(date("Y-m-d H:i:s") . "\n", 3, $log);
error_log(print_r($_POST, true), 3, $log);
header("Content-Type: text/xml");
echo '<?xml version="1.0" encoding="UTF-8"?>';
?>
<Response>
<Reject reason="busy" />
</Response>
これを reject.php と言う名前で Web サーバに置き、同じディレクトリに reject.log を作成して Web サーバからの書込み権限を与える。
試しにブラウザでアクセスしてみると、以下のように表示される。同時に reject.log にログが出力されていれば成功だ。
なお、このままの状態だと Twilio のサーバから以外でも、URL を知ってさえいれば TwiML を取得できてしまう (実際ブラウザで表示できてるし)。対策としては、下記のページを見ると BASIC 認証を施すのが簡単そう。あと SSL のオレオレ証明書には現時点では非対応とのこと。
- セキュリティ – Twilio Docs
Voice Request URL の登録
作成したプログラムの URL を Twilio に登録する。
Twilio のサインアップはあらかじめ済ませておく。Twilio にログインし、[電話番号] をクリックしたあと表示されるページで、設定したい電話番号 (050-XXXX-XXXX) をクリックする。
次に表示されるページで、Voice Request URL を入力して [変更を保存する] をクリックすれば完了だ。
電話をかけてみる
以上でアプリケーション側の準備ができたので、いよいよ Twilio の番号に電話をかけてみる。今回は発信に 050 plus を使う。ピッポッパッ。
すると、トライアルアカウントである旨アナウンスが流れたあと、電話が切れる。通話料を見てみると……。
無料だと思ってたのに課金され奴ww なんでだろう。トライアルアカウントのアナウンスが流れる分の通話料か?まぁいいや今度聞いてみよう (誰に)。
そして Web サーバ側の reject.log を確認すると、以下のようにメタデータを取得できている。
2013-10-19 14:05:13
Array
(
[AccountSid] => xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
[CalledVia] => 0503154xxxx
[FromState] =>
[ToZip] =>
[Called] => +81503154xxxx
[FromCountry] => JP
[CallerCountry] => JP
[CalledZip] =>
[Direction] => inbound
[FromCity] =>
[ForwardedFrom] => 0503154xxxx
[CalledCountry] => JP
[CallerState] =>
[CallSid] => xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
[CalledState] =>
[From] => +8150yyyyyyyy
[CallerZip] =>
[FromZip] =>
[CallStatus] => ringing
[ToCity] =>
[ToState] =>
[To] => +81503154xxxx
[ToCountry] => JP
[CallerCity] =>
[ApiVersion] => 2010-04-01
[Caller] => +8150yyyyyyyy
[CalledCity] =>
)
ちなみに Web サーバのログには次のように残っていた。ご多分に漏れず AWS を使っているらしい。
23.22.14.xxx - - [19/Oct/2013:14:05:13 +0900] "POST /path/to/reject.php HTTP/1.1" 200 52 "-" "TwilioProxy/1.1"
まとめ
以上のように、Twilio を使って、発信者の電話番号などを Web アプリケーションで簡単に取得することができた。POST で送られてくるメタデータに応じて TwiML を動的に生成するプログラムを作成すれば、もっと色んなことができそうだ。
コメント