在一個完整的會員系統中,除了會員通知外,還需要讓管理員具備 一對多的公告能力,例如:系統維護公告、活動通知、緊急訊息。若沒有集中化的公告管道,管理員可能需要透過多種工具分別通知會員,既容易出錯,也難以統一管理。
透過 API Gateway x SNS / SES,可以實現由管理員後台統一發布公告,並自動推送到 Email 或其他通道。
此 Lab 的定位是 後台訊息發布模組,解決以下痛點:
(1) 管理員公告缺乏集中化,造成通知延遲與不一致。
(2) 難以跨管道(Email / SMS / Push)同時發布訊息。
(3) 缺乏彈性與稽核機制,難以追蹤誰發布了公告。
在整體 Serverless 架構中,它屬於 系統後台模組,負責公告訊息的統一入口,並整合至既有會員通知通道(SES / SNS)。
Admin
角色的使用者能呼叫公告 API。createdBy
、createdAt
,方便後續追蹤。進入「SNS」頁面。
點選「建立主題 (Create topic)」。
選擇「標準」類型,並創建主題。
建立完成。
選擇剛建立的 SNS 主題(Topic)。
點擊 「建立訂閱 (Create subscription)」。
新增訂閱者的電子信箱。
創建完成。
確認:該收件信箱將收到一封確認信,請務必點擊信中的連結來啟用訂閱。
點擊確認連結後的畫面。
完成驗證。
進入「Lambda」頁面。
創建一個新的函數。
輸入函數名稱,並選擇編撰語言。
跳過建議畫面。
寫入程式碼,並部署。
程式碼範例
// index.mjs (使用 Node.js SDK v3)
import { SNSClient, PublishCommand } from "@aws-sdk/client-sns";
const snsClient = new SNSClient({ region: process.env.AWS_REGION });
const TOPIC_ARN = process.env.SNS_TOPIC_ARN;
if (!TOPIC_ARN) {
// 確保環境變數已設定
throw new Error('Environment variable SNS_TOPIC_ARN must be set.');
}
export const handler = async (event) => {
try {
// 1. 解析 API Gateway 傳入的 JSON Body
const requestBody = JSON.parse(event.body);
// 2. 構造訊息 Payload
const messagePayload = {
subject: requestBody.subject || '系統通知',
content: requestBody.message || '沒有內容的公告。',
// 嘗試從 API Gateway Context 獲取管理員資訊
createdBy: event.requestContext?.authorizer?.claims?.['cognito:username'] || 'Admin Portal',
createdAt: new Date().toISOString()
};
// 3. 構造 SNS Publish 參數
const params = {
TopicArn: TOPIC_ARN,
Subject: `系統公告: ${messagePayload.subject}`,
MessageStructure: "json",
Message: JSON.stringify({
default: messagePayload.content, // 給 SMS、SQS 等用
email: messagePayload.content, // Email 訂閱者只收到這段
sms: messagePayload.content // 簡訊可用
}),
};
// 4. 發布訊息
const command = new PublishCommand(params);
await snsClient.send(command);
console.log("✅ Announcement successfully published to SNS.");
return {
statusCode: 200,
body: JSON.stringify({ status: "success", message: "Announcement published" }),
};
} catch (error) {
console.error("❌ Failed to process or publish announcement:", error);
return {
statusCode: 500,
body: JSON.stringify({ status: "error", message: error.message || "Internal server error." }),
};
}
};
進入「組態」分頁,設定環境變數。
變數key「SNS_TOPIC_ARN」,Value為你在 SNS 的ARN。
進入「IAM 」頁面。
進入IAM role的頁面,點選該Lambda自動創建的IAM role。
新增「許可政策」。
增加SNS的「Publish」權限。
授權範圍為指定的SNS。
點選下一步。
設定「許可政策」名稱。
完成畫面。
進入「API Gateway」頁面。
進入之前創建的HTTP API Gateway中。
建立新的路由路徑。
設定動作為「POST」,路徑可以自定義。
設定整合的配置。
選擇剛剛創建的Lambda函數。
完成畫面。
透過終端機(terminal)向Cognito取得 session
。
第一段:
aws cognito-idp initiate-auth \
--auth-flow USER_PASSWORD_AUTH \
--client-id <Cognito_APP_CLIENT_ID> \
--auth-parameters USERNAME=<username>,PASSWORD=<password>
透過終端機(terminal),用 session
向Cognito拿到對應的 IdToken
或 AccessToken
。
第二段
aws cognito-idp respond-to-auth-challenge \
--client-id <Cognito_APP_CLIENT_ID> \
--challenge-name SOFTWARE_TOKEN_MFA \
--session <上一步回傳的Session> \
--challenge-responses USERNAME=<username>,SOFTWARE_TOKEN_MFA_CODE=<六位數驗證碼>
範例程式碼
# 替換 YOUR_API_ENDPOINT 和 YOUR_TOKEN
API_URL="https://YOUR_API_ID.execute-api.YOUR_REGION.amazonaws.com/prod/announce"
ADMIN_TOKEN="YOUR_ACTUAL_JWT_TOKEN"
curl -X POST \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"subject": "系統緊急維護", "message": "服務將於 15 分鐘後停機,請提前儲存您的資料。"}' \
"$API_URL"
API 回應:您應收到 HTTP 200
和 JSON Body:{"status": "success", "message": "Announcement published"}
。
Lambda Logs:檢查 CloudWatch Logs for PublishAnnouncement
函數,確認 Log 顯示 ✅ Announcement successfully published to SNS.
。
(1) 進到Lambda對應的CloudWatch頁面。
(2) 進到最近一筆的Log紀錄內。
(3) 有看到已經成功寄出。
Email 驗證:檢查信件,主旨為:系統公告: 系統緊急維護
,內容為一個 JSON 格式的訊息。
今天的 Lab 建立了一個 集中化的管理員公告系統,讓管理員能透過 Portal 發布公告,並由 SNS 自動分發至 Email(SES)或其他管道。這樣的架構解決了公告散亂、無法追蹤的問題,同時具備可擴充性,未來可支援多種通知通道,形成一個可靠的 系統訊息廣播中樞。