# 微信认证API开发说明手册 ## 概述 本文档为前端开发工程师提供微信认证相关API的详细使用说明,包括路由路径、请求参数、响应格式、错误码说明以及前端示例代码。 **重要说明**:本系统已升级为符合微信官方规范的授权流程,使用15分钟有效期的微信授权码换取长期有效的openid作为用户唯一标识。 ## 微信授权流程说明 1. **前端获取授权码**:通过微信小程序API获取临时授权码(15分钟有效期) 2. **后端换取openid**:使用授权码调用微信API获取用户openid 3. **用户身份管理**:以openid作为用户唯一标识进行注册、登录等操作 ## 基础信息 - **API基础路径**: `/api/parse` - **Content-Type**: `application/json` - **字符编码**: `UTF-8` - **响应格式**: JSON ## 统一响应格式 所有API接口都遵循统一的JSON响应格式: ```json { "reason": "successed|failed", "return_code": 200, "result": { // 具体数据对象 }, "error": "错误信息(仅在失败时返回)" } ``` ## HTTP状态码说明 | 状态码 | 说明 | |--------|------| | 200 | 请求成功 | | 201 | 创建成功 | | 400 | 请求参数错误 | | 401 | 认证失败 | | 404 | 资源不存在 | | 409 | 资源冲突(如用户已存在) | | 500 | 服务器内部错误 | --- ## 1. 用户注册 ### 接口信息 - **路径**: `POST /api/parse/wechat-register` - **功能**: 注册新的微信用户 - **认证**: 无需认证 ### 请求参数 | 参数名 | 类型 | 必填 | 说明 | 示例 | |--------|------|------|------|------| | wechat_code | string | 是 | 微信授权码(15分钟有效期) | "wx_code_12345abcde" | | phone_number | string | 否 | 手机号码 | "13800138000" | | id_card_number | string | 否 | 身份证号码 | "110101199001011234" | | platform | string | 否 | 微信平台类型,默认为小程序 | "miniprogram" | ### 请求示例 ```json { "wechat_code": "wx_code_12345abcde", "phone_number": "13800138000", "id_card_number": "110101199001011234", "platform": "miniprogram" } ``` ### 响应示例 #### 成功响应 (201) ```json { "reason": "successed", "return_code": 201, "result": { "id": "1", "openid": "wx_openid_abcd1234567890123456", "phone_number": "13800138000", "id_card_number": "110101199001011234", "login_status": false, "user_status": "active", "created_at": "2024-01-15T10:30:00+08:00" } } ``` #### 失败响应 (409) ```json { "reason": "failed", "return_code": 409, "result": null, "error": "用户已存在,openid: wx_openid_abcd1234567890123456" } ``` ### 前端示例代码 #### JavaScript (Fetch API) ```javascript async function registerWechatUser(wechatCode, phoneNumber = null, idCardNumber = null, platform = 'miniprogram') { try { const response = await fetch('/api/parse/wechat-register', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ wechat_code: wechatCode, phone_number: phoneNumber, id_card_number: idCardNumber, platform: platform }) }); const data = await response.json(); if (data.return_code === 201) { console.log('注册成功:', data.result); return { success: true, data: data.result }; } else { console.error('注册失败:', data.error); return { success: false, error: data.error }; } } catch (error) { console.error('网络错误:', error); return { success: false, error: '网络请求失败' }; } } // 使用示例 registerWechatUser('wx_code_12345abcde', '13800138000', '110101199001011234') .then(result => { if (result.success) { // 注册成功处理 alert('注册成功!'); } else { // 注册失败处理 alert('注册失败: ' + result.error); } }); ``` #### jQuery ```javascript function registerWechatUser(wechatCode, phoneNumber, idCardNumber) { $.ajax({ url: '/api/parse/wechat-register', type: 'POST', contentType: 'application/json', data: JSON.stringify({ wechat_code: wechatCode, phone_number: phoneNumber, id_card_number: idCardNumber }), success: function(data) { if (data.return_code === 201) { console.log('注册成功:', data.result); alert('注册成功!'); } else { console.error('注册失败:', data.error); alert('注册失败: ' + data.error); } }, error: function(xhr, status, error) { console.error('请求失败:', error); alert('网络请求失败'); } }); } ``` --- ## 2. 用户登录 ### 接口信息 - **路径**: `POST /api/parse/wechat-login` - **功能**: 微信用户登录,通过授权码获取openid并更新登录状态和时间 - **认证**: 无需认证 ### 请求参数 | 参数名 | 类型 | 必填 | 说明 | 示例 | |--------|------|------|------|------| | wechat_code | string | 是 | 微信授权码(15分钟有效期) | "wx_code_12345abcde" | | platform | string | 否 | 微信平台类型,默认为小程序 | "miniprogram" | ### 请求示例 ```json { "wechat_code": "wx_code_12345abcde", "platform": "miniprogram" } ``` ### 响应示例 #### 成功响应 (200) ```json { "reason": "successed", "return_code": 200, "result": { "id": "1", "openid": "wx_openid_abcd1234567890123456", "phone_number": "13800138000", "id_card_number": "110101199001011234", "login_status": true, "login_time": "2024-01-15T14:30:00+08:00", "user_status": "active" } } ``` #### 失败响应 (401) ```json { "reason": "failed", "return_code": 401, "result": null, "error": "用户不存在或账户状态异常" } ``` ### 前端示例代码 #### JavaScript (Fetch API) ```javascript async function loginWechatUser(wechatCode, platform = 'miniprogram') { try { const response = await fetch('/api/parse/wechat-login', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ wechat_code: wechatCode, platform: platform }) }); const data = await response.json(); if (data.return_code === 200) { console.log('登录成功:', data.result); // 保存用户信息到本地存储 localStorage.setItem('wechat_user', JSON.stringify(data.result)); return { success: true, data: data.result }; } else { console.error('登录失败:', data.error); return { success: false, error: data.error }; } } catch (error) { console.error('网络错误:', error); return { success: false, error: '网络请求失败' }; } } // 使用示例 loginWechatUser('wx_code_12345abcde') .then(result => { if (result.success) { // 登录成功处理 window.location.href = '/dashboard'; } else { // 登录失败处理 alert('登录失败: ' + result.error); } }); ``` #### Axios ```javascript import axios from 'axios'; async function loginWechatUser(wechatCode) { try { const response = await axios.post('/api/parse/wechat-login', { wechat_code: wechatCode }); if (response.data.return_code === 200) { // 登录成功 return { success: true, data: response.data.result }; } else { return { success: false, error: response.data.error }; } } catch (error) { console.error('登录请求失败:', error); return { success: false, error: '网络请求失败' }; } } ``` --- ## 3. 用户登出 ### 接口信息 - **路径**: `POST /api/parse/wechat-logout` - **功能**: 微信用户登出,更新登录状态 - **认证**: 无需认证 ### 请求参数 | 参数名 | 类型 | 必填 | 说明 | 示例 | |--------|------|------|------|------| | openid | string | 是 | 微信用户openid | "wx_openid_abcd1234567890123456" | ### 请求示例 ```json { "openid": "wx_openid_abcd1234567890123456" } ``` ### 响应示例 #### 成功响应 (200) ```json { "reason": "successed", "return_code": 200, "result": { "message": "用户已成功登出" } } ``` #### 失败响应 (404) ```json { "reason": "failed", "return_code": 404, "result": null, "error": "用户不存在" } ``` ### 前端示例代码 #### JavaScript (Fetch API) ```javascript async function logoutWechatUser(openid) { try { const response = await fetch('/api/parse/wechat-logout', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ openid: openid }) }); const data = await response.json(); if (data.return_code === 200) { console.log('登出成功'); // 清除本地存储的用户信息 localStorage.removeItem('wechat_user'); return { success: true }; } else { console.error('登出失败:', data.error); return { success: false, error: data.error }; } } catch (error) { console.error('网络错误:', error); return { success: false, error: '网络请求失败' }; } } // 使用示例 logoutWechatUser('wx_openid_abcd1234567890123456') .then(result => { if (result.success) { // 登出成功处理 window.location.href = '/login'; } else { // 登出失败处理 console.error('登出失败:', result.error); } }); ``` --- ## 4. 获取用户信息 ### 接口信息 - **路径**: `GET /api/parse/wechat-user` - **功能**: 获取指定微信用户的详细信息 - **认证**: 无需认证 ### 请求参数 | 参数名 | 类型 | 必填 | 传递方式 | 说明 | 示例 | |--------|------|------|----------|------|------| | openid | string | 是 | Query参数 | 微信用户openid | "wx_openid_abcd1234567890123456" | ### 请求示例 ``` GET /api/parse/wechat-user?openid=wx_openid_abcd1234567890123456 ``` ### 响应示例 #### 成功响应 (200) ```json { "reason": "successed", "return_code": 200, "result": { "id": "1", "openid": "wx_openid_abcd1234567890123456", "phone_number": "13800138000", "id_card_number": "110101199001011234", "login_status": true, "login_time": "2024-01-15T14:30:00+08:00", "user_status": "active", "created_at": "2024-01-15T10:30:00+08:00", "updated_at": "2024-01-15T14:30:00+08:00" } } ``` #### 失败响应 (404) ```json { "reason": "failed", "return_code": 404, "result": null, "error": "未找到openid为 wx_openid_abcd1234567890123456 的用户" } ``` ### 前端示例代码 #### JavaScript (Fetch API) ```javascript async function getWechatUserInfo(openid) { try { const url = `/api/parse/wechat-user?openid=${encodeURIComponent(openid)}`; const response = await fetch(url, { method: 'GET', headers: { 'Content-Type': 'application/json', } }); const data = await response.json(); if (data.return_code === 200) { console.log('获取用户信息成功:', data.result); return { success: true, data: data.result }; } else { console.error('获取用户信息失败:', data.error); return { success: false, error: data.error }; } } catch (error) { console.error('网络错误:', error); return { success: false, error: '网络请求失败' }; } } // 使用示例 getWechatUserInfo('wx_openid_abcd1234567890123456') .then(result => { if (result.success) { // 显示用户信息 displayUserInfo(result.data); } else { // 处理错误 alert('获取用户信息失败: ' + result.error); } }); function displayUserInfo(userInfo) { document.getElementById('user-id').textContent = userInfo.id; document.getElementById('user-phone').textContent = userInfo.phone_number || '未设置'; document.getElementById('user-status').textContent = userInfo.login_status ? '在线' : '离线'; } ``` #### jQuery ```javascript function getWechatUserInfo(openid) { $.ajax({ url: '/api/parse/wechat-user', type: 'GET', data: { openid: openid }, success: function(data) { if (data.return_code === 200) { console.log('获取用户信息成功:', data.result); displayUserInfo(data.result); } else { console.error('获取用户信息失败:', data.error); alert('获取用户信息失败: ' + data.error); } }, error: function(xhr, status, error) { console.error('请求失败:', error); alert('网络请求失败'); } }); } ``` --- ## 5. 更新用户信息 ### 接口信息 - **路径**: `PUT /api/parse/wechat-user` - **功能**: 更新微信用户的个人信息 - **认证**: 无需认证 ### 请求参数 | 参数名 | 类型 | 必填 | 说明 | 示例 | |--------|------|------|------|------| | openid | string | 是 | 微信用户openid | "wx_openid_abcd1234567890123456" | | phone_number | string | 否 | 要更新的手机号码 | "13900139000" | | id_card_number | string | 否 | 要更新的身份证号码 | "110101199001011234" | ### 请求示例 ```json { "openid": "wx_openid_abcd1234567890123456", "phone_number": "13900139000", "id_card_number": "110101199001011234" } ``` ### 响应示例 #### 成功响应 (200) ```json { "reason": "successed", "return_code": 200, "result": { "id": "1", "openid": "wx_openid_abcd1234567890123456", "phone_number": "13900139000", "id_card_number": "110101199001011234", "login_status": true, "login_time": "2024-01-15T14:30:00+08:00", "user_status": "active", "created_at": "2024-01-15T10:30:00+08:00", "updated_at": "2024-01-15T16:45:00+08:00" } } ``` #### 失败响应 (404) ```json { "reason": "failed", "return_code": 404, "result": null, "error": "未找到openid为 wx_openid_abcd1234567890123456 的用户" } ``` ### 前端示例代码 #### JavaScript (Fetch API) ```javascript async function updateWechatUserInfo(openid, updateData) { try { const requestData = { openid: openid, ...updateData }; const response = await fetch('/api/parse/wechat-user', { method: 'PUT', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(requestData) }); const data = await response.json(); if (data.return_code === 200) { console.log('更新用户信息成功:', data.result); return { success: true, data: data.result }; } else { console.error('更新用户信息失败:', data.error); return { success: false, error: data.error }; } } catch (error) { console.error('网络错误:', error); return { success: false, error: '网络请求失败' }; } } // 使用示例 const updateData = { phone_number: '13900139000', id_card_number: '110101199001011234' }; updateWechatUserInfo('wx_openid_abcd1234567890123456', updateData) .then(result => { if (result.success) { // 更新成功处理 alert('信息更新成功!'); // 更新页面显示的用户信息 displayUserInfo(result.data); } else { // 更新失败处理 alert('更新失败: ' + result.error); } }); ``` #### Vue.js 示例 ```javascript // 在Vue组件中使用 export default { data() { return { userForm: { openid: 'wx_openid_abcd1234567890123456', phoneNumber: '', idCardNumber: '' }, loading: false }; }, methods: { async updateUserInfo() { this.loading = true; try { const response = await fetch('/api/parse/wechat-user', { method: 'PUT', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ openid: this.userForm.openid, phone_number: this.userForm.phoneNumber, id_card_number: this.userForm.idCardNumber }) }); const data = await response.json(); if (data.return_code === 200) { this.$message.success('信息更新成功!'); // 更新本地用户数据 this.updateLocalUserData(data.result); } else { this.$message.error('更新失败: ' + data.error); } } catch (error) { this.$message.error('网络请求失败'); console.error('更新用户信息失败:', error); } finally { this.loading = false; } }, updateLocalUserData(userData) { // 更新本地存储的用户数据 localStorage.setItem('wechat_user', JSON.stringify(userData)); } } }; ``` --- ## 前端集成指南 ### 微信小程序获取授权码 在微信小程序中,需要先获取授权码,然后传递给后端API: ```javascript // 微信小程序端代码 wx.login({ success: function(res) { if (res.code) { // 将授权码发送给后端 const wechatCode = res.code; // 调用注册或登录API registerOrLogin(wechatCode); } else { console.error('获取微信授权码失败'); } }, fail: function(err) { console.error('微信登录失败:', err); } }); // 注册或登录函数 async function registerOrLogin(wechatCode) { // 先尝试登录 const loginResult = await loginWechatUser(wechatCode); if (loginResult.success) { // 登录成功,保存用户信息 wx.setStorageSync('user_info', loginResult.data); wx.showToast({ title: '登录成功', icon: 'success' }); } else if (loginResult.error && loginResult.error.includes('不存在')) { // 用户不存在,尝试注册 wx.showModal({ title: '首次使用', content: '检测到您是首次使用,是否注册账号?', success: async function(modalRes) { if (modalRes.confirm) { const registerResult = await registerWechatUser(wechatCode); if (registerResult.success) { wx.setStorageSync('user_info', registerResult.data); wx.showToast({ title: '注册成功', icon: 'success' }); } else { wx.showToast({ title: '注册失败', icon: 'error' }); } } } }); } else { wx.showToast({ title: '登录失败', icon: 'error' }); } } ``` ### 用户状态管理 ```javascript // 检查用户登录状态 function checkUserLoginStatus() { const userInfo = wx.getStorageSync('user_info'); if (userInfo && userInfo.openid) { // 验证用户状态是否仍然有效 return getWechatUserInfo(userInfo.openid) .then(result => { if (result.success && result.data.login_status) { return { isLoggedIn: true, userInfo: result.data }; } else { // 清除无效的本地数据 wx.removeStorageSync('user_info'); return { isLoggedIn: false }; } }); } return Promise.resolve({ isLoggedIn: false }); } // 用户登出 async function logoutUser() { const userInfo = wx.getStorageSync('user_info'); if (userInfo && userInfo.openid) { const result = await logoutWechatUser(userInfo.openid); if (result.success) { wx.removeStorageSync('user_info'); wx.showToast({ title: '已退出登录', icon: 'success' }); // 跳转到登录页面 wx.redirectTo({ url: '/pages/login/login' }); } } } ``` ### 环境配置 确保在不同环境中正确配置API基础路径: ```javascript // config.js const config = { development: { apiBaseUrl: 'http://localhost:5000/api/parse' }, production: { apiBaseUrl: 'https://your-domain.com/api/parse' } }; const currentEnv = 'development'; // 根据实际环境设置 export const API_BASE_URL = config[currentEnv].apiBaseUrl; // 在API调用中使用 async function registerWechatUser(wechatCode, phoneNumber, idCardNumber, platform = 'miniprogram') { const response = await fetch(`${API_BASE_URL}/wechat-register`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ wechat_code: wechatCode, phone_number: phoneNumber, id_card_number: idCardNumber, platform: platform }) }); return response.json(); } ``` --- ## 错误处理最佳实践 ### 1. 统一错误处理函数 ```javascript function handleApiError(data) { const errorMessages = { 400: '请求参数错误', 401: '认证失败', 404: '资源不存在', 409: '资源冲突', 500: '服务器内部错误' }; const message = data.error || errorMessages[data.return_code] || '未知错误'; return message; } // 使用示例 async function apiCall() { try { const response = await fetch('/api/parse/wechat-login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ wechat_code: 'test' }) }); const data = await response.json(); if (data.return_code === 200) { return { success: true, data: data.result }; } else { const errorMessage = handleApiError(data); return { success: false, error: errorMessage }; } } catch (error) { return { success: false, error: '网络连接失败' }; } } ``` ### 2. 请求重试机制 ```javascript async function apiCallWithRetry(url, options, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { try { const response = await fetch(url, options); const data = await response.json(); // 如果是服务器错误且还有重试次数,则重试 if (data.return_code === 500 && i < maxRetries - 1) { await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1))); // 递增延迟 continue; } return data; } catch (error) { if (i === maxRetries - 1) throw error; await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1))); } } } ``` ### 3. 请求拦截器示例 (Axios) ```javascript import axios from 'axios'; // 创建axios实例 const apiClient = axios.create({ baseURL: '/api/parse', timeout: 10000, headers: { 'Content-Type': 'application/json' } }); // 响应拦截器 apiClient.interceptors.response.use( response => { const data = response.data; if (data.return_code >= 200 && data.return_code < 300) { return data; } else { return Promise.reject(new Error(data.error || '请求失败')); } }, error => { console.error('API请求失败:', error); return Promise.reject(error); } ); // 使用示例 async function loginUser(wechatCode) { try { const data = await apiClient.post('/wechat-login', { wechat_code: wechatCode }); return { success: true, data: data.result }; } catch (error) { return { success: false, error: error.message }; } } ``` --- ## 常见问题 (FAQ) ### Q1: 如何处理网络超时? A: 建议设置合理的超时时间(如10秒),并提供重试机制: ```javascript const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 10000); fetch('/api/parse/wechat-login', { signal: controller.signal, // ... 其他选项 }).finally(() => { clearTimeout(timeoutId); }); ``` ### Q2: 如何存储用户登录状态? A: 建议使用localStorage或sessionStorage存储用户信息: ```javascript // 登录成功后存储 localStorage.setItem('wechat_user', JSON.stringify(userData)); // 检查登录状态 function isUserLoggedIn() { const user = localStorage.getItem('wechat_user'); return user && JSON.parse(user).login_status; } // 登出时清除 localStorage.removeItem('wechat_user'); ``` ### Q3: 如何处理并发请求? A: 对于同一用户的多个请求,建议使用请求队列或防抖机制: ```javascript let pendingRequest = null; async function loginWithDebounce(wechatCode) { if (pendingRequest) { return pendingRequest; } pendingRequest = loginWechatUser(wechatCode); try { const result = await pendingRequest; return result; } finally { pendingRequest = null; } } ``` ### Q4: 如何实现自动重新登录? A: 可以在应用启动时检查本地存储的用户信息并验证: ```javascript async function autoLogin() { const storedUser = localStorage.getItem('wechat_user'); if (!storedUser) return false; const userData = JSON.parse(storedUser); // 验证用户状态是否仍然有效 const result = await getWechatUserInfo(userData.wechat_code); if (result.success && result.data.login_status) { return true; } else { // 清除无效的本地数据 localStorage.removeItem('wechat_user'); return false; } } // 应用启动时调用 autoLogin().then(isLoggedIn => { if (isLoggedIn) { // 跳转到主页面 window.location.href = '/dashboard'; } else { // 跳转到登录页面 window.location.href = '/login'; } }); ``` --- ## 版本信息 - **文档版本**: v2.0.0 - **API版本**: v2.0.0 - **最后更新**: 2025-01-15 - **维护者**: DataOps团队 - **更新内容**: 升级为基于openid的微信认证系统,符合微信官方授权规范 ## 环境配置要求 ### 后端环境变量 在部署前,请确保设置以下环境变量: ```bash # 微信小程序配置(必需) WECHAT_MINIPROGRAM_APP_ID=your_miniprogram_app_id_here WECHAT_MINIPROGRAM_APP_SECRET=your_miniprogram_app_secret_here # 微信公众号配置(可选) WECHAT_OFFICIAL_APP_ID=your_official_account_app_id_here WECHAT_OFFICIAL_APP_SECRET=your_official_account_app_secret_here # 数据库配置 DATABASE_URL=postgresql://username:password@localhost:5432/dataops_db ``` ### 数据库初始化 首次部署时,请执行以下SQL脚本: ```bash # 创建微信用户表 psql -U username -d database_name -f database/create_wechat_users.sql # 如果从旧版本升级,执行迁移脚本 psql -U username -d database_name -f database/migrate_wechat_code_to_openid.sql ``` --- ## 联系支持 如有问题或建议,请联系: - **技术支持**: tech-support@dataops.com - **API文档**: https://docs.dataops.com/api - **GitHub**: https://github.com/dataops/platform