# 小程序 web-view Token 传递问题分析与修复方案 --- ## 一、问题现象 H5 页面一直显示"正在获取登录信息...",无法正常加载首页。 ## 二、排查过程 ### 2.1 小程序端日志 ✅ ``` [web_view] 原始URL: ✅ https://mp.yizhezhe.com/app_03/?token=eyJ0eX... [web_view] 最终传给 web-view 的 URL: ✅ https://mp.yizhezhe.com/app_03/?token=eyJ0eX... [web_view] token: ✅ eyJ0eXAiOiJ... [web_view] JWT payload: { ✅ 解码正常 "uid": 7, "phone": "13693687880", "openid": "oauWC1zc7..." } ``` ### 2.2 H5 端日志 ❌ ``` initialUrl: https://mp.yizhezhe.com/app_03/ ← 无 token url: https://mp.yizhezhe.com/app_03/ ← 无 token hasTokenParam: false ← URL 无 token 参数 search: [] ← query string 为空 step: wx-postMessage-done ``` ### 2.3 根因定位 **Nginx 配置**(之前排查过一次已修复)、**小程序代码**、**URL 拼接逻辑** 都没有问题。 问题出在 **微信 web-view 组件的内部机制**:当 uni-app 在 `onLoad` 中动态设置 `` 的 `src` 属性时,微信内部加载 web-view 的**首次页面请求会丢弃 query string(`?token=xxx`)**,导致 H5 收到的 URL 不带 token。 这是微信 web-view 的已知行为,跟 Nginx 无关,跟小程序代码逻辑也无关。 --- ## 三、修复方案 ### 3.1 方案:用 hash(`#token=xxx`)替代 query(`?token=xxx`) 微信 web-view 在 URL 重定向/动态设 src 时,**hash 片段是唯一 100% 不被丢弃的部分**。 ### 3.2 小程序端改动(uni-app) 改一个文件(`index.vue` 或 web-view 所在页面),构造 URL 时把 `?` 改为 `#`: ```javascript // ─── 改前(query) ─── const base = 'https://mp.yizhezhe.com/app_03/'; const url = base + '?token=' + encodeURIComponent(token); // 最终: https://mp.yizhezhe.com/app_03/?token=eyJ0eX... // ↑ 被微信 web-view 丢弃 // ─── 改后(hash) ─── const base = 'https://mp.yizhezhe.com/app_03/'; const url = base + '#token=' + encodeURIComponent(token); // 最终: https://mp.yizhezhe.com/app_03/#token=eyJ0eX... // ↑ 微信任何场景都不丢 hash ``` ### 3.3 H5 端改动(已部署) H5 的 `LoginPage.tsx` 已更新,读取 token 的逻辑改为: ```typescript // 1. 优先从 query 读(兼容开发环境和直接 URL 访问) const params = new URLSearchParams(window.location.search); let token = params.get('token'); // 2. query 没有则从 hash 读(微信 web-view 场景) if (!token) { const hash = window.location.hash; if (hash.startsWith('#token=')) { token = decodeURIComponent(hash.replace('#token=', '')); } } // 3. 后续解码逻辑不变... ``` **不需要额外操作,部署后直接生效。** ### 3.4 改动量 | 端 | 改几个文件 | 改几行 | |----|----------|--------| | 小程序 | 1 个文件(web-view 页面) | 1 行(`?` → `#`) | | H5 | 已部署,无需再改 | 0 | --- ## 四、验证步骤 1. 小程序端改 `?` 为 `#` 2. 重新编译小程序 3. 点击进入 web-view 4. H5 顶部 Debug 面板的 `step` 应该显示 `token-from-hash`,然后跳到 decode-ok → fetch-ok → 跳首页 5. 确认无误后 H5 端可清理 DebugPanel 代码 --- ## 五、补充说明 ### 为什么不用其他方案? | 方案 | 问题 | |------|------| | `postMessage` 双向通信 | 小程序 → H5 没有直接 API,只能通过 URL 变化 | | 在 web-view 初始化前等 token | 同当前方案,需前端额外处理竞态 | | `wx.miniProgram.navigateTo` 重定向 | 会造成页面闪烁,且 query 同样可能丢失 | | `evalJavascript` | 各版本兼容性不一致 | **hash 方案改动最小、最可靠。**