LINEアプリのメッセージは、ユーザーアクションをきっかけに送信されます。例えば予約完了のお知らせは、ユーザーの予約申し込みアクションに基づいて送信されます。では、予約一日前とか2時間前とかにリマインドメッセージを送信する場合にはどうするのか、解説したいと思います。

メッセージの送信は基本的にはユーザーアクションをきっかけにする必要があります。最初のメッセージ送信は「ユーザーによる予約」アクションに対して実行されることになりますが、そのメッセージ送信に対する戻り値として、後続メッセージ送信のための「サービス通知トークン」が得られるので、それを後続メッセージを送信で使うことになります。後続メッセージを送信する際に「チャンネルアクセストークン」(LINEアプリにログインしていなくてもサーバーのみで発行可能)を発行し、このアクセストークンをヘッダーに、サービス通知トークンをボディとして記述することでメッセージ送信が可能になります。一方、「予約一日前」とか「2時間前に送信」にメッセージを送信するアクションの起点は、例えばAWS Lambdaなどを使って(予約データ確認とメッセージ送信を行う)APIを定時実行する関数を用意することになります。ここではアプリをデプロイしているrender.comのサービスを使います。
render.comではCron Jobの仕組みを利用して、サーバーレス関数(Serverless Functions)を定期的に実行することができます。Cron Jobは、UNIX系オペレーティングシステムで利用されるスケジューリング機能で、定期的に繰り返し実行するタスク(Cronタスク)を自動化するための仕組みです。render.comのコンソールにて上部メニューの「+」からCron Jobを選択すれば簡単に設定できます。(Cron Jobは定額$1/month + バックグランド実行時間に応じた従量料金がかかります)。設定のポイントとなる項目は、「Schedule」と「Command」です。
Schedule: Cronの書式は5つの数字からなります。左から、分 時 日 年 曜日 を表す数字で、例えば、毎日0時0分(世界標準時)にタスクを実行するには以下になります。
0 0 * * *
Command:LINUXのコマンドです。例えば”/api/cron”のapiを実行したいとすると
curl https://{url root}/api/cron
となります。本番環境ではセキュリティを考慮した対応が必要です。
api/cronの内容は例えばこんな感じ。
//予約前日の日時が取得されたとする。この翌日に予約が入っているユーザーに送信する
export async function GET(request: NextRequest) {
let date = new Date()
date.setDate(date.getDate()+1) //翌日のDateオブジェクトを取得
const tomorrowStr = date.toISOString() //標準時で9時間遅れ。正午ならば日付は日本と同じ
const tomorrow = tomorrowStr.split("T")[0] //翌日の日付
//ステートレスアクセストークンを取得する関数(詳細は前回記事)
const accessToken = await issueChannelAccessToken()
try {
//予約日がtomorrowと一致する予約を抽出
let { data: reservations, error } = await supabase
.from('reservation')
.select("*")
.eq("day",tomorrow)
if (reservations){
for (const reservation of reservations){
const date = reservation.start
const message:Message2 = {
templateName:"remind_d_b_ja",
params:{
date: date,
address: "----",
daytime: "1日",
shop_name: reservation.shop,
charge_name: reservation.staff,
reservation_contents: "カット"
},
notificationToken: reservation.notificationToken
}
//後続メッセージを送信する関数(基本は最初のメッセージと同じ)
const postData = await sendServiceMessage2(accessToken, message)
//notificationTokenを更新
updateReservation(reservation.id, postData.notificationToken)
}
return NextResponse.json({date:tomorrowStr, reservation:reservations})
} else {
return NextResponse.json({ error: "エラー" }, { status: 500 });
}
} catch (error) {
return NextResponse.json({ error: "エラー" }, { status: 500 });
}
}
以上により、予約アプリのメッセージ関連の実装が完了しました。


