├── .gitignore ├── UML.png ├── UML.txt └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /UML.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chooin/wechat-spa/HEAD/UML.png -------------------------------------------------------------------------------- /UML.txt: -------------------------------------------------------------------------------- 1 | title 微信授权时序图 2 | 3 | 用户 -> 单页面(SPA): 进入项目 4 | alt sessionStorage 中不存在 is_auth 5 | 单页面(SPA)-> 单页面(SPA): 存储 URL “#” 后面的路径到 localStorage 6 | 单页面(SPA) -> auth.html : 跳转到 7 | alt localStorage 中不存在 wechat_openid 8 | auth.html -> 微信 OAuth2.0 : 跳转到 9 | 微信 OAuth2.0 -> auth.html : 返回 code 10 | auth.html -> 后端服务 : 提交 code 11 | 后端服务 --> auth.html : 返回 wechat_openid、token 等信息,存储到 localStorage 12 | else localStorage 中存在 wechat_openid 13 | alt 不存在 token 或 token 过期 14 | auth.html -> 后端服务 : 提交 wechat_openid 15 | 后端服务 --> auth.html : 有 token,则将 token 存储到 localStorage 16 | end 17 | end 18 | auth.html -> auth.html : 设置 is_auth 等于 Date.now(),存储到 sessionStorage 19 | auth.html -> 单页面(SPA): 跳转到根路径 20 | 单页面(SPA)-> 单页面(SPA): localStorage 中获取 “#” 后面的路径,再通过路由勾子跳转到实际要访问的地址 21 | end 22 | 单页面(SPA)-> 用户 : 展示信息 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 微信端单页面应用(SPA)常见问题汇总及解决方案 2 | 3 | - [非常重要](#非常重要) 🌈🌈🌈 4 | - [微信授权时序图](#微信授权时序图) 5 | - [安装和使用微信 JS-SDK](#安装和使用微信-js-sdk) 6 | - [标题更新](#标题更新) 7 | - [微信分享](#微信分享) 8 | - [微信支付](#微信支付) 9 | - [白屏](#白屏) 10 | 11 | ## 非常重要: 12 | 13 | 路由启用 hash 模式,hash 务必是 `#`,如:`https://example.com/#/home/index` 14 | 15 | > 采用 history 模式,页面路由改变后无法复制出改变后的 URL 地址 16 | 17 | 参数使用 `?` 的形式获取,如:`https://example.com/#/product/detail?id=1` 18 | 19 | > 不采用 `?` 的形式获取参数则需要配置很多支付安全目录 20 | 21 | 新建一个页面用于获取 wechat_openid、token 等操作,用户第一次进入 SPA 项目后的都需要跳转到 auth.html 页面,如:在根目录 static 文件夹下新建 auth.html,[微信授权时序图](#微信授权时序图) 22 | 23 | > 解决需要配置很多支付安全目录的问题(网上很多资料都说在支付页面添加 `?`,如:`https://example.com/?#/payment/index?order_id=1`,这样会使路由很混乱,我不建议你采用添加 `?` 的形式去解决支付问题) 24 | 25 | Nginx 配置 26 | 27 | ``` 28 | add_header "Cache-Control" "no-cache, private"; 29 | ``` 30 | 31 | > 解决 window.location.href 跳转页面被浏览器缓存的问题 32 | 33 | 涉及调用 JS-SDK 的页面都得重新配置 wx.config() 34 | 35 | > 你懂的~ 36 | 37 | ## 微信授权时序图: 38 | 39 | 40 | 41 | > is_auth:is_auth 存在说明已经经过 auth.html 页面跳转 42 | 43 | ## 安装和使用微信 JS-SDK 44 | 45 | ### 方法 1 (推荐) 46 | 47 | 在入口 index.html 文件引入微信的 JS-SDK 文件,webpack 配置参考:[中文](https://webpack.docschina.org/configuration/externals/) / [English](https://webpack.js.org/configuration/externals/) 48 | 49 | index.html 50 | 51 | ``` html 52 | 53 | ``` 54 | 55 | webpack.config.js 56 | 57 | ``` js 58 | externals: { 59 | wx: 'wx' 60 | } 61 | ``` 62 | 63 | 如何使用: 64 | 65 | ``` js 66 | import wx from 'wx' 67 | 68 | wx.ready(() => { 69 | console.log('Hello Wechat!') 70 | }) 71 | ``` 72 | 73 | ### 方法 2 74 | 75 | 如何安装: 76 | 77 | ``` sh 78 | yarn add weixin-js-sdk 79 | # 或 80 | npm install weixin-js-sdk --save 81 | ``` 82 | 83 | 如何使用: 84 | 85 | ``` js 86 | import wx from 'weixin-js-sdk' 87 | 88 | wx.ready(() => { 89 | console.log('Hello Wechat!') 90 | }) 91 | ``` 92 | 93 | ## 标题更新 94 | 95 | 在切换页面路由之后需在 body 里面添加 iframe,随后移除掉 iframe 即可,代码如下 96 | 97 | ```js 98 | // iPhone,iPod,iPad 下无法更新标题 99 | if (/ip(hone|od|ad)/i.test(window.navigator.userAgent)) { 100 | let iframe = document.createElement('iframe') 101 | iframe.style.display = 'none' 102 | iframe.src = '/favicon.ico' 103 | iframe.onload = () => { 104 | setTimeout(() => { 105 | iframe.remove() 106 | }, 10) 107 | } 108 | document.body.appendChild(iframe) 109 | } 110 | ``` 111 | 112 | ## 微信分享 113 | 1. 分享配置都正确,进入链接后页面显示不对 114 | 115 | **解决方案:** 在分享的地址后面添加一个随机字符串,如:`https://example.com/#/product/detail?id=1&share_at=${Date.now()}` 116 | 117 | **微信分享参考代码:** 118 | 119 | ```js 120 | import wx from 'wx' 121 | import axios from 'axios' 122 | 123 | const share = ({ 124 | title, 125 | desc, 126 | fullPath, 127 | imgUrl 128 | }) => { 129 | let link = fullPath.indexOf('?') > -1 130 | ? `https://example.com/#${fullPath}&share_at=${Date.now()}` 131 | : `https://example.com/#${fullPath}?share_at=${Date.now()}` 132 | wx.showAllNonBaseMenuItem() 133 | wx.onMenuShareTimeline({ 134 | title, 135 | link, 136 | imgUrl 137 | }) 138 | wx.onMenuShareAppMessage({ 139 | title, 140 | desc, 141 | link, 142 | imgUrl 143 | }) 144 | } 145 | 146 | const $_wechat = () => { 147 | return new Promise((resolve, reject) => { 148 | // 获取服务端微信配置信息 149 | axios.get('https://api.example.com/v1/wechat/config', { 150 | params: { 151 | url: window.location.href.split('#')[0] 152 | } 153 | }).then(res => { 154 | wx.config({ 155 | debug: false, 156 | appId: res.data.appId, 157 | timestamp: res.data.timestamp, 158 | nonceStr: res.data.nonceStr, 159 | signature: res.data.signature, 160 | jsApiList: [ 161 | 'onMenuShareTimeline', 162 | 'onMenuShareAppMessage' 163 | ] 164 | }) 165 | wx.ready(() => { // 配置 wx.config 成功 166 | resolve({ 167 | wx, 168 | share 169 | }) 170 | }) 171 | }).catch(() => { 172 | reject(new Error('微信签名接口异常')) 173 | }) 174 | }) 175 | } 176 | 177 | // 调用分享 178 | $_wechat().then(res => { 179 | res.share({ // 配置分享 180 | title: 'wechat-spa', 181 | desc: 'Wechat SPA', 182 | fullPath: '/home/index', 183 | imgUrl: 'https://www.baidu.com/img/bd_logo1.png' 184 | }) 185 | }).catch(_ => { 186 | console.warn(_.message) 187 | }) 188 | ``` 189 | 190 | ## 微信支付 191 | 192 | 1. 支付安全目录,iOS 识别支付安全目录路径规则是进入 SPA 应用的第一个页面所对应的 URL 193 | 194 | 第一次进入的 URL | iOS 获取到的安全目录 195 | --------- | -------- 196 | https://example.com/#/home/index | https://example.com/#/home/index 197 | https://example.com/#/me/index | https://example.com/#/me/index 198 | https://example.com/#/product/index | https://example.com/#/product/index 199 | 200 | 这样我们要配置很多的安全目录路径,但微信平台仅允许设置3个安全目录路径,直接进入 SPA 应用的页面是行不通的 201 | 202 | **解决思路:** 用户都得先进入 SPA 应用的根目录 `https://example.com/`,然后通过 SPA 应用路由提供的钩子重定向到自己想要访问的页面,[微信授权时序图](#微信授权时序图) 203 | 204 | ## 白屏 205 | 206 | 微信支付后立即跳转到其他页面有一定几率出现白屏(长按屏幕可以复制出文字或图片地址),解决方案: 207 | 208 | ``` js 209 | // 延迟跳转即可解决 210 | setTimeout(() => { 211 | window.location.replace('/payment/success') // 跳转逻辑 212 | }, 500) 213 | ``` 214 | 215 | > 微信内置浏览器的 bug,**图片无法批量上传**也可以通过 `setTimeout` 方法解决 216 | 217 | ## 问题反馈 218 | 219 | 如内容有误请反馈给我,谢谢 220 | 221 | 有什么问题可以加我好友,大家一起交流 222 | 223 | QQ:465353876 224 | 225 | 226 | --------------------------------------------------------------------------------