解决 iOS 微信浏览器中 Vue Router 跳转导致微信 JS-SDK 签名失败的问题

问题描述

在 Vue 3 + Vite 项目中,使用微信 JS-SDK 的扫码功能时,遇到了一个奇怪的问题:

  • 在 iOS 微信浏览器中,从登录页跳转到核销管理页面后,扫码功能无法正常工作
  • 控制台报错:invalid signature(签名验证失败)
  • Android 微信浏览器中正常,问题仅出现在 iOS 设备上

问题原因分析

1. 项目配置

项目使用了 Vite 的 base path 配置:

// vite.config.ts
export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, root, "");
  return {
    base: env.VITE_PUBLIC_PATH || "/h5/",
    // ...
  };
});

路由配置也使用了相同的 base path:

// src/router/index.ts
const router = createRouter({
  history: createWebHistory("/h5"),
  routes
});

2. 原始代码问题

登录成功后,使用 Vue Router 进行页面跳转:

// ❌ 错误的跳转方式
router.push("/admin/verify");

问题分析:

  1. Vue Router 的 history 模式使用 pushState API,不会改变地址栏 URL
  2. 微信 JS-SDK 在 iOS 微信浏览器中会检测当前页面的 URL 进行签名验证
  3. 使用 router.push 跳转后,地址栏 URL 没有变化,导致签名验证时使用的 URL 与签名时的 URL 不一致
  4. 因此出现 invalid signature 错误

3. iOS 与 Android 的差异

  • Android 微信浏览器:对 URL 变化的检测相对宽松
  • iOS 微信浏览器:对 URL 变化的检测更严格,必须看到地址栏 URL 实际变化

解决方案

修改登录跳转代码

router.push 改为 window.location.href,并使用完整的路径(包含 base path):

// src/views/admin/Login.vue
if (response.code === 200) {
  // 保存管理员token
  setAdminToken(response.token || "");
  // 显示成功提示
  showToast({
    message: "登录成功",
    type: "success",
    duration: 1500,
    onClose: () => {
      // 提示关闭后跳转到管理页面
      // 使用 window.location.href 而不是 router.push,确保地址栏变化,微信签名才能成功
      window.location.href = "/h5/admin/verify";
    }
  });
}

完整代码对比

修改前:

// ❌ 错误的方式
if (response.code === 200) {
  setAdminToken(response.token || "");
  showToast({
    message: "登录成功",
    type: "success",
    duration: 1500,
    onClose: () => {
      router.push("/admin/verify");  // 地址栏不会变化
    }
  });
}

修改后:

// ✅ 正确的方式
if (response.code === 200) {
  setAdminToken(response.token || "");
  showToast({
    message: "登录成功",
    type: "success",
    duration: 1500,
    onClose: () => {
      // 使用 window.location.href 而不是 router.push,确保地址栏变化,微信签名才能成功
      window.location.href = "/h5/admin/verify";  // 完整路径,包含 base path
    }
  });
}

技术要点总结

1. 为什么使用 window.location.href

  • window.location.href 会触发完整的页面跳转,地址栏 URL 会实际变化
  • 微信 JS-SDK 能正确检测到新的 URL
  • 签名验证时使用的 URL 与当前页面 URL 一致

2. 为什么必须使用完整路径?

  • 项目配置了 base: "/h5/",实际访问路径需要包含这个前缀
  • 路由配置中定义的是 /admin/verify,但完整路径是 /h5/admin/verify
  • 使用完整路径确保跳转到正确的页面

3. 什么时候使用 router.push,什么时候使用 window.location.href

使用 router.push

  • 普通页面跳转(不需要微信 JS-SDK 签名)
  • 单页应用内部导航
  • 需要保持应用状态的情况

使用 window.location.href

  • 需要触发完整页面跳转的场景
  • 微信 JS-SDK 需要检测 URL 变化的场景
  • 需要确保地址栏 URL 实际变化的情况

验证结果

修改后,在 iOS 微信浏览器中:

  • ✅ 登录后跳转正常
  • ✅ 地址栏 URL 正确变化为 /h5/admin/verify
  • ✅ 微信 JS-SDK 签名验证通过
  • ✅ 扫码功能正常工作

相关文件

  • src/views/admin/Login.vue - 登录页面
  • src/views/admin/Verify.vue - 核销管理页面(使用微信扫码)
  • vite.config.ts - Vite 配置文件(base path 配置)
  • src/router/index.ts - 路由配置

总结

在需要微信 JS-SDK 签名的场景中,特别是 iOS 微信浏览器,使用 window.location.href 进行页面跳转,确保地址栏 URL 实际变化,可以避免签名验证失败的问题。这是一个典型的平台差异导致的问题,需要针对性地处理。


技术栈: Vue 3 + Vite + Vue Router + 微信 JS-SDK
问题平台: iOS 微信浏览器
解决时间: 2025年

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐