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

2019.12.20

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

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は、以下のようになっています。

<br /><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">
<p>div#section-chat{<br />
    width: 410px;<br />
    border:1px gray double;<br />
}<br />
div#logView {<br />
    background-color:darkturquoise;<br />
    border: 1px solid #ccc;<br />
    padding: 4px;<br />
    width: 400px;<br />
    height: 500px;<br />
    overflow: scroll;<br />
}</p>
<p>textarea#chatContent {<br />
    padding: 4px;<br />
    font-size: 1em;<br />
    width: 400px;<br />
    height: 50px;<br />
}</p>
<p>log {<br />
    margin: 4px;<br />
    padding: 4px;<br />
    border-radius: 4px;<br />
    min-width: 50%;<br />
    max-width: 85%;<br />
}</p>
<p>log.req {<br />
    float: left;<br />
    background-color:white;<br />
}</p>
<p>log.res {<br />
    text-align: right;<br />
    float: right;<br />
    background-color:beige;<br />
}<br />
log.err {<br />
    text-align: right;<br />
    float: right;<br />
    color: #f77;<br />
}<br />
</style>


<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 id="contactDetails" name="contactDetails"><input id="startChat" type="submit" value="Start Chat" />
<input id="endChat" type="button" value="End chat" /></form>
<div id="section-chat" style="display: none;">
<div id="logView"></div>
<textarea id="chatContent"></textarea>
<input id="sendChat" type="button" value="Send" />

</div>

5 最後に

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

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

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