https://d226lax1qjow5r.cloudfront.net/blog/blogposts/using-vonage-apis-with-mongodb-atlas-part-5/mongodb_vonage_p5.png

MongoDB AtlasでVonage APIを使う - パート5

最終更新日 May 24, 2023

所要時間:1 分

このシリーズでは

MongoDB AtlasとVonage APIsのシリーズの最後に、アプリ内メッセージングAPIを紹介します。 アプリ内 Messages API を見てみましょう。.このシリーズの他のパートでは、パート 1 で MongoDB Atlas と Vonage のセットアップ、パート 2 でアプリケーションに Vonage Verify を追加する方法、Messages API と Meetings API を使って顧客とのやり取りを可能にする方法を紹介し、最後に In-App Messaging API を使ってサイトの管理セクションにログインしているユーザーに通知を送る方法を紹介します。

In-App Messaging

In-App Messagingは包括的なAPIコール会話セットの一部であり、APIのもう半分は当社のIn-App Voice製品です。その名前が示すように、In-App Messagingはあるクライアントデバイスから別のクライアントデバイスへのテキストメッセージの送信を処理し、In-App Voiceは音声トラフィックを処理します。これらのAPIには、iOS、Android、モダンなウェブブラウザ用のSDKがあります。デモではWeb Client SDKを紹介しますが、これを拡張してWeb、iOS、Androidのどの組み合わせからでもプラットフォーム間通信を可能にすることができます。

In-App MessagesとIn-App Voiceは、Conversations製品を構成する他の2つのAPIによってサポートされています。Conversation APIは1人または複数のメンバー間のイベントで、Users APIはユーザーのコンテキスト情報を処理します。一般的なワークフローは、ユーザがアプリケーションで認証され、Users API でユーザに関連付けられます。このUserは様々なConversationsのMemberになります。 イベントストアのような様々なトリガーイベントで構成されます。 text, message:submitted, member:joinedなど。

各Client SDKは、これらのバックエンドサーバーと対話し、Voiceまたはテキストイベントを通じてリアルタイムのコミュニケーションを促進します。これにより、開発者は当社のAPIと対話するための1つのインターフェイスを持つことができ、SDKは当社のAPIとの接続と動作のすべての作業を処理します。これにより、プラットフォーム依存のメッセージングシステムや、異なるプラットフォーム間でメッセージをシャントする方法を考え出す必要がなくなります。

レストランのデモでは、ログインしている管理者ユーザーにメッセージを送るために、In-App Messages APIを使用します。これにより、リクエストされた会議へのリンクを含むポップアップが画面に表示されます。私たちは単一の通知のためにそれを使用していますが、チャットシステム全体にこれを拡張することができます。ここでは nexmo-clientを使用し、バックエンドのサーバーコードでカスタムクライアントを使用してConversation APIと通信します。

管理者への通知

まず、管理セクションの仕組みから見ていきましょう。ユーザがミーティングをリクエストしたときにポップアップ通知を表示したい。ポップアップ通知には を使います。これはトースト形式のポップアップを生成するVueJSプラグインです(トーストとは、画面の下にポップアップして消える小さな通知のことです)。

どうやって通知を受け取るのだろう?私たちは nexmo-clientウェブSDKを使用してVonageアプリケーションに接続し、適切なConversationまたは一連のメッセージを購読する必要があります。私たちは 通知コンポーネントを作成しました。

import ConversationClient from 'nexmo-client'
import { createToaster } from '@meforma/vue-toaster'
import { authenticationStore } from '../stores/authenticationStore';

const authStore = authenticationStore();
const toaster = createToaster({ dismissable: true });

async function boot() {
    const data = await fetch(import.meta.env.VITE_API_URL + '/jwt', {
        method: 'POST',
        body: JSON.stringify({username: authStore.username}),
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer ' + authStore.token
        }
    })
        .then(resp => resp.json())
        .catch(err => console.log(err));
    
    const jwt = data.token
    const conversationID = data.conversation

    const client = new ConversationClient({ debug: true })
    let app = await client.createSession(jwt)
    const conversation = await app.getConversation(conversationID)

    conversation.on("support_request", async (sender: any, event: any) => {
        toaster.show(`${event.body.email} has request support: <a target="_blank" href="${event.body.host_url}">Join Meeting</a>`);
    });
}

boot()

ウェブSDKをVonageに接続するには認証トークンが必要です。このトークンは、パート1でVonageアプリケーションを作成したときに生成した秘密鍵を使って署名されたJWTです。このJWTによって、Web SDKはVonage APIと会話し、認証することができます。これは MongoDB Realms が管理者ユーザーを認証するのと同じ方法です。

Conversations API用のクライアントJWTの作成に関する完全な情報については、こちらをご覧ください、 のドキュメントをご覧ください。.JWTをどのように作成するかについては、すぐに例を見ながら説明しますが、今はVueJSのコードを続けましょう。今は、バックエンドサーバーにユーザー用のJWTを生成するように依頼することだけを心配すればよいのです。

バックエンドサーバーは2つの情報を返します - 署名されたVonage JWTと、私たちが接続するための会話IDです。どの会話をリッスンするかをウェブSDKに伝えるために、これが必要になる。

その後、新しい ConversationClient()パッケージから nexmo-clientパッケージからそして createSession(jwt)を呼び出し、バックエンドが作成したJWTを渡します。これでウェブアプリケーションがVonageに認証されます。そして、バックエンド・サーバーが私たちに返したIDである特定の会話を取得するように指示します。

私たちのアプリケーションは今、イベントをリッスンしているが、何も処理していない。メッセージを処理するには conversation.on()メソッドを使わなければなりません。というカスタム・メッセージを使い、その名前を最初のパラメーターとして渡します。 support_requestというカスタム・メッセージを使い、その名前を最初のパラメータとして渡します。番目のパラメーターはハンドラー関数です。ハンドラ関数はサポートリクエストから情報を抽出し、通知をポップアップします。

以上です。管理セクションにログインして 注文を見るをクリックしてください。新しいウィンドウを開き、顧客としてログインし、注文を送信し、ビデオ通話を開始すると、新しい通知が管理ウィンドウにポップアップ表示されるはずです。

トークンの生成方法は?

バックエンドのコードを見る前に、JWTの作り方を見てみよう。有効なクライアント側トークンを作成するには、JWTに2つの重要な情報を追加しなければなりません。それは subトークンが生成されるユーザーです。もうひとつは pathJWTがアクセスできるパスのリストです。

app.post('/jwt', async (req, res) => {
    const { username } = req.body;
    const conversation = await conversations.fetchByName('pos-notifications');
    const conversationPath = `/*/conversations/${conversation.id}/**`;
    let acl = {
        "paths": {
            "/*/sessions/**": {},
          }
    }
    acl.paths[conversationPath] = { methods: ['GET'] }

    const key = readFileSync(process.env.VONAGE_PRIVATE_KEY);
    const token = tokenGenerate(process.env.VONAGE_APPLICATION_ID, key, {
        sub: username,
        acl: acl,
    });
    res.json({ token, conversation: conversation.id })
})

トークンを必要なものだけに制限するために、ACLを /*/sessions/**そして /*/conversations/<conversation-id>/**.これは、私たちのJWTが、私たちの通知が送信される特定の会話に対してのみ有効であることを意味します。 pos-notifications.もし誰かがトークンを乗っ取ったとしても、1つの会話にしかアクセスできない。

JWTはさらに、会話へのリクエストのみを許可するよう指示することで、安全性を確保する。 GETリクエストのみを許可する。つまり、フロントエンドやJWTを使おうとする人は、会話を読むことしかできず、それを変更することはできない。アプリケーションでは、JWTのパスとメソッドをできるだけ厳密に制限する必要があります。

通知の作成

会話から読み取る方法は知っている。もし server.tsファイルに飛び込んで /api/website/video-callルートに移動すると、そこで新しいイベントが生成されます。

const orderRecord = await client.db('restaurant_pos_demo')
    .collection('orders')
    .updateOne(
        { _id: new ObjectId(orderNumber) },
        { $set: { meetingUrl: data._links.host_url.href}}
    )
    .then(async (document) => {
        const userRecord = await client.db('restaurant_pos_demo')
            .collection('users')
            .findOne({ _id: new ObjectId(decodedToken.user_id) });

        await conversations.addEventToConversation(
            'pos-notifications',
            userRecord.username, 
            {
                type: 'custom:support_request',
                body: { 
                    host_url: data._links.host_url.href,
                    email: userRecord.username
                }
            });

        res.json({
            guest_url: data._links.guest_url.href
        })
    });

新しいミーティングのURLでオーダーを更新する。それが終わったら、MongoDBで usersコレクションを使って findOne().これで認証されたユーザーのユーザーレコードが取得できます。 conversations.addEventToConversation()を使って会話に新しいイベントをプッシュできます。すべての通知には pos-notifications.

addEventToConversation()は、会話にイベントを追加するために必要な基本的な作業の多くを処理するラッパーで、多くの検索やセットアップを行ってくれる conversation.tsのメソッドコレクションの一部です。

前にも述べたように、Conversations APIはConversations APIとUsers APIを組み合わせたものだ。を呼び出すと addEventToConversation()を呼び出すと、このメソッドは指定された名前の会話を取得しようとします。その会話ルックアップは、指定された名前の会話(この場合は、 pos-notification)を持つ会話を生成します。

次に、イベントを添付するメンバーが必要です。メンバーは特定の会話に参加しているユーザーです。メンバーは1つの会話にしか参加できません。しかし、ユーザーは複数の会話のメンバーになることができます。 addEventToConversation()は、指定されたメールアドレスでメンバーを検索しようとします。そのメンバーが会話に参加していない場合、イベントも追加されます。そのメールアドレスを持つユーザを検索します。そのユーザーが存在しない場合、そのユーザーを作成します。そして、そのユーザがメンバーとして会話に追加され、メンバー情報が返されます。

そして、新しいイベントを会話にプッシュすることができる。イベントは会話を聞いている接続中のクライアントに伝搬されます。サーバ上でイベントを送信すると、"Orders "ページでログインしているユーザはイベントとポップアップ通知を受け取ります。

結論

これはConversations APIでできることのほんの一部です。タイプ通知、画像共有、メッセージ保存など、ユーザーが期待する全ての機能を備えたチャットインターフェースを構築することができる。その上、全てリアルタイムでクロスプラットフォームです。ウェブユーザーは、Androidクライアントや他のウェブクライアントと同じように、iOSクライアントに通知を送ることができる。

また、In-App Voiceと組み合わせて、複数のクライアント間でリアルタイムの音声を提供したり、Voice APIと組み合わせて、アプリケーションのユーザーが電話をかけたり、その逆も可能です。顧客はレストランに電話し、レストランはブラウザで応答することができます!

今回でMongoDB AtlasとVonageのAPIの紹介は終わりです。このシリーズが、私たちの各プラットフォームが何を提供し、どのようにあなたのお役に立てるかを見ていただくきっかけになれば幸いです。ご不明な点がございましたら、いつでも開発者までお問い合わせください。

ハッピーなコーディングだ!

シェア:

https://a.storyblok.com/f/270183/384x384/3bc39cbd62/christankersley.png
Chris Tankersleyデベロッパー・リレーションズ・ツーリング・マネージャー

クリスはデベロッパー・リレーションズ・ツーリング・マネージャーで、お気に入りのツールを開発するチームを率いています。彼は15年以上、クライアントワークからビッグデータ、大規模システムに至るまで、様々な言語と種類のプロジェクトでプログラミングをしてきました。オハイオ州に住み、家族と過ごしたり、ビデオゲームやTTRPGゲームをしたりしている。