Picture of the author
Published on

สร้างระบบสั่งสินค้าผ่าน LINE OA ฟรี! ใช้แค่ HTML + Google Sheet + Google Apps Script

Cover

ลองจินตนาการแบบนี้...

คุณมี LINE OA อยู่แล้ว ลูกค้าทักมาตลอดว่า “วันนี้มีผักอะไรขายบ้างคะ?” คุณก็ต้องเปิดมือถือ ดูว่ามีอะไร แล้วก็พิมพ์ตอบเอง พอมีคนสั่ง คุณก็ต้องไปลิสต์ใส่กระดาษ หรือถ้าเก่งหน่อยก็ Google Sheet แต่ทุกอย่างก็ยัง แมนนวล อยู่ดี เหนื่อยใช่ไหมล่ะ ?

คุณคิดว่า “มันน่าจะมีวิธีที่ลูกค้ากดสั่งเองผ่าน LINE ได้เลย แล้วข้อมูลไปลง Google Sheet อัตโนมัติ แถมระบบแจ้งเตือนให้ด้วย” และคุณคิดถูกครับ — มันทำได้! และที่ดียิ่งกว่านั้นคือ ทุกอย่างฟรี! และคนทั่วไปสามารถเรียนรู้และทำได้ด้วยตัวคุณเอง

ในบทความนี้คุณจะได้เรียนรู้แบบ step-by-step:

  • ทำ Rich menu ให้ลูกค้ากดเลือกดูผักที่มี
  • ส่ง Flex Message กลับไปให้ลูกค้าเลือก “สั่งซื้อ”
  • ลูกค้ากดสั่ง → เปิดหน้าเว็บที่คุณทำเองไว้
  • เว็บดึงรายการผักจาก Google Sheet
  • ลูกค้ากรอกจำนวน แล้วกด “ยืนยันสั่งซื้อ”
  • ระบบจะ:
    • เก็บข้อมูลเข้า Google Sheet
    • แจ้งเตือน LINE Group ว่ามีออเดอร์ใหม่
    • ตอบกลับ LINE user ว่า “คุณสั่งผักเรียบร้อยแล้ว”
  • ทั้งหมดนี้จะใช้เพียง:
    • LINE Official Account (ฟรี 300 ข้อความ/เดือน)
    • Google Apps Script (ฟรี)
    • Google Sheet (ฟรี)
    • เว็บ HTML ที่คุณเคยทำไว้ (หรือทำตามในบทความนี้)

ออกแบบ Flow การทำงานของระบบ

  1. LINE OA
    • ลูกค้ากดปุ่มใน Rich Menu ของ LINE OA → ส่งข้อความ type: flex กลับไปให้ลูกค้า
    • Flex Message แสดงรายการเมนู เช่น "สั่งผักวันนี้" → มีปุ่ม สั่งซื้อ ซึ่งเมื่อกดแล้ว จะเปิดหน้าเว็บ HTML (บน GitHub Pages หรือ Firebase Hosting ก็ได้)
  2. หน้าเว็บ HTML
    • อ่าน line userId จาก query parameter ที่แนบมากับลิงก์
    • ดึงรายการผักจาก Google Sheet (ผ่าน Apps Script)
    • แสดงฟอร์มให้ลูกค้าเลือกผัก + ใส่จำนวน
    • เมื่อกด “ยืนยันสั่งซื้อ” → ส่งข้อมูลออเดอร์ไปยัง Apps Script
  3. Google Apps Script (GAS)
    • รับข้อมูล order (userId, รายการผัก, จำนวน, เวลา)
    • เพิ่มข้อมูลเข้า Google Sheet
    • ส่งข้อความแจ้งเตือนเข้า LINE group (เช่น "มีออเดอร์จาก คุณ A")
    • ส่งข้อความยืนยันกลับไปยัง LINE user ("คุณได้สั่งผักเรียบร้อยแล้ว ✅")

💬 ใช้ประโยชน์จาก LINE Messaging API:

  • Rich Menu สร้าง entry point ให้ลูกค้า
  • Flex Message UX ดี สวยกว่า text ธรรมดา
  • Push Message/Reply Message ใช้ตอบกลับลูกค้าแบบอัตโนมัติ
  • LINE Group ใช้เป็นช่องทางแจ้งเตือน admin / คนจัดผัก

. . .

1. สร้างหน้า HTML สั่งผัก (แสดงรายการจาก Google Sheet + ส่งออเดอร์)

  • ดึง ชื่อผัก + ราคา จาก Google Sheet มาสร้าง form
  • ลูกค้ากรอกจำนวน แล้วกด "ยืนยัน"
  • ส่งข้อมูล + userId กลับไปยัง Google Apps Script

โครงสร้าง Google Sheet ที่ใช้

เราจะใช้ชีตชื่อ ProductList

ผักราคา
คะน้า25
ผักกาดขาว20

อีกชีตหนึ่งจะชื่อ “Orders” ไว้เก็บรายการสั่งซื้อ

สร้าง HTML + JS

สร้างไฟล์ order.html และ order.js

<!DOCTYPE html>
<html lang="th">
<head>
  <meta charset="UTF-8">
  <title>สั่งผัก</title>
</head>
<body>
  <h2>รายการผัก</h2>
  <form id="order-form"></form>

  <button id="submit-btn">ยืนยันการสั่งซื้อ</button>
  <p id="response"></p>

  <script src="order.js"></script>
</body>
</html>
const urlParams = new URLSearchParams(window.location.search);
const userId = urlParams.get('userId');
const orderForm = document.getElementById('order-form');

// URL Apps Script ที่จะโหลดรายการผัก
const productsURL = 'https://script.google.com/macros/s/XXXXXXX/exec?action=getProducts';
// URL Apps Script ที่จะรับออเดอร์
const submitURL = 'https://script.google.com/macros/s/XXXXXXX/exec';

fetch(productsURL)
  .then(res => res.json())
  .then(products => {
    products.forEach((item, index) => {
      const div = document.createElement('div');
      div.innerHTML = `
        <label>${item.name} (${item.price} บาท): </label>
        <input type="number" name="${item.name}" price="${item.price}" min="0" value="0"><br><br>
      `;
      orderForm.appendChild(div);
    });
  });

document.getElementById('submit-btn').addEventListener('click', () => {
  const inputs = orderForm.querySelectorAll('input');
  const orderItems = [];

  inputs.forEach(input => {
    const qty = parseInt(input.value);
    if (qty > 0) {
      orderItems.push({ name: input.name, quantity: qty, price: input.price });
    }
  });

  if (orderItems.length === 0) {
    document.getElementById('response').innerText = "กรุณาใส่จำนวนผักที่ต้องการ";
    return;
  }

  const orderData = {
    userId,
    order: orderItems
  };

  fetch(submitURL, {
    method: 'POST',
    mode: 'no-cors',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(orderData)
  });

  document.getElementById('response').innerText = "ส่งออเดอร์เรียบร้อยแล้ว!";
  orderForm.reset();
});

อย่าลืมกลับมาอัพเดต productsURL และ submitURL หลังจาก Deploy Google App Script แล้ว


. . .

2. อัปโหลด Project HTML+JS ไปยัง GitHub และ Deploy เป็น GitHub Pages

2.1 สร้าง GitHub Repository

  • คลิกปุ่ม New repository
  • ตั้งชื่อ Repository และเปิดให้เป็น Public
  • กด Create repository

2.2 อัปโหลดไฟล์ด้วย Git CLI หรือ GUI (Sourcetree)

วิธีที่ง่ายที่สุด: ใช้ GitHub บนเว็บ

  • เข้า repository ที่เพิ่งสร้าง
  • คลิก Add file > Upload files
  • ลากไฟล์ทั้งหมดใน Project ใส่ใน Repository
  • Commit ไฟล์เหล่านั้นไปที่ main branch

2.3 Deploy เป็น GitHub Pages

  • ไปที่ Settings > Pages
  • ตรง Source ให้เลือก
    • Branch: main
    • Folder: /root
  • กด Save
  • รอสักครู่ GitHub จะสร้างลิงก์แบบนี้ให้ https://username.github.io/ชื่อ Repository/
  • นำ URL Github Pages กลับไปใส่ในปุ่ม "สั่งซื้อเลย" ของ Flex Message ใน Google App Script ขั้นตอนถัดไป

. . .

3. สร้าง Rich Menu เพื่อตอบกลับ Flex Message กดปุ่มสั่งสินค้าเปิดหน้าเว็บ HTML

🎯 เป้าหมายของเรา

  • ลูกค้ากดปุ่มจาก Rich Menu → ส่งข้อความ สั่งผัก ให้ LINE OA
  • LINE OA ส่ง Flex Message กลับมามีปุ่ม “สั่งซื้อผักวันนี้” → เปิดหน้าเว็บ HTML ที่เราเตรียมไว้
  • ส่ง LINE userId ไปด้วยในลิงก์ เพื่อรู้ว่าใครเป็นคนสั่ง

3.1 สร้าง Rich Menu

  • เข้าไปที่ LINE Official Account Manager และเข้าสู่ระบบ
  • เลือกแท็บ หน้าหลัก -> หน้าจอแชท -> ริชเมนู
  • เลือก สร้างใหม่ กรอกข้อมูลให้ครบ เลือกเทมเพลต -> เลือกแอ็กชัน -> ข้อความ ใส่คำว่า สั่งผัก -> บันทึก
  • รอ 1-2 นาที ลองเข้าไปดูที่ LINE OA จะเห็น Rich Menu แสดงขึ้นมา

3.2 เขียน Google App Script ตอบกลับเป็น Flex Message

  • เข้าไปที่ Google Sheet เลือก Extensions -> App Script ใส่ Code ตามนี้ใน Code.gs
function doPost(e) {
  const event = JSON.parse(e.postData.contents).events[0];
  const replyToken = event.replyToken;
  const message = event?.message?.text;

  if (event?.type === "message" && message === "สั่งผัก") {
    const userId = event.source.userId;

    const flexMessage = {
      type: 'flex',
      altText: 'เมนูสั่งผัก',
      contents: {
        type: 'bubble',
        body: {
          type: 'box',
          layout: 'vertical',
          contents: [
            {
              type: 'text',
              text: 'สั่งผักวันนี้ 🌿',
              weight: 'bold',
              size: 'lg'
            },
            {
              type: 'button',
              action: {
                type: 'uri',
                label: 'สั่งซื้อเลย',
                uri: `https://your-site.github.io/order.html?userId=${userId}`
              },
              style: 'primary'
            }
          ]
        }
      }
    };

    UrlFetchApp.fetch("https://api.line.me/v2/bot/message/reply", {
      method: 'post',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${LINE_TOKEN}`
      },
      payload: JSON.stringify({
        replyToken: replyToken,
        messages: [flexMessage]
      })
    });

    return ContentService.createTextOutput("ok");
  }

  return ContentService.createTextOutput("no action");
}
  • เลือก Deploy -> New deployment -> Web app
    • Execute as Me
    • Who has access Anyone
  • จะได้ URL ประมาณนี้ https://script.google.com/macros/s/.../exec
  • กลับไปที่ LINE Developer Console > Messaging API > เอา URL กลับไปใส่ที่ Webhook URL > กด Verify
  • ลองทดสอบกดสั่งผักผ่าน LINE OA ต้องได้ Flex Message ตอบกลับมาจาก LINE OA

. . .

4. เขียน Google Apps Script รับออเดอร์ + แจ้งเตือน LINE Group + ตอบกลับลูกค้า

  • สร้าง endpoint /exec ให้รับ POST จากเว็บ HTML
  • บันทึกข้อมูลลง Google Sheet (sheet: Orders)
  • ส่งข้อความแจ้งเตือนเข้า LINE group
  • ส่งข้อความยืนยันกลับหา user ผ่าน LINE OA

โครงสร้าง Google Sheet ที่ใช้

เราจะใช้ชีตชื่อ Orders

วันที่User IDรายการผักจำนวน (กก.)ราคาต่อหน่วยยอดขาย
21/04/2025 11:00Uxxxyyyzzzคะน้า225.0050.00
const LINE_TOKEN = 'YOUR_LINE_CHANNEL_ACCESS_TOKEN';

function doGet(e) {
  if (e.parameter.action === 'getProducts') {
    const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('ProductList');
    const data = sheet.getDataRange().getValues();
    const products = [];

    for (let i = 1; i < data.length; i++) {
      products.push({
        name: data[i][0],
        price: data[i][1]
      });
    }

    return ContentService
      .createTextOutput(JSON.stringify(products))
      .setMimeType(ContentService.MimeType.JSON);
  }

  return ContentService.createTextOutput("Invalid request");
}

function doPost(e) {

  //เขียนต่อจาก Code Flex Message ข้อ 3.1 เพราะจะใช้ doPost ด้วยกันทั้งหมด กรณีเรียกเข้ามาด้วย POST Method
  const data = JSON.parse(e.postData.contents);
  const userId = data.userId;
  const order = data.order;

  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Orders');
  const today = new Date();
  const items = ""

  order.map(item => 
      items += `${item.name} จำนวน ${item.quantity} กก. ราคา = ${item.price * item.quantity} บาท\n`
      sheet.appendRow([
        today, 
        userId, 
        item.name,
        item.quantity,
        item.price,
        item.quantity * item.price
      ]);
  );

  // 2. Notify LINE Group
  const messageToGroup = `📦 มีออเดอร์ใหม่จากลูกค้า\n📋 รายการผัก \n${items}`;
  pushGroupMessage(messageToGroup);

  // 3. Reply to LINE User
  const messageToUser = `✅ คุณได้สั่งผักเรียบร้อยแล้ว\n📋 รายการผัก \n ${items}\nขอบคุณที่สั่งกับเรา!`;
  pushUserMessage(userId, messageToUser);

  return ContentService.createTextOutput("OK");
}

function pushUserMessage(to, msg) {
  const payload = JSON.stringify({
    to,
    messages: [{
      type: "text",
      text: msg
    }]
  });

  UrlFetchApp.fetch("https://api.line.me/v2/bot/message/push", {
    method: "post",
    headers: {
      "Content-Type": "application/json",
      "Authorization": "Bearer " + LINE_TOKEN
    },
    payload
  });
}

function pushGroupMessage(message) {
  const groupId = PropertiesService.getScriptProperties().getProperty("LINE_GROUP_ID");

  if (!groupId) {
    Logger.log("❗ ยังไม่มี groupId กรุณาเชิญบอทเข้ากลุ่มและส่งข้อความ 1 ครั้งก่อน");
    return;
  }

  const payload = {
    to: groupId,
    messages: [{ type: "text", text: message }]
  };

  const options = {
    method: "post",
    contentType: "application/json",
    headers: { Authorization: LINE_TOKEN },
    payload: JSON.stringify(payload)
  };

  UrlFetchApp.fetch("https://api.line.me/v2/bot/message/push", options);
}

ใน Google App Script เรา New deployment ไปแล้วในข้อ 3. เพื่อไม่ให้ต้องแก้ไข GAS URL ใน HTML บ่อยๆ เพราะทุกครั้งที่ New deployment จะได้ URL ใหม่เสมอ รอบนี้ให้เลือก

Manage deployment -> กดรูปดินสอ -> Version เลือก New version -> กรอก Description > กด Deploy

แบบนี้เราจะใช้ GAS URL ที่ Deploy รอบแรกได้เลยไม่ต้องอัพเดต URL ทุกครั้ง

  • doGet() สำหรับหน้าเว็บเรียกดูรายการผัก
  • doPost() สำหรับรับออเดอร์จากเว็บ → บันทึก → แจ้งเตือน → ตอบกลับ
  • pushUserMessage() ฟังก์ชันที่ใช้ส่งข้อความไปยัง LINE ลูกค้า
  • pushGrouoMessage() ฟังก์ชันที่ใช้ส่งข้อความไปยัง LINE Group ที่มี LINE OA อยู่ด้วย

LINE_TOKEN และ LINE_GROUP_ID เอามาจากไหน ? อยู่ในขั้นตอนต่อไป


. . .

5. วิธีหา LINE Channel Access Token และ LINE Group ID

LINE Channel Access Token

  1. ไปที่ LINE Developers Console
  2. เลือก Provider > Messaging API channel ที่คุณสร้างไว้
  3. ไปที่แท็บ Messaging API
  4. เลื่อนลงมาจนเจอหัวข้อ Channel access token (long-lived)
  5. กด Issue เพื่อสร้าง token (หรือ Copy ถ้ามีอยู่แล้ว)

LINE Group ID

LINE ไม่เปิดให้ดู Group ID ตรง ๆ จาก UI แต่มีวิธีขอจาก LINE OA โดยตรง

  1. แก้ไข doPost ตามนี้ คือการ Setup event.source.groupId เข้าไปใน LINE_GROUP_ID และ Deploy อีกครั้ง
function doPost(e) {
  //...

  //ใส่ไว้บนสุดก่อน If Flex Message
  if (event.source.type === 'group') {
    PropertiesService.getScriptProperties().setProperty("LINE_GROUP_ID", event.source.groupId);
    Logger.log("Group ID: " + event.source.groupId);
  }

  //...
}
  1. LINE Developer Console ตั้งค่า Webhook URL ไปที่ Messaging API -> Webhook settings -> Webhook URL ของ LINE ไปที่ Google Apps Script เอา URL https://script.google.com/macros/s/.../exec มาใส่
  2. เชิญ LINE OA ของคุณเข้าไปใน LINE Group (ที่ใช้แจ้งเตือนออเดอร์)
  3. ส่งข้อความใดก็ได้ใน Group
  4. แค่นี้ก็จะได้ Group ID เข้าไปอยู่ใน LINE_GROUP_ID แล้วครับ

. . .

6. ทดสอบ

  • เข้า LINE OA กด Rich Menu สั่งผัก
  • LINE OA ส่ง Flex Message กลับมา
  • กดปุ่ม 'สั่งผักวันนี้' ใน Flex Message
  • แสดงหน้า HTML ที่เรา Deploy ไว้ที่ Github Pages
  • หน้า HTML ต้องแสดงรายการผักจาก Google Sheet ได้ถูกต้อง
  • ลองกรอกข้อมูลสั่งผัก และกดยืนยัน
  • Sheet Orders ใน Google Sheet จะต้องมีรายการผักที่เราสั่งเข้าไป
  • LINE OA ต้องตอบเรากลับมาว่า สั่งผักเรียบร้อยแล้ว...
  • LINE Group ต้องมี LINE OA บอกว่า มีรายการสั่งผักใหม่เข้ามา...

แนวทางต่อยอดระบบนี้

💡 1. เพิ่มระบบ “ดูรายการที่เคยสั่ง” ใน Rich Menu ดึงจาก Google Sheet Orders มาแสดงแบบ Table

💡 2. เพิ่มระบบสมาชิก / โปรไฟล์ เช็กเบอร์โทร / ที่อยู่จัดส่ง โดยใช้ LINE Profile API

💡 3. จัดการรายการสินค้าแบบมีสต็อก เพิ่มคอลัมน์ “จำนวนคงเหลือ” ใน Google Sheet Productlist แล้วหักออกหลังจากมีออเดอร์

💡 4. เชื่อมชำระเงิน ส่งลิงก์ PromptPay QR Code หรือ LINE Pay ให้กับคนสั่งสินค้าหลังจากสั่งสินค้าสำเร็จ

💡 5. สร้างใบส่งสินค้าหรือใบเสร็จรายวัน กรณีที่มีออเดอร์ Google App Script มีระบบ Trigger สามารถตั้งเวลาให้สร้างเอกสารได้ทุกวัน และจัดเก็บไว้ในโฟลเดอร์ Google Drive

💡 6. ทำระบบติดตามยอดค้างชำระ เมื่อครบกำหนดชำระ แต่ยังไม่มีการชำระเงินเข้ามา กรณีลูกค้าชำระแบบเครดิต LINE OA จะเช็คสถานะการชำระเงินใน Google Sheet ทุกวัน ถ้ายังไม่ชำระ จะส่งข้อความหาผู้สั่งซื้อ ว่ามียอดค้างชำระ


ถ้าใครลองทำแล้วติดปัญหาหรือมีข้อสงสัยเพิ่มเติม หรือผมตกหล่นส่วนไหนไป คอมเม้นกันเข้ามาได้เลยครับ 😎👇🏻

หรือถ้าสนใจอยากมีระบบแบบนี้เอาไว้ให้กับธุรกิจของตัวเอง ติดต่อเข้ามาได้ครับ Facebook