はじめに
Vonage は CPaaS(Communications Platform as a Service)のプロバイダーで、SMS送信や音声通話などのコミュニケーション機能をAPI連携で実装できるサービスを提供されています。
本記事では Vonage から提供されている API を用いて SMS送信とパスワードなし認証を実装してみました。
開発環境
Vonage では様々なプログラミング言語の SDK が用意されています。
今回は PHP のフレームワークである Laravel を用いて実装します。
- PHP v8.2
- Laravel v10.x
Vonage API を用いた実装方法を確認することが目的であるため、本記事では画面を作成せずに Artisan コマンドを作成し、簡略化を図っております。
Laravel で Vonage を使用するためのパッケージとして、Vonage のサイトで紹介されている vonage/vonage-laravel
と Laravelの公式マニュアルで紹介されている laravel/vonage-notification-channel
があります。
今回は Laravel の公式マニュアルに記載されている laravel/vonage-notification-channel
を使用して進めていきます。
ちなみに、どちらを用いても SMS 送信やパスワードなし認証は実装可能です。
使用準備
Laravel の公式マニュアルに従って、Vonage を使用するための準備を進めていきます。
まずは以下のコマンドを実行して、composer でパッケージをインストールします。
composer require laravel/vonage-notification-channel guzzlehttp/guzzle
インストールが完了したら、.env
に Vonage を使用するために必要な情報を記述します。
VONAGE_KEY=[VonageのDashboardで取得したAPI key]
VONAGE_SECRET=[VonageのDashboardで取得したAPI Secret]
これだけで準備完了です。
SMS送信
入力されたメッセージを送信する Artisan コマンドを作成して、SMS送信の動作を確認してみます。
こちらの実装では、Vonage の SMS API を使用しています。
Notifications を使用して送信する方法
Laravel の公式マニュアルには Notifications(通知)の機能を活用してSMS送信を行う方法が記載されています。
まずは VonageNotification.php
を作成します。
class VonageNotification extends Notification
{
use Queueable;
private string $message;
public function __construct(string $message = '')
{
$this->message = $message;
}
public function via(object $notifiable): array
{
return ['vonage'];
}
public function toVonage(object $notifiable): VonageMessage
{
$from = 'Laravel App'; // 送信先で表示される送信者ID
return (new VonageMessage)->from($from)->content($this->message);
}
}
次に、作成した VonageNotification.php
を用いてSMS送信を行う Artisan コマンドを作成します。
class SendSms extends Command
{
protected $signature = 'send:sms';
public function handle()
{
$message = $this->ask('What message do you want to send?');
$to = '送信先の電話番号';
Notification::route('vonage', $to)->notify(new VonageNotification($message));
}
}
それでは実際にコマンドを実行して、動作確認を行ってみます。$to
の値を自分の電話番号に置き換えてから実行してください。
php artisan send:sms
What message do you want to send?:
> Hello world!
スマホで確認したところ、入力したメッセージが届いていました。
また、標準のままだと日本語が文字化けしてしまうため、日本語を送信するためには unicode()
を実行する必要があります。
public function toVonage(object $notifiable): VonageMessage
{
- return (new VonageMessage)->from($from)->content($this->message);
+ return (new VonageMessage)->from($from)->content($this->message)->unicode();
}
Vonage ファサードを用いて送信する方法
vonage/vonage-laravel
の README に記載されている方法で、シンプルな記述でSMS送信を行うことができます。
class SendSms extends Command
{
protected $signature = 'send:sms';
public function handle()
{
$message = $this->ask('What message do you want to send?');
$to = '送信先の電話番号';
$from = 'Laravel App'; // 送信先で表示される送信者ID
Vonage::sms()->send(new SMS($to, $from, $message));
}
}
パスワードなし認証
SMS/音声/メールを用いたパスワードなし認証を行う Artisan コマンドを作成して、動作を確認してみます。
こちらの機能では、Vonage の Verify API を使用しています。
マニュアルによると、旧バージョンの Verify V1 と現バージョンの Verify V2 が提供されているようです。
Verify V1
まずは旧バージョンを用いて実装してみます。V1 では、SMSと音声(読み上げ)による組み合わせで認証を行うことが可能です。デフォルトのワークフロー(workflow_id = 1)では SMS → 音声 → 音声の流れで認証が行われます。
- ワークフロー開始
- SMS で PIN コードを送信
~ 数分間経過 ~ - 電話が掛かってきて PIN コードを読み上げ
~ 数分間経過 ~ - 電話が掛かってきて PIN コードを読み上げ
~ 数分間経過 ~ - ワークフロー終了
ちなみにワークフローは 7 種類あり、workflow_id を指定すれば選択可能です。
public const WORKFLOW_SMS_TTS_TSS = 1; // SMS → 音声 → 音声(デフォルト)
public const WORKFLOW_SMS_SMS_TSS = 2; // SMS → SMS → 音声
public const WORKFLOW_TTS_TSS = 3; // 音声 → 音声
public const WORKFLOW_SMS_SMS = 4; // SMS → SMS
public const WORKFLOW_SMS_TTS = 5; // SMS → 音声
public const WORKFLOW_SMS = 6; // SMS
public const WORKFLOW_TTS = 7; // 音声
また、発行する PIN コードの長さは 4桁 または 6桁 を選択可能です。
public const PIN_LENGTH_4 = 4;
public const PIN_LENGTH_6 = 6;
それではデフォルトのワークフロー(SMS → 音声 → 音声)でパスワードなし認証を行う Artisan コマンドを作成して実行してみます。ちなみに、PINコードは 6桁 を指定しています。
発行した PIN コードに対しては 3 回までチェックが可能です。3 回失敗すると PIN コードが無効となり、ワークフローが終了します。
class VerifyV1 extends Command
{
protected $signature = 'verify:v1';
public function handle()
{
$to = '送信先の電話番号';
$from = 'Sender ID';
$brand = 'Brand Name';
// 認証開始
$workflowId = \Vonage\Verify\Request::WORKFLOW_SMS_TTS_TSS;
$request = new \Vonage\Verify\Request($to, $brand, $workflowId);
$request->setCodeLength(\Vonage\Verify\Request::PIN_LENGTH_6);
$request->setLocale('ja-jp');
$request->setSenderId($from);
$response = Vonage::verify()->start($request);
$failedCount = 0;
while ($failedCount < 3) {
$code = $this->ask('Please enter the verification code');
try {
// PIN コードのチェック
$result = Vonage::verify()->check($response->getRequestId(), $code);
$responseData = $result->getResponseData();
if ($responseData['status'] === "0") {
break;
}
} catch (\Vonage\Client\Exception\Exception $e) {
$failedCount++;
$this->error($e->getMessage());
}
}
// 結果メッセージの表示
if ($failedCount < 3) {
$this->info('Successfully authenticated');
} else {
$this->error('Authentication has failed');
}
}
}
認証成功の場合
Artisan コマンドを実行すると、スマホに SMS が送信されました。
受信した PIN コードを入力すると、認証成功のメッセージが表示されました。
認証失敗の場合
誤った PIN コードを3回入力して失敗すると、ワークフローが終了となり、認証失敗のメッセージが表示されました。
Verify V2
次に現バージョンを用いて実装してみます。V2 では独自のワークフローを柔軟に組み上げることが可能です。使用できるチャンネルは以下の通りです。
- SMS
- 音声
- WhatsApp Interactive / WhatsApp Codeless
- 電子メール
- サイレント認証(SIM を用いた認証)
今回は、SMS → 電子メール → 音声 のワークフローでパスワードなし認証を行う Artisan コマンドを作成して実行してみます。ちなみに、PINコードの桁数も 4桁 ~ 10桁 で柔軟に選択可能となりました。
記事投稿時点では Verify V2 は日本語に対応しておりません。
class VerifyV2 extends Command
{
protected $signature = 'verify:v2';
public function handle()
{
$toPhoneNumber = '送信先の電話番号';
$toEmail = '送信先のメールアドレス';
$brand = 'Laravel App';
// 認証開始
$request = new SMSRequest($toPhoneNumber, $brand);
$request->setLength(10); // PIN コードの桁数を指定
$request->setTimeout(60); // PIN コードの有効期限を指定
$emailWorkflow = new VerificationWorkflow(VerificationWorkflow::WORKFLOW_EMAIL, $toEmail);
$request->addWorkflow($emailWorkflow);
$voiceWorkflow = new VerificationWorkflow(VerificationWorkflow::WORKFLOW_VOICE, $toPhoneNumber);
$request->addWorkflow($voiceWorkflow);
$response = Vonage::verify2()->startVerification($request);
$isAuthenticated = false;
while (true) {
$code = $this->ask('Please enter the verification code (Enter "no" to exit)');
if ($code === 'no') {
try {
// ワークフローのキャンセル
Vonage::verify2()->cancelRequest($response['request_id']);
} catch (\Exception $e) {
$this->error($e->getMessage());
}
break;
}
// PIN コードのチェック
try {
$result = Vonage::verify2()->check($response['request_id'], $code);
if ($result === true) {
$isAuthenticated = true;
break;
}
} catch (\Exception $e) {
$this->error($e->getMessage());
}
}
// 結果メッセージの表示
if ($isAuthenticated) {
$this->info('Successfully authenticated');
} else {
$this->error('Authentication has failed');
}
}
}
認証成功の場合
Artisan コマンドを実行すると、スマホに SMS が送信されました。
そのまま何もしないで SMS に記載された PIN コードの有効期限が過ぎると、メールが届きました。
そのまま何もしないでメールに記載された PIN コードの有効期限が過ぎると、スマホに着信がありました。読み上げられた PIN コードを入力すると、認証成功のメッセージが表示されました。
認証失敗の場合
誤った PIN コードを入力するとエラーが表示されました。また、"no" と入力するとワークフローが終了となり、認証失敗のメッセージが表示されました。
おわりに
Vonage の SMS API と Verify API を用いて、SMS 送信とパスワードなし認証を実装してみました。
割と簡単に実装することができるので、こういった機能を求められた場合は CPaaS の選択肢の1つとして Vonage を検討してみてはいかがでしょうか?
また、本記事では紹介しきれなかった音声通話(Voice API)などを Laravel(PHP)で実装する場合は、vonage/vonage-php-sdk-core
の README を参考にされると良いと思います。