【Vonage】最新CPaaSのWebRTCを使って通話してみた

- Vonage の [Receiving an in-app voice call](https://developer.vonage.com/ja/client-sdk/tutorials/phone-to-app/introduction/javascript) を触ってみて得たことを共有します。チュートリアルや本記事を通じて、Client SDK や Voice API を学ぶことができ、WebRTC を使って着信に応答するアプリを作成できます。
- 2021年12月現在の Vonage API の仕様に合わせて適宜書き換えたり、自分好みで進め方を変えてる部分があります。最新情報は[公式ドキュメント](https://developer.vonage.com/ja/client-sdk/overview)をご覧ください。

https://developer.vonage.com/ja/client-sdk/overview

#必要なもの

- Vonage API Key（[作成する](https://dashboard.nexmo.com/)）
- [client-sdk-tutorials](https://github.com/nexmo-community/client-sdk-tutorials)
- [Node.js](https://nodejs.org/en/)
- [Expressjs](https://expressjs.com/)
- [localtunnel](https://github.com/localtunnel/localtunnel)


rbenv や goenv に慣れてる方だと、Node.jsのバージョン管理はnodenvが使いやすいかもしれないです。

#Webサーバーの準備

プロジェクトをクローンする

```
git clone https://github.com/nexmo-community/client-sdk-tutorials.git
cd client-sdk-tutorials/phone-to-app-js
```

package.json を生成して、必要な依存関係をインストール

```
npm init -y
npm install express localtunnel --save
npm install nexmo-client --save
```

server.js の `const subdomain = 'SUBDOMAIN';` を任意のドメインに書き換える

```diff
- const subdomain = 'SUBDOMAIN';
+ const subdomain = 'onakasuita4649';
```

server.js 実行

```
node server.js
# URLはアプリケーションの作成で使用するのでメモしてください
App available at: https://onakasuita4649.loca.lt
```

#アプリケーションの作成

[Nexmo CLI](https://developer.vonage.com/ja/client-sdk/tutorials/phone-to-app/prerequisites/javascript) でも操作できますが、個人的にダッシュボードの方が見やすかったです。


1) ログイン後「Create a new application」を押す
![スクリーンショット_2021-12-09_10_47_17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604757/901291bf-7084-e742-1774-b41dd85a3bea.png)

2) ①〜③を入力したら「新しいアプリケーションの作成」を押す
①好きなアプリケーション名を入力
②秘密鍵はあとで JWT の生成で使用
③Webhook URL を指定。回答 URL は GET / イベント URL は POST
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3630343735372f63643561653763352d616462302d383062372d323435632d6235636232653463303265372e706e67-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604757/f154a43e-aaa1-e2e8-956a-b65683e576ed.png)


###作成したアプリケーションに Vonage 番号をリンク

画面下半分の番号一覧から、右側の「Link」ボタンを押す。

![スクリーンショット_2021-12-09_11_05_23-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604757/5c99953d-c5c9-d624-5cdb-209d2d9ccb1e.png)


#クライアントの準備
###Admin 用 JWT の生成

この後のユーザー作成で使用します。

公式ドキュメントでは [Nexmo CLI](https://developer.vonage.com/ja/client-sdk/tutorials/phone-to-app/prerequisites/javascript) や Server SDK での紹介が多いですが、ここでは [JWT Generator](https://developer.vonage.com/jwt) を使用します。

①先ほどの秘密鍵
②作成したアプリケーションの ID
③期限
④生成された JWT （①~③を入力すると自動生成されます）
![スクリーンショット_2021-12-09_11_17_37-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604757/19de7e9c-1c47-9a27-0adf-3d8b1332d2ed.png)

###ユーザー作成
####ポイント

- Admin用JWTを使用
- 日本の電話番号を使用する場合はシンガポール(SNG)のデータセンターをエンドポイントに指定

以下は自分が書いた記事ですが、日本から電話機で発信するとシンガポールのデータセンターに会話が自動的に作成されるため、応答するユーザーもシンガポールに作成する必要があります。

ユーザーを作成したけど、会話と異なるデータセンターに存在すれば着信に応答しようとしても音声通話ができないので注意が必要です。自分もハマりました...

https://qiita.com/kusunoyuta/items/9eeb77cd901819c5b08e#%E3%83%87%E3%83%BC%E3%82%BF%E3%82%BB%E3%83%B3%E3%82%BF%E3%83%BC%E3%81%AE%E8%A8%AD%E5%AE%9A

[Nexmo CLI](https://developer.vonage.com/ja/client-sdk/tutorials/phone-to-app/prerequisites/javascript) だとエンドポイントが指定できず、デフォルトで米国のデータセンターにユーザーが作成されるのでREST APIを使用します。

```
curl -X "POST" "https://api-sg-1.nexmo.com/beta/users" \
     -H 'Authorization: Bearer '生成されたAdmin用JWT\
     -H 'Content-Type: application/json' \
     -d $'{
  "name": "Alice",
  "display_name": "Alice"
}'
```
Create a User

https://developer.vonage.com/ja/conversation/code-snippets/user/create-user

ユーザーID がレスポンスに含まれていれば成功です。

```
{"id":"USR-xxxxxxxxxxxxx","href":"https://api-sg-1.nexmo.com/beta/users/USR-xxxxxxxxxxxxx"}
```

以下のレスポンスが返ってきた場合はJWTを生成し直すか、期限を見直すと改善するかもしれません。

```
{"description":"You provided an expired token. Please provide a valid token.","code":"system:error:expired-token"}
```

###クライアントユーザー用JWTの生成

ここでも [JWT Generator](https://developer.vonage.com/jwt) を使用します。
赤枠がAdmin用から増えてる項目です。

![スクリーンショット_2021-12-09_11_38_25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604757/7ce705ae-f978-e7af-a5b0-4837aa288b89.png)

sub には先ほど作成したユーザー名を、[ACL](https://developer.vonage.com/ja/conversation/guides/jwt-acl#acls) には以下の例のように入力します。
適宜必要なパスを指定しましょう。

```
{
	"paths": {
		"/**": {}
	}
}
```

###NexmoClient 初期化

- client_js.html

書き換え前

```
new NexmoClient({ debug: true })
.login("PASTE ALICE JWT HERE")
.then(app => {

// ・・・（中略）・・・
```

生成したユーザー用 JWT を貼り、ここも[エンドポイントを SNG に指定](https://qiita.com/kusunoyuta/items/9eeb77cd901819c5b08e#%E3%83%87%E3%83%BC%E3%82%BF%E3%82%BB%E3%83%B3%E3%82%BF%E3%83%BC%E3%81%AE%E8%A8%AD%E5%AE%9A)します。
書き換え後

```
new NexmoClient({
  nexmo_api_url: "https://api-sg-1.nexmo.com",
  url: "wss://ws-sg-1.nexmo.com",
  ips_url: "https://api-sg-1.nexmo.com/v1/image",
  debug: true 
}).login("生成したユーザー用JWT")
.then(app => {

// ・・・（中略）・・・
```

###NexmoClient ログイン

client_js.html をブラウザで開きます。
デベロッパーツールに`session:success`が表示されていればクライアントのログインが成功です。
つぎは、いよいよ着信に応答してみます。

![スクリーンショット_2021-12-22_23_29_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604757/51a3409e-73e2-18bd-8fde-5d35bdcd5f5a.png)




##着信に応答

アプリケーションに紐付けた Vonage 番号に発信します。

電話をかけるとデベロッパーツールには`member:invited`が表示され
Webページ上には "You are receiving a call"が表示されます。

マイクの使用許可を求められたら、必ず「許可」を押してください。
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3630343735372f31323630616233342d643136642d613535332d613366632d6162376531663439323435332e706e67-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604757/f61b4061-cca1-1a7c-c7c8-d06656e2a81f.png)



Answer ボタンを押せば着信に応答できるはずです。
通話を切断する場合は Hang Up ボタンを、応答前に切断したい場合は Reject を押しましょう。


お疲れさまでした。

##雑感

紹介したのは　[Receiving an in-app voice call](https://developer.vonage.com/ja/client-sdk/tutorials/phone-to-app/introduction/javascript) というチュートリアルですが、システム障害通知やコールセンター構築、予約の電話通知なども、VonageをはじめとしたCPaaSを使えば比較的短期間で実現できるのでうれしいですね。

今回はあまり触れていないですが、開発前に会話の概念(Inbound legやOutbound leg)を確認しておくと幸せになれるかもです。

Inbound legやOutbound legを指定して会話を制御できるのですが、自分側か相手側のどちらかを通話中にミュートにしたい、待機音を流したい、といった時に開発が一層充実すると思います。

会話の概念

https://developer.vonage.com/ja/conversation/concepts/conversation

Voice API
通話中にミュート制御

https://developer.vonage.com/api/voice?theme=dark#updateCall

Voice API
オーディオファイルを通話中に再生

https://developer.vonage.com/api/voice?theme=dark#startStream