かねまさ(エンジニア)
[twilio]php laravelを使用して通話接続機能を実装
かねまさ(エンジニア)
2024.08.06
IT技術
はじめに
アカウント作成・電話番号購入の説明は本記事では行いませんのでご了承ください。
また、実務で使っているコードではなく今回の記事用に作成したソースコードのため、紹介するコードが実際に動作できるかは確認しておりません。
背景
以下要件の実装を実務で行うことになりました。
・Aからアクションがあった場合にAとBの電話の接続を行う(Aは外部サイトからのアクションを想定)
やりたいこと
顧客Aがプランに興味があるボタン(アクション)を押下した場合に顧客Aに即座に電話をかけ、会社Bと顧客Aを接続するようなこと
処理の流れのイメージ
-
顧客Aがアクションを起こしたことをキャッチ
-
対象の顧客Aをキューに入れる
-
会社Bから顧客Aに対して接続用電話番号から電話をかける
-
顧客Aが電話に出たらデキューする
-
会社Bの接続用電話番号から会社Bの実際の電話番号に電話をかける
-
会社Bの接続用電話番号を介して顧客Aと留学会社Bの接続が完了
テーブル構成
actions_table
1Schema::create('actions', function (Blueprint $table) {
2 $table->id();
3 $table->string('action_phone_number', 255);
4 $table->foreignId('company_id')->constrained();
5 $table->timestamps();
6 });
companies_table
1Schema::create('companies', function (Blueprint $table) {
2 $table->id();
3 $table->string('company_phone_number', 255);
4 $table->string('connect_phone_number', 255);
5 $table->timestamps();
6 });
実装
route
1Route::post('outgoing-callback/from-inquiry/{action}', CallbackFromActionController::class)->name('api.call.twilio.callback.from-action');
2Route::post('twilio/outgoing-call/{action}', CallToActionController::class)->name('api.call.twilio.call');
controller
CallToActionController
CallToActionControllerでは以下のことを行なっております。
-
対象の顧客Aをキューに入れ、待っている間に指定した音楽を再生させる
-
会社Bから顧客Aに対して接続用電話番号から電話をかける
statusCallbackオプションを指定すると次のアクションを実行することができます。
1<?php namespace App\Http\Controllers\Call\Twilio;
2 use App\Http\Controllers\Controller;
3 use App\Models\Action;
4 use Illuminate\Http\JsonResponse;
5 use Twilio\TwiML\VoiceResponse;
6 use Twilio\Rest\Client;
7
8 class CallToActionController extends Controller {
9 /* * 顧客Aへの発信処理 */
10 public function __invoke(Action $action): JsonResponse {
11 // TwilioClientをインスタンス化
12 $sid = getenv("TWILIO_ACCOUNT_SID");
13 $token = getenv("TWILIO_AUTH_TOKEN");
14 $twilio = new Client($sid, $token);
15
16 // 対象の顧客Aをキューに入れる
17 $voiceResponse = new VoiceResponse();
18 $voiceResponse->enqueue("action-{$action->id}", [
19 'waitUrl' => 'wait-music.xml',
20 ]);
21
22 // 会社Bから顧客Aに対して接続用電話番号から電話をかける
23 $twilio->calls->create($action->action_phone_number, $action->company->connect_phone_number, [
24 'statusCallback' => route('api.call.twilio.callback.from-action', $action),
25 ]);
26
27 return response()->json(['message' => 'success'], 200);
28 }
29}
CallbackFromActionController
CallbackFromActionControllerでは以下のことを行なっております。
-
CallToActionControllerで接続した顧客Aが電話に出たら、会社Bに電話をかける
-
顧客Aが電話に出たらデキューし、指定した音声を流す
-
会社Bの接続用電話番号から会社Bの実際の電話番号に電話をかける
-
会社Bの接続用電話番号を介して顧客Aと留学会社Bの接続が完了
1<?php namespace App\Http\Controllers\Call\Twilio;
2 use App\Http\Controllers\Controller;
3 use App\Models\Action; use Illuminate\Http\JsonResponse;
4 use Illuminate\Http\Request; use Twilio\TwiML\VoiceResponse;
5 use Twilio\Rest\Client;
6
7 class CallbackFromActionController extends Controller {
8 /* * Handle the incoming request. */
9 public function __invoke(Action $action, Request $request): JsonResponse {
10 // TwilioClientをインスタンス化
11 $sid = getenv("TWILIO_ACCOUNT_SID");
12 $token = getenv("TWILIO_AUTH_TOKEN");
13 $twilio = new Client($sid, $token);
14
15 // 顧客Aが電話に出たら、会社Bに電話をかける
16 if ($request['CallStatus'] === 'in-progress') {
17 // 顧客Aが電話に出たらデキューする
18 $voiceResponse = new VoiceResponse();
19 $voiceResponse->say("プランに興味があるボタンを押したお客様です", ['language' => 'ja-JP']);
20 $voiceResponse->dial()->queue("action-{$action->id}");
21
22 // 会社Bの接続用電話番号から会社Bの実際の電話番号に電話をかける
23 $twilio->calls->create($action->company->company_phone_number, $action->company->connect_phone_number);
24 }
25
26 // 会社Bの接続用電話番号を介して顧客Aと留学会社Bの接続が完了
27 return response()->json(['message' => 'success'], 200);
28 }
補足
上記の実装は以下の観点を考慮しておりません。
・電話履歴の保存
・顧客A or 会社Bが電話に出なかった場合のハンドリング
電話履歴の保存を行いたい場合は電話履歴テーブルを追加し適宜対応してみてください。
電話に出なかった場合のハンドリングについては以下URLをのcall statusを確認し適宜ハンドリングを行なってください。
まとめ
いかがだったでしょうか?
処理的には活用機会のない処理かもしれませんが、
コードを追っていくと理解が深まると思います。
この記事で少しでもお役に立てたら幸いです。
ライトコードでは、エンジニアを積極採用中!
ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。
採用情報へ
かねまさ(エンジニア)
Show more...プライベートの休日はインドアもアウトドアもどちらになることもあります。
おすすめ記事
immichを知ってほしい
キムくん(エンジニア)
2024.10.31