# 租戶站台介接指引(Member Center + Send Engine) 此文件給**租戶站台**使用,描述如何: - 訂閱 / 確認 / 退訂 / 偏好管理(Member Center) - 建立發信任務(Send Engine) 不包含 Member Center ↔ Send Engine 的內部事件同步細節。 --- ## 1. 系統流程圖(租戶站台角度) ``` Tenant Site | | (1) Subscribe v Member Center | | (2) Send confirmation email v End User | | (3) Confirm link v Member Center Tenant Site | | (4) Request unsubscribe token v Member Center | | (5) Unsubscribe with token v Member Center Tenant Site | | (6) Create send job v Send Engine | | (7) Deliver via ESP v End User ``` --- ## 2. Auth / Scope(租戶站台) 租戶站台沒有真人帳號,使用 **Client Credentials** 取得 access token。 - 向 Member Center 申請 OAuth Client - OAuth Client 建議使用 `usage=send_api`(專供發送);`tenant_api` 留給其他租戶 API - scope 依用途最小化 建議 scopes: - `newsletter:send.write`(Send Engine 建立發信任務) - `newsletter:send.read`(查詢發信狀態,若需要) > Send Engine 會驗證 token 內的 `tenant_id` 與 scope。 ### 取得 Token(範例) ```bash curl -s -X POST https://{member-center}/oauth/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials&client_id=&client_secret=&scope=newsletter:send.write" ``` ### 使用 Token(範例) ```bash curl -s -X POST https://{send-engine}/api/send-jobs \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ \"tenant_id\": \"\", \"list_id\": \"\", \"subject\": \"Weekly\", \"body_text\": \"Hello\" }' ``` ### Send Engine 驗證 Token(JWT / JWKS) - Send Engine 以 Member Center 的 JWKS 驗簽 access token(JWS)。 - 驗證重點:`iss`、`aud`、`scope`、`tenant_id`、`exp`。 - `iss`:由 Member Center `Auth__Issuer` 設定(例:`http://localhost:7850/`) - `aud`:Send Engine 流程預設 `send_engine_api`(可用 `Auth__SendEngineAudience` 覆寫) --- ## 3. API 表格(租戶站台 → Member Center) | 功能 | Method | Path | 必填 | 說明 | |---|---|---|---|---| | 訂閱 | POST | `/newsletter/subscribe` | `list_id`, `email` | 回傳 `confirm_token` | | 確認訂閱 | GET | `/newsletter/confirm` | `token` | double opt-in 確認 | | 申請退訂 token | POST | `/newsletter/unsubscribe-token` | `list_id`, `email` | 回傳 `unsubscribe_token` | | 退訂 | POST | `/newsletter/unsubscribe` | `token` | 單一清單退訂 | | 讀取偏好 | GET | `/newsletter/preferences` | `list_id`, `email` | 需 list_id + email | | 更新偏好 | POST | `/newsletter/preferences` | `list_id`, `email`, `preferences` | 需 list_id + email | --- ### 訂閱(範例) ```bash curl -s -X POST https://{member-center}/newsletter/subscribe \ -H "Content-Type: application/json" \ -d '{ "list_id": "", "email": "user@example.com", "preferences": {"lang": "zh-TW"} }' ``` ### 申請退訂 token(範例) ```bash curl -s -X POST https://{member-center}/newsletter/unsubscribe-token \ -H "Content-Type: application/json" \ -d '{ "list_id": "", "email": "user@example.com" }' ``` ### 退訂(範例) ```bash curl -s -X POST https://{member-center}/newsletter/unsubscribe \ -H "Content-Type: application/json" \ -d '{ "token": "" }' ``` --- ## 4. API 表格(租戶站台 → Send Engine) | 功能 | Method | Path | 必填 | 說明 | |---|---|---|---|---| | 建立發信任務 | POST | `/api/send-jobs` | `list_id`, `subject`, `body_html/body_text` | 發送排程 | | 查詢發信任務 | GET | `/api/send-jobs/{id}` | `id` | 讀取狀態 | | 取消發信任務 | POST | `/api/send-jobs/{id}/cancel` | `id` | 取消發送 | ### 建立發信任務(範例) ```bash curl -s -X POST https://{send-engine}/api/send-jobs \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "tenant_id": "", "list_id": "", "name": "Weekly Update", "subject": "Weekly Update", "body_html": "

Hello

", "body_text": "Hello", "scheduled_at": "2026-02-11T02:00:00Z" }' ``` --- ## 5. 安全注意事項(租戶站台) - `list_id + email` 為租戶隔離最小邊界,必須一併提供 - 不要保存退訂 token;使用時再向 Member Center 申請 - Token 必須妥善保管,避免跨租戶濫用