import { getApiBase } from '../utils/apiConfig'; // src/services/authService.js /** * 认证服务层 - 处理所有认证相关的 API 调用 */ import { logger } from '../utils/logger'; const isProduction = process.env.NODE_ENV === 'production'; const API_BASE_URL = getApiBase(); /** * 统一的 API 请求处理 * @param {string} url - 请求路径 * @param {object} options - fetch 选项 * @returns {Promise} - 响应数据 */ const apiRequest = async (url, options = {}) => { const method = options.method || 'GET'; const requestData = options.body ? JSON.parse(options.body) : null; // 记录请求日志 logger.api.request(method, url, requestData); try { const response = await fetch(`${API_BASE_URL}${url}`, { ...options, headers: { 'Content-Type': 'application/json', ...options.headers, }, credentials: 'include', }); // 检查响应是否为 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; // 记录错误响应 logger.api.error(method, url, new Error(errorMessage), requestData); } catch (parseError) { logger.warn('authService', 'Failed to parse error response as JSON', { url }); } } throw new Error(errorMessage); } // 安全地解析 JSON 响应 if (isJson) { try { const data = await response.json(); // 记录成功响应 logger.api.response(method, url, response.status, data); return data; } catch (parseError) { logger.error('authService', 'apiRequest', parseError, { url }); throw new Error('服务器响应格式错误'); } } else { throw new Error('服务器响应不是 JSON 格式'); } } catch (error) { // ❌ 移除 console.error,使用 logger logger.api.error(method, url, error, requestData); // 如果是网络错误,提供更友好的提示 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_ready', // ✅ 修复:与后端返回的状态一致 REGISTER_SUCCESS: 'register_ready', // ✅ 修复:与后端返回的状态一致 EXPIRED: 'expired', AUTH_DENIED: 'auth_denied', // 用户拒绝授权 AUTH_FAILED: 'auth_failed', // 授权失败 }; /** * 状态提示信息映射 */ export const STATUS_MESSAGES = { [WECHAT_STATUS.WAITING]: '使用微信扫一扫登陆', [WECHAT_STATUS.SCANNED]: '扫码成功,请在手机上确认', [WECHAT_STATUS.AUTHORIZED]: '授权成功,正在登录...', [WECHAT_STATUS.EXPIRED]: '二维码已过期', [WECHAT_STATUS.AUTH_DENIED]: '用户取消授权', [WECHAT_STATUS.AUTH_FAILED]: '授权失败,请重试', }; export default authService;