在前幾天,我們已經完成了訂單建立、狀態更新與通知 Worker。
但你可能會發現一個問題:
目前的通知只有單向——要嘛通知顧客、要嘛通知管理者。
今天,我們要升級成「雙向通知系統」,讓同一筆訂單能同時通知 顧客與群組,但推播的內容又能依角色不同而有所區分。
在實務中,通知的對象不只一種:
顧客端:需要知道訂單進度,例如「您的飲品已完成,請準備取餐」。
店家端(群組):需要接收摘要通知,例如「新訂單 #125,紅茶拿鐵 x2,外送」。
如果用相同訊息推播給兩邊,不僅顯得冗長,還容易造成資訊混亂。
因此,我們要打造一套可彈性推播的邏輯:根據接收者角色,動態產出不同訊息內容。
可以用一張簡單的流程圖來理解整體邏輯:
const GROUP_ID = process.env.LINE_GROUP_ID; // 管理群組
群組 ID 可以從 LINE Developers > Messaging API > Webhook events log 中取得。
Day 12 有提到過,大家可以去回顧一下!
顧客 userId 則是訂單中儲存的 userId
欄位。
我們可以建立一個通用的通知方法:
// src/utils/notificationService.js
const client = require('../lib/lineClient');
const buildUserMsg = require('./notifyUser');
const buildGroupMsg = require('./notifyGroup');
const logger = require('../lib/logger');
const GROUP_ID = process.env.LINE_GROUP_ID;
async function sendOrderNotification(order) {
const messages = [];
if (order.userId) {
messages.push(client.pushMessage(order.userId, buildUserMsg(order)));
}
if (GROUP_ID) {
messages.push(client.pushMessage(GROUP_ID, buildGroupMsg(order)));
}
try {
await Promise.all(messages);
logger.info(`[Notify] 成功通知 orderId=${order._id}`);
} catch (err) {
logger.error(`[NotifyError] orderId=${order._id}`, err);
}
}
module.exports = { sendOrderNotification };
這樣的設計能確保兩方都能即時獲得訊息,同時保持各自關心的重點內容。
無論你是在訂單建立的 API、或是 Redis Worker 中執行推播任務,
只要將訂單資料傳入 sendOrderNotification()
即可。
// Worker 例子
queue.process('notifyOrder', async (job) => {
const order = job.data;
try {
await sendOrderNotification(order);
console.log(`✅ 已通知顧客與群組:${order._id}`);
} catch (err) {
console.error(`❌ 通知失敗:${err.message}`);
}
});
若希望管理群組看到更清晰的訂單摘要,可以升級為 Flex Message:
const groupMessage = {
type: 'flex',
altText: '新訂單通知',
contents: {
type: 'bubble',
body: {
type: 'box',
layout: 'vertical',
contents: [
{ type: 'text', text: '🛍 新訂單', weight: 'bold', size: 'lg' },
{ type: 'text', text: `編號:${order._id}`, size: 'sm', color: '#888' },
{ type: 'text', text: `品項:${order.item} x${order.quantity}` },
{ type: 'text', text: `取貨方式:${order.pickupMethod}` },
{ type: 'text', text: `狀態:${order.status}`, color: '#0A84FF', weight: 'bold' },
],
},
},
};
推播容易出錯的情境包含:
使用者封鎖 BOT。
群組 ID 錯誤。
LINE Access Token 過期。
因此建議加上錯誤監控與日誌紀錄:
try {
await client.pushMessage(order.userId, userMessage);
} catch (err) {
console.error(`[UserNotifyError] userId=${order.userId}`, err);
}
try {
await client.pushMessage(GROUP_ID, groupMessage);
} catch (err) {
console.error(`[GroupNotifyError] groupId=${GROUP_ID}`, err);
}
完成後,我們可以看到:
顧客端會收到取貨提醒。
管理者群組則會收到完整訂單摘要。
這讓整個系統真正達到「雙向即時同步」的效果。
理解群組通知與個人通知的差異。
學會如何同時推播不同對象。
讓 Worker 根據角色產生不同的訊息內容。
為後續的金流、Webhook、自動通知打下基礎。
明天(Day 26),我們要進入管理介面的世界,
打造能查看完整訂單明細的 Dashboard,
讓整套系統正式邁向「可視化後台」階段!