0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Twilio FlexとAPI Gateway、Lambda、DynamoDBを連携させて架電してきたユーザがVIPユーザかFlex画面に表示させてみる

Last updated at Posted at 2021-12-22

はじめに

この記事は、Twilio Flex Advent Calendar 2021の22日目の記事です。

普段、AWS周りをよくさわることが多いのですが、今回はTwilioに挑戦してみます。そして、Twilio Flexはじめて知りました。

とても面白そうなサービスだと思い、また簡単に無料トライアルを開始することできたので、今回、Twilio FlexとAWSのサービスを連携する系のブログを書きたいと思います。

やりたいこと

電話をかけてきたユーザがVIPユーザなのか、そうでないのかDynamoDBのテーブルに保存してあるユーザ情報をもとに判定して、Twilio Flexの着信画面に表示したい

着信時にVIPユーザからの着信であればvipをつけて表示
2021-12-22_1_07_38.png

概要図

今回、構築するシステムの全体像はこんなかんじです。

image.png

TwilioとAWSとの連携はAPI Gatewayを使って連携します。

Twilio FunctionsからAPI Gateway + Lambda + DynamoDBで構築したAPIを実行し架電したユーザ情報を取得、Functionsで受け取ったレスポンス値からVIPか判定し、Flex画面に表示する流れとなります。

(フロー作成するStudioから直接APIを実行できそうではあったのですが、今回、柔軟性が高いTwilio Functionsを利用しています。)

前提

  • AWSアカウントは発行済みで利用できる状態になっている

  • IAMユーザの設定がされている状態になっている

  • AWS CLIなど利用できるようにアクセスキー、クレデンシャルの設定がされている状態になっている

  • Serverless FrameworkがインストールできるNode.js環境がある

Twilio Flexをセットアップ

下記ブログを参考にセットアップしていきます。

ログイン後、「Explore Products」 => 「All Products」 => SolutionsのFlexを選択

image.png

「Create my Flex account」をクリック

image.png

アカウント名を入力し、Verifyをクリック

image.png

数分でFlex環境が作成されます。

image.png

Flexの画面が表示されたら、右上にある「COMPLETE」をクリックしていきタスクを完了しておきます。

2021-12-16_17_37_54.png

また、右上を確認すると、自分自身の状態がAvailableになっていることがわかります。

これは自分自身が有効なワーカーとしてログインしているということになります。

Availableの状態だと課金されて続けるので、状態をオフラインにしておきます。そうすれば、Flexの課金が止まります。

利用していないときは適宜オフラインにしておきましょう。

オフラインの方法は右上の自分自身のアイコン付近をクリックして、プルダウンメニューから「Offline」を選択することでオフラインにできます。

着信のテスト

下記ブログを参考に着信のテストを行っておきましょう。より理解が深まるとかと思います。

APIGateway + Lambda + DynamoDBを使って簡易APIを実装

Twilio Flexのセットアップが完了したので、次はAPIの実装を行います。

DynamoDBに保存されているユーザ情報が取得する簡易なAPIを実装します。

サンプル実装なので認証はAPIキーで行います。

例としては、下記のようにAPIを実行するとvipかどうか情報が取得できるAPIを実装する想定です。

$ curl -X GET "<endpoint>/dev/users/<id>" -H "x-api-key: XXXXXXXXXXXXXXX"
{"ID": "<id>", "vip": true}

また、今回は手順を簡単にするためServerless Frameworkを使いデプロイします。

環境

  • Node.js: v16.13.0

  • Lambdaのランタイム: python 3.8

$ serverless --version
Framework Core: 2.69.1
Plugin: 5.5.1
SDK: 4.3.0
Components: 3.18.1

Serverless Framework をインストール

$ npm install serverless -g

プロジェクトを作成

$ serverless create --template aws-python3

雛形作成されたら、ファイルを編集していきます。

handler.pyを下記のように編集します。

import json
import boto3
from botocore.exceptions import ClientError

def hello(event, context):
    print(event)
    id = event["pathParameters"]["id"]
    body = {
        "ID": id,
        "vip": False
    }
    dynamodb = boto3.resource("dynamodb")
    table = dynamodb.Table("test-table")
    response = {
        "statusCode": 200,
        "body": json.dumps(body)
    }
    try:
        res = table.get_item(Key={"ID": str(id)})
        print(res["Item"])
        response["body"] = json.dumps(res["Item"])
        print(response)
        return response
    except KeyError:
        return response
    except ClientError as e:
        print(e.response["Error"]["Message"])

DynamoDBにデータがなければ、vipの値がfalseが、データがあれば上書きして返すようにしています。

「test-table」というテーブル名でDynamoDBのテーブルを作成する予定なので、そのテーブル名を指定しています。

サンプル実装ですので本番環境での利用はお控えください。

serverless.ymlを下記のように編集します。

service: twilio-sample
frameworkVersion: "2"

provider:
  name: aws
  runtime: python3.8
  lambdaHashingVersion: 20201221
  apiGateway:
    apiKeys:
      - testKey
    usagePlan:
      quota:
        limit: 1000
        offset: 2
        period: MONTH
      throttle:
        burstLimit: 200
        rateLimit: 100
  iam:
    role:
      statements:
        - Effect: Allow
          Action:
            - dynamodb:GetItem
          Resource:
            - "*"
functions:
  hello:
    handler: handler.hello
    events:
      - http:
          private: true
          path: users/{id}
          method: get
          request:
              parameters:
                  paths:
                      id: true

# DynamoDBのテーブルを作成
resources:
  Resources:
    StateTable:
      Type: "AWS::DynamoDB::Table"
      Properties:
        AttributeDefinitions:
          - AttributeName: ID
            AttributeType: S
        KeySchema:
          - AttributeName: ID
            KeyType: HASH
        BillingMode: PAY_PER_REQUEST
        TableName: test-table

サンプル実装なのでLambda関数は「hello」というデフォルトの関数名のままにしています。適宜変更ください。

「test-table」というテーブル名でDynamoDBのテーブルが作成されます。

デプロイ

AWSのプロファイルをデプロイ先アカウントに向け、デプロイします。

下記コマンドを実行し、リソースの情報など出力されたら成功です!

$ sls deploy
Serverless: Stack update finished...
Service Information
service: twilio-sample
stage: dev
region: us-east-1
stack: twilio-sample-dev
resources: 17
api keys:
  testKey: xxxxxxxxxxxxxxxxx
endpoints:
  GET - https://xxxxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/users/{id}
functions:
  hello: twilio-sample-dev-hello
layers:
  None

出力されたapi keyendpointを控えておきます。

DynamoDBにデータ保存

次は、バージニアリージョンに作成されたDynamoDBのテーブルにデータを追加します。

AWSのマネージメントコンソールからDynamoDBのサービスページに移動し、作成されたテーブル「test-table」を選択します。

追加するデータのIDは今回、電話番号になります。「+81」を先頭につけて、電話番号の先頭0を削った形で値を設定してください。

例: 090xxxxyyyy のとき +8190xxxxyyyy を値に設定

次に「新しい属性の追加」でboolを選択し、属性名を「vip」とし、値を「True」にして保存してください。

image.png

APIの動作確認

curlで動作確認してみます。

想定通りのレスポンスが返ってこればOKです。

DynamoDBに登録していないIDでリクエストするとvipfalseになってかえってくることも確認しておきましょう。

$ curl -X GET "https://xxxxxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/users/+8190xxxxyyyy" -H "x-api-key: XXXXXXX"
{"ID": "+8190xxxxyyyy", "vip": true}%   

Twilio Functionsの設定

API側の準備もできたので、次はTwilio Flexと連携するためのTwilio Functionsの設定を行っていきます。

フロー作成するStudioにHTTPをコールするMake HTTP Requestがありますが、ヘッダーの設定ができない?ようだったので、より柔軟なTwilio Functionsを今回利用します。

Twilio Functions は
Twilio ログイン後、「Explore Products」 => 「All Products」 => Developer toolsのFunctionsを選択すると表示されます。

ピン留めされていなければしておきましょう。

image.png

Servicesは今回「test」として作成していきます。適宜変更ください。

Functionsから外部APIを実行する

今回、手順簡略化するために、はじめからある/welcomeを編集する形で進めます。

image.png

下記のように編集します。

const axios = require('axios');
exports.handler = async (context, event, callback) => {
  const apiKey = context.API_KEY;
  const endpoint = context.ENDPOINT;

  const tel = event['data'];
  const { data } = await axios.request({
    url: `${endpoint}/users/${tel}`,
    method: 'GET',
    headers: {
      'X-Api-Key': apiKey
    }
  });

  let message = '';

  if(data.vip) {
    message = 'vip'
  }

  return callback(null, {
    message: message
  });
};

処理の流れを簡単に解説すると

  • Functionに入力されるeventに含まれる、電話番号情報を取得
  • 先程実装した、APIを実行
  • APIのレスポンスに含まれるvipがTrueならmessageにvipをいれる
  • callbackでmessageを返す

という処理を行っています。

環境変数を設定する

API Keyやエンドポイントはコードに埋め込みはせずに環境変数から取得するようにするため、Environment Variablesに設定します。

今回、API_KEYENDPOINTを設定しています。

ENDOPOINTにはhttps://xxxxxxx.execute-api.us-east-1.amazonaws.com/devという形で値を登録しています。

image.png

ここで設定した値はcontextから値を取得できます。

contextのサンプル

{
  PATH: '/welcome',
  AUTH_TOKEN: 'xxxxxxxxxxxxxxxxxxxxxxxxxx',
  SERVICE_SID: 'xxxxxxxxxxxxxxxxxxxxxxxxxx',
  API_KEY: 'xxxxxxxxxxxxxxxxxxxxxxxxxx',
  ENVIRONMENT_SID: 'xxxxxxxxxxxxxxxxxxxxxxxxxx',
  ENDPOINT: 'https://xxxxxxx.execute-api.us-east-1.amazonaws.com/dev',
  ACCOUNT_SID: 'xxxxxxxxxxxxxxxxxxxxxxxxxx',
  DOMAIN_NAME: 'xxxxxx.twil.io',
  getTwilioClient: [
    Function
  ]
}

Twilio Functionsで利用するライブラリを追加

functions内で利用するライブラリはDependenciesから追加することで利用できるようになります。

今回、APIをリクエストするためにaxiosを追加しています。

image.png

デプロイ

saveを押して、Deploy Allボタンを押すことで反映されます。

Twilio Studio でフローを編集する

Twilio Studioが左ペインになければ、
ログイン後、「Explore Products」 => 「All Products」 => Developer toolsのStudioを選択するとアクセスできます。

ピン留めされていなければしておきましょう。

image.png

Voice IVRを編集

デフォルトで用意されているものがあるので、それを編集していきます。

着信したら実行されるフローが「Vocie IVR」になります。

image.png

Twilio Functionsをフローに挟むために、Run Functionを追加します。

image.png

下記のようにフローを編集します。
2021-12-22_1_15_39.png

function_1の設定は下記のようにします。

2021-12-22_1_17_25.png

Function Parametersdata,**{{trigger.call.From}}**として追加しておきます。

**{{trigger.call.From}}**は着信があった電話番号になります。

triggerで取得できる値のドキュメント

ここで設定した値がeventsに入ってきます。

設定できたら、Saveボタンを押します。

Flexの着信画面にVIPかどうか表示させる

FlexのUIはカスタマイズすることが可能です。

ですが、プラグイン開発が必要になったりするため、今回は既存仕組みを編集する形で対応します。

着信画面にデータを渡しているのはSendCallToAgentの「Send To Flex」Widgetを編集して対応

StudioからTaskRouter(着信画面など)にコールを引き渡す役目をするのが、「Send To Flex」Widgetになります。

ここでは、すでにSendCallToAgentとして実装されていますので、こちらを少し修正して着信画面にVIPかどうか表示させたいと思います。

つまり、SendCallToAgentのATTRIBUTESを下記のように修正します。

{ "type": "inbound", "name": "({{widgets.function_1.parsed.message}})  {{trigger.call.From}}" }

2021-12-22_1_32_39.png

現在、nameパラメータを使うことで、Flexの着信画面に電話番号が表示されるようになっています。

そこにFunctionから受け取った値({{widgets.function_1.parsed.message}})を追加しています。

設定を反映

修正したフローをTwilio Studioに反映させるためには、最後にパブリッシュする必要があります。

画面上部にあるPublishボタンを押します。

image.png

動作確認

DynamoDBに登録されている電話番号からFlexに電話をかけてみます。

すると、想定通りVIPと表示されました!

2021-12-22_1_07_38.png

DynamoDBのデータを消して、再度着信してみると、今度はVIPが表示されなくなりました!

2021-12-22_1_09_29.png

もし、うまくいかなければAWS側のCloudWatch Logsに出力されるLambdaのログを確認するとよいかと思います。

AWS環境の片付け

検証後のお片付け

フルマネージドサービスを利用しているので、時間で課金されることはないですが削除するには

下記コマンドを実行することでAWSのリソースを削除することができます。

$ sls remove

参考サイト

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?