[12日目] 学校の食堂をIT化させる話　LINE Messaging APIで作る食堂IT化（前編）

こんにちは、なりかくんと申します。
この記事はなりかくん Advent Calender 2023の12日目の記事です。

この話は、1日目から始めた学校の食堂をIT化させる話の続きとなります。前回は、LINEを使った食堂キャッシュレスシステムの決済までのシステムの流れを紹介しました。

今回は、そのシステムを具体的に紹介していきたいと思います。

# サーバーレス環境
今回、サーバーレス環境を目指してシステムを作ることを目標にしました。最初は、Google App Scriptを利用しすべて処理をする予定でした。
そして、GASでプログラムも完成まで作りました。十分これでも動いたので、プログラムを簡単に公開しておきます。（誰かの役に立てばいいかも）

以下がプログラムです。

```js
const LINE_TOKEN = PropertiesService.getScriptProperties().getProperty('LINE_TOKEN');
const LINE_REPLY_ENDPOINT = 'https://api.line.me/v2/bot/message/reply';
const ERROR_MSG = "エラーが発生しました。";

function doGet (e) {
  return responseErrorCreate(201, "Not Content");
}

function doPost(e) {
  let eventData = JSON.parse(e.postData.contents).events[0];
  let replyToken = eventData.replyToken;
  const userId = eventData.source.userId;
  if (eventData.type == "message") {
    let messageType = eventData.message.type;
    try {
      if (messageType == "text") {
        let userMessage = eventData.message.text;
        if (userMessage == "混雑状況") {
          lineReply(replyToken, [getKonzatu()]);
          return responseCreate("OK");
        } else if (userMessage == "メニュー") {
          lineReply(replyToken, [getMenuCategory()]);
          return responseCreate("OK");
        }
      }
    } catch (err) {
      Logger.log(err.message);
      lineReply(replyToken, [createMsg(ERROR_MSG)]);
      return responseErrorCreate(500, err.message);
    }
  } else if (eventData.type == "postback") {
    let backData = eventData.postback.data;
    // ここにポストバック時の処理を追加
  }
}

function createMsg (msg) {
  return {
    'type': 'text',
    'text': msg
  }
}

function lineReply(replyToken, replyJson) {
    let payload = {
    'replyToken': replyToken,
    'messages': replyJson
  };

  let options = {
    'payload' : JSON.stringify(payload),
    'method'  : 'POST',
    'headers' : {"Authorization" : "Bearer " + LINE_TOKEN},
    'contentType' : 'application/json'
  };
  UrlFetchApp.fetch(LINE_REPLY_ENDPOINT, options);
}

const responseErrorCreate = (statusCode, message) => {
  const response = {
    statusCode: statusCode,
    message: message
  }
  return JSON.stringify(response)
}

const responseCreate = (data) => {
  const response = {
    statusCode: 200,
    data: data
  }
  return JSON.stringify(response)
}
```

簡単に解説しておきます。まあ、わかる人ならすぐわかるプログラムになるのですが...

GASをAPIサーバーとしておき、WebHookでLINEからデータを受け取ります。POSTが飛んで来たら、GAS上では
```js
function doPost(e) {
    // 処理
}
```
とすれば、POSTのイベントが取れるみたいです。

そして、LINEから飛んできたデータの中の返信用Tokenとメッセージ内容などを整理しているのが、このコードです。
```js
let eventData = JSON.parse(e.postData.contents).events[0];
let replyToken = eventData.replyToken;
const userId = eventData.source.userId;
if (eventData.type == "message") {
    let messageType = eventData.message.type;
    try {
        if (messageType == "text") {
            let userMessage = eventData.message.text;
            // メッセージの処理
        }
    } catch (err) {
        // エラー時の処理
    }
} else if (eventData.type == "postback") {
    let backData = eventData.postback.data;
    // ここにポストバック時の処理を追加
}
```
まあ、シンプルですね。わざわざ返信用トークンを利用する理由としては返信用Tokenを利用しないとLINE Messaging APIにはレートリミットがあるからです。
コードの解説は、まあAI(GoogleのBird)にでも任せときましょう（適当）
> このコードは、LINE Messaging APIのWebhookイベントを処理するコードです。
> 
> イベントの種類（messageまたはpostback）を判別し、メッセージの種類やポストバックデータに応じて処理を行います。
> 
> 具体的な処理内容は、ボットの機能によって異なります。
> 
> このように、LINE Messaging APIの基本的な処理を行うことができます。

まあ、これでいいでしょう。

後は返信らへんですんね、これもシンプルです。
```js
function lineReply(replyToken, replyJson) {
    let payload = {
    'replyToken': replyToken,
    'messages': replyJson
  };

  let options = {
    'payload' : JSON.stringify(payload),
    'method'  : 'POST',
    'headers' : {"Authorization" : "Bearer " + LINE_TOKEN},
    'contentType' : 'application/json'
  };
  UrlFetchApp.fetch(LINE_REPLY_ENDPOINT, options);
}
```

ただ、LINE Messaging APIにGASのUrlFetchAppでfetchしているだけです。シンプル is the ベスト！！

後は、別ファイルに分けてメニュー表などを作っています。ですが、決済部分でPayPay APIを叩く際にSDKを使いたいわけです。

ですが、さすがにGAS用のSDKを用意されているわけでもなくPayPay Node.js SDK(※1)はありますがGASでは使うことが出来ません。

※1 paypayopa-sdk-node https://github.com/paypay/paypayopa-sdk-node

めんどくさいな、ということでやっぱりLINE BotもPythonで書こうという流れになりました。

# 最後に
ってことで、いったんここまでで前編ということで終わります。
次はPythonを使って書こう！ってなったのでそれをやっていこうと思います。

最後までお読みいただきありがとうございました。