Files
app_03_pregnancy/docs/miniprogram-fix-plan.md

3.8 KiB
Raw Blame History

小程序 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 中动态设置 <web-view> 的 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 时把 ? 改为 #:

// ─── 改前(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 的逻辑改为:

// 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 方案改动最小、最可靠。