147 lines
4.6 KiB
JavaScript
147 lines
4.6 KiB
JavaScript
// src/services/authService.js
|
||
/**
|
||
* 认证服务层 - 处理所有认证相关的 API 调用
|
||
*/
|
||
|
||
const isProduction = process.env.NODE_ENV === 'production';
|
||
const API_BASE_URL = isProduction ? "" : process.env.REACT_APP_API_URL;
|
||
|
||
/**
|
||
* 统一的 API 请求处理
|
||
* @param {string} url - 请求路径
|
||
* @param {object} options - fetch 选项
|
||
* @returns {Promise} - 响应数据
|
||
*/
|
||
const apiRequest = async (url, options = {}) => {
|
||
try {
|
||
const response = await fetch(`${API_BASE_URL}${url}`, {
|
||
...options,
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
...options.headers,
|
||
},
|
||
credentials: 'include', // 包含 cookies
|
||
});
|
||
|
||
// 检查响应是否为 JSON
|
||
const contentType = response.headers.get('content-type');
|
||
const isJson = contentType && contentType.includes('application/json');
|
||
|
||
if (!response.ok) {
|
||
let errorMessage = `HTTP error! status: ${response.status}`;
|
||
if (isJson) {
|
||
try {
|
||
const errorData = await response.json();
|
||
errorMessage = errorData.error || errorData.message || errorMessage;
|
||
} catch (parseError) {
|
||
console.warn('Failed to parse error response as JSON');
|
||
}
|
||
}
|
||
throw new Error(errorMessage);
|
||
}
|
||
|
||
// 安全地解析 JSON 响应
|
||
if (isJson) {
|
||
try {
|
||
return await response.json();
|
||
} catch (parseError) {
|
||
console.error('Failed to parse response as JSON:', parseError);
|
||
throw new Error('服务器响应格式错误');
|
||
}
|
||
} else {
|
||
throw new Error('服务器响应不是 JSON 格式');
|
||
}
|
||
} catch (error) {
|
||
console.error(`Auth API request failed for ${url}:`, error);
|
||
// 如果是网络错误,提供更友好的提示
|
||
if (error.message === 'Failed to fetch' || error.name === 'TypeError') {
|
||
throw new Error('网络连接失败,请检查网络设置');
|
||
}
|
||
throw error;
|
||
}
|
||
};
|
||
|
||
export const authService = {
|
||
/**
|
||
* 获取微信二维码授权链接(PC扫码登录)
|
||
* @returns {Promise<{auth_url: string, session_id: string}>}
|
||
*/
|
||
getWechatQRCode: async () => {
|
||
return await apiRequest('/api/auth/wechat/qrcode');
|
||
},
|
||
|
||
/**
|
||
* 获取微信H5授权链接(移动端网页授权)
|
||
* @param {string} redirectUrl - 授权成功后的回调地址
|
||
* @returns {Promise<{auth_url: string}>}
|
||
*/
|
||
getWechatH5AuthUrl: async (redirectUrl) => {
|
||
return await apiRequest('/api/auth/wechat/h5-auth', {
|
||
method: 'POST',
|
||
body: JSON.stringify({ redirect_url: redirectUrl }),
|
||
});
|
||
},
|
||
|
||
/**
|
||
* 微信H5授权回调处理
|
||
* @param {string} code - 微信授权code
|
||
* @param {string} state - 状态参数
|
||
* @returns {Promise<{success: boolean, user?: object, token?: string}>}
|
||
*/
|
||
handleWechatH5Callback: async (code, state) => {
|
||
return await apiRequest('/api/auth/wechat/h5-callback', {
|
||
method: 'POST',
|
||
body: JSON.stringify({ code, state }),
|
||
});
|
||
},
|
||
|
||
/**
|
||
* 检查微信扫码状态
|
||
* @param {string} sessionId - 会话ID
|
||
* @returns {Promise<{status: string, user_info?: object}>}
|
||
*/
|
||
checkWechatStatus: async (sessionId) => {
|
||
return await apiRequest('/api/auth/wechat/check', {
|
||
method: 'POST',
|
||
body: JSON.stringify({ session_id: sessionId }),
|
||
});
|
||
},
|
||
|
||
/**
|
||
* 使用微信 session 登录
|
||
* @param {string} sessionId - 会话ID
|
||
* @returns {Promise<{success: boolean, user?: object, token?: string}>}
|
||
*/
|
||
loginWithWechat: async (sessionId) => {
|
||
return await apiRequest('/api/auth/login/wechat', {
|
||
method: 'POST',
|
||
body: JSON.stringify({ session_id: sessionId }),
|
||
});
|
||
},
|
||
};
|
||
|
||
/**
|
||
* 微信状态常量
|
||
*/
|
||
export const WECHAT_STATUS = {
|
||
NONE: 'none',
|
||
WAITING: 'waiting',
|
||
SCANNED: 'scanned',
|
||
AUTHORIZED: 'authorized',
|
||
LOGIN_SUCCESS: 'login_success',
|
||
REGISTER_SUCCESS: 'register_success',
|
||
EXPIRED: 'expired',
|
||
};
|
||
|
||
/**
|
||
* 状态提示信息映射
|
||
*/
|
||
export const STATUS_MESSAGES = {
|
||
[WECHAT_STATUS.WAITING]: '请使用微信扫码',
|
||
[WECHAT_STATUS.SCANNED]: '扫码成功,请在手机上确认',
|
||
[WECHAT_STATUS.AUTHORIZED]: '授权成功,正在登录...',
|
||
[WECHAT_STATUS.EXPIRED]: '二维码已过期',
|
||
};
|
||
|
||
export default authService;
|