はじめまして!
チャネルトークのアプリサーバー開発チュートリアルへようこそ。
このドキュメントを通じて、以下の作業を行うことができます。
アプリストア(App Store)の簡単な理解
アプリ開発
アプリインストール
アプリの使用方法
このドキュメントでは、アプリストアとそのサブコンセプトの概要を説明します。各項目に関する詳細情報は、開発ガイドを併せてご参照ください。
app-tutorial(typescript、go)でこのドキュメントに挿入されたコードを一括で確認できます。
これからは、チャネルトークの開発者でなくても、自社のチャネルに必要なカスタムサードパーティアプリを開発し、チャネルに登録することができます!
開発者はチャネルトークの仕様に適合した特別なアプリを開発し、アプリストアサーバーに登録します。
チャネル管理者はアプリストアプラットフォームで登録済みアプリの一覧を確認し、自身のチャネルに登録できます。
アプリを非公開(Private)で登録し、開発者本人が所有するチャネルでのみ使用することも、全体公開(Public)してチャネルアプリストアのエコシステムに貢献することも可能です。
アプリストアの詳細については、別のページでご確認いただけます。
すでに準備済みのアプリサーバーがある場合は、開発者ポータルから直接アプリを登録してみてください。(→Developer Portal)
チャネルトークでは、サードパーティがアプリストアを容易に理解しアプリを開発できるよう、サンプルアプリであるapp-tutorial(typescript、go)を提供しています。
このアプリは次のツールを使用して開発されました。
typescript
go
まだ上記のツールをインストールしていない場合は、該当するページを参考にして事前に準備してください。
サンプルアプリはTypeScriptとGo言語で開発されていますが、アプリストアとアプリサーバー間のインターフェース仕様に準拠している場合、他の言語を使用しても問題ありません。
app-tutorial(typescript、go)は次の2つの動作を実行できるように実装されています。
チームメンバーがWAMで「ボットとしてグループメッセージを送信」ボタンをクリックした場合、アプリサーバーがボットプロファイルを使用してグループメッセージを送信します。
チームメンバーがWAMで「チームメンバーとしてグループメッセージを送信」ボタンをクリックした場合、WAMがチームメンバープロフィールを使用してグループメッセージを送信します。
開発プロセスに関する説明なしで、すぐにサンプルアプリをテストしたい場合は、このドキュメントの最後のテストパートをご参照ください。
アプリサーバーを開発する前に、まずアプリを登録する必要があります。開発者ポータルに移動して、アプリ登録を始めましょう!
チャネルトークは、開発者もアプリストアサーバーに簡単にアプリを登録できる開発者ポータルを提供しています!(→Developer Portal)
1. アプリ名の設定
アプリ登録ページの右上にある [アプリを作成] ボタンを確認できます。
アプリ名を設定し、[確認] をクリックしてください。
確認をクリックした瞬間にアプリが作成されます!
でもご安心ください。アプリ名は後から変更可能です :)
2. アプリ基本情報の入力
1で確認をクリックすると、基本情報入力画面に進みます。
各項目に必要な情報を入力してください。
Type | Description |
|---|---|
アプリアイコン | アプリストアおよびCommand使用時に表示されるアイコンのアップロード |
アプリ名 | アプリストアに表示されるアプリ名 |
アプリ概要 | アプリの説明 |
詳細説明 | アプリの詳細な説明および使用方法など |
スクリーンショット | アプリの機能を表現する画像(最大5枚) |
ユーザーガイド | アプリのインストール方法と使用方法に関する外部ガイド文書など |
3. App ID 確認
基本情報ページをよく見ると、Application IDという項目を確認できます。
この値は、クライアント、アプリストア、アプリサーバー間のリクエストおよびレスポンス時にアプリを識別するために使用されます。アプリ開発時にはアプリサーバーの環境設定に必ず必要な値ですので、App IDを確認できる場所を必ず確認しておいてください。
右側のクリップアイコンをクリックすると、すぐにコピーできます。
基本情報ページのサーバー設定項目は、アプリサーバーが動作を開始する時点で登録すれば問題ありません。
アプリ開発後、アプリサーバーを起動するにはApp Secretを知っている必要があります。
App Secretはアプリ設定の認証・権限ページで新規発行/再発行できます。
アプリサーバーは、App Secretを使用してアプリおよびチャネル権限の操作を実行するための認証トークンを取得する必要があります。
チームメンバーとユーザーの権限に関する認証トークンの発行は、チャネルトークのクライアントとアプリストアの間で行われる操作であり、新しく開発されるアプリサーバーでは、チームメンバーとユーザーの認証トークンを受け取って検証したり、新たに発行したりする動作は行いません。
1. App Secretを発行する
Secret項目右側の発行ボタンをクリックして、新しいApp Secretを発行できます。
App Secretはアプリのセキュリティのために発行後、安全に保管する必要があります。外部に漏洩した場合は必ず再発行して使用してください。
App Secretの詳細な説明はAuthenticationページでご確認ください。(→Authentication)
本格的にアプリを開発する前に、アプリでどのような動作を実行できるかを事前に設定しておく必要があります。この際、アプリで実行できる動作を権限(Permission)と呼びます。
アプリの権限は、アプリ設定の認証・権限で設定可能です。(→Developer Portal)
クライアントからアプリストアへ、またはアプリからアプリストアへリクエストを送信した際、アプリ設定で定義されていない権限を使用するリクエストは失敗として処理されます。権限設定はアプリ配布後も修正可能ですが、アプリの開発内容と実際の動作に影響を与えるため、事前に動作範囲を明確に定義し項目を設定しておくことが重要です。
権限設定画面では、アプリで使用可能な権限の一覧を確認できます。
権限は大きく3つの項目に細分化されます。
Type | Descrption | Sample |
|---|---|---|
Channel | チャネルが実行可能な操作に対する権限 | ボットメッセージ送信、ユーザーおよび管理者情報の確認など |
User | ユーザーが実行可能な操作に対する権限 | (ユーザーが)ユーザーチャット送信など |
Manager | チームメンバーが実行可能な操作に対する権限 | チームチャット送信、ダイレクトチャット送信、(チームメンバーが)ユーザーチャット送信など |
権限リストを確認し、アプリで使用したい権限にチェックを入れて保存してください。
デスクアプリを使用するチームメンバーやフロントにアクセスするユーザーは、チャットウィンドウにCommandを入力することでアプリが提供する機能をトリガーできます。
Commandは次の2つのタイプに分類されます。
Type | Description |
|---|---|
Desk Command | 管理画面Webアプリでチームメンバーが実行可能なCommand |
Front Command | フロントWebでユーザーが実行可能なCommand |
どのユーザーにどの機能を開放するかを決定した後、以下の形式でCommandを定義してください。queryにはアプリ機能を実行するために必要な値が入力されます。
/<Command Trigger> <query 1> <query 2> ... <query N>例えば、チャネルトークのBuilt-in(標準提供アプリ)アプリのGIFコマンドは、次のような形で提供されます。
1. チャットウィンドウに/gifと入力した場合、最近人気のGIF検索キーワードを推薦します。
/gif 2. チャットウィンドウに/gif <search keyword>と入力した場合、そのまま Command を実行すると、該当する <search keyword> に適合するGIF 画像を表示します。
/gif thumbこのとき検索されたGIF画像をチャットウィンドウに送信する動作はWAMで行われます。
WAMは、チャネルのデスクおよびフロントアプリウェブとは分離された別の画面を通じて、ユーザーのリクエストをアプリに仲介する役割を果たします。WAMの詳細については、開発者ガイドのWAM関連ページでご確認ください。(→WAM)
WAMで実行する操作に対する権限も、前述のアプリ権限設定で定義されている必要がある点にご注意ください。
このドキュメントで紹介するサンプルアプリは、次のCommandをチャットウィンドウに入力して実行することで、デスクにWAM画面を表示します。
/tutorialつまり、CommandはWAM画面をデスクまたはフロントに表示すると同時に、必要なパラメータをWAMに伝達するためのトリガーと言えます。
アプリからアプリへ、あるいは他のメカニズムを通じてFunctionを直接呼び出す場合、チャットウィンドウを通じて入力するCommandは必須ではない可能性があります。
Functionの詳細については、開発者ガイドのFunction関連ページでご確認ください。Commandに関する追加的な概念も開発者ガイドで併せてご確認いただけます。
Functionは、Commandから受け取った値に基づいてアプリで実際の動作を実行するためのインターフェースです。
アプリサーバーは、各動作について以下のインターフェースを遵守する必要があります。
1. Method、Params、Contextで構成されるJSON形式のリクエストを受け取ります。
上記リクエストで注目すべき点は以下の通りです。
params.chatおよびcontextの情報は、アプリストアで認証トークンを確認して自動的に入力される値であり、この値は信頼できます。特定のチャネルでのみ動作すべきというルールが必ず保証される必要がある場合、アプリで
context.channelの値を検証してください。Commandで入力した
query値はparams.inputsを通じて受け取ります。
これは、Functionがアプリによって実行されるアクションの仕様と、この時点で必要な値と同じであることを意味します。
2. 以下の形式のJSONレスポンスをアプリストアに返す必要があります。
WAM Functionからのレスポンス
General Functionからのレスポンス
Commandの実行を通じてチームメンバーまたはユーザーにWAMを表示するには、WAM Functionが必須で提供される必要があります。
wamArgsには、WAMが次の動作のために必要とする値や、Commandから受け取った値(クエリ)を処理した結果が含まれています。
例えば、サンプルアプリは以下の2つの権限を必要とし、WAM Functionを含む2つのFunctionを提供します。
1. 設定した権限
writeGroupMessage: ボットがグループにメッセージを投稿します。(アプリで実行する操作)writeGroupMessageAsManager: チームメンバがグループにメッセージを作成します。(WAMで実行する操作)
2. WAM Function
リクエスト
レスポンス
3. マネージャーとしてグループメッセージを送信するGeneral Function
リクエスト
レスポンス
上記の内容を参考に、アプリで提供しようとする機能ごとにFunctionをそれぞれ定義してください。この際、FunctionのMethodは異なるアプリ間で重複する可能性があります。
Functionに関する詳細は、開発者ガイドのFunction関連ページをご確認ください。
実際のアプリ開発時に考慮すべき事項は以下の通りです。
環境設定
アプリおよびチャネルタイプの権限のための認証トークンの発行とキャッシュ
WAMおよびWAMに対する静的ページ(WAMエンドポイント)の提供
アプリサーバーの実行と同時にCommandの登録
各FunctionとFunction Endpointの実装
以下の内容を参考に一つずつ実装してみましょう!
1. 環境設定
アプリは実行時に次の値を使用できる必要があります。
Field | Description |
|---|---|
App ID | アプリ登録時に確認できます。 |
App Secret | アプリ設定の「認証と権限」で発行できます。 |
App Store Endpoint | <> |
アプリサーバーで環境変数をうまく使えるように用意しておいてください。
2. アプリおよびチャネルタイプの権限のための認証トークンの発行とキャッシュ
アプリサーバーでは、チームメンバーとユーザーに対するトークンの発行およびキャッシュには関与しません。
この役割は、アプリストアが提供するWam-controllerが代わりに担ってくれます。
Wam-controllerの詳細については、開発者ガイドの該当ページをご確認ください。
アプリサーバーでチャネルタイプの動作を実行しない場合は、3番目の項目に直接進んでください。
アプリサーバーで管理すべきトークンのタイプは2種類です。
ここでアプリタイプトークンの詳細な説明は、4番目の項目でご確認ください。
Type | Description | Need to cache? |
|---|---|---|
App | アプリが実行できる操作に関する権限 | X |
Channel | チャネルが実行できる操作に関する権限 | O |
アプリ設定で保存したチャネルタイプの動作をアプリサーバーが正常に実行するためには、チャネルタイプトークンを繰り返し発行し、この値をキャッシュするロジックが必ず必要です。
キャッシュ
キャッシュメモリはプロジェクト全体でグローバルにアクセス可能である必要があります。
ここで重要なポイントは、トークンには有効期限が存在し、キャッシュされたトークンはこの時間が経過すると消滅しなければならないという点です。
Type | Description | Duration |
|---|---|---|
Access Token | 実際の認証情報を持つトークン、関数呼び出しに使用されるトークン | 30 Min. |
Refresh Token | Access Tokenを再発行するためのトークン | 7 Days |
また、Access Tokenの発行にはリクエストに対するrate-limitが存在するため、トークンのキャッシュが必要です。
これに関する詳細な説明は、開発者ガイドの認証と権限のセクションでご確認いただけます。(→Authentication)
使用されるキャッシュライブラリ、キャッシュの実装は実装言語やアプリの動作によって異なる可能性があるため、このドキュメントでは省略します。コード全文はGitHubで公開されています。(→キャッシュ実装コード)
キャッシュキーとトークンの有効期間設定
サンプルアプリでは、以下の方法で各トークンタイプに合った有効期間とキャッシュキーを取得できるように実装しました。
トークン定義時には以下の点を考慮してください。
キャッシュキーは固定値ではなく、ChannelIDに対して一意な値として定義されていれば問題ありません。
サーバーで実際のリクエストが処理される時間を考慮し、アクセストークンとリフレッシュトークンの実際の有効期間よりわずかに短い値をキャッシュのTTLとして設定しました。(
Duration()メソッドをご確認ください。)Durationをアプリサーバーコードで定義せず、トークン発行レスポンスで返される
expires_in、expired_at値を活用することも可能です。
上記コードはGitHubで公開されています。(→トークンモデル実装コード)
トークン発行リクエスト
それでは実際トークンを発行してみましょう!
以下の2つのMethodのNative Functionをアプリストアにリクエストすることで、新しいトークンを発行したり、既存のトークンを更新することができます。
issueTokenrefreshToken
Native Functionは次のような形式を持ちます。
Native Functionの詳細については、開発者ガイドのFunction関連ページをご確認ください。(→Function)
Native FunctionのParamsとResultには、以下の値が入力されます。
実際のトークン発行リクエストが成功した際のレスポンスにはより多くの情報が必要ですが、サンプルアプリはAccessTokenとRefreshTokenの値のみを使用するため、TokenResponseにはこの2つの値のみを定義しています。
実際のトークンリクエストおよびレスポンスについては、開発者ガイドの認証と権限のセクションを参照してください。(→Authentication)
以下は、上記のDTOを使用してアプリストアに特定のチャネルに対する新しいトークン発行をリクエストする例です。
上記の例では、go-resty/restyライブラリを使用してアプリストアにリクエストを送信しています。
重要な点は以下の通りです。
App Secretは環境変数から取得します。
トークンは各
ChannelIDごとに発行する必要があります。リクエストは
PUT https://app-store-api.channel.io/general/v1/native/functionで送信します。
このように発行されたトークンはキャッシュに保存しておき、新しいリクエストを送信する際に使用できます。
Refresh Tokenの有効期間が長いため、既に発行されたAccess Tokenが期限切れになった場合、Refresh Tokenを使用してトークンを更新できます。トークンの更新は、refreshToken関数を使用し、トークン発行と同様の方法で実行します。
認証ロジック全体の実装はGitHubで公開されています。(→認証実装コード)
3. WAMおよびWAMに対する静的ページ(WAMエンドポイント)の提供
チームメンバーとユーザーがコマンドを実行した際に画面に表示するWAM画面を作成する必要があります。
開発者ガイドのWAMおよびWam-controller関連ページを参照し、WAMを実装してください。(→WAM)
GitHubでサンプルアプリのWAM実装例をご確認いただけます。サンプルアプリの場合、ボットプロフィールメッセージ送信動作(sendAsBot)はアプリサーバーが、チームメンバーとしてメッセージ送信動作はWAMが担当していることを忘れないでください。
WAM実装後、リクエストが来た際にアプリストアがこのWAMにアクセスできるよう、WAMエンドポイントを提供する必要があります。
例えば、サンプルアプリでは以下のようなハンドラーを追加しました。
実際のアプリストアでは、このような方法でWAM Pathを計算し、WAMにアクセスします。
<WAM Endpoint registered in server settings>/<Action Function Name of the corresponding Command>したがって、サンプルアプリのサーバー設定に登録するWAMエンドポイントの実際の値は<Root Endpoint of App Server>/resource/wamとなります。
4. アプリサーバーの実行と同時にCommandの登録
権限設定パートで、権限のタイプにはChannel、User、Managerの3種類があると説明したことを覚えていますか?
実はアプリ設定画面で選択しなくても自動的に登録される権限と権限タイプがもう一つあります。それがApp権限です。
Type | Description | Example |
|---|---|---|
Channel | チャネルが実行可能な操作に対する権限 | ボットメッセージ送信、ユーザーおよび管理者情報の確認など |
User | ユーザーが実行可能な操作に対する権限 | (ユーザーが)ユーザーチャット送信など |
Manager | チームメンバーが実行可能な操作に対する権限 | チームチャット送信、ダイレクトチャット送信、(チームメンバーが)ユーザーチャット送信など |
App | アプリが実行できる操作に関する権限 | コマンドの登録など←NEW! |
アプリサーバーは実行と同時にコマンドをアプリストアに登録する必要があります。
アプリはアプリタイプトークンを使用して、自身がアプリ権限を持っていることをアプリストアに証明します。コマンド登録はアプリサーバー起動時に初回1回のみ実行されるため、アプリトークンをサーバーに継続的に保存しておく必要はありません。
アプリトークンの発行方法は非常に簡単です!トークン発行パートで説明したチャネルタイプトークンの発行と全く同じです。
唯一異なる点は、トークン発行時にParamsのフィールドにchannel IDを渡さないことです。
正確なトークン発行リクエストおよびレスポンスについては、開発者ガイドの認証セクションをご参照ください。(→Authentication)
Commandの登録はトークン発行と同様にNative Functionを使用します。
以下に示すRegisterCommandsParamを、トークン発行パートで見たNative FunctionのParamsに入れてリクエストします。つまり、以前使用したIssueTokenParamsの代わりにRegisterCommandsParamsを使用してください。
以下の事項にご注意ください。
トークンの発行および更新リクエストは、セキュリティのためApp Secretを必要とし、この値はNative Functionの
Paramsに入れて渡します。コマンド登録リクエストは、セキュリティのためアプリトークンを必要とし、この値はリクエストヘッダー(
x-access-token)に入れて渡します。コマンド登録リクエストは、サーバーが起動すると同時に実行する必要があります。
コマンド登録に関するコード全文はGitHubでご確認ください。
コマンド登録に関する正確なリクエストとレスポンスについては、開発者ガイドのコマンド関連ページをご確認ください。(→Command)
5. 各FunctionとFunction Endpointの実装
ここでは、「Functionを定義する」パートで定義したサンプルアプリのFunctionと実際の処理ロジックをコードで実装します。(→Function)
サンプルアプリは次の2つの関数を提供します。
Method | Operation |
|---|---|
tutorial | WAM Argumentを返します。(WAM Function) |
sendAsBot | ボットプロフィールでグループメッセージを作成します。 |
Function Handler
アプリから送信されるFunctionリクエストを受け取るエンドポイントを設定する必要があります。
一般的に<root path>/functions形式のEndpointが使用されます。この値は後ほどアプリ設定ページのサーバー設定で使用されるFunction Endpointとなります。
以下のようにHandlerコードを作成してください。
JsonFunctionRequestは、Function定義パートで説明したMethod、Params、Contextを持つJSONリクエストをGoの構造体として定義したものです。JsonFunctionRequestでMethodを確認し、どのFunctionか(tutorial? sendAsBot?)を判断してそれぞれ処理します。エラーが発生した場合でも、200 OK ステータスコードと共にインターフェースに適合した形式のレスポンスを返す必要があります。
リクエストおよびレスポンス形式については、このドキュメントの「Functionを定義する」パートを参照してください。
tutorial (WAM Function)
JsonFunctionRequestの Methodが tutorialの場合、他の動作なしに次のレスポンスをすぐに返せば良いです。
sendAsBot (General Function)
この関数がアプリサーバーに送信されると、アプリサーバーはボットプロファイルにグループメッセージを送信します。
この際、WritePlainTextToGroup(...)はApp Storeサーバーに対してwriteGroupMessageのネイティブ関数をリクエストする関数です。
この関数を呼び出す際、リクエストのparamsに含まれる値を取り出して使用している点にご注目ください。Commandを通じてここに別のクエリを追加することも可能です。
Native Functionリクエスト及び上記に関連するコード全文はGitHubで公開されています。
追加のFunctionが必要な場合は、自由に追加してください!
開発したアプリを正常に動作させるには、アプリ設定でFunction EndpointとWAM Endpointを登録する必要があります。(→Developer Portal)
アプリ開発パートをしっかり進めれば、アプリサーバーに2つのAPIエンドポイントを作成できます。
Type | Description |
|---|---|
Function Endpoint | Functionをリクエストし結果を受け取るためのAPI URL |
WAM Endpoint | WAM Argumentsをリクエストし結果を受け取るためのAPI URL |
基本情報 → サーバー設定で値を正しく入力し、保存してください。
Signing Keyについては設定画面に記載されたガイドをご確認ください。
サンプルアプリのFunction EndpointとWAM Endpointは以下の通りです。
Type | Description |
|---|---|
Function Endpoint | Functionをリクエストし結果を受け取るためのAPI URL |
WAM Endpoint | WAM Argumentsをリクエストし結果を受け取るためのAPI URL |
サンプルアプリはngrokを使用してローカル環境でテスト可能です!詳細はテストパートをご参照ください。
管理画面のアプリストアプラットフォームで、自身が登録したアプリを確認できます。
アプリ設定を「公開(Public)」に設定していない場合、アプリリスト下部の「作成した非公開アプリ」から登録したアプリを確認できます。該当するアプリカードをクリックしてアプリ画面に移動しましょう。
1. インストール
アプリ画面に移動すると、右側に「インストール」ボタンが表示されます。ボタンをクリックしてインストールを開始します。
アプリをインストールする前に、アプリ登録時に設定した権限が正しく含まれているか確認してください。権限に問題がなければ、「確認」ボタンをクリックしてアプリをインストールします。
2. アプリサーバーを起動
これでチャネルトークのチャットウィンドウでアプリとCommandを使用できるようになりました!
3. Commandの確認
アプリサーバーが動作を開始すると、アプリ情報画面にコマンドタブが表示されていることを確認できます。コマンドタブでは、チームメンバーおよびユーザーがトリガーできるコマンド一覧と、コマンド使用のトグルを確認できます。
アプリサーバーのEndpointを完全に公開し、アプリを全体公開でデプロイする前に、ローカル環境でWAMとFunctionをテストしてください。
このドキュメントでは、ngrokを使用してローカル環境でサンプルアプリをテストする方法をご紹介します。ngrokがまだ準備されていない場合は、該当ページを参照してツールを準備してください。
他の方法を使用したい場合、必ずしもこの方法に従う必要はありません。以下の内容を参考に、ご自身で開発したアプリをテストすることも可能です。
1. プロジェクトのダウンロード
GitHubからapp-tutorialプロジェクトをダウンロードしてください。
$ git clone https://github.com/channel-io/app-tutorial2. アプリ環境設定変数の準備
サンプルアプリの環境変数ファイルに必要な情報を記入します。
チャネルトークはサンプルアプリのApp IDとApp Secretを公開しません。
サンプルアプリをテストする場合は、まずアプリ登録でテストアプリを1つ作成し、必要な値を準備してください。新しく作成したテストアプリは、writeGroupMessageとwriteGroupMessageAsManager権限を必ず持つ必要があります。
stageはそのままにしておくことを推奨します。appId,appSecretには準備した値を入力してください。
3. アプリサーバーの実行
READMEの説明に従ってアプリを実行してください。
4. ngrokの実行
アプリストアから送信されるリクエストを、サンプルアプリを実行中のローカルEndpointに転送するためにngrokを実行します。
ngrokを実行する際に渡す転送引数は、テストする環境によって異なる場合があります。
ngrokを実行後、切り替わる画面でngrokが提供するEndpointを確認できます。この値がFunction EndpointとWAM EndpointのルートEndpointとなります。
ここで、サンプルアプリのEndpointがhttps://app-tutorial.ap.ngrok.ioになることがわかります。
5. アプリ設定にEndpointを登録
このドキュメントの「サーバー設定」パートを参照し、テストアプリの設定ページでFunction EndpointとWAM Endpointを保存してください。
2つの値はそれぞれ以下の通りです。
Function Endpoint:
https://app-tutorial.ap.ngrok.io/functionsWAM Endpoint:
https://app-tutorial.ap.ngrok.io/resource/wam
6. アプリのインストール
このドキュメントの「アプリのインストール」パートを参照し、テストチャネルにアプリをインストールしてください。
新しく登録したテストアプリは、アプリがインストールされたチャネルでのみ使用できます。
7. Commandの使用
チャットウィンドウに Commandを入力してみましょう!
Command入力
WAM起動(Command実行)
ボットおよびチームメンバーによるグループメッセージ作成
各ボタンをクリックすると、以下のメッセージがグループチャットに送信されます。
チャネルアプリを開発するためのチュートリアルはこれで全て終了です!