VonageコミュニケーションAPIを使ってみる

本日はAdvent第１弾（個人的に第１弾なだけ）と言うことで、Vonageさんが提供するコミュニケーションAPIに関してご紹介します。

コミュニケーションAPIといっても、できることが盛りだくさんで、大きく分けると
1. **Video API**, ビデオ配信管理機能
1. **Messages API**, MMS,SMS,Facebook,WhatsApp,Viberとかへのメッセージ配信できるAPI
1. **SMS API**,ショートメッセージを送る機能
1. **Voice API**, 音声管理API
1. **In-App Voice**, アプリ内にボイス機能が実装できるサービス
1. **SIP TRUNKING**, VoIPで通をを送受信できるようにするサービス
1. **In-App Message**, アプリ内でメッセージ送信できるサービス
1. **Conversation API**, 複数のコミュニケーションチャンネルをまとめて表示できるサービス
1. **EMail**, メール送るサービス（まだ準備中かな・・ドキュメント見当たらず、SendInBlueのようなので、これはまた別の機会に）
1. **Dispatch**, マルチチャンネルのメッセージ配信サービス

と大きく分けて10区分ほどですが、さらにできることは区分ごとにたくさんあり・・ちょっとカオス。とにかくできることが多く・・カバーするのは到底無理なので、本日は、Video API, Message API, SMS API, Voice APIを紹介いたします。他も見てみたい方はこちらのオフィシャルドキュメントを参照ください。

https://www.vonagebusiness.jp/communications-apis/apis/

それでは早速、順に紹介していきます。　

# Video API

Videoを利用する際には Video Chat EmbdedとVonage Video APIがあります。ウェブページ上にて簡単にビデオチャット機能搭載したいときは、Video Chat Embededでコピペするだけで自身のサイトにビデオチャット機能を乗せることができます。

今日時点ではVideo APIは別アカウントを作成する必要があり、ログインも別となっています。近日マージされるようです、管理画面にそんな旨の記載がありました。

iOS,Androidでの実装もできますが、今回はウェブでの実装を紹介します。iOS, Androidのインプリ方法知りたい方はコメントにリクエスト残しておいてください、次回書いてみます。

先ずは下記のコードをお好みのIDEで用意してください。

```html
<html>
<body>
<!-- OpenTok.js library -->
<script src="https://static.opentok.com/v2/js/opentok.js"></script>
<script>

// credentials
var apiKey = '{YOUR API KEY}';
var sessionId = '{YOUR SESSION ID}';
var token = '{YOUR TOKEN}';

// connect to session
var session = OT.initSession(apiKey, sessionId);

// create publisher
var publisher = OT.initPublisher();
session.connect(token, function(err) {
   // publish publisher
   
});
  session.publish(publisher);
  
// create subscriber
session.on('streamCreated', function(event) {
   session.subscribe(event.stream);
});

</script>
</body>
</html>
```

コメントしている各部分を順に入れていくだけで、ビデオチャットが実装できます。

## 認証情報

管理画面からの情報をここにコピペするだけでOKです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241909/6ceecf8b-c692-a604-74fa-264ca28e0fa5.png)

まずはセッションIDを生成します、次に

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241909/3c84cc65-1d78-5916-b337-44ef2cdae43a.png)

そして

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241909/5c95fce4-177d-4dbf-8175-1b7f99c8a4a5.png)

これで、apiKey, sessionId, tokenがそろいましたので下記のように変数を用意して設定します。各値をダイナミックに生成するためのAPIも用意されていますので、実際はそれを使ってサービスをつくることになります。

```javascript
var apiKey = '{YOUR API KEY}';
var sessionId = '{YOUR SESSION ID}';
var token = '{YOUR TOKEN}';
```

## パブリッシャー(配信者)としての接続

まずは、配信者が必要なので、配信者としての接続を行います。

```javascript
var session = OT.initSession(apiKey, sessionId);

// create publisher
var publisher = OT.initPublisher();
session.connect(token, function(err) {
   // publish publisher
   
});
```

ここまでは設定で、実際に接続するのは下記のコードです。

```javascript
session.publish(publisher);
```

## サブスクライバー(視聴者)の接続

次は配信を見る視聴者を接続します。

```javascript
session.on('streamCreated', function(event) {
   session.subscribe(event.stream);
});
```

## 配信確認

ここでビデオが配信されていることを確認。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241909/a3b3812a-9ef6-56ad-81dd-4ee29e55adb9.png)

## ビデオチャット実装確認
もう一つのブラウザーで同じコードを実装して、Video通話を実装してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241909/93647463-118b-453c-9966-a7151b3c27ba.png)

一人なので、意味ないですが・・実装は確認できました。

ひと昔、自身でシステム作った事もありますが、このサービス作った方が１万倍速い実装が可能です。さらに詳細気になる方はこちらのドキュメント参照ください。

https://tokbox.com/developer/get-started

# Messages API

カバーする内容が多いので、サクサクいきます。次はMessage APIになります。管理画面から新しいアプリケーション作成をクリックし、認証で必要となるトークンを発行。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241909/25a29d0d-f488-20bf-05cd-c3e8e5dc3eee.png)


そして、Message APIを有効にします。ここで、着信URLとステータスURLが必要となりますので、作成していきます。一旦どのような処理をするものなのかは未定として、場所だけ用意します。

```csharp

  public class VonageController : Controller
  {
      [HttpPost, Route("/vonage/messageapi/inbound")]
      public IActionResult InComiing()
      {
          return Ok();
      }

      [HttpPost, Route("/vonage/messageapi/status")]
      public IActionResult Status()
      {
          return Ok();
      }
  }
  
```

一旦受け口をセットしたら、最後に新しいアプリケーション作成をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241909/6d669355-b6d4-75e2-a84a-711c9baa57d3.png)

そして、ここから先はこちらの記事にて過去まとめたので、ご参照ください。

https://qiita.com/syantien/items/7ec5c37f9dd8226c206f

とりま、コア部分のコードは下記になります、こちらもSDK使うことで簡単に実装できます。

```csharp
 public async Task SendWhatsAppMessageAsync(string number, string text)
        {
            var appId = _config.Value.Vonage.AppId;
            var privateKeyPath = _config.Value.Vonage.PrivateKeyPath;

            var credentials = Credentials.FromAppIdAndPrivateKeyPath(appId, privateKeyPath);

            var vonageClient = new VonageClient(credentials);

            var request = new WhatsAppTextRequest
            {
                To = number,
                From = "{YOUR WHATSAPP NUM}",
                Text = text
            };

            var response = await vonageClient.MessagesClient.SendAsync(request);

            Debug.WriteLine(JsonSerializer.Serialize(response));
        }
```



# SMS API

どんどん行きます。次はSMS　API、こちらは簡単で、SMSを送信するAPIになります。Vonage経由でSMSを送信するのは鬼簡単です。先ほど取得したトークンを利用して下記のコードを実装します。

SDKのインストール

```
Install-Package Vonage
```

実装コード


```csharp

var credentials = Credentials.FromAppIdAndPrivateKeyPath(appId, privateKeyPath);

var vonageClient = new VonageClient(credentials);

var request = new Vonage.Messages.Sms.SmsRequest
{
    To = to,
    From = brandName,
    Text = "An SMS sent using the Vonage Messages API"
};

var response = await vonageClient.MessagesClient.SendAsync(request);
```

これだけです。一度設定行えばあとは実装はすごく簡単です。

# Voice API

こちらのAPIも鬼簡単です。とはいえ事前に番号の設定など、手間は多少あります。その辺りのサポートはVonageさんの方でもサポートしていただけると思いますので、直接連絡してみてくださいませ。簡単といいましたが、このAPI群は機能が多くすべてカバーすると広辞苑レベルになってしまうため、ポイントだけ紹介します。

## 電話かける

既にSDKはインストール済みという前提で、下記のコードを実装するだけで電話をかけることができます。

```csharp

 public async Task Execute()
        {
            var vonageApplicationId = Environment.GetEnvironmentVariable("VONAGE_APPLICATION_ID") ?? "VONAGE_APPLICATION_ID";
            var vonagePrivateKeyPath = Environment.GetEnvironmentVariable("VONAGE_PRIVATE_KEY_PATH") ?? "VONAGE_PRIVATE_KEY_PATH";
            var toNumber = Environment.GetEnvironmentVariable("TO_NUMBER") ?? "TO_NUMBER";
            var vonageNumber = Environment.GetEnvironmentVariable("VONAGE_NUMBER") ?? "VONAGE_NUMBER";                                    

            var creds = Credentials.FromAppIdAndPrivateKeyPath(vonageApplicationId, vonagePrivateKeyPath);
            var client = new VonageClient(creds);

            var answerUrl = "https://nexmo-community.github.io/ncco-examples/text-to-speech.json";
            var toEndpoint = new PhoneEndpoint() { Number = toNumber };
            var fromEndpoint = new PhoneEndpoint() { Number = vonageNumber };

            var command = new CallCommand() { To = new Endpoint[] { toEndpoint }, From = fromEndpoint, AnswerUrl = new[] { answerUrl } };
            var response = await client.VoiceClient.CreateCallAsync(command);

            Console.WriteLine($"Call Created with call uuid: {response.Uuid}");
        }

```

## 電話を受ける

こちらも下記のコードだけで実装ができます。

```csharp

　　[Route("[controller]")]
    public class ReceiveInboundCallController : Controller
    {
        [HttpGet("webhooks/answer")]
        public string Answer()
        {            
            var talkAction = new TalkAction
            { 
                Text = "Thank you for calling from " +
                $"{string.Join(" ", Request.Query["from"].ToString().ToCharArray())}"
            };
            var ncco = new Ncco(talkAction);
            return ncco.ToString();
        }
    }

```

ここで、Nccoってなんだろうと思ったかはこちらを参照ください。ざっくり言うと、コールアクションをまとめたjsonファイルになります。

https://qiita.com/Noboru_Goto/items/718b9fae1201f1ca325d

## 会話を録音する

「品質向上のためお客様の会話は録音されます」をしたいときは下記のコードを実装するだけです。既存のコードに　`public async Task<IActionResult> Recording()`　を追加して実装するだけです。

```csharp
  [Route("[controller]")]
    public class RecordCallController : Controller
    {   
        [HttpGet("webhooks/answer")]
        public IActionResult Answer()
        {
            var toNumber = Environment.GetEnvironmentVariable("TO_NUMBER") ?? "TO_NUMBER";
            var vonageNumber = Environment.GetEnvironmentVariable("VONAGE_NUMBER") ?? "VONAGE_NUMBER";
            var host = Request.Host.ToString();
            //Uncomment the next line if using ngrok with --host-header option
            //host = Request.Headers["X-Original-Host"];
            var sitebase = $"{Request.Scheme}://{host}";

            var recordAction = new RecordAction()
            {
                EventUrl = new string[] { $"{sitebase}/recordcall/webhooks/recording" },
                EventMethod = "POST"
            };

            var connectAction = new ConnectAction() { From = vonageNumber, Endpoint = new[] { new PhoneEndpoint{ Number = toNumber } } };

            var ncco = new Ncco(recordAction, connectAction);            
            return Ok(ncco.ToString());
        }
                
        [HttpPost("webhooks/recording")]
        public async Task<IActionResult> Recording()
        {            
            var record = await WebhookParser.ParseWebhookAsync<Record>(Request.Body, Request.ContentType);            
            Console.WriteLine($"Record event received on webhook - URL: {record?.RecordingUrl}");
            return StatusCode(204);
        }
    }
   
```

## ユーザーのダイアルインプットを処理する

スピーチ入力で処理をする方法もありますが、今日はダイアルの処理を紹介します。「オペレーターに直接話したいかたは０を」を実装したい場合はこちらです。

```csharp

public class HandleDtmfInputController : Controller
    {
        [HttpGet("[controller]/webhooks/answer")]
        public IActionResult Answer()
        {
            var host = Request.Host.ToString();
            //Uncomment the next line if using ngrok with --host-header option
            //host = Request.Headers["X-Original-Host"];

            var eventUrl = $"{Request.Scheme}://{host}/webhooks/dtmf";

            var talkAction = new TalkAction() { Text = "Hello please press any key to continue" };
            var inputAction = new MultiInputAction()
            {
                EventUrl = new[] { eventUrl },
                Dtmf = new DtmfSettings { MaxDigits = 1}
            };
            var ncco = new Ncco(talkAction, inputAction);
            return Ok(ncco.ToString());
        }

        [HttpPost("webhooks/dtmf")]
        public IActionResult Dtmf()
        {            
            var input = WebhookParser.ParseWebhook<MultiInput>(Request.Body, Request.ContentType);
            var talkAction = new TalkAction { Text = $"You Pressed {input?.Dtmf.Digits}, goodbye" };
            var ncco = new Ncco(talkAction);
            return Ok(ncco.ToString());
        }
    }
}

```

# 迷ったらここ

ダッシュで進めましたが、迷ったらこちらへ、開発者用のドキュメントがまとまっています。多くの記事がまだ英語ですが、サンプルコードみたら大体わかります。

https://developer.vonage.com/ja/home

今日紹介したAPIは全て無料でトライできるようになっていますので、コアな部分をテスト実装し、あとは自社のサービスに組み込んでイントラクティブなアプリケーションを作ってみてください。

# 実際に利用しているケース

現在開発している、電子レシートサービス「レシートローラー」ではVonageさんのAPIを利用し、様々チャンネルで電子レートを受けてれるようにしています。受け取れるチャンネルが増えていくほど、すべてを自社で個別に開発するのは無理ゲームなので、このようなサービスがあると大変助かります。

電子レシートサービスはこちらです。

https://receiptroller.com

APIも公開していますので、こちらもご利用ください。

https://api.receiptroller.com

そして、採用中でございます。社会問題解決に興味あるエンジニアの方はご連絡ください。（特にオープンポジション記載はありません、開発全般募集中）

# 次

ということで、盛りだくさんな機能を紹介しました。次回は実際にAPIを活用したアプリケーションを作ってみたいと思います。　12月15日予定。