[Amazon Connect] 独自UIのチャットクライアントを設置してみました。(amazon-connect-chat.jsを利用)

1 はじめに

CX事業本部の平内(SIN)です。

Amazon Connect(以下、Connect)では、先月から、音声での対応に加えて、チャットでの利用も可能になっています。

前回、Amazonで提供されている、startChatContactAPIを利用してチャットクライアントの設置を試してみました。
チャットクライアントを設置してみました。(amazon-connect-chat-interface.jsを利用)

startChatContactAPIでは、チャット用のUIが、ウィジェットとして提供されていますが、今回は、同じくAmazonから提供されている
amazon-connect-chatjsを使用して、独自のUIでチャットクライアントを設置してみました。

最初に、利用している様子です。

2 amazon-connect-chat.js

今回使用した、amazon-connect-chat.jsについては、下記の手順で生成できます。

$ git clone https://github.com/amazon-connect/amazon-connect-chatjs
$ cd amazon-connect-chatjs/
$ npm install
$ npm run release
$ ls -la dist
-rw-r--r--   1 sin  staff  1154611 12 20 05:04 amazon-connect-chat.js

また、使用方法は、以下のとおりです。

(1) 初期化 (connect.ChatSession.setGlobalConfig)

connect.ChatSession.setGlobalConfigで、connectオブジェクトを初期化します。 loggerregionをパラメータとしますが、loggerの方は、省略可能です。

var globalConfig = {
//   loggerConfig: {
//     logger: logger,
//     level: connect.ChatSession.LogLevel.INFO, //DEBUG, INFO, WARN, ERROR
//   },
  region: "ap-northeast-1"
};

connect.ChatSession.setGlobalConfig(globalConfig);

(2) セッションの生成 (connect.ChatSession.create)

connect.ChatSession.createでチャットのセッションを生成します。

セッションの生成には、ContactIdParticipantIdParticipantTokenの3つが必要ですが、これらは、startChatContact の戻り値として得られます。

今回の構成も、startChatContactは、Lambda側で実装されていますので、クライアント側からは、API Gateway経由これらの値を取得することになります。

chatDetails = {
  ContactId: "xxxx",
  ParticipantId: "xxxx",
  ParticipantToken: "xxxx"
};

args = {
    chatDetails: chatDetails,
    type: "CUSTOMER", // "AGENT"
    //"options": options,
    //"websocketManager": WebSocketManager
};

var chatSession = connect.ChatSession.create(inputForChatSession);

(3) 接続 (session.connect)

connect()で、セッションが開始されます。セッション開始後は、以下のイベントを処理することが可能になります。

  • onConnectionEstablished セッション成立
  • onMessage チャット相手からのメッセージ受信
  • onTyping チャット相手がタイプ中
  • onConnectionBroken セッション断

(4) メッセージの受信 (onMessage)

チャット中の各種のメッセージは、onMessageで受け取ることができます。

送受信のテキストは、message.data.Type == "MESSAGE"で処理できます。また、message.data.ParticipantRoleを見て、顧客からなのか、エージェントからなのか、又は、システムからなのかを判断できます。

session.onMessage((message) => {
  if(message.data.Type == "MESSAGE"){
      if(message.data.Content){
          if(message.data.ParticipantRole == "CUSTOMER"){
              // 送信テキストの処理
          }else {
              // 受信テキストの処理
          }
      }
  }
  ・・・//略

相手先からチャットが切断された場合は、message.data.ContentTypeevent.chat.endedとなっているmessage.data.Type == "EVENT"のメッセージを受けとることになります。

session.onMessage((message) => {
  if(message.data.Type == "EVENT") {
      if(message.data.ContentType == "application/vnd.amazonaws.connect.event.chat.ended"){
          // チャットが切断された際の処理
      }
  ・・・//略

(5) メッセージの送信 (sendMessage)

sendMessageを使用してメッセージを送信します。

session.controller.sendMessage({
    message: message,
    contentType: "text/plain"
})

(6) タイプ中(sendEvent)

sendEventを使用してタイプ中である事を相手側に伝えることができます。今回は、実装していません。

session.controller.sendEvent({
    contentType: "application/vnd.amazonaws.connect.event.typing"
});

(7) セッションの切断 (disconnectParticipant)

セッションの切断は、disconnectParticipantを使用して行います。

session.controller.disconnectParticipant();

3 設置

このチャットは、startChatContactを、Lambda側で実装しています。

Lambdaの実装と、API Gatewayの設置に関しては、下記とまったく同じですので、ここでは、省略させて下さい。

4 html

実装したhtmlは、以下のようになっています。

<!DOCTYPE html>
<html>
<head>

<script src="https://sdk.amazonaws.com/js/aws-sdk-2.283.1.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="amazon-connect-chat.js"></script>
<style language="text/css">

div#section-chat{
    width: 410px;
    border:1px gray double;
}
div#logView {
    background-color:darkturquoise;
    border: 1px solid #ccc;
    padding: 4px; 
    width: 400px;
    height: 500px;
    overflow: scroll;
}

textarea#chatContent {
    padding: 4px;
    font-size: 1em;
    width: 400px;
    height: 50px;
}

log {
    margin: 4px;
    padding: 4px;
    border-radius: 4px;
    min-width: 50%;
    max-width: 85%;
}

log.req {
    float: left;
    background-color:white;
}

log.res {
    text-align: right;
    float: right;
    background-color:beige;
}
log.err {
    text-align: right;
    float: right;
    color: #f77;
}
</style>
</head>
<body>
<script>
    $('#section-chat').hide('slide');

    const apiGatewayEndpoint = 'https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev';
    const region = 'ap-northeast-1';

    connect.ChatSession.setGlobalConfig({
        region: region
    });
    var session;
    $(document).ready((a) => {
        $("#sendChat").click(() => { 
            sendChat();
        });
        $("#endChat").click(() => { 
            endChat();
        });
    });
    $(function () {
        $('#contactDetails').submit(function (e) {
            const customerName = 'customer';
            e.preventDefault();
            $('#logView').empty();
            var initiateChatRequest = {
                ParticipantDetails: {
                    DisplayName: customerName
                },
                // ContactFlowId: contactFlowId,
                // InstanceId: instanceId
            };
            $.ajax({
                url: apiGatewayEndpoint,
                type: "POST",
                async: false,
                data: JSON.stringify(initiateChatRequest),
                success: function(result) {
                    console.log("Success!");
                    console.log(JSON.stringify(result));
                    session = connect.ChatSession.create({
                        chatDetails: result.data.startChatResult,
                        type: "CUSTOMER"
                    });
                },
                error: function(result) {
                    console.log("Error:");
                    console.log(result);
                },
                complete: function(data) {
                    console.log("Complete: " + JSON.stringify(data));
                    session.connect().then((response) => {
                        console.log("successful connection: " + JSON.stringify(response));
                        $('#section-chat').fadeIn(400);
                        return response;
                    }, (error) => {
                        console.log("unsuccessful connection " + JSON.stringify(error));
                        return Promise.reject(error);
                    });
                    session.onConnectionEstablished((data) => {
                        console.log("Established!");
                    })
                    session.onMessage((message) => {
                        console.log("Received message: " + JSON.stringify(message));
                        if(message.data.Type == "MESSAGE"){
                            if(message.data.Content){
                                if(message.data.ParticipantRole == "CUSTOMER"){
                                    appendLog(message.data.Content, 'req');
                                }else {
                                    appendLog(message.data.Content, 'res');
                                }
                            }
                        } else if(message.data.Type == "EVENT") {
                            if(message.data.ContentType == "application/vnd.amazonaws.connect.event.chat.ended"){
                                $('#section-chat').hide('slide');
                            }
                        }
                    });
                    session.onTyping((typingEvent) => {
                        if (typingEvent.data.ParticipantRole === "AGENT") {
                            console.log("Agent is typing... ");
                        }
                    });
                    session.onConnectionBroken((data) => {
                        console.log("Connection broken.");
                    });
                }
            });
        });
    });
    function sendChat() {
        var message = $('#chatContent').val();
        console.log("sendMessage " + message);
        session.controller.sendMessage({
            message: message,
            contentType: "text/plain"
        })
        $('#chatContent').val('');
        $('#chatContent').focus();
    }

    function endChat() {
        $('#section-chat').hide('slide');
        session.controller.disconnectParticipant();
    }

    $('#chatContent').focus();

    function appendLog(message, className) {
      $('<log>', { class:className, text:message }).appendTo('#logView');
      $('#logView').scrollTop(self.innerHeight);
    }

</script>
<form name="contactDetails" id="contactDetails">
    <input type="submit" id="startChat" value="Start Chat"></input>
    <input type="button" id="endChat" value="End chat"></div>
</form>

<div id= "section-chat" style="display: none">
        <div id="logView"></div>
        <textarea type="text" id="chatContent"></textarea>
        <input type="button" id="sendChat" value="Send"></input>
</div>
</body>
</html>

5 最後に

今回は、独自のUIで、Connectのチャットクライアントを設置してみました。

UIを自由に設計できるため、各種の場面・利用方法でチャットの利用が可能になってきます。また、今回使用した amazon-connect-chat.js は、エージェント側の実装も可能なようですので、オペレーター側の応用も検討できそうで、夢が広がります。

Connectのオムニチャネル強力です。

コメントは受け付けていません。