需求: H5页面调用微信扫一扫扫描二维码,获取二维码内容 技术: vue,vuex 参考文档:微信开放文档 踩坑: Android正常打开扫一扫,ios必须刷新一下才能打开(最后有解决办法) 步骤:
-
在vue项目npm安装微信sdk npm install weixin-js-sdk
安装完成之后在页面引入(在全局也行) import wx from "weixin-js-sdk";
-
点击扫一扫请求后台接口获取所需参数 sys_click() {
let that = this;
$.ajax({
url: "请求地址",
type: "POST",
dataType: "JSON",
data: {
url:that.wxUrl,
},
success: res => {
that.resMsg = res;
wx.config({
debug: false,
appId: that.resMsg.appId,
timestamp: that.resMsg.timestamp,
nonceStr: that.resMsg.nonceStr,
signature: that.resMsg.signature,
jsApiList: ["scanQRCode"]
});
}
});
}
-
调用手机摄像头, 如果wx.config 失败会wx.error ,如果成功就wx.ready wx.error(res => {
alert("出错了:" + res.errMsg);
});
wx.ready(() => {
wx.scanQRCode({
needResult: 1,
scanType: ["qrCode"],
success: res => {
alert("扫描成功", res.resultStr);
that.coding = res.resultStr;
}
});
});
4.如果这时候Android已经成功调起摄像头,而ios报invalid signature 签名错误,那么就需要用到vuex 报错原因:请求后台传入的页面地址(url参数)问题,如果Android和ios传一样的地址就会报错,举个例子说明一下 假如扫码页面是B页面,页面地址是123,B页面是从A页面跳过来的,而A页面的地址是456,这个时候你如果url参数都传123就不行,因为ios会用A页面的地址去生成签名,而Android则会用B页面的地址去生成签名,所以传入后台的url参数必须是不一样的
解决办法:在扫码的上一个页面判断手机机型,或者全局判断,如果是ios就把当前页面的地址存入vuex里面的state变量里面(这里vuex里面的变量名我取的是wxUrl)。如果是Android,就在扫码页面把地址存入vuex,请求接口的时候就用vuex里面的变量 判断是否是ios方法: let u = navigator.userAgent;
let isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
全部代码
A页面(从这个页面跳转到扫码页面)
<template>
<div>
<button @click="goCode">跳转扫码页面</button>
</div>
</template>
<script>
import {mapMutations} from 'vuex';
export default {
components: {
mapMutations,
},
created() {
this.isIOS();
},
methods: {
...mapMutations(['saveUrl','judgeModels']),
isIOS(){
let u = navigator.userAgent;
let isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
this.judgeModels(isiOS);
if(isiOS){
this.saveUrl(window.location.href)
}
},
goCode(){
this.$router.push({
name: "serve",
params: {
id: 123456
}
});
},
}
};
</script>
B页面(扫码页面)
<template>
<div>
<input type="text" v-model="coding" placeholder="扫描二维码获取" />
<button @click="sys_click">扫一扫</button>
</div>
</template>
<script>
import wx from "weixin-js-sdk";
import {mapState, mapMutations} from 'vuex';
export default {
components: {
mapState,
mapMutations,
},
computed:{
...mapState(['model','wxUrl']),
},
data() {
return {
coding:'',
resMsg: {}
};
},
mounted() {
if (!this.$route.params.id) {
this.$router.go(-1);
return;
}
if(this.model=='android'){
this.saveUrl(window.location.href)
}
},
methods: {
...mapMutations(['saveUrl']),
sys_click() {
let that = this;
$.ajax({
url: "请求地址",
type: "POST",
dataType: "JSON",
data: {
url:that.wxUrl,
},
success: res => {
that.resMsg = res;
wx.config({
debug: false,
appId: that.resMsg.appId,
timestamp: that.resMsg.timestamp,
nonceStr: that.resMsg.nonceStr,
signature: that.resMsg.signature,
jsApiList: ["scanQRCode"]
});
}
});
wx.error(res => {
alert("出错了:" + res.errMsg);
});
wx.ready(() => {
wx.scanQRCode({
needResult: 1,
scanType: ["qrCode"],
success: res => {
alert("扫描成功", res.resultStr);
that.coding = res.resultStr;
}
});
});
},
},
};
</script>
vuex页面
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
wxUrl: '',
model:''
},
mutations: {
saveUrl(state, value) {
state.wxUrl = value;
},
judgeModels(state, value){
if(value){
state.model = 'ios';
}else{
state.model = 'android'
}
}
},
})
|