iT邦幫忙

2025 iThome 鐵人賽

DAY 24
0
Build on AWS

從一個網站的誕生,看懂 AWS 架構與自動化的全流程!系列 第 24

Day 24 多管道通知整合:SNS x Lambda 打造訊息廣播系統(LINE)

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20251008/20172743L1EUezRvXi.png

一、前言

在會員系統中,通知功能不應侷限於單一管道,使用者可能需要透過 Email、SMS、App 推播甚至 Slack/LINE Bot 等方式接收訊息。透過 Amazon SNS 搭配 Lambda,可以建立一個彈性、可擴充的多管道廣播系統,確保訊息能快速傳遞給正確的目標。

這個 Lab 解決的痛點是「多管道通知」的彈性與一致性。若單純用 SES 只能發 Email,用 SMS API 成本與整合不易,而 SNS 作為中心化通知 Hub,可以輕鬆整合不同訂閱端點。Lambda 則能作為橋樑,將訊息轉換並發送到客製化的外部系統(如 Slack、LINE)。在整體 Serverless 架構中,它是「通知中樞」,串接使用者事件與外部通道。

二、需要使用到的服務

  • Amazon SNS:作為訊息主題 (Topic),管理多個訂閱者。
  • AWS Lambda:作為訊息轉換器與推送外部服務的橋樑。
  • Amazon SES / SMS(或外部 API):分別用於 Email 與 SMS 通知。
  • CloudWatch Logs:監控 Lambda 執行狀態,便於除錯。
  • LINE API:由LINE官方提供的API,可以串接訊息。

三、架構/概念圖

https://ithelp.ithome.com.tw/upload/images/20251008/20172743XePHKLMSC7.png

四、技術重點

  1. 使用 Filter Policy 避免所有訂閱者都收到相同訊息,可根據通知類型(活動、警告、公告)過濾。
  2. Lambda 中應加入 重試機制與錯誤處理,避免外部 API 失敗造成訊息遺失。
  3. 針對高頻率事件,可以考慮批次聚合後再通知,降低干擾與成本。
  4. 使用 CloudWatch MetricsSNS Dead-Letter Queue (DLQ),確保失敗訊息能被追蹤。

五、Lab流程

1️⃣ 前置作業

1. 創建一個 Lambda (有存取 SNS、CloudWatch、SES 的權限)

2. 驗證 SES 發信 Email Domain 或 Sender。

3. 創建一個 SNS Topic,且用SES驗證過的信箱訂閱。(Day23)

2️⃣ 主要配置

1. 啟用LINE API

  1. 登入LINE官方帳號:https://tw.linebiz.com/login/。
    https://ithelp.ithome.com.tw/upload/images/20251008/20172743PTooIkKmzz.png

  2. 選擇要開通API的官方帳號。(這會需要自行創建)
    https://ithelp.ithome.com.tw/upload/images/20251008/20172743TSB1zbfjnT.png

  3. 進入API頁面,並點選「啟用」。
    https://ithelp.ithome.com.tw/upload/images/20251008/2017274364IR6OPmH3.png

  4. 創建一個「服務提供者」。
    https://ithelp.ithome.com.tw/upload/images/20251008/20172743eFF5jM7cat.png

  5. 這邊先略過。
    https://ithelp.ithome.com.tw/upload/images/20251008/20172743fdA5UTiyQG.png

  6. 點選確認啟用。
    https://ithelp.ithome.com.tw/upload/images/20251008/20172743VarbbQFwDd.png

  7. 啟用完成畫面。
    https://ithelp.ithome.com.tw/upload/images/20251008/20172743zO1wmO1Wer.png

2. 進入LINE研發頁面,獲取API Access Token

  1. 進入LINE的研發頁面:https://developers.line.biz/console/
    https://ithelp.ithome.com.tw/upload/images/20251008/20172743B0Ek0Ap8wI.png

  2. 登入帳號。
    https://ithelp.ithome.com.tw/upload/images/20251008/20172743e27LQnHR6B.png

  3. 進入剛剛創建的API中。
    https://ithelp.ithome.com.tw/upload/images/20251008/20172743AeceNCXaNf.png

  4. 進入API頁面,並創建Access Token(長時間有效的)。
    https://ithelp.ithome.com.tw/upload/images/20251008/20172743Zvkb1qE10o.png

  5. 將Access Token複製下來。(後面Lambda的環境變數會使用)
    https://ithelp.ithome.com.tw/upload/images/20251008/20172743mG8M8wmjG5.png

  6. 也把user ID複製下來。(後面Lambda的環境變數會使用)
    https://ithelp.ithome.com.tw/upload/images/20251008/201727434vkSsVKQ5z.png

3. 創建Lambda程式碼(觸發LINE API)

  1. 進入「Lambda」頁面。
    https://ithelp.ithome.com.tw/upload/images/20251008/2017274392ZLucZcA3.png

  2. 創建一個新的函數。
    https://ithelp.ithome.com.tw/upload/images/20251008/20172743sC2X4csChN.png

  3. 輸入函數名稱,並選擇編撰語言。
    https://ithelp.ithome.com.tw/upload/images/20251008/20172743HxeqXCMq1R.png

  4. 跳過建議畫面。
    https://ithelp.ithome.com.tw/upload/images/20251008/20172743YKbEnWHYde.png

  5. 寫入程式碼,並部署。

    • 程式碼範例

      // index.mjs (LINE Notifier - SNS Subscriber)
      
      const LINE_TOKEN = process.env.LINE_CHANNEL_ACCESS_TOKEN;
      const LINE_USER_ID = process.env.LINE_USER_ID;
      const LINE_PUSH_URL = "https://api.line.me/v2/bot/message/push"; // 使用 LINE Messaging API Push URL
      
      if (!LINE_TOKEN || !LINE_USER_ID) {
          throw new Error('LINE_TOKEN and LINE_USER_ID environment variables must be set.');
      }
      
      export const handler = async (event) => {
        try {
          // SNS 會將訊息放在 event.Records[0].Sns.Message 中,解析 SNS 事件,提取 --message 內容
          const snsRecord = event.Records[0];
          const incomingMessage = snsRecord.Sns.Message; 
      
          // 檢查訊息是否為 JSON 格式(如果您用 CLI 傳送純文字,這裡可以直接用;如果是 JSON 則需要解析)
          let messageText = incomingMessage; 
      
          try {
              // 嘗試解析 JSON 格式 (如果 SNS 發送的是複雜 JSON)
              const parsedMessage = JSON.parse(incomingMessage);
              // 如果是 JSON,我們假設純文字內容在 'content' 屬性中
              messageText = parsedMessage.content || incomingMessage; 
          } catch (e) {
              // 如果解析失敗,則它就是純文字,保持 messageText 不變
          }
      
          // 2. 🎯 使用解析後的訊息內容替換硬編碼
          const messageToSend = `🔔 系統通知:${messageText}`;
      
          const res = await fetch(LINE_PUSH_URL, { // 使用修正後的 URL 變數
            method: "POST",
            headers: {
              "Content-Type": "application/json",
              "Authorization": `Bearer ${LINE_TOKEN}`,
            },
            body: JSON.stringify({
              to: LINE_USER_ID,
              messages: [
                {
                  type: "text",
                  text: messageToSend, // 傳送從 SNS 獲取的內容
                },
              ],
            }),
          });
      
          if (!res.ok) {
            const errText = await res.text();
            console.error("LINE API error:", errText);
            throw new Error(errText);
          }
      
          console.log(`✅ LINE message sent successfully: ${messageText}`);
          return {
            statusCode: 200,
            body: JSON.stringify({ message: "LINE message sent" }),
          };
        } catch (err) {
          console.error("❌ Lambda failed:", err);
          return {
            statusCode: 500,
            body: JSON.stringify({ error: err.message }),
          };
        }
      };
      

    https://ithelp.ithome.com.tw/upload/images/20251008/20172743OwAxWzA7sk.png

  6. 進入「組態」分頁,設定環境變數。
    https://ithelp.ithome.com.tw/upload/images/20251008/201727433wY1KsrXqK.png

  7. 設定以下環境變數:
    LINE_USER_ID = <要發訊息的目標 LINE userId>
    LINE_CHANNEL_ACCESS_TOKEN = <你剛產生的 LINE access token>
    https://ithelp.ithome.com.tw/upload/images/20251008/20172743u2PQiQhSpi.png

  8. 完成畫面。
    https://ithelp.ithome.com.tw/upload/images/20251008/20172743e64nkZW9E5.png

5. 讓SNS串接Lambda(Lambda訂閱SNS Topic)

  1. 進入「SNS」頁面。
    https://ithelp.ithome.com.tw/upload/images/20251008/201727438JvGsgiiNt.png

  2. 進到Day23創建的主題中。
    https://ithelp.ithome.com.tw/upload/images/20251008/20172743ImJfGAVMqV.png

  3. 建立一個新的訂閱。
    https://ithelp.ithome.com.tw/upload/images/20251008/20172743LpFotaA9CE.png

  4. 設定Lambda函數。
    https://ithelp.ithome.com.tw/upload/images/20251008/20172743kZsAZQKQ3d.png

  5. 完成畫面。
    https://ithelp.ithome.com.tw/upload/images/20251008/20172743H3T5Ei691Y.png

3️⃣ 測試驗證

1. 使用AWS CLI ,將內容發布到SNS Topic

https://ithelp.ithome.com.tw/upload/images/20251008/20172743qm1OqjtiYn.png

2. 收到E-mail通知(Day23完成的部分)

https://ithelp.ithome.com.tw/upload/images/20251008/20172743OqnjZI2M1S.png

3. 同時也收到LINE通知

https://ithelp.ithome.com.tw/upload/images/20251008/20172743IEljRCwqS1.png

六、結語

今天的 Lab 展示了如何透過 SNS 作為多管道通知核心,並搭配 Lambda 擴充整合外部服務,實現 Email、SMS、Slack/LINE 等多樣化的通知廣播。這不僅提升了系統的互動性,也讓管理員能更彈性地設計通知流程,在安全性、成本與維護性上取得平衡。


上一篇
Day 23 管理員公告系統:API Gateway x SNS / SES 訊息發布
系列文
從一個網站的誕生,看懂 AWS 架構與自動化的全流程!24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言