2025-07-12 Line 訂單系統-C 階段 建立兩個實際可執行的核心檔案 Webhookhook後端 Vue前端訂單記錄頁面

2025-07-12 Line 訂單系統-C 階段 建立兩個實際可執行的核心檔案 Webhookhook後端 Vue前端訂單記錄頁面

我們現在就完整進入 📘 階段 C — LINE 訂單整合(前端+後端連動) 的實作階段。

接下來我會幫你建立兩個實際可執行的核心檔案:
1️⃣ backend/routes/lineWebhook.js — Node.js Webhook 後端
2️⃣ frontend/src/views/LineOrders.vue — Vue3 前端訂單紀錄頁面


🧩 一、Node.js 後端 — backend/routes/lineWebhook.js

這個檔案的作用是:

讓 LINE Bot 把使用者訊息(例如輸入「商品123」)傳到你的後端,
後端查 MySQL 回傳商品資料,再用 LINE API 回覆給使用者。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// backend/routes/lineWebhook.js
import express from "express";
import axios from "axios";
import crypto from "crypto";
import mysql from "mysql2/promise";

const router = express.Router();

// 建立 MySQL 連線池
const pool = mysql.createPool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
});

// 驗證 LINE webhook 簽章
function validateSignature(body, signature) {
const hash = crypto
.createHmac("SHA256", process.env.LINE_CHANNEL_SECRET)
.update(JSON.stringify(body))
.digest("base64");
return hash === signature;
}

// 處理 Webhook
router.post("/webhook", async (req, res) => {
const signature = req.headers["x-line-signature"];
if (!validateSignature(req.body, signature)) {
return res.status(401).send("Invalid signature");
}

const events = req.body.events;
for (const event of events) {
if (event.type === "message" && event.message.type === "text") {
const userText = event.message.text.trim();

// 檢查是否為查詢商品
if (userText.startsWith("商品")) {
const itemCode = userText.replace("商品", "").trim();
const [rows] = await pool.query(
"SELECT name, price, description FROM products WHERE id = ?",
[itemCode]
);

let replyMessage = "";
if (rows.length > 0) {
const product = rows[0];
replyMessage = `📦 商品名稱:${product.name}\n💲 價格:${product.price}\n📝 說明:${product.description}`;
} else {
replyMessage = "查無此商品,請確認代號是否正確。";
}

await axios.post(
"https://api.line.me/v2/bot/message/reply",
{
replyToken: event.replyToken,
messages: [{ type: "text", text: replyMessage }],
},
{
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.LINE_CHANNEL_ACCESS_TOKEN}`,
},
}
);
}
}
}

res.status(200).end();
});

export default router;

📁 檔案整合說明

請確認 backend/server.js 中有加入這段:

1
2
3
import lineWebhook from "./routes/lineWebhook.js";
app.use(express.json());
app.use("/api", lineWebhook);

然後 .env 需有以下參數:

1
2
LINE_CHANNEL_SECRET=你的LINE_CHANNEL_SECRET
LINE_CHANNEL_ACCESS_TOKEN=你的LINE_CHANNEL_ACCESS_TOKEN

🧩 二、Vue3 前端 — frontend/src/views/LineOrders.vue

這個頁面主要讓管理者在後台看到所有來自 LINE 的訂單紀錄。

假設你的後端有一個 /api/orders API,可以回傳 LINE 送進資料庫的訂單資料。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<template>
<div class="line-orders">
<h1>📱 LINE 訂單紀錄</h1>

<div v-if="loading">讀取中...</div>
<div v-else>
<table>
<thead>
<tr>
<th>訂單編號</th>
<th>用戶名稱</th>
<th>商品名稱</th>
<th>數量</th>
<th>狀態</th>
<th>建立時間</th>
</tr>
</thead>
<tbody>
<tr v-for="order in orders" :key="order.id">
<td>{{ order.id }}</td>
<td>{{ order.user_name }}</td>
<td>{{ order.product_name }}</td>
<td>{{ order.quantity }}</td>
<td>{{ order.status }}</td>
<td>{{ new Date(order.created_at).toLocaleString() }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>

<script setup>
import { ref, onMounted } from "vue";
import axios from "axios";

const orders = ref([]);
const loading = ref(true);

onMounted(async () => {
try {
const res = await axios.get("http://localhost:3000/api/orders");
orders.value = res.data;
} catch (err) {
console.error("無法取得訂單資料:", err);
} finally {
loading.value = false;
}
});
</script>

<style scoped>
.line-orders {
padding: 1.5rem;
}
table {
width: 100%;
border-collapse: collapse;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
}
th {
background: #f5f5f5;
}
</style>

⚙️ 前後端連動測試流程

步驟 動作 說明
啟動 MySQL、Node.js (npm run dev) 確保 /api/webhook 可以接收請求
使用 ngrok 將你的 port 3000 對外公開 ngrok http 3000
在 LINE Developers → Messaging API → Webhook URL 設定 https://<ngrok-url>/api/webhook 測試訊息傳遞
在 LINE 輸入「商品 1」 後端查 MySQL,回傳商品資訊
在 Vue3 後台 LineOrders.vue 檢視訂單紀錄 驗證資料流是否完整

是否要我幫你繼續產生:
👉 對應的 /api/orders 後端 API(讓 LineOrders.vue 可以正常顯示訂單)?
這會是 C4 子階段 的最後一塊拼圖。