
LINE MINI App คือ แอปที่อยู่ภายในแอป LINE ที่พัฒนาด้วยเทคโนโลยีของเว็บแอปพลิเคชัน โดยมีการเพิ่มความสามารถในการเข้าถึงข้อมูลผู้ใช้งาน และสามารถตอบสนองกับห้องแชทได้ ผ่านการเรียกใช้ฟังก์ชันต่างๆจาก SDK ที่ LINE เตรียมไว้ให้
ความสามารถหลักของ LINE MINI App คือการเข้าถึงข้อมูลพื้นฐานของผู้ใช้ที่เปิดใช้งาน เช่น userId, email, displayImage, pictureUrl, statusMessage โดยที่ผู้ใช้ไม่ต้องทำการ Login ใดๆ อีกทั้งยังสามารถส่งข้อความรูปแบบต่างๆในนามของผู้ใช้กลับไปที่ห้องแชทได้ เช่น Text message หรือ Flex message เป็นต้น นอกจากนี้ยังสามารถส่งข้อความแจ้งเตือนผ่าน Service Messages ผ่าน LINE OA ที่ผู้ใช้งานไม่จำเป็นต้องเพิ่มเพื่อนอีกด้วย
นอกจากนี้รองรับการใช้งานบน External Browser ซึ่งมาพร้อมกับ LINE Login ในการยืนยันตัวตนผู้ใช้ โดยที่นักพัฒนาไม่จำเป็นต้อง Implement ระบบ Authentication เอง
ใน Codelab นี้คุณจะได้เรียนรู้ฟังก์ชันพื้นฐานต่างๆ และการทำงานของ LINE MINI App พร้อมทั้งลงมือสร้าง LINE MINI App ตัวแรกของคุณขึ้นมา

ใน Codelab นี้เราจะพัฒนา LINE MINI App ด้วย StackBlitz ซึ่งเป็น Editor แบบออนไลน์ที่ไม่ต้องติดตั้งโปรแกรมใดๆ และเราสามารถแชร์ URL ของโปรเจคให้กับผู้อื่นได้ โดยโปรเจคที่แชร์ จะอนุญาตให้ผู้อื่นเข้าถึงโค้ดทั้งหมด แต่จะไม่สามารถแก้ไขโปรเจคของเราได้


จุดเริ่มขบวนสำหรับการพัฒนาแอปพลิเคชันต่างๆบนแพลทฟอร์มของ LINE คือคุณจะต้องสมัครเป็น LINE Developer ก่อน


Provider คือ superset ของแอปทั้งหลายที่เราจะพัฒนาขึ้นรวมถึง LINE MINI App ด้วย โดยการสร้างเพียงให้ระบุชื่อของ Provider ลงไป ซึ่งอาจจะตั้งเป็นชื่อตัวเอง, ชื่อบริษัท, ชื่อทีม หรือชื่อกลุ่มก็ได้

Channel คือ subset ของ Provider ซึ่งเปรียบเสมือนแอปพลิเคชัน


หลังจากที่คุณมี Provider และ LINE MINI App channel เรียบร้อยแล้ว ขั้นตอนต่อไปเราจะมาตั้งค่าเพื่อใช้งาน LINE MINI App กัน โดยใน channel ให้เราเลือกแท็บชื่อ Web app settings

Endpoint URL: URL ที่รองรับ HTTPS ซึ่งใน Codelab นี้ให้คุณระบุ Endpoint URL ของ StackBlitz ที่ได้จากขั้นตอนที่ 2 ลงไปในช่องของ Developing

โดย URL ของ LINE MINI App ที่เราจะนำไปใช้จะอยู่ที่ LIFF URL แบบ Developing

หลังจากที่คุณได้ผูก Endpoint URL เข้ากับ LINE MINI App แล้ว คราวนี้เราจะมาลงมือโค้ดกัน โดยการจะใช้งานคำสั่งต่างๆภายใน LINE MINI App จะเริ่มจากการ initialize ตัว LIFF SDK ขึ้นมาก่อน
index.html ใน StackBlitz แล้ว Uncomment ตัว LIFF SDK ใน <script src="https://static.line-scdn.net/liff/edge/2/sdk.js"></script>
index.js แล้วเพิ่มคำสั่ง initialize ตัว LIFF app ด้วย LIFF ID ที่คุณได้จากขั้นตอนที่ 4 ในฟังก์ชัน main()// Initialize LIFF SDK
await liff.init({ liffId: "YOUR-LIFF-ID" })
เพื่อให้มั่นใจว่าเราสามารถเรียกใช้งานฟังก์ชันต่างๆใน LINE MINI App ได้ ดังนั้นให้เพิ่มโค้ดชุดนี้ลงไป หลังจากการ initialize ตัว LIFF SDK เพื่อตรวจสอบว่า LINE MINI App ของเราสามารถแยก OS ที่เปิดใช้งานได้
// Try a function
switch (liff.getOS()) {
case "android": body.style.backgroundColor = "#d1f5d3"; break
case "ios": body.style.backgroundColor = "#eeeeee"; break
}
วิธีการใช้งาน ให้เราเอา URL ของ LINE MINI App ในขั้นตอนที่ 4 ซึ่งมีลักษณะ https://miniapp.line.me/YOUR-LIFF-ID

หลังจากที่เราเรียกคำสั่ง liff.init() ไปแล้ว ในกรณีที่เราเปิด LINE MINI App กับแอป LINE บน iOS หรือ Android ตัว LINE MINI App จะทำการ Login ให้อัตโนมติ ซึ่งทำให้เราสามารถเข้าถึงข้อมูลของผู้ใช้ได้ทันทัน
index.html ให้เราเพิ่มโค้ดนี้เข้าไปที่ section ที่ชื่อว่า profile เพื่อแสดงผลข้อมูลพื้นฐานต่างๆของผู้ใช้<section id="profile">
<img id="pictureUrl" src="https://vos.line-scdn.net/imgs/apis/ic_mini.png">
<p id="userId"></p>
<p id="displayName"></p>
<p id="statusMessage"></p>
<p id="email"></p>
</section>
index.js ให้เราสร้างฟังก์ชัน getUserProfile() ขึ้นมา โดยให้เอาโค้ดชุดนี้ไปวางไว้ด้านล่างสุดของไฟล์async function getUserProfile() {
const profile = await liff.getProfile();
pictureUrl.src = profile.pictureUrl ? profile.pictureUrl : 'https://vos.line-scdn.net/imgs/apis/ic_mini.png';
userId.innerHTML = '<b>userId:</b> ' + profile.userId;
statusMessage.innerHTML = '<b>statusMessage:</b> ' + profile.statusMessage;
displayName.innerHTML = '<b>displayName:</b> ' + profile.displayName;
}
getUserProfile() ที่บรรทัดล่างสุดของฟังก์ชัน main()async function main() {
// ...
getUserProfile()
}
การจะขอเข้าถึง Email ของผู้ใช้เราจำเป็นจะต้องขอ permission



index.js ใน StackBlitz ให้เพิ่มโค้ดบรรทัดนี้เข้าไปในฟังก์ชัน getUserProfile()async function getUserProfile() {
// ...
email.innerHTML = "<b>email:</b> " + liff.getDecodedIDToken().email
}

หนึ่งในข้อดีของการพัฒนา LINE MINI App ก็คือการที่ LINE Login ได้เข้ามา Integrate ร่วม ทำให้เราสามารถยืนยันตัวตนผู้ใช้งานได้ง่าย ไม่ต้องพัฒนาเรื่อง Authentication เอง และนอกจากนี้เรายังสามารถใช้งานฟีเจอร์ต่างๆกับ External Browser บนสมาร์ทโฟน ได้เทียบเท่ากับการใช้งาน LINE MINI App กับแอป LINE บนสมาร์ทโฟนเช่นกัน
เราจะตรวจสอบว่าผู้ใช้เปิด LINE MINI App กับแอป LINE หรือ External Browser บนสมาร์ทโฟนเพื่อที่จะแสดงปุ่ม Log In และ Log Out ในกรณีที่ผู้ใช้เปิดด้วย External Browser บนสมาร์ทโฟน
index.html ให้เราเพิ่มโค้ด HTML เข้าไปที่ section ที่ชื่อว่า button เพื่อแสดงปุ่มทั้งสอง(กรณีที่เปิดด้วย External Browser)<section id="button">
<button id="btnLogIn">Log In</button>
<button id="btnLogOut">Log Out</button>
</section>
index.js ให้เอาโค้ดชุดนี้ไปแทนที่ getUserProfile() ในฟังก์ชัน main()async function main() {
// ...
if (liff.isInClient()) {
getUserProfile()
} else {
btnLogIn.style.display = "block"
btnLogOut.style.display = "block"
}
}
สำหรับการทดสอบใน External Browser ให้คัดลอก URL ของ LINE MINI App ไปเปิดใน External Browser บนสมา์ทโฟน เช่น Safari หรือ Chrome ด้วยตนเอง

ในไฟล์ index.js เราจะแยกการแสดงผลปุ่ม Log In และ ปุ่ม Log Out ตามสถานะการ Log In liff.isLoggedIn() โดยให้เอา if else ชุดนี้ไปแทนที่ if else ชุดเดิมในฟังก์ชัน main()
async function main() {
// ...
if (liff.isInClient()) {
getUserProfile()
} else {
if (liff.isLoggedIn()) {
btnLogIn.style.display = "none"
btnLogOut.style.display = "block"
getUserProfile()
} else {
btnLogIn.style.display = "block"
btnLogOut.style.display = "none"
}
}
}
คราวนี้เราก็จะมาสร้าง listener ให้กับปุ่ม โดยให้เอาโค้ดชุดนี้ไปวางไว้ด้านล่างสุดของไฟล์ index.js
btnLogIn.onclick = () => {
liff.login()
}
btnLogOut.onclick = () => {
liff.logout()
window.location.reload()
}
Refresh หน้า LINE MINI App บนสมาร์ทโฟนอีกครั้ง จากนั้นทดลองกดปุ่ม Log In และ Log Out

LINE MINI App สามารถส่งข้อความรูปแบบต่างๆใน LINE ไปยังห้องแชทที่ LINE MINI App ถูกเปิดขึ้นมาได้ เช่น Text หรือ Flex message

<section id="button">
<button id="btnSend">Send Message</button>
<!-- ... -->
</section>
index.js ให้เอาโค้ดชุดนี้ไปวางไว้ด้านล่างสุดของไฟล์async function sendMsg() {
if (liff.getContext().type !== "none" && liff.getContext().type !== "external") {
await liff.sendMessages([
{
"type": "text",
"text": "This message was sent by sendMessages()"
}
])
alert("Message sent")
}
}
Send Message โดยให้เอาโค้ดชุดนี้ไปวางไว้ด้านล่างสุดของไฟล์ index.jsbtnSend.onclick = () => {
sendMsg()
}
liff.sendMessages() ไม่สามารถใช้งานได้ใน External Browser ดังนั้นเราจะแสดงปุ่มนี้ในกรณีที่เปิด LINE MINI App จากแอป LINE บนสมาร์ทโฟนเท่านั้นasync function main() {
if (liff.isInClient()) {
btnSend.style.display = "block"
getUserProfile()
} else {
// ...
}
}

LINE MINI App สามารถแชร์ข้อความรูปแบบต่างๆใน LINE ไปยัง เพื่อน หรือ กลุ่ม ได้

<section id="button">
<button id="btnShare">Share Target Picker</button>
<!-- ... -->
</section>
index.js ให้เราเพิ่มฟังก์ชัน shareMsg() โดยให้เอาโค้ดชุดนี้ไปวางไว้ด้านล่างสุดของไฟล์async function shareMsg() {
await liff.shareTargetPicker([
{
type: "image",
originalContentUrl: "https://vos.line-scdn.net/imgs/apis/ic_mini.png",
previewImageUrl: "https://vos.line-scdn.net/imgs/apis/ic_mini.png"
}
])
}
Share Target Picker โดยให้เอาโค้ดชุดนี้ไปวางไว้ด้านล่างสุดของไฟล์ index.jsbtnShare.onclick = () => {
shareMsg()
}
liff.shareTargetPicker() จะสามารถใช้ได้ในกรณีที่ผู้ใช้ Log In แล้ว ดังนั้นเราจะแสดงปุ่มนี้ 2 ตำแหน่งในฟังก์ชัน main()async function main() {
if (liff.isInClient()) {
btnShare.style.display = "block"
// ...
} else {
if (liff.isLoggedIn()) {
btnShare.style.display = "block"
// ...
} else {
// ...
}
}
}

เราสามารถเรียกใช้งาน QR Code Reader เพื่ออ่านค่าที่อยู่ใน QR code แล้วส่งค่านั้นกลับมายัง LINE MINI App ได้

index.html ใน StackBlitz เพิ่มโค้ดชุดนี้ใน section ที่ชื่อ feature<section id="feature">
<p id="code"></p>
</section>
button<section id="button">
<button id="btnScanCode">Scan Code</button>
<!-- ... -->
</section>
index.js ให้เราเพิ่มฟังก์ชัน scanCode() โดยให้เอาโค้ดชุดนี้ไปวางไว้ด้านล่างสุดของไฟล์async function scanCode() {
const result = await liff.scanCodeV2()
code.innerHTML = "<b>Code: </b>" + result.value
}
Scan Code โดยให้เอาโค้ดชุดนี้ไปวางไว้ด้านล่างสุดของไฟล์ index.jsbtnScanCode.onclick = () => {
scanCode()
}
main()async function main() {
if (liff.isInClient()) {
btnScanCode.style.display = "block"
// ...
} else {
if (liff.isLoggedIn()) {
btnScanCode.style.display = "block"
// ...
} else {
// ...
}
}
}
ในตัวอย่างนี้จะมีคำว่า LINE Developers Thailand อยู่ใน QR code ซึ่งเมื่ออ่านค่ามาได้แล้ว จะมีการส่งค่ากลับมาแสดงใน LINE MINI App ตรงส่วนที่เขียนว่า Code

ในบางกรณีที่คุณต้องการจะเปิดเว็บไซต์ภายนอก LINE MINI App คุณสามารถใช้ฟังก์ชัน liff.openWindow() เพื่อเปิดมัน โดยทำตามขั้นตอนดังนี้
index.html ให้คุณเพิ่มปุ่ม Open Window โดยให้เพิ่มโค้ดชุดนี้ใน section ชื่อ button<section id="button">
<button id="btnOpenWindow">Open Window</button>
<!-- -->
</section>
index.jsbtnOpenWindow.onclick = () => {
liff.openWindow({
url: window.location.href,
external: true
})
}
liff.openWindow() นั้นสามารถใช้งานได้ทั้งแอป LINE บนสมาร์ทโฟน และ External Browser บนสมาร์ทโฟน และไม่จำเป็นต้อง Log In เพื่อใช้งาน ดังนั้นให้เพิ่มโค้ดบรรทัดนี้ไว้ด้านล่างสุดของฟังก์ชัน main()async function main() {
if (!liff.isInClient()) {
if (liff.isLoggedIn()) {
// ...
} else {
// ...
}
} else {
// ...
}
btnOpenWindow.style.display = "block"
}

นอกจากการกดปิด LINE MINI App เองด้วยการกดสัญลักษณ์ X ที่มุมขวาบนแล้ว เราก็ยังสามารถปิด LINE MINI App ด้วยโค้ดได้ โดยในตัวอย่างนี้ จะแทนที่ alert("Message sent") ด้วย liff.closeWindow() ที่ฟังก์ชัน sendMsg() ในไฟล์ index.js
async function sendMsg() {
if (liff.getContext().type !== "none") {
await liff.sendMessages([
{
"type": "text",
"text": "This message was sent by sendMessages()"
}
])
liff.closeWindow()
}
}
เมื่อเรากดส่งข้อความกลับไปยังห้องแชทเรียบร้อย ตัว LINE MINI App ก็จะปิดตัวเองทันที

อีกหนึ่งความสามารถของ LINE MINI App ที่ช่วยให้ผู้ใช้งานเข้าถึงตัว LINE MINI App ได้สะดวกมากยิ่งขึ้นคือการเพิ่ม Shortcut icon ที่หน้า Home screen ของสมาร์ทโฟน โดยเมื่อมีการคลิกตัว Shortcut จะสามารถกระโดดมาเปิด LINE MINI App ได้ทันทีโดยไม่ต้องเข้าผ่านแอป LINE
<section id="button">
<button id="btnShortcut">Add Shortcut</button>
<!-- ... -->
</section>
index.js ซึ่งเราจะต้องแทนที่ YOUR-LIFF-ID ด้วย LIFF ID ที่ได้จากขั้นตอนที่ 4 btnShortcut.onclick = async () => {
await liff.createShortcutOnHomeScreen({
url: "https://miniapp.line.me/YOUR-LIFF-ID",
})
}
liff.createShortcutOnHomeScreen() จะสามารถใช้ได้ในกรณีที่ผู้ใช้ Log In แล้ว ดังนั้นเราจะแสดงปุ่มนี้ 2 ตำแหน่งในฟังก์ชัน main()async function main() {
if (liff.isInClient()) {
btnShortcut.style.display = "block"
// ...
} else {
if (liff.isLoggedIn()) {
btnShortcut.style.display = "block"
// ...
} else {
// ...
}
}
}

ในการใช้งานบางกรณีเราอาจต้องการให้ LINE MINI App ทำงานร่วมกับ LINE Chatbot เช่น เมื่อซื้อสินค้าผ่าน LINE MINI App เสร็จก็ให้ LINE Chatbot ส่งใบเสร็จยืนยันการซื้อสินค้ากลับไป ซึ่งกรณีนี้เราสามารถเชื่อมต่อทั้งบริการทั้งสองเข้าด้วยกัน เพื่อให้แน่ใจว่าผู้ใช้งาน LINE MINI App ได้เป็นเพื่อนกับ LINE Chatbot เราแล้ว โดยผ่านฟีเจอร์ที่ชื่อ Linked LINE Official Account


หลังจากที่เราได้เชื่อมต่อ LINE MINI App เข้ากับ LINE Chatbot แล้ว เราจะสามารถตรวจสอบสถานะความเป็นเพื่อนระหว่าง ผู้ใช้งาน กับ LINE Chatbot ได้อีกด้วย ทั้งนี้เราอาจต้องการยืนยันว่าผู้ใช้งานรายนั้นๆ ได้เพิ่ม LINE Chatbot ของเราไปเป็นเพื่อนแล้ว ก่อนที่เราจะส่งข้อความไปหาเขา
index.html ให้เราเพิ่มโค้ด HTML เข้าไปที่ section ที่ชื่อว่า feature <section id="feature">
<!-- ... -->
<p id="friendShip"></p>
</section>
index.js ให้เอาโค้ดชุดนี้ไปวางไว้ด้านล่างสุดของไฟล์ และอย่าลืมแก้ไข BOT-ID ให้เป็น ID ของ Bot ที่คุณได้เชื่อมต่อไว้async function getFriendship() {
let msg = "Hooray! You and our chatbot are friend."
const friend = await liff.getFriendship()
if (!friend.friendFlag) {
msg = "<a href=\"https://line.me/R/ti/p/@BOT-ID\">Follow our chatbot here!</a>"
}
friendShip.innerHTML = msg;
}
liff.getFriendship() จะสามารถใช้ได้ในกรณีที่ผู้ใช้ Log In แล้ว ดังนั้นเราจะเรียกใช้ getFriendship() ในกรณีที่เปิด LINE MINI App กับแอป LINE บนสมาร์ทโฟน และในกรณีที่ผู้ใช้งานได้ Log In แล้วใน External Browser บนสมาร์ทโฟนที่ฟังก์ชัน main()async function main() {
if (liff.isInClient()) {
// ...
getFriendship()
} else {
if (liff.isLoggedIn()) {
// ...
getFriendship()
} else {
// ...
}
}
}

ยินดีด้วยครับ ถึงตรงนี้คุณก็มี LIFF app ตัวแรกเป็นของคุณเองแล้ว!!!