记录最近项目遇到的问题
vue开发的h5页面,需要获取扫码用户的微信openid,以前用的都是history模式,这次用的是hash模式,文章两种情况都会讲到。
微信获得授权官方地址
1.history模式
在config文件夹下定义一个js文件方便使用(例如:defaultSettings.js)
function urlencode (str) { //转换一下location,主要针对hash的#
str = (str + '').toString();
return encodeURIComponent(str).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').
replace(/\)/g, '%29').replace(/\*/g, '%2A').replace(/%20/g, '+').replace(/#/g, '%23');
}
export const WX_CONFIG = {
appid: 'wx606f2d67dc8aaa74',//测试微信账户
appsecret: '07209d9a9b4f8c9290771d67bcd07888',//测试微信账户
location: window.location.href,//测试url
redirect () {
// 路径里面不允许用#,会报redirect_uri参数有误
window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${this.appid}&redirect_uri=${urlencode(this.location)}/&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect`
}
}
我这里进入页面没有openid都获取openid所以放在了(permission.js)路由守卫里面写
import { WX_CONFIG } from '@/config/defaultSettings' //(记得引入文件)
router.beforeEach((to, from, next) => {
NProgress.start() // start progress bar
// 路由发生变化修改页面title
if (to.meta.title) {
document.title = to.meta.title
}
// 获取路由query参数
store.commit('user/SetUrlQuery', to.query)
//404通过,有openId通过
if (to.name == '404' || Vue.ls.get('openid')) {
next()
//没有openid则去获取
} else if (!Vue.ls.get('openid')) {
// 有code调用接口
if (to.query.code) {
store.dispatch('user/GetOpenId', to.query.code).then(res => {
if (res.errcode) {
WX_CONFIG.redirect()
}
// 设置openid
Vue.ls.set('openid', res.openid)
// next({name:to.name})
next()
}).catch(err => {
WX_CONFIG.redirect()
console.log(err)
})
// 否则重定向页面
}else{
WX_CONFIG.redirect()
}
}
})
在user.js文件中
const user = {
namespaced: true,
state: {
code:'',
unitId: '',
urlQuery:{},
userInfo: {
openId: '',
phoneNbr:'',
name:'',
}
},
mutations: {
setUserInfo (state, info) {
vm.$ls.set('userInfo',JSON.stringify(info))
state.userInfo = JSON.parse(JSON.stringify(info))
state.unitId = state.userInfo.unitId
},
// 设置Url参数
SetUrlQuery(state, info) {
state.urlQuery = Object.assign(JSON.parse(Vue.ls.get('urlQuery')) || {},info)
Vue.ls.set('urlQuery', JSON.stringify(state.urlQuery))
},
},
actions: {
//获取openid
GetOpenId(state,code) {
return new Promise((resolve, reject) => {
util.http({
baseURL:'',
url: 'wxapi/sns/oauth2/access_token',
method: 'get',
params: {
code,
grant_type:'authorization_code',
secret:WX_CONFIG.appsecret,
appid:WX_CONFIG.appid,
}
}).then(res => {
resolve(res)
}).catch((err) => {
reject(err)
})
})
},
// 获取用户信息
GetInfo ({ commit }, token) {
return new Promise((resolve, reject) => {
getUser(token).then(res => {
commit('setUserInfo', { ...res.data, phoneNbr: res.data.phone })
resolve(JSON.parse(JSON.stringify(res)))
}).catch((err) => {
reject(err)
})
})
},
}
}
export default user
打包到线上的话需要配置代理(第一次做这个的时候就是不知道要配置代理,我本地测试都很正常打包到线上http404)
devServer: {
proxy: {
'/green/wxapi': {// 微信接口跨域(我这边指向的路径文件名是green)
'target': 'https://api.weixin.qq.com',
'secure': true, // false为http访问,true为https访问
'changeOrigin': true, // 跨域访问设置,true代表跨域
'pathRewrite': { // 路径改写规则
'^/green/wxapi': ''
}
}
}
}
前端配置完代理后记得tomcat也需要对应配置(记得清理缓存重启,确定前端没错的情况下在postman测试还是没转过去的话,让配置tomcat的小伙伴看看是不是入口路径啥的是不是不止一个,导致没指向到正确的地址,说多了都是泪!!!!)history模式基本就是这样了
location ^~ /green/wxapi/ {
proxy_pass https://api.weixin.qq.com/;
# proxy_redirect off;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header Host $host;
# proxy_set_header X-Forwarded-proto https;
}
2.hash模式
在config文件夹下定义一个js文件方便使用(例如:defaultSettings.js)同history模式
我这里进入页面没有openid都获取openid所以放在了(permission.js)路由守卫里面写
hash模式下运行程序会自动改变url的顺序code会接在域名后(例如:http://xxxxx.xxxx.cn/green/?code=0714Fy0w3AIujZ2cdB2w3dK04G04Fy0X&state=STATE#/passCertixxxx?unitId=010069xxxxxxx)其实原来的路径还有别参数然后别的参数就接在最后了
import { WX_CONFIG } from '@/config/defaultSettings' // 引入
router.beforeEach((to, from, next) => {
NProgress.start() // start progress bar
if (to.meta.title) {// 路由发生变化修改页面title
document.title = to.meta.title
}
// 第一反应是把路径变为正常的(如下,但是后续成功后会报40029或者40163错误码表示code被使用过了,打断点明明就调用了一次也是很懵,没想到拿是否存在code当条件这都不行,然后把下面这段注掉就好了,这也行????最后就是路径还是乱的,但是获取code就行)
// if (window.location.href.indexOf('visitor/?code') != -1) {
// const url = window.location.href.split('')
// const right = url.splice(url.indexOf('#')).join('')
// url.splice(url.indexOf('?'), 0, right)
// window.location.href = url.join('')
// }
// 获取路由query参数
// store.commit('user/SetUrlQuery', to.query)
// 获取url中的参数 hash模式下
function getPathObj (str) {
return str.indexOf('?code=') == -1 ? false : str.substr(str.indexOf('?code=')+6,32)
}
const code = getPathObj(window.location.href);
//404通过,有openId通过
if (to.name == '404' || Vue.ls.get('openid')) {
next()
//没有openid则去获取
} else if (!Vue.ls.get('openid')) {
// 有code调用接口
if (code) {
store.dispatch('user/GetOpenId', code).then(res => {
// console.log('res: ', res);
if (res.errcode) {
WX_CONFIG.redirect()
}
console.log('openid------', res.openid);
// alert(res.openid)
// 设置openid
Vue.ls.set('openid', res.openid)
store.state.user.userInfo.openId = res.openid
// next({name:to.name})
next()
}).catch(err => {
WX_CONFIG.redirect()
console.log(err)
})
// 否则重定向页面
} else {
WX_CONFIG.redirect()
}
}
})
其他,同history模式