LINE Messaging APIを発行するためのWeb資格証明の作成方法について、以前の記事で紹介しています。折角なので、この記事で作成したWeb資格証明(静的識別子はLINE_CHANNEL_ACCESS_TOKEN)を使用したAPEXアプリケーションを作ってみます。
作成するAPEXアプリケーションに、以下の2つの操作を実装します。
- LINE公式アカウントが受信したメッセージに返答する
- LINE公式アカウントが受信した写真を保存する
LINE公式アカウントが受信したメッセージは、Webhookによって表LINE_MESSAGESに保存されます。この処理はすでに作成済みで、そのまま流用します。
作成したアプリケーションは以下のように動作します。LINE公式アカウントがメッセージを受信したことはAPEXアプリケーションでは検知しないため、手動でページをリロードしてレポートを再表示しています。
LINEアプリケーションの画面です。メッセージありがとうございます!とあるのは、LINE公式アカウントにデフォルトで設定されている応答メッセージです。
以下よりAPEXアプリケーションの作成手順を紹介します。
クイックSQLの以下のモデルから、受信した写真を保存する表LINE_IMAGESを作成します。
# prefix: line
images
message_id vc20 /pk
content blob
content_type vc80
SQLワークショップのユーティリティのクイックSQLより、表の作成を行います。左ペインにモデルを記述し、SQLの生成、SQLスクリプトを保存、レビューおよび実行を順次クリックします。表LINE_IMAGESの作成までを実施し、APEXアプリケーションは作成しません。
LINE公式アカウントが受信したメッセージは、対話モード・レポートで表示します。以下のDDLを実行し、対話モード・レポートのソースとして使用するビューLINE_MESSAGES_Vを作成します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
create or replace view line_messages_v | |
as | |
select | |
cm.id, cm.is_valid, cm.received_date | |
,cm.source_type, cm.source_user_id, cm.reply_token | |
,cm.message_type, cm.message_text | |
,cm.message_id, cm.content_provider_type | |
,dbms_lob.getlength(ig.content) content, ig.content_type | |
from | |
( | |
select m.id, m.is_valid, m.received_date | |
,c.source_type, c.source_user_id, c.reply_token | |
,c.message_type, c.message_text | |
,c.message_id, c.content_provider_type | |
from line_messages m, | |
json_table(m.content, '$' | |
columns | |
( | |
source_type varchar2(20) path '$.events.source.type' | |
,source_user_id varchar2(100) path '$.events.source.userId' | |
,reply_token varchar2(100) path '$.events.replyToken' | |
,message_type varchar2(20) path '$.events.message.type' | |
,message_text varchar2(4000) path '$.events.message.text' | |
,message_id varchar2(100) path '$.events.message.id' | |
,content_provider_type varchar2(20) path '$.events.message.contentProvider.type' | |
) | |
) as c | |
where c.message_id is not null | |
) cm left outer join line_images ig | |
on cm.message_id = ig.message_id | |
/ |
1行のDDLなので、SQLコマンドに貼り付けて実行します。
アプリケーション作成ウィザードを起動し、空のアプリケーションを作成します。
名前はLINE応答とします。それ以外は変更せず、アプリケーションの作成をクリックします。
作成するページのタイプとして、対話モード・レポートを選択します。
ページ定義のページ番号は2とします。後ほど記述するコードにページ番号が含まれているため、ここでは必ず2を指定します。レポート・ページの名前はLINEメッセージ、ページ・モードは標準とします。
フォーム・ページを含めるをONにします。フォーム・ページ番号は3、フォーム・ページ名は受信メッセージ、フォーム・ページ・モードにモーダル・ダイアログを選択します。受信したメッセージへの返信と受信した写真の保存は、フォームのページに実装します。
データ・ソースの表/ビューの名前として、先ほど作成したビューLINE_MESSAGES_Vを選択します。
ナビゲーションのブレッドクラムの使用、ナビゲーションの使用ともにデフォルトのONを選択します。
次へ進みます。
以上で、ページの作成をクリックします。
対話モード・レポートとフォームのページが作成されます。
作成された対話モード・レポートの列CONTENTを選択し、タイプをBLOBのダウンロードに変更します。LINE公式アカウントが受信した写真を列CONTENTからダウンロードできるようにします。
BLOB属性の表名にLINE_IMAGES、BLOB列にCONTENT、主キー列1にMESSAGE_ID、MIMEタイプ列にCONTENT_TYPEを選択します。
ファイル名列を指定すると、写真をダウンロードする際にファイル名が付きます。LINE公式アカウントが受信した写真には名前が付いていないため、ファイル名列は指定していません。
ここで一覧されるメッセージはLINE公式アカウントが受信し、Webhookの処理で表に書き込まれます。フォームからメッセージを投入することは無いため、ボタンCREATEを削除します。
以上で、受信したメッセージを一覧する対話モード・レポートはできました。
続いてページ番号3のフォームのページを変更します。
非表示になっている主キーのページ・アイテムP3_MESSAGE_IDを除いて、すべてのページ・アイテムを表示のみに変更します。
少しフォームを見やすくするため、ページ・アイテムP3_IS_VALID、P3_RECEIVED_DATE、P3_SOURCE_TYPE、P3_CONTENT、P3_CONTENT_TYPEを選択し、レイアウトの新規行の開始をOFFに変更します。
返信する文字列を保持するページ・アイテムP3_REPLY_TEXTを作成します。
識別の名前はP3_REPLY_TEXT、タイプとしてテキスト領域を選択します。ラベルはReply Textとします。
返信するときだけページ・アイテムが表示されるように、サーバー側の条件としてタイプにアイテム = 値を選択し、アイテムにP3_MESSAGE_TYPE、値にtextを指定します。
最初にボタンDELETEを削除します。
ボタンSAVEはラベルを保存に変更します。動作のデータベース・アクションは- 選択 -に変更し、データベース・アクションとして未指定の状態にします。
サーバー側の条件のタイプとしてアイテム = 値を選択します。アイテムにP3_CONTENT_PROVIDER_TYPEを選択し、値にlineを指定します。
サーバー側の条件のタイプにアイテム = 値を選択します。アイテムとしてP3_MESSAGE_TYPEを選択し、値にtextを指定します。
左ペインでプロセス・ビューを開きます。これよりLINE Messaging APIを発行し、返信と写真の保存を行うプロセスを実装します。
左ペインでプロセス・ビューを開きます。これよりLINE Messaging APIを発行し、返信と写真の保存を行うプロセスを実装します。
ウィザードにより作成されたプロセスプロセス・フォーム受信メッセージを削除します。
プロセスを作成しダイアログを閉じるの上に配置します。
LINE Messaging APIのReply APIについては、以下を参照しています。応答メッセージは応答トークン(replyToken)を使って送信しています。ドキュメントによると応答トークンは1分以内で使用する必要がある、とのことなので実際にはボットなどによる自動返信に用いるもので、今回のサンプルのように人による返信の場合は、応答メッセージ以外を使用することになるでしょう。
https://developers.line.biz/ja/reference/messaging-api/#send-reply-message
Messaging APIのReply APIはメッセージとしてカウントされませんが、Push APIはカウントされます。
https://www.linebiz.com/jp/service/line-official-account/plan/
識別の名前はReplyとします。タイプとしてコードの実行を選択し、ソースのPL/SQLコードとして以下を記述します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
declare | |
C_ENDPOINT constant varchar2(80) := 'https://api.line.me/v2/bot/message/reply'; | |
l_request json_object_t; | |
l_request_clob clob; | |
l_messages json_array_t; | |
l_message json_object_t; | |
l_response_clob clob; | |
begin | |
l_request := json_object_t(); | |
l_request.put('replyToken', :P3_REPLY_TOKEN); | |
l_message := json_object_t(); | |
l_message.put('type','text'); | |
l_message.put('text', :P3_REPLY_TEXT); | |
l_messages := json_array_t(); | |
l_messages.append(l_message); | |
l_request.put('messages', l_messages); | |
l_request_clob := l_request.to_clob(); | |
/* 返信 */ | |
apex_debug.info(l_request_clob); | |
apex_web_service.clear_request_headers(); | |
apex_web_service.set_request_headers('Content-Type','application/json',p_reset = false); | |
l_response_clob := apex_web_service.make_rest_request( | |
p_url => C_ENDPOINT | |
,p_http_method => 'POST' | |
,p_body => l_request_clob | |
,p_credential_static_id => 'LINE_CHANNEL_ACCESS_TOKEN' | |
); | |
if apex_web_service.g_status_code <> 200 then | |
raise_application_error(-20001, 'LINE Reply Error = ' || apex_web_service.g_status_code); | |
end if; | |
end; |
サーバー側の条件のボタン押下時にREPLYを指定します。
同様の手順にてプロセスSaveを作成します。ソースのPL/SQLコードとして以下を記述します。LINE Messaging APIのドキュメントの以下を参照しています。
https://developers.line.biz/ja/docs/messaging-api/receiving-messages/#getting-content-sent-by-users
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
declare | |
C_ENDPOINT constant varchar2(80) := 'https://api-data.line.me/v2/bot/message/{messageId}/content'; | |
l_url varchar2(200); | |
l_response_blob blob; | |
l_count number; | |
l_content_type varchar2(80); | |
begin | |
select count(*) into l_count from line_images where message_id = :P3_MESSAGE_ID; | |
if l_count > 0 then | |
return; -- すでに保存済みであれば何もしない。 | |
end if; | |
/* データを取得する */ | |
l_url := replace(C_ENDPOINT, '{messageId}', :P3_MESSAGE_ID); | |
-- apex_debug.info(l_url); | |
apex_web_service.clear_request_headers(); | |
l_response_blob := apex_web_service.make_rest_request_b( | |
p_url => l_url | |
,p_http_method => 'GET' | |
,p_credential_static_id => 'LINE_CHANNEL_ACCESS_TOKEN' | |
); | |
if apex_web_service.g_status_code <> 200 then | |
raise_application_error(-20001, 'LINE Content Error = ' || apex_web_service.g_status_code); | |
end if; | |
/* Content-Typeヘッダーを取得する */ | |
for i in 1..apex_web_service.g_headers.count | |
loop | |
if apex_web_service.g_headers(i).name = 'Content-Type' then | |
l_content_type := apex_web_service.g_headers(i).value; | |
exit; | |
end if; | |
end loop; | |
/* 取得したイメージを表LINE_IMAGESに保存する。 */ | |
insert into line_images(message_id, content, content_type) | |
values(:P3_MESSAGE_ID, l_response_blob, l_content_type); | |
end; |
サーバー側の条件のボタン押下時にSAVEを指定します。
プロセスダイアログを閉じるを選択し、サーバー側の条件の値をSAVE,REPLYに変更します。
以上でアプリケーションは完成です。アプリケーションを実行すると、記事の先頭のGIF動画のように動作します。
今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/line-messaging-api-sample.zip
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完