Swagger API 文檔
完整的 API 規格、參數說明,可直接測試 API
登入 MCC Manager,建立群組和服務,取得整合所需的參數。
service_suuid、GROUP_JWT、SERVICE_CODEredirect_uri 加入白名單(需完全匹配)
在 MCC Manager 中啟用並設定 Google / LINE / Facebook 登入。
https://members.managers.center/auth/idp/{provider}/callbackgoogle、line、facebook
前端導向 MCC 啟動登入,處理回調取得 code,再由後端兌換憑證。
GET /auth/idp/{provider}/startresponse_mode=code(安全性最高)
| 參數 | 說明 | 使用位置 |
|---|---|---|
service_suuid |
服務識別碼 | 前端 |
redirect_uri |
登入完成後的回調網址 | 前端 |
GROUP_JWT |
群組 Bearer Token | 後端 |
SERVICE_CODE |
服務代碼(X-Service-Code) | 後端 |
⚠️ GROUP_JWT 和 SERVICE_CODE 是敏感資訊,務必存放在後端環境變數中!
const MCC_BASE = 'https://members.managers.center';
const SERVICE_SUUID = 'your-service-suuid';
const REDIRECT_URI = 'https://your-site.com/callback';
function loginWith(provider) {
const params = new URLSearchParams({
service_suuid: SERVICE_SUUID,
redirect_uri: REDIRECT_URI,
response_mode: 'code'
});
window.location.href =
`${MCC_BASE}/auth/idp/${provider}/start?${params}`;
}
// callback.html - 先檢查錯誤,再處理 code
const params = new URLSearchParams(location.search);
const error = params.get('error');
const errorDescription = params.get('error_description');
const provider = params.get('provider');
if (error === 'idp_not_configured') {
showMessage(`${provider || '該'} 登入尚未設定,請使用其他方式`);
return;
}
if (error) {
showMessage(errorDescription || '登入發生錯誤');
return;
}
const code = params.get('code');
if (code) {
// 將 code 送給後端兌換
fetch('/api/auth/exchange', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ code })
}).then(r => r.json())
.then(data => {
if (data.success) {
localStorage.setItem('member_suuid', data.data.member_suuid);
localStorage.setItem('access_token', data.data.accessToken);
}
});
}
const MCC_BASE = 'https://members.managers.center';
const GROUP_JWT = process.env.GROUP_JWT; // 從環境變數取得
const SERVICE_CODE = process.env.SERVICE_CODE;
app.post('/api/auth/exchange', async (req, res) => {
const { code } = req.body;
const response = await fetch(`${MCC_BASE}/auth/idp/exchange`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${GROUP_JWT}`,
'X-Service-Code': SERVICE_CODE,
'Content-Type': 'application/json'
},
body: JSON.stringify({ code })
});
const data = await response.json();
res.json(data); // { success: true, data: { member_suuid, accessToken } }
});
// 驗證會員 accessToken 是否有效
app.post('/api/member/check', async (req, res) => {
const { member_suuid, access_token } = req.body;
const response = await fetch(`${MCC_BASE}/member/check`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${GROUP_JWT}`,
'X-Service-Code': SERVICE_CODE,
'X-Member-Suuid': member_suuid,
'X-Member-Access-Token': access_token,
'Content-Type': 'application/json'
}
});
const data = await response.json();
// { success: true, data: { member_suuid, email, display_name, ttl, ... } }
res.json(data);
});
整合時請根據以下錯誤情境進行處理。完整 API 錯誤規格請參考 Swagger 文檔。
| 情境 | HTTP | 回應形式 | error / 參數 | 說明 |
|---|---|---|---|---|
| 缺 service_suuid | 400 | JSON/HTML | BAD_REQUEST | missing service_suuid |
| 缺 redirect_uri | 400 | JSON/HTML | BAD_REQUEST | missing redirect_uri |
| 找不到 service | 404 | JSON/HTML | NOT_FOUND | service not found |
| redirect_uri 未白名單 | 400 | JSON/HTML | BAD_REQUEST | redirect_uri not allowed |
| IdP 未設定 | 302 | 導回 redirect_uri | error=idp_not_configured, error_description, provider | 用戶會被導回前端 callback,需解析 query |
⚠️ IdP 未設定時會 302 導回 redirect_uri 並帶 error、error_description、provider,前端 callback 必須先檢查這些參數。
| 情境 | HTTP | error | 說明 |
|---|---|---|---|
| 缺 code 或 state | 400 | BAD_REQUEST | missing code/state |
| state 無效 | 400 | BAD_REQUEST | invalid state |
| IdP 未回傳 email | 400 | BAD_REQUEST | IdP did not provide email |
| 內部錯誤 | 500 | INTERNAL_ERROR | callback error |
| 情境 | HTTP | error | details.reason |
|---|---|---|---|
| 無效 code | 400 | BAD_REQUEST | field: code |
| code 已用或過期 | 410 | GONE | code_consumed_or_expired |
| 群組不符 | 403 | FORBIDDEN | group_mismatch |
| 服務不符 | 403 | FORBIDDEN | service_mismatch |
| 內部錯誤 | 500 | INTERNAL_ERROR | internal |
| 情境 | HTTP | error | details.reason |
|---|---|---|---|
| 會員不存在 | 404 | NOT_FOUND | member_not_found |
| 密碼錯誤 | 401 | UNAUTHORIZED | invalid_password |
| 帳號停用 | 403 | FORBIDDEN | account_disabled |
| 欄位驗證失敗 | 400 | BAD_REQUEST | field: ... |
{ success: true, data: {...}, messages: [...] }{ success: false, error: "ERROR_CODE", messages: [...], details?: { reason, field, ... } }redirect_uri?error=idp_not_configured&error_description=...&provider=lineGROUP_JWT 和 SERVICE_CODE 只能存放在後端環境變數,切勿暴露給前端
response_mode=code,避免 token 暴露在 URL 中