# 前端API适配方案 ## 1. 问题概述 在将后端从 PHP (ThinkPHP 6.0) 迁移到 .NET 10 的过程中,前端 UniApp 项目需要进行适配调整。主要问题包括: 1. **请求格式不兼容**:前端使用 `application/x-www-form-urlencoded`,后端期望 `application/json` 2. **请求方式不一致**:同一接口在不同页面使用不同的请求方式(GET/POST) 3. **部分接口遗漏**:如 `/api/goods_list`、`/api/coupon` 等接口未正确对接 ## 2. 当前前端请求机制分析 ### 2.1 请求封装 (`honey_box/common/request.js`) 当前请求封装的关键特点: ```javascript // POST 请求使用 form-urlencoded if (method.toUpperCase() == 'POST') { header = { 'content-type': 'application/x-www-form-urlencoded', // ... } } else { // GET 请求使用 json header = { 'content-type': 'application/json', // ... } } ``` ### 2.2 签名机制 前端对所有请求都添加了签名参数: - `timestamp`: 时间戳 - `nonce`: 随机字符串 - `sign`: MD5签名 签名算法: 1. 参数按键名排序 2. 拼接为 `key=value&` 格式 3. 添加密钥 `host + timestamp` 4. MD5 加密 ## 3. 适配方案 ### 方案一:前端统一改为 JSON 格式(推荐) #### 3.1 修改 `request.js` 将 POST 请求的 Content-Type 改为 `application/json`: ```javascript // 修改前 if (method.toUpperCase() == 'POST') { header = { 'content-type': 'application/x-www-form-urlencoded', // ... } } // 修改后 if (method.toUpperCase() == 'POST') { header = { 'content-type': 'application/json', // ... } } ``` #### 3.2 完整修改示例 ```javascript static request(param, backpage, backtype) { return new Promise((resolve, reject) => { // ... 参数检查代码 ... const url = param.url || '' const method = param.method || 'POST' const data = param.data || {} const Loading = param.Loading || false const token = uni.getStorageSync('token') let client = platform.code // ... URL 拼接代码 ... // 添加签名参数 data.timestamp = Math.floor(Date.now() / 1000) data.nonce = RequestManager.generateNonce() // 生成签名 const sortedParams = {} Object.keys(data).sort().forEach(key => { sortedParams[key] = data[key] }) let signStr = '' for (const key in sortedParams) { if (typeof sortedParams[key] === 'object') { signStr += key + '=' + JSON.stringify(sortedParams[key]) + '&' } else { signStr += key + '=' + sortedParams[key] + '&' } } const timestamp = data.timestamp const appSecret = host + timestamp signStr = signStr.substring(0, signStr.length - 1) + appSecret const sign = md5(signStr) data.sign = sign // 统一使用 JSON 格式 const header = { 'content-type': 'application/json', client: client, token: token, adid: uni.getStorageSync('_ad_id'), clickid: uni.getStorageSync('_click_id') } // ... 发起请求代码 ... }) } ``` ### 方案二:后端兼容 form-urlencoded(备选) 如果不想修改前端,可以在后端添加中间件支持 form-urlencoded: ```csharp // 在 Program.cs 中添加 builder.Services.AddControllers() .AddNewtonsoftJson() .ConfigureApiBehaviorOptions(options => { // 支持 form-urlencoded }); ``` 但这种方案不推荐,因为: 1. 增加后端复杂度 2. 不符合 RESTful API 规范 3. 后续维护困难 ## 4. 接口请求方式统一 ### 4.1 当前接口请求方式对照表 | 接口路径 | PHP 旧版 | C# 新版 | 前端当前使用 | 需要调整 | |---------|---------|---------|-------------|---------| | `/api/config` | GET/POST | GET | GET | ✅ 无需调整 | | `/api/getPlatformConfig` | GET/POST | GET | GET | ✅ 无需调整 | | `/api/getAdvert` | GET/POST | GET/POST | GET | ✅ 无需调整 | | `/api/getDanye` | GET/POST | GET | GET | ✅ 无需调整 | | `/api/goods_list` | POST | POST | POST | ✅ 无需调整 | | `/api/goods_detail` | POST | POST | POST | ✅ 无需调整 | | `/api/user` | POST | POST | GET | ⚠️ 需要调整 | | `/api/login` | POST | POST | POST | ✅ 无需调整 | | `/api/mobileLogin` | POST | POST | POST | ✅ 无需调整 | | `/api/coupon_list` | POST | POST | POST | ✅ 无需调整 | | `/api/order_list` | POST | POST | POST | ✅ 无需调整 | ### 4.2 需要调整的接口 #### `/api/user` - 获取用户信息 **问题**:前端 `user.js` 使用 GET 请求,后端期望 POST ```javascript // honey_box/common/server/user.js // 修改前 export const getUserInfo = async () => { const res = await RequestManager.get('/userInfo'); // ... } // 修改后 export const getUserInfo = async () => { const res = await RequestManager.post('/user'); // ... } ``` ## 5. 遗漏接口清单 根据分析,以下接口可能存在问题: ### 5.1 商品相关 | 接口 | 状态 | 说明 | |-----|------|-----| | `POST /api/goods_list` | ⚠️ 需检查 | 前端请求格式需改为 JSON | | `POST /api/goods_detail` | ⚠️ 需检查 | 前端请求格式需改为 JSON | ### 5.2 优惠券相关 | 接口 | 状态 | 说明 | |-----|------|-----| | `POST /api/coupon_list` | ⚠️ 需检查 | 前端请求格式需改为 JSON | | `POST /api/coupon_detail` | ⚠️ 需检查 | 前端请求格式需改为 JSON | | `POST /api/coupon_ling` | ⚠️ 需检查 | 前端请求格式需改为 JSON | ### 5.3 订单相关 | 接口 | 状态 | 说明 | |-----|------|-----| | `POST /api/ordermoney` | ⚠️ 需检查 | 前端请求格式需改为 JSON | | `POST /api/orderbuy` | ⚠️ 需检查 | 前端请求格式需改为 JSON | ## 6. 实施步骤 ### 第一阶段:修改请求封装(核心) 1. 修改 `honey_box/common/request.js` 2. 将 POST 请求的 Content-Type 改为 `application/json` 3. 测试基础接口(登录、配置获取) ### 第二阶段:统一接口调用方式 1. 检查 `honey_box/common/server/` 下所有接口文件 2. 统一使用正确的请求方式(GET/POST) 3. 确保接口路径与后端一致 ### 第三阶段:逐模块测试 1. 用户认证模块(登录、注册、绑定手机号) 2. 商品模块(列表、详情、奖品) 3. 订单模块(下单、支付、抽奖) 4. 仓库模块(回收、发货) 5. 福利模块(签到、任务) ## 7. 代码修改清单 ### 7.1 `honey_box/common/request.js` ```diff - header = { - 'content-type': 'application/x-www-form-urlencoded', - client: client, - token: token, - adid: uni.getStorageSync('_ad_id'), - clickid: uni.getStorageSync('_click_id') - } + header = { + 'content-type': 'application/json', + client: client, + token: token, + adid: uni.getStorageSync('_ad_id'), + clickid: uni.getStorageSync('_click_id') + } ``` ### 7.2 `honey_box/common/server/user.js` ```diff export const getUserInfo = async () => { - const res = await RequestManager.get('/userInfo'); + const res = await RequestManager.post('/user'); if (res.status == 1) { res.data.money = common.removeTrailingZeros(res.data.money); res.data.integral = common.removeTrailingZeros(res.data.integral); res.data.money2 = common.removeTrailingZeros(res.data.money2); return res.data; } else { return null; } }; ``` ## 8. 测试验证 ### 8.1 测试用例 | 测试项 | 预期结果 | 实际结果 | |-------|---------|---------| | 获取系统配置 | 返回配置数据 | | | 手机号登录 | 返回 token | | | 获取用户信息 | 返回用户数据 | | | 获取商品列表 | 返回商品分页数据 | | | 获取优惠券列表 | 返回优惠券数据 | | | 创建订单 | 返回订单信息 | | ### 8.2 调试工具 前端已集成 eruda 调试工具,可在开发环境查看网络请求详情。 ## 9. 注意事项 1. **签名机制保持不变**:修改 Content-Type 不影响签名计算 2. **Token 传递方式不变**:继续通过 header 传递 3. **响应格式不变**:后端返回格式与 PHP 版本保持一致 4. **错误码保持一致**:status 码含义不变 ## 10. 回滚方案 如果修改后出现问题,可以: 1. 恢复 `request.js` 中的 Content-Type 为 `application/x-www-form-urlencoded` 2. 在后端添加 form-urlencoded 支持中间件 3. 逐步排查问题接口