【免費教學】LINE+1 系統製作教學 (2024年版)

0元教學文製作LINE+1免費整單系統

沒時間自己學?專人可協助或指導你

進階LINE Bot規劃打造LINE群組機器人

目標:自己做一個LINE+1系統、LINE免費整單系統!

LINE群組賣東西、想利用LINE群組透過+1炒熱氣氛經營團購預約活動,整理資料卻超崩潰?或是想在LINE官方帳號內,發起+1活動,但不知道怎麼弄?

這篇LINE免費教學就要免費0元手把手陪你弄一個簡易的LINE群組機器人,他會變身LINE整單系統小幫手,+1, +2, -1 會統一人頭彙整預約訂單到Google Spreadsheet雲端

以下教你程式碼直接複製貼上

LINE+1示範範例加入柔兒官方帳號LINE

(需要真人專人協助與進階版教學,歡迎LINE內聯繫官網留下資料

官方帳號+1示範:加入柔兒LINE 

直接文字輸入+1, +2, -1,或是圖文選單切到「+1示範」點選+1, +2, -1

把LINE+1系統製作在LINE官方帳號內:加入柔兒LINE OA > 圖文選單切到「+1示範」> 試試看LINE+1預約

群組+1示意圖:簡易line群組整單系統,計算+1 

免費團購系統、免費預約系統,自己弄一個!把官方帳號加入群組,他就幫忙計算+1。並且透過名單和Google雲端看到哪些LINE+1用戶。

LINE+1系統,把官方帳號加入到群組: 把+1機器人 加入群組 > 彼此可以看見 +1 狀態 > Google 可以整理+1團購名單

步驟一:理解和設計好你的 +1邏輯!

以下複製柔兒示範的LINE+1系統後(+1示範:加入柔兒LINE),你可以做到:

步驟二:到LINE Developer後台取得Channel access token

如果你已經是柔兒粉想必都讀過這篇:LINE多層圖文選單綁定教學。和那篇一樣,我們必須取得Channel access token。

LINE+1系統如果是要套用在現有的官方帳號上,則就是需要去取得既有帳號的Channel access token喔!

步驟開一個Google Spreadsheet,連動當成好友LINE+1的資料庫

因為需要把LINE+1機器人的+1名單紀錄到資料庫,但因為內建的 LINE Bot 沒有資料紀錄的功能,所以我們使用不用錢的 Google Spreadsheet 試算表當成+1資料庫,紀錄哪些人報名或是卡位了。

Google Spreadsheet試算表,開立一個全新表單。做以下準備:

步驟:使用Google Apps Scripts 製作LINE+1預約團購系統機器人

1/ 到 Google Apps Scripts,開立一支新的Script。

2/ 複製下方收合群組內的程式碼,貼到你開的Script內。

展開,複製這份程式碼,貼到Google Apps Scripts

function doPost(e) {

   // LINE Messenging API Token

   var CHANNEL_ACCESS_TOKEN = '貼上你的Channel access token'; // LINE Bot API Token

   // 以 JSON 格式解析 User 端傳來的 e 資料

   var msg = JSON.parse(e.postData.contents);


   // for debugging

   Logger.log(msg);

   console.log(msg);


   const replyToken = msg.events[0].replyToken;

   const user_id = msg.events[0].source.userId;

   const userMessage = msg.events[0].message.text;

   const event_type = msg.events[0].source.type;


   const sheet_url = '貼上你的 Google sheet 試算表網址';

   const sheet_name = '貼上你的 Google sheet 試算表下的工作表名稱';

   const SpreadSheet = SpreadsheetApp.openByUrl(sheet_url);

   const reserve_list = SpreadSheet.getSheetByName(sheet_name);

  

   const maxium_member = 100; // 正式預約人數上限

   const waiting_start = maxium_member+1; // 候補人數開始的欄位,無需修改

   const waiting_member = 5; // 開放候補人數


   // 必要參數宣告

   var current_list_row = reserve_list.getLastRow(); // 取得工作表最後一欄( 直欄數 )

   var reply_message = []; // 空白回覆訊息陣列,後期會加入 JSON


   // 查詢傳訊者的 LINE 帳號名稱

   function get_user_name() {

       // 判斷為群組成員還是單一使用者

       switch (event_type) {

           case "user":

               var nameurl = "https://api.line.me/v2/bot/profile/" + user_id;

               break;

           case "group":

               var groupid = msg.events[0].source.groupId;

               var nameurl = "https://api.line.me/v2/bot/group/" + groupid + "/member/" + user_id;

               break;

       }


       try {

           //  呼叫 LINE User Info API,以 user ID 取得該帳號的使用者名稱

           var response = UrlFetchApp.fetch(nameurl, {

               "method": "GET",

               "headers": {

                   "Authorization": "Bearer " + CHANNEL_ACCESS_TOKEN,

                   "Content-Type": "application/json"

               },

           });

           var namedata = JSON.parse(response);

           var reserve_name = namedata.displayName;

       }

       catch {

           reserve_name = "not avaliable";

       }

       return String(reserve_name)

   }


   // 回傳訊息給line 並傳送給使用者

   function send_to_line() {

       var url = 'https://api.line.me/v2/bot/message/reply';

       UrlFetchApp.fetch(url, {

           'headers': {

               'Content-Type': 'application/json; charset=UTF-8',

               'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN,

           },

           'method': 'post',

           'payload': JSON.stringify({

               'replyToken': replyToken,

               'messages': reply_message,

           }),

       });

   }


   // 將輸入值 word 轉為 LINE 文字訊息格式之 JSON

   function format_text_message(word) {

       let text_json = [{

           "type": "text",

           "text": word

       }]


       return text_json;

   }


  

   var reserve_name = get_user_name();


   if (typeof replyToken === 'undefined') {

       return;

   };


   if (userMessage == "+1") { {

           if (current_list_row < maxium_member) {

               reserve_list.getRange(current_list_row + 1, 1).setValue(reserve_name);

               current_list_row = reserve_list.getLastRow();


               reply_message = format_text_message(reserve_name + "您已成功卡位,是第 " + current_list_row + " 位。" + "還有 " + (maxium_member - current_list_row) + " 位名額")


           }

           // 人數超過最大正式名額時,進入候補

           else if (current_list_row >= maxium_member & current_list_row < (waiting_member + maxium_member)) {

               reserve_name = "候補:" + reserve_name;

               reserve_list.getRange(current_list_row + 1, 1).setValue(reserve_name);

               reply_message = format_text_message("已經超過 100 人。" + reserve_name + " 已經為你排候補");


           }

           else {

               reply_message = format_text_message("⚠️ 額滿!已達 " + maxium_member + "人");

           }

       }


       send_to_line()

   }


   else if (userMessage == "+2") {

           if (current_list_row < maxium_member) {

               let name_array = [[reserve_name], [reserve_name]];

               reserve_list.getRange(current_list_row + 1, 1, 2, 1).setValues(name_array);

               current_list_row = current_list_row + 2;


               reply_message = format_text_message(reserve_name + "成功卡了2位" + "還有" + (maxium_member - current_list_row) + "位名額");


           }


           else if (current_list_row >= maxium_member & current_list_row < maxium_member + 2) { // +2 時不給候補

               let waiting_list_name = "候補:" + reserve_name;

               let waiting_names_array = [[waiting_list_name], [waiting_list_name]];

               reserve_list.getRange(current_list_row + 1, 1, 2, 1).setValues(waiting_names_array);


               reply_message = format_text_message(reserve_name + "預約2位候補");


           }

           // 名單超過 100 人時不新增,回傳通知訊息

           else {

               reply_message = format_text_message("⚠️ 報名額滿!已達 100 人");

           }

  

       send_to_line();

   }


   else if (userMessage == "-1") {


       let all_members = reserve_list.getRange(1, 1, current_list_row, 1).getValues().flat();

       let leaving_member_index = all_members.indexOf(reserve_name);


       if (leaving_member_index != -1) {

           let checking_range = leaving_member_index + 1;

           var waiting_add = reserve_list.getRange(waiting_start, 1).getValue();


           reserve_list.getRange(checking_range, 1).clearContent();

           current_list_row = reserve_list.getLastRow();

           move_all_data();


           var state = reserve_name + "您已釋出名額";

       }

       else {

           var state = "您尚未卡位成功,不用減一"

       }


       if (waiting_add != "") {

           reply_message = [{

               "type": "text",

               "text": state

           }, {

               "type": "text",

               "text": waiting_add + "候補進入名單"

           }]

       }

       else {

           reply_message = format_text_message(state);

       }


       // 將取消報名者下方所有資料向上移動

       function move_all_data() {

           let all_members = reserve_list.getRange(1, 1, current_list_row, 1).getValues().flat();

           let spaced_cell_index = all_members.indexOf("");

           let modify_range = current_list_row - spaced_cell_index - 1;

           let tmp_data = reserve_list.getRange(spaced_cell_index + 2, 1, modify_range, 1).getValues();


           reserve_list.getRange(spaced_cell_index + 1, 1, modify_range, 1).setValues(tmp_data);

           reserve_list.getRange(current_list_row, 1).clearContent();

       }


       send_to_line();

   }



   else if (userMessage == "名單") {

       var ready_namelist = "【 卡位名單 】\n";

       var all_members = reserve_list.getRange(1, 1, current_list_row, 1).getValues().flat();


       for (var x = 0; x <= all_members.length-1; x++) {

           ready_namelist = ready_namelist + "\n" + all_members[x];

       }

       reply_message = [

           {

               "type": "text",

               "text": "共有 " + current_list_row + " 位卡位"

           },

           {

               "type": "text",

               "text": ready_namelist

           }]


       send_to_line();

   }


   // 其他非關鍵字的訊息則不回應( 避免干擾群組聊天室 )

   else {

       console.log("else here,不回應.")

   }

}

3/ 把紅字取代或改成適合你情境的,請見下面截圖示意。

步驟部署你的LINE+1系統,自己弄的LINE免費訂單系統上線!

完成App Script程式碼更新到自己Google環境後,接著我們要把這個LINE+1系統,部署到雲端囉!

依序有下面七大步驟!請見下方影片示範如何部署。

備註小提醒:如果後來又改了Google App Script的程式碼,都要重新部署&替換LINE Developer的連結哦!

步驟LINE群組機器人製作成功!把LINE+1機器人加入到其他群組內

以上簡易LINE+1系統機器人,適合於line群組賣東西或是舉辦活動時,需要即時管理LINE活動名單或課程預約的情況,如健身房課程、瑜伽課程、研討會報名、社群活動等等,為LINE好友和品牌提供便利和即時的互動方式。也能將資料收回在自己的Google資料庫統計和去連動資料庫內的更多資料。

題外話:假設我有很多活動要+1加一,怎麼辦?

目前這篇文教學的LINE整單系統,一次就處理一檔活動或一個產品喔。

如果是連續性的活動,可以開不同的Sheet工作表名稱來收集資料,調整App Script的工作表欄位名稱,再取得不同的Webhook連結後,上傳更新到LINE部署,就能在同一個Google Spreadsheet雲端繼續搜集+1名單囉。

進階LINE Bot 自動回應訊息,LINE機器人一對一專人支援/指導

加入柔兒LINE 看範例~

更多LINE代管經營、LINE代超服務,柔兒團隊顧問,都可討論看看來協助你!請 加入柔兒LINE  以及 官網填單  留下您的資訊唷

撰文者

楊涵柔 May

柔兒數位 Gentler Digit》負責人

睿鼎數位 12CM Taiwan》行銷總監

英邦德科技 Inbound》創辦人