ITTIRIT T.
3 min readFeb 4, 2021

ตัวอย่าง Line Notify Service แจ้งเตือน [Google apps script+html+JS]

บทความนี้เป็นตัวอย่างการใช้งาน Line Notify Service ซึ่งใช้บริการต่างๆดังนี้

(เหมาะกับผู้เริ่มต้นและมีความสนใจ)

Google apps script ::: Webhook

Google sheets ::: Database

Github, Github Pages ::: Endpoint, Callback

Video ขั้นตอนต่างๆ (ไม่มีเสียง) https://drive.google.com/drive/folders/1lSkyPOz-V0RCsJCmSzElzR9AFUMZhoRV?usp=sharing

BOT ตัวอย่าง ::: https://lin.ee/0d9L15L

(รหัสนักเรียนทดสอบ 1101-1110)

sheet : https://docs.google.com/spreadsheets/d/17bpsFoFEaPaYM2mTYEhPSjcjpo2Io9vC-QRUVmwlwpE/edit

Repository ::: https://github.com/itchampclub/check.std

ทำความเข้าใจ Liff ผู้ปกครอง (index.html)

function letg() {
var x = document.getElementById("tex1");
var x2 = document.getElementById("stdid").value;
liff.getProfile().then(function(profile) {
var uid = profile.userId;
var uname = profile.displayName;
var xos = liff.getOS();
x.innerHTML = "<br>StdId: " + x2+
"<br>userId: " + uid+
"<br>displayName: " + uname;
window.location.replace('https://notify-bot.line.me/oauth/authorize?response_type=code&client_id=vF9AoTvZ7nBfkMV8EoW6t8&redirect_uri=https://itchampclub.github.io/check.std/link.html&scope=notify&state='+x2+'&stdid='+x2);
});
}

รับค่าจากรหัสนักเรียนจาก input ที่ผู้ปกครองใส่ เมื่อกด Submit จะ Redirect ไปยัง OAuth2 authorization endpoint URI. ของ Line Notify Service พร้อมกับ parameter เมื่อ authorization เรียบร้อยจะ Redirect กลับไปยัง redirect url ที่เรากำหนด ในที่นี้คือ link.html พร้อมกับ parameter code, state

ทำความเข้าใจ Liff ผู้ปกครอง (link.html)

const xurl = "https://script.google.com/macros/s/AKfycbwZ45XwPorbnJurIlYBjKC4opBgQSE03piQ_0Z-K35aGlDta2_oz0QE/exec";
var myParam = window.location.search;
var exc = myParam.split('code=')[1].split('&')[0];
var excst = myParam.split('state=')[1].split('&')[0];
function letg() {
liff.getProfile().then(function(profile) {
var uid = profile.userId;
var uname = profile.displayName;
//alert(uid+'****'+exc+'****'+excst);
var xmlhttp = new XMLHttpRequest();
var theUrl = xurl+'?code='+exc+'&state='+excst+'&uid='+uid+'&uname='+uname;
xmlhttp.open('GET', theUrl);
xmlhttp.send();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var jsonResponse = JSON.parse(this.responseText);
}
alert(jsonResponse.desc);
liff.closeWindow();
}});

Get request ไปยัง Webhook linebot พร้อม parameter

  • code ที่ได้จาก authentication
  • รหัสนักเรียน
  • uid
  • displayname

และรอรับ return กลับ เพื่อ alert ผู้ใช้

ทำความเข้าใจโค๊ดในส่วน Webhook linebot

function doGet(e) {
var code = e.parameter.code;
var state = e.parameter.state;
var uid = e.parameter.uid;
var uname = e.parameter.uname;
var formData = {
'grant_type': 'authorization_code',
'code': code,
'redirect_uri': 'https://itchampclub.github.io/check.std/link.html', //https://notify-bot.line.me/my/services/
'client_id': 'vF9AoT*******MV8EoW6t8', //https://notify-bot.line.me/my/services/
'client_secret': 'ExgbZDYXxxoDWBA**********V76EQi8PR' //https://notify-bot.line.me/my/services/
};
var options = {
'method' : 'post',
'payload' : formData
};
var gettext = UrlFetchApp.fetch('https://notify-bot.line.me/oauth/token', options);
var profiledata = JSON.parse(gettext.getContentText());
var tokenn = profiledata.access_token;
var checkid = sheet.getRange(2, 3, sheet.getLastRow(),sheet.getLastColumn()).getValues();
for(var i = 0;i<checkid.length; i++){
if(state == checkid[i][0]){
var goodid = true;
sheet.getRange(i+2,1).setValue(uid);
sheet.getRange(i+2,2).setValue(uname);
sheet.getRange(i+2,6).setValue(tokenn);
}
}
if(goodid){
var result = {"desc": "ลงทะเบียนสำเร็จ"};
return ContentService.createTextOutput(JSON.stringify(result) ).setMimeType(ContentService.MimeType.JSON);
}else{
var result = {"desc": "ลงทะเบียนไม่สำเร็จ/ไม่พบรหัสนักเรียน"};
return ContentService.createTextOutput(JSON.stringify(result) ).setMimeType(ContentService.MimeType.JSON);
}
}

function doGet(e) รับ Request+Params จาก Liff ผู้ปกครอง

code = code ที่ได้จาก Authentication Notify Service
state = รหัสนักเรียน
uid = UID ของผู้ปกครอง
uname = DisplayName ของผู้ปกครอง

UrlFetchApp.fetch(‘https://notify-bot.line.me/oauth/token', options);

Post request เพื่อขอ access token จาก Line Notify Service

var checkid = sheet.getRange(2, 3, sheet.getLastRow(),sheet.getLastColumn()).getValues();
for(var i = 0;i<checkid.length; i++){
if(state == checkid[i][0]){
var goodid = true;
sheet.getRange(i+2,1).setValue(uid);
sheet.getRange(i+2,2).setValue(uname);
sheet.getRange(i+2,6).setValue(tokenn);
}
}

สร้างเงื่อนไขตรวจสอบ รหัสนักเรียนที่ได้รับจาก Get Request กับ รหัสนักเรียนที่มีอยู่ใน Sheet หากเข้าเงื่อนไขให้บันทึก uid, uname และ access token ลงในแถวนั้นๆ และส่ง return กลับไปหา User

if(goodid){
var result = {"desc": "ลงทะเบียนสำเร็จ"};
return ContentService.createTextOutput(JSON.stringify(result) ).setMimeType(ContentService.MimeType.JSON);
}else{
var result = {"desc": "ลงทะเบียนไม่สำเร็จ/ไม่พบรหัสนักเรียน"};
return ContentService.createTextOutput(JSON.stringify(result) ).setMimeType(ContentService.MimeType.JSON);
}
}

ส่ง return alert กลับไปยัง Liff ของ User

ทำความเข้าใจ Liff ครู (scan.html)

const xurl = "https://script.google.com/macros/s/AKfycbzqOuwbqy_pAyrXJy0RZ5gJ6Agfs23ZutdlScOpt0STJTScXt8z3fze/exec";
var stdcode = code.data;
var xmlhttp = new XMLHttpRequest();
var theUrl = xurl+'?stdcode='+stdcode;
xmlhttp.open('GET', theUrl);
xmlhttp.send();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var jsonResponse = JSON.parse(this.responseText);
}
alert(jsonResponse.desc);
}

Get request ไปยัง GG Apps Script Scan&Notify พร้อม parameter

  • รหัสนักเรียน

เพื่อแจ้งเตือนไปยังผู้ปกครองและรอรับ return กลับ เพื่อ alert ผู้ใช้

ทำความเข้าใจโค๊ดในส่วน Scan and Notify

function doGet(e) {
var stdcode = e.parameter.stdcode;
var checkid = sheet.getRange(2, 3, sheet.getLastRow(),sheet.getLastColumn()).getValues();
for(var i = 0;i<checkid.length; i++){
if(stdcode == checkid[i][0]){
var goodid = true;
var stdpaid = sheet.getRange(i+2,2).getValue();
var stdid = sheet.getRange(i+2,3).getValue();
var first = sheet.getRange(i+2,4).getValue();
var last = sheet.getRange(i+2,5).getValue();
var stdtoken = sheet.getRange(i+2,6).getValue();
}
}
if(goodid){
notiMsg('แจ้งเตือน\nรหัส '+stdid+'\nนักเรียนเข้าเรียนปกติ\nชื่อ '+first+' '+last+'\nผู้ปกครอง '+stdpaid, stdtoken);
var result = {"desc": "แจ้งเตือนสำเร็จ"};
return ContentService.createTextOutput(JSON.stringify(result) ).setMimeType(ContentService.MimeType.JSON);
}else{
var result = {"desc": "แจ้งเตือนไม่สำเร็จ/ไม่พบรหัสนักเรียน"};
return ContentService.createTextOutput(JSON.stringify(result) ).setMimeType(ContentService.MimeType.JSON);
}
}

function doGet(e) รับ Request+Params จาก Liff ครู

stdcode = รหัสนักเรียนที่ได้จากการเปิด Liff Scan QR Code

สร้างเงื่อนไขตรวจสอบ รหัสนักเรียนที่ได้รับจาก Get Request กับ รหัสนักเรียนที่มีอยู่ใน Sheet หากเข้าเงื่อนไขให้ดึงข้อมูลที่มีอยู่ในแถวนั้นๆ มาแจ้งเตือนไปยังผู้ปกครองและส่ง return กลับไปหา User