HaniBlindBox/docs/前端适配调整/前端API适配方案.md
2026-01-03 15:21:36 +08:00

8.4 KiB
Raw Blame History

前端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)

当前请求封装的关键特点:

// 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

// 修改前
if (method.toUpperCase() == 'POST') {
    header = {
        'content-type': 'application/x-www-form-urlencoded',
        // ...
    }
}

// 修改后
if (method.toUpperCase() == 'POST') {
    header = {
        'content-type': 'application/json',
        // ...
    }
}

3.2 完整修改示例

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

// 在 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

// 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

- 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

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. 逐步排查问题接口