LINE Webhook

 LINEのWebhook URLをGAS (Google Apps Script)で作成する場合のテンプレートを以下に示す。

// channel access token (long lived) LINE Developers 
const ACCESS_TOKEN = '{アクセストークン}';

/**
 * POSTメッセージ受付処理
 */
function doPost(e) {
  // イベントの取得
  var events = JSON.parse(e.postData.contents).events;
  
  // イベントループ
  events.forEach(function(event){
    
    // WebHookで受信した応答用Token
    var replyToken = event.replyToken;

    // ユーザID
    var userId = event.source.userId;

    var responseMessage = [];

    // イベントタイプによって処理を分岐
    switch(event.type) {
      // テキストイベント
      case 'message':
        const userMessage = event.message.text;
        responseMessage = respondUser(userMessage, userId);
        break;
      // ポストバックイベント
      case 'postback':
        const data = event.postback.data
        responseMessage = respondPostback(data, userId);
        break;
      default:
        responseMessage.push({'type':'text','text':'unknown type=' + event.type});
    }
    
    // 応答メッセージ用のAPI URL
    var url = 'https://api.line.me/v2/bot/message/reply';
    
    UrlFetchApp.fetch(url, {
      'headers': {
        'Content-Type': 'application/json; charset=UTF-8',
        'Authorization': 'Bearer ' + ACCESS_TOKEN,
      },
      'method': 'post',
      'payload': JSON.stringify({
        'replyToken': replyToken,
        'messages': responseMessage,
      }),
    });
    
  });
  
  return ContentService.createTextOutput(JSON.stringify({'content': 'post ok'})).setMimeType(ContentService.MimeType.JSON);
}
/**
  * ユーザが入力したメッセージに応じた処理を行って応答メッセージを返す
  */
function respondUser(userMessage,userId) {
  let res = new Response();
  const userSheet = getUserSheet(userId);
  
  // ユーザメッセージに応じてレスポンスを変える
  if(userMessage == 'こんにちは'){
    res.pushLineText('はい、こんにちは。ようこそ服薬管理デモへ!');
    res.pushLineSticker('11537','52002738');
  } else if(userMessage == '私は誰'){
    res.pushLineText(userId);
  } else {
    res.pushLineText(userMessage + 'ですか?');
  }

  return res.getMessage();
}
/**
 * ポストバックイベントハンドラ
 */
function respondPostback(data, userId) {
  let res = new Response();
  const userSheet = getUserSheet(userId);
  res.pushLineText('data=' + data);
  return res.getMessage();
}
/**
  * userIdからユーザシートを取得する
  */
function getUserSheet(userId) {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(userId);
  if (sheet == null) {
    // シートがない場合は作成する
    sheet = SpreadsheetApp.getActiveSpreadsheet().insertSheet();
    sheet.setName(userId);
    sheet.getRange(1, 1).setValue('登録日時');
    sheet.getRange(1, 2).setValue(new Date());
    sheet.getRange(2, 1).setValue('状態');
    sheet.getRange(2, 2).setValue(0);
  }
  const status = sheet.getRange(2, 2).getValue();
  return {"status": status, "sheet": sheet};
}

LINEからのWebhookリクエストに対してdoPost関数が呼び出され、引数eからイベントオブジェクト配列が取り出され、各々のイベントオブジェクトに対してイベントループ処理が実行される。

イベントループ内では、イベントオブジェクト event からユーザID event.source.userId とイベントタイプevent.typeが取り出され、この値に応じて処理を分岐する。たとえば、イベントタイプがテキストイベント(event.type == 'message')であれば、入力されたメッセージ event.message.text が取り出され、メッセージ処理関数 respondUserに渡される。また、イベントタイプがポストバックイベント(event.type == 'postback')であれば、渡されたデータ event.postback.data が取り出され、ポストバックデータ処理関数 respondPostbackに渡される。

respondUser関数は、ユーザが入力したメッセージに応じた処理を行い、レスポンスメッセージ配列を返す。なお、レスポンスメッセージはLINE Messaging APIのレスポンスメッセージを管理するクラス Response を利用して作成している。これを使えば、例えばテキストメッセージはメソッドpushLineTextを使って、スタンプメッセージはpushLineStickerを使って簡単に作成できる。クラス Responseのソースを以下に示す。

/**
 * LINE Messaging API Response class
 */
class Response {
  // コンストラクタ―
  constructor() {
    this.messages = [];
  }
  // LINEテキストメッセージを追加する
  pushLineText(text) {
    this.pushMessage({
      "type": "text",
      "text": text,
    });
  }
  // LINEスタンプメッセージを追加する
  pushLineSticker(packageId, stickerId) {
    this.pushMessage({
      "type": "sticker",
      "packageId": '' + packageId,
      "stickerId": '' + stickerId
    });
  }
  // LINE画像メッセージを追加する
  pushLineImage(originalContentUrl, previewImageUrl) {
    this.pushMessage({
      "type": "image",
      "originalContentUrl": originalContentUrl,
      "previewImageUrl": previewImageUrl
    });
  }
  // LINEテンプレートメッセージ(ボタン)を追加する
  pushLineTemplateButton(altText, thumbnailImageUrl, title, text, defaultAction, actions) {
    this.pushMessage({
      "type": "template",
      "altText": altText,
      "template": {
        "type": "buttons",
        "thumbnailImageUrl": thumbnailImageUrl,
        "imageAspectRatio": "rectangle",
        "imageSize": "contain",
        "imageBackgroundColor": "#FFFFFF",
        "title": title,
        "text": text,
        "defaultAction": defaultAction,
        "actions": actions
      }
    });
  }
  // LINEテンプレートメッセージ(カルーセルテンプレート)を追加する
  pushLineTemplateCarousel(altText, columns) {
    this.pushMessage({
      "type": "template",
      "altText": altText,
      "template": {
        "type": "carousel",
        "columns": columns,
        "imageAspectRatio": "rectangle",
        "imageSize": "contain"
      }
    });
  }
  // カスタムペイロードメッセージを追加する
  pushMessage(line_message) {
    this.messages.push(line_message);
  }
  // レスポンスメッセージを取得する
  getMessage() {
    return this.messages;
  }

}

/**
 * LINE カルーセルのカラムクラス
 */
class CarouselColumn {
  constructor() {
    this.columns = [];
  }
  // カラムを追加する
  add(thumbnailImageUrl, title, text, defaultAction, actions){
    this.columns.push({
      "thumbnailImageUrl": thumbnailImageUrl,
      "imageBackgroundColor": "#FFFFFF",
      "title": title,
      "text": text,
      "defaultAction": defaultAction,
      "actions": actions
    });
  }
}

このクラスを利用すれば、例えば画像メッセージは次のようにして作成できる。

  const res = new Response();
  const imageUrl = "{画像のURL}";
  res.pushLineImage(imageUrl, imageUrl);

さらにテンプレートボタンメッセージは次のようにして作成できる。

  const defaultAction = {
    "type": "uri",
    "label": "詳しく見る",
    "uri": "https://semi2020kumw.blogspot.com/"
  };
  const actions = [];
  actions.push({
    "type": "postback",
    "label": "購入",
    "data": "action=buy&itemid=123"
  });
  actions.push({
    "type": "message",
    "label": "カートに入れる",
    "text": "1週間後に北海道を予約"
  });
  actions.push(defaultAction);
  res.pushLineTemplateButton('テンプレートメッセージ(ボタン)', imageUrl, 'メニュー', '選択してください。', defaultAction, actions);

さらにテンプレートカルーセルメッセージはカルーセルのカラムクラスを用いて次のように作成できる。

  const cCols = new CarouselColumn();
  cCols.add(imageUrl, 'メニュー', 'これは1つ目のカラムです', defaultAction, actions);
  cCols.add(imageUrl, 'メニュー', 'これは2つ目のカラムです', defaultAction, actions);
  res.pushLineTemplateCarousel('テンプレートメッセージ(カルーセルテンプレート)', cCols.columns); 

0 件のコメント:

コメントを投稿