前回SMSを飛ばすサンプルプログラムの実行までを試しましたが、今回はTwilio クライアント JavaScript APIを使用し電話をかける部分を作ります。
※ローカルの開発環境の方は、この先のTwilio クライアント JavaScript APIを使用した電話発信には外部公開サーバが必要です。ローカル環境からの発信には最下部を参照して下さい。
###2.アプリ構成
・quadclient.php (メイン画面&コール)
・quad-client-twiml.php (電話番号選定)
・base.css
・normalize.css https://github.com/necolas/normalize.css/
それからTwilio-phpヘルパーライブラリー
https://jp.twilio.com/docs/php/install
こちらのソースコードをベースにしています。
https://jp.twilio.com/docs/quickstart/php/client/outgoing-calls
<?php
include '../twilio-php/Services/Twilio/Capability.php';
// put your Twilio API credentials here
$accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$authToken = 'YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY';
// put your Twilio Application Sid here
// 取得したTwiml APP のSidを設定
$appSid = 'APZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ';
// put your default Twilio Client name here
$clientName = 'QuadPhone';
// get the Twilio Client name from the page request parameters, if given
if (isset($_REQUEST['client'])) {
$clientName = $_REQUEST['client'];
}
$capability = new Services_Twilio_Capability($accountSid, $authToken);
$capability->allowClientOutgoing($appSid);
$capability->allowClientIncoming($clientName);
$token = $capability->generateToken();
?>
<!DOCTYPE html>
<html>
<head>
<title>Quad Client</title>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0">
<link href="css/normalize.css" rel="stylesheet" type="text/css">
<link href="css/base.css" rel="stylesheet" type="text/css">
<link href='https://fonts.googleapis.com/css?family=Roboto:400,100,300,500,700,900' rel='stylesheet' type='text/css'>
<script type="text/javascript"
src="//static.twilio.com/libs/twiliojs/1.2/twilio.min.js"></script>
<script type="text/javascript"
src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js">
</script>
</head>
<script type="text/javascript">
Twilio.Device.setup("<?php echo $token; ?>");
Twilio.Device.ready(function (device) {
$("#log").text("Client '<?php echo $clientName ?>' is ready");
});
Twilio.Device.error(function (error) {
$("#log").text("Error: " + error.message);
});
Twilio.Device.connect(function (conn) {
$("#log").text("Successfully established call");
});
Twilio.Device.disconnect(function (conn) {
$("#log").text("Call ended");
});
Twilio.Device.incoming(function (conn) {
$("#log").text("Incoming connection from " + conn.parameters.From);
// accept the incoming connection and start two-way audio
conn.accept();
});
Twilio.Device.presence(function (pres) {
if (pres.available) {
// create an item for the client that became available
$("<li>", {id: pres.from, text: pres.from}).click(function () {
$("#number").val(pres.from);
call();
}).prependTo("#people");
}
else {
// find the item by client name and remove it
$("#" + pres.from).remove();
}
});
// クリックされた要素でコール先を変更する仕様に改変
function call(obj) {
// get the phone number or client to connect the call to
params = {"PhoneNumber": obj.id};
Twilio.Device.connect(params);
}
function hangup() {
Twilio.Device.disconnectAll();
}
</script>
</head>
<body>
<div class="title-area">
<h1><div id="log">Loading...</div></h1>
</div>
<div class="container">
<ul class="glid-block">
<li class="glid-cell">
<button onClick="call(this);" id="fushimi">
<div class="image-block">
<img src="img/face.png" alt="">
</div>
<p class="number">fushimi</p>
</button>
</li>
<li class="glid-cell">
<button onClick="call(this);" id="segawa">
<div class="image-block">
<img src="img/face.png" alt="">
</div>
<p>segawa</p>
</button>
</li>
<li class="glid-cell">
<button onClick="call(this);" id="sasaki">
<div class="image-block">
<img src="img/face.png" alt="">
</div>
<p>sasaki</p>
</button>
</li>
</ul>
</div>
<div class="general-foot">
<li>
<button class="hangup general-hangup" onclick="hangup();">
Hangup
</button>
</li>
<li>
<button class="call general-call" onclick="call(this);" id="office">
Call to main phone
</button>
</li>
</div>
</body>
</html>
<?php
header('Content-type: text/xml');
// put a phone number you've verified with Twilio to use as a caller ID number
$callerId = "+16698004184";
// put your default Twilio Client name here, for when a phone number isn't given
$number = "+81358296297";
$member = array("fushimi" => "+818000000000",
"segawa" => "+818000000001",
"sasaki" => "+818000000002",
"office" => "+813000000003");
// 受け取ったパラメータの名前でコール先を決定
if (isset($_REQUEST['PhoneNumber'])) {
if (array_key_exists(htmlspecialchars($_REQUEST['PhoneNumber']),$member)){
$number = $member[htmlspecialchars($_REQUEST['PhoneNumber'])];
}
}
// wrap the phone number or client name in the appropriate TwiML verb
// by checking if the number given has only digits and format symbols
if (preg_match("/^[\d\+\-\(\) ]+$/", $number)) {
$numberOrClient = "<Number>" . $number . "</Number>";
} else {
$numberOrClient = "<Client>" . $number . "</Client>";
}
?>
<Response>
<Dial callerId="<?php echo $callerId ?>">
<?php echo $numberOrClient ?>
</Dial>
</Response>
button{
border: none;
background: none;
}
/* line 4, ../scss/_original.scss */
body {
background-color: #f7f7f7;
font-family: 'Roboto', sans-serif;
position: relative; }
/* line 10, ../scss/_original.scss */
.title-area {
padding: 40px 0; }
/* line 13, ../scss/_original.scss */
.title-area h1 {
font-size: 48px;
font-weight: 100;
text-align: center;
margin: 0; }
/* line 21, ../scss/_original.scss */
.container {
display: block;
overflow: scroll;
padding: 0 10%;
width: 100%;
max-height: 76%; }
/* line 38, ../scss/_original.scss */
.glid-block {
display: block;
width: 100%;
height: auto;
padding: 0;
margin: 0; }
/* line 45, ../scss/_original.scss */
.glid-block:after {
content: "";
display: table;
clear: both; }
/* line 52, ../scss/_original.scss */
.glid-cell {
display: block;
width: 33.333333%;
padding: 16px 20px;
float: left; }
/* line 59, ../scss/_original.scss */
.glid-cell a {
display: block;
width: 100%;
height: 100%;
color: #333;
text-decoration: none; }
/* line 68, ../scss/_original.scss */
.glid-cell .image-block {
display: block;
width: 100%;
border-radius: 50%;
background-color: #fff;
overflow: hidden;
line-height: 0; }
/* line 76, ../scss/_original.scss */
.glid-cell .image-block img {
width: 100%; }
/* line 81, ../scss/_original.scss */
.glid-cell p {
text-align: center;
font-size: 16px; }
/* line 88, ../scss/_original.scss */
.general-foot {
display: table;
width: 100%;
padding: 40px 10%;
position: fixed;
bottom: 0;
background-color: #f7f7f7; }
/* line 96, ../scss/_original.scss */
.general-foot li{
display: table-cell;
vertical-align: middle;
text-align: center;
width: 50%;
padding-left: 10px;
padding-right: 10px;
}
.general-foot .general-call {
display: block;
text-align: center;
text-decoration: none;
font-size: 16px;
color: #fff;
width: 100%;
border-radius: 24px;
padding: 1em;
background-color: #4dce52; }
.general-foot .general-hangup {
display: block;
text-align: center;
text-decoration: none;
font-size: 16px;
color: #fff;
width: 100%;
border-radius: 24px;
padding: 1em;
background-color: #e65172; }
/* line 10, ../scss/base.scss */
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box; }
/* line 19, ../scss/base.scss */
html {
font-size: 62.5%; }
@media screen and (max-width: 800px) {
/* line 19, ../scss/base.scss */
html {
font-size: 54.7%; } }
/* line 29, ../scss/base.scss */
body {
font-size: 1.0rem;
line-height: 1;
color: #363636;
word-wrap: break-word;
vertical-align: middle; }
/* line 42, ../scss/base.scss */
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
position: relative; }
今回iPadでいい感じに見えるように組んで、いざiPad Air(iOS9.1)で検証してみるとTwilio APIがLoadingのまま止まってしまい、iPadのSafariでは動かなかった。
PCの方はOSX(El Capitan)のSafari9で動作確認済み。
iPadで使えるようにするにはアプリ化するか、と思ったクリスマスイブの夜でした。。
おまけ。
ローカル開発環境から電話発信する場合にはApp SIDが不要な下記の記述で可能です。
<?php
// Get the PHP helper library from twilio.com/docs/php/install
require_once('twilio-php/Services/Twilio.php'); // 環境に合わせて変えて下さい
// Your Account Sid and Auth Token from twilio.com/user/account
$sid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
$token = "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY";
$client = new Services_Twilio($sid, $token);
$call = $client->account->calls->create("+1NNNNNNNNNN", "+81NNNNNNNNNN", "http://demo.twilio.com/docs/voice.xml", array());
// echo $call->sid;
最終的には社内に居てSlackで着席状況を確認してコール可能な人だけ、表示するなどステータス更新できると良いなと。
Slack botも強化が必要そうだ。。