├── .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 |
--------------------------------------------------------------------------------