hookehuyr

refactor(api): 简化 API 参数结构并更新配置

- 移除 API 中的 `t` 参数和 `client_name` 参数,简化 URL 构建
- 更新生产/开发环境域名为 manulife.onwall.cn
- 启用授权模式(ENABLE_AUTH_MODE = true)
- 将废弃的 substr 替换为 substring
- 添加认证调试指南文档(docs/auth-debug-guide.md)
- 更新 API 文档状态(testing/developing)
- 优化登录和退出登录的 JSDoc 注释

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
......@@ -125,7 +125,7 @@ paths:
x-apifox-ordering: 0
security: []
x-apifox-folder: 意见反馈
x-apifox-status: released
x-apifox-status: developing
x-run-in-apifox: https://app.apifox.com/web/project/7792797/apis/api-413906670-run
components:
schemas: {}
......
......@@ -99,7 +99,7 @@ paths:
x-apifox-ordering: 0
security: []
x-apifox-folder: 意见反馈
x-apifox-status: released
x-apifox-status: developing
x-run-in-apifox: https://app.apifox.com/web/project/7792797/apis/api-413906671-run
components:
schemas: {}
......
......@@ -96,7 +96,7 @@ paths:
x-apifox-ordering: 0
security: []
x-apifox-folder: 消息
x-apifox-status: released
x-apifox-status: developing
x-run-in-apifox: https://app.apifox.com/web/project/7792797/apis/api-413906673-run
components:
schemas: {}
......
......@@ -103,7 +103,7 @@ paths:
x-apifox-ordering: 0
security: []
x-apifox-folder: 消息
x-apifox-status: released
x-apifox-status: developing
x-run-in-apifox: https://app.apifox.com/web/project/7792797/apis/api-413906672-run
components:
schemas: {}
......
......@@ -90,7 +90,7 @@ paths:
x-apifox-ordering: 0
security: []
x-apifox-folder: 用户
x-apifox-status: released
x-apifox-status: testing
x-run-in-apifox: https://app.apifox.com/web/project/7792797/apis/api-413906668-run
components:
schemas: {}
......
......@@ -49,10 +49,6 @@ paths:
password:
example: '000000'
type: string
openid:
description: 要绑定的小程序openid
example: ''
type: string
required:
- uuid
- password
......@@ -81,7 +77,7 @@ paths:
x-apifox-ordering: 0
security: []
x-apifox-folder: 用户
x-apifox-status: released
x-apifox-status: testing
x-run-in-apifox: https://app.apifox.com/web/project/7792797/apis/api-413906666-run
components:
schemas: {}
......
# 退出登录
# 退出登录并解绑openid
## OpenAPI Specification
......@@ -10,7 +10,7 @@ info:
paths:
/srv/:
post:
summary: 退出登录
summary: 退出登录并解绑openid
deprecated: false
description: ''
tags:
......@@ -68,7 +68,7 @@ paths:
x-apifox-ordering: 0
security: []
x-apifox-folder: 用户
x-apifox-status: released
x-apifox-status: testing
x-run-in-apifox: https://app.apifox.com/web/project/7792797/apis/api-413906667-run
components:
schemas: {}
......
......@@ -75,7 +75,7 @@ paths:
x-apifox-ordering: 0
security: []
x-apifox-folder: 用户
x-apifox-status: released
x-apifox-status: developing
x-run-in-apifox: https://app.apifox.com/web/project/7792797/apis/api-413906669-run
components:
schemas: {}
......
......@@ -29,18 +29,11 @@ paths:
type: string
- name: a
in: query
description: 文件夹名称
description: ''
required: true
example: openid
schema:
type: string
- name: t
in: query
description: 接口的具体功能
required: true
example: wxapp
schema:
type: string
- name: code
in: query
description: ''
......@@ -109,7 +102,7 @@ paths:
x-apifox-ordering: 0
security: []
x-apifox-folder: 微信
x-apifox-status: released
x-apifox-status: testing
x-run-in-apifox: https://app.apifox.com/web/project/7792797/apis/api-413906665-run
components:
schemas: {}
......
# MiniProgramAuth 接口联调指南
## 📋 配置完成情况
### ✅ 已完成的配置
1. **域名配置**
- 开发环境:`https://oa-dev.onwall.cn`
- 生产环境:`https://manulife.onwall.cn`
2. **接口路径统一**
- 统一使用 `a=openid` 参数
- 完整接口:`https://oa-dev.onwall.cn/srv/?a=openid&f=manulife`
3. **授权模式**
- 已启用:`ENABLE_AUTH_MODE = true`
4. **请求参数**
- 移除了 `client_name` 参数
- 保留 `f=manulife` 业务模块标识
## 🧪 测试步骤
### 步骤 1: 启动项目
```bash
# 开发环境(默认使用 oa-dev.onwall.cn)
pnpm dev:weapp
```
### 步骤 2: 微信开发者工具配置
1. 打开微信开发者工具
2. 导入项目(选择项目根目录)
3. **不勾选**"不校验合法域名"(测试真实接口)
4. 确保已登录微信开发者账号
### 步骤 3: 测试授权流程
#### 测试点 1: 首次授权(无 sessionid)
**操作**
1. 清除小程序缓存(微信开发者工具 → 清除缓存 → 清除全部)
2. 刷新小程序
3. 观察控制台日志
**预期结果**
```
✅ 应该看到以下流程:
1. app.js 启动时调用 silentAuth()
2. Taro.login() 获取微信 code
3. 调用接口: POST https://oa-dev.onwall.cn/srv/?a=openid&f=manulife
4. 请求体: { code: "xxx" }
5. 接口返回: { code: 1, data: { user: {...} } }
6. 提取 cookie 并写入 localStorage.sessionid
```
**检查点**
- [ ] 控制台无错误
- [ ] `localStorage.sessionid` 有值
- [ ] 接口返回 `code: 1`
#### 测试点 2: 已授权用户(有 sessionid)
**操作**
1. 关闭小程序
2. 重新打开(不清除缓存)
3. 观察控制台日志
**预期结果**
```
✅ 应该看到以下流程:
1. hasAuth() 返回 true(检测到 sessionid)
2. 跳过授权流程
3. 直接进入首页
```
**检查点**
- [ ] 不会重复调用授权接口
- [ ] 直接显示首页内容
#### 测试点 3: 401 自动刷新
**操作**
1. 手动删除 `localStorage.sessionid`
2. 访问任何需要登录的接口
3. 观察自动刷新流程
**预期结果**
```
✅ 应该看到以下流程:
1. 接口返回 401
2. request.js 拦截器捕获 401
3. 调用 refreshSession()
4. Taro.login() 获取新 code
5. 重新调用授权接口
6. 重放原始请求
```
**检查点**
- [ ] 用户无感知(静默刷新)
- [ ] 原始请求自动重放成功
- [ ] 新的 sessionid 已保存
#### 测试点 4: 授权页跳转(降级方案)
**操作**
1. 模拟授权失败(修改接口返回错误)
2. 观察是否跳转到授权页
**预期结果**
```
✅ 应该看到以下流程:
1. 授权失败
2. 保存当前页面路径
3. 跳转到 /pages/auth/index
4. 授权成功后回跳原页面
```
**检查点**
- [ ] 正确跳转到授权页
- [ ] 授权成功后回跳正确
- [ ] 路径参数不丢失
## 📊 接口说明
### 请求格式
```http
POST https://oa-dev.onwall.cn/srv/?a=openid&f=manulife
Content-Type: application/json
{
"code": "微信登录code"
}
```
### 响应格式
**成功响应**
```json
{
"code": 1,
"msg": "success",
"data": {
"user": {
"id": 123,
"avatar_url": "https://...",
"name": "用户姓名"
}
}
}
```
**Cookie 处理**
- 后端通过 `Set-Cookie` 头返回 sessionid
- 小程序端从 `response.cookies[0]` 读取
- H5 端从 `response.header['set-cookie']` 读取
## 🐛 常见问题排查
### 问题 1: 接口返回 404
**原因**:接口路径错误
**检查**
```javascript
// 确认 buildApiUrl 构建的 URL
console.log(buildApiUrl('openid'))
// 应该输出: https://oa-dev.onwall.cn/srv/?a=openid&f=manulife
```
**解决**:确认后端接口参数为 `a=openid`
### 问题 2: 接口返回 403
**原因**:域名未白名单
**检查**
- 微信开发者工具 → 详情 → 本地设置
- 确认是否勾选了"不校验合法域名"
**解决**
1. 开发阶段:勾选"不校验合法域名"
2. 生产环境:在微信公众平台配置服务器域名白名单
### 问题 3: Cookie 未保存
**原因**:后端未返回 Set-Cookie
**检查**
```javascript
// 在 refreshSession 中添加日志
const response = await Taro.request({...})
console.log('响应头:', response.header)
console.log('Cookie:', response.cookies)
```
**解决**
- 确认后端返回了 `Set-Cookie`
- 小程序端确保返回格式正确
### 问题 4: 授权后仍然跳转登录页
**原因**:sessionid 未正确保存
**检查**
```javascript
// 在控制台执行
console.log(Taro.getStorageSync('sessionid'))
```
**解决**
- 确认 `extractCookie()` 函数正确提取了 cookie
- 确认 `Taro.setStorageSync('sessionid', cookie)` 成功执行
## 🔍 调试技巧
### 1. 开启详细日志
`src/utils/request.js` 拦截器中添加日志:
```javascript
// 请求拦截器
config => {
console.log('🔵 请求:', config.url, config.data)
return config
}
// 响应拦截器
response => {
console.log('🟢 响应:', response.config.url, response.data)
return response
}
// 错误拦截器
error => {
console.error('🔴 错误:', error.config?.url, error.response?.status)
return Promise.reject(error)
}
```
### 2. 监控网络请求
微信开发者工具 → Network 面板:
- 查看 `openid` 接口请求
- 确认请求参数和响应格式
- 检查 Cookie 是否正确返回
### 3. 查看 Storage
微信开发者工具 → Storage 面板:
- 确认 `sessionid` 存在
- 查看值是否正确
## ✅ 验收标准
联调通过的标准:
- [ ] 首次授权能成功获取 sessionid
- [ ] 已授权用户能直接进入首页
- [ ] 401 时能自动刷新 sessionid
- [ ] 授权失败时能跳转到授权页
- [ ] 授权成功后能正确回跳
- [ ] 所有接口请求都能带上 sessionid
## 📝 后续优化建议
1. **添加加载提示**:授权时显示 loading
2. **错误提示优化**:友好的错误文案
3. **重试机制**:授权失败时的重试策略
4. **埋点统计**:授权成功率统计
## 📞 联系方式
如有问题,请联系开发团队。
......@@ -31,7 +31,6 @@ export const getProfileAPI = (params) => fn(fetch.get(Api.GetProfile, params));
* @param {Object} params 请求参数
* @param {string} params.uuid
* @param {string} params.password
* @param {string} params.openid (可选) 要绑定的小程序openid
* @returns {Promise<{
* code: number; // 状态码
* msg: string; // 消息
......@@ -41,7 +40,7 @@ export const getProfileAPI = (params) => fn(fetch.get(Api.GetProfile, params));
export const loginAPI = (params) => fn(fetch.post(Api.Login, params));
/**
* @description 退出登录
* @description 退出登录并解绑openid
* @remark
* @param {Object} params 请求参数
* @returns {Promise<{
......
import { fn, fetch } from '@/api/fn';
const Api = {
MiniProgramAuth: '/srv/?a=openid&t=wxapp',
MiniProgramAuth: '/srv/?a=openid',
}
/**
......
......@@ -134,7 +134,7 @@ export const refreshSession = async (options) => {
// 换取后端会话(服务端通过 Set-Cookie 返回会话信息)
const response = await Taro.request({
url: buildApiUrl('openid_wxapp'),
url: buildApiUrl('openid'),
method: 'POST',
data: request_data,
})
......
/*
* @Date: 2026-01-29 10:48:35
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2026-02-02 15:28:09
* @LastEditTime: 2026-02-02 16:43:52
* @FilePath: /manulife-weapp/src/utils/config.js
* @Description: 文件描述
*/
......@@ -17,18 +17,17 @@
* @type {string}
*/
const BASE_URL = process.env.NODE_ENV === 'production'
? 'https://your-production-domain.com' // 🔧 修改为生产环境域名
: 'https://your-dev-domain.com' // 🔧 修改为开发环境域名
? 'https://manulife.onwall.cn' // 生产环境域名
: 'https://manulife.onwall.cn' // 开发环境域名
// : 'https://oa-dev.onwall.cn' // 开发环境域名
/**
* 接口默认公共参数(避免在多个文件里硬编码)
* - f:业务模块标识(请修改为您的业务模块)
* - client_name:客户端标识(请修改为您的应用名称)
* - a: 文件夹名称
* - t :接口的具体功能
* - f:业务模块标识
* - a: 接口功能参数
*/
export const REQUEST_DEFAULT_PARAMS = {
f: 'manulife', // 🔧 修改为业务模块标识
f: 'manulife', // 业务模块标识
}
/**
......@@ -36,6 +35,6 @@ export const REQUEST_DEFAULT_PARAMS = {
* - true: 启用授权检查、自动跳转登录、401自动续期
* - false: 禁用所有授权相关功能(所有授权检查直接通过,不跳转登录页)
*/
export const ENABLE_AUTH_MODE = false
export const ENABLE_AUTH_MODE = true // 启用授权模式
export default BASE_URL
......
......@@ -42,7 +42,7 @@ const wxInfo = () => {
const parseQueryString = url => {
if (!url) return {};
var json = {};
var arr = url.indexOf('?') >= 0 ? url.substr(url.indexOf('?') + 1).split('&') : [];
var arr = url.indexOf('?') >= 0 ? url.substring(url.indexOf('?') + 1).split('&') : [];
arr.forEach(item => {
var tmp = item.split('=');
json[tmp[0]] = tmp[1];
......@@ -184,15 +184,14 @@ const get_bill_status_text = (status) => {
/**
* @description 构建 API 请求 URL(带默认公共参数)
* @param {string} action 接口动作名称(例如:openid_wxapp
* @param {string} action 接口动作名称(例如:openid)
* @param {Object} [params={}] 额外 query 参数
* @returns {string} 完整请求 URL(BASE_URL + /srv/?a=...&f=...&client_name=...
* @returns {string} 完整请求 URL(BASE_URL + /srv/?a=...&f=...)
*/
const buildApiUrl = (action, params = {}) => {
const queryParams = new URLSearchParams({
a: action,
f: REQUEST_DEFAULT_PARAMS.f,
client_name: REQUEST_DEFAULT_PARAMS.client_name,
...params,
})
return `${BASE_URL}/srv/?${queryParams.toString()}`
......