在vue项目中引入jssdk所遇到的各种问题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
在vue项⽬中引⼊jssdk所遇到的各种问题
由于在最近的项⽬中,需要⽤到扫⼀扫⼆维码签到的功能,在纯H5的页⾯中要实现这个是不太可能的,所以考虑⽤jssdk或者混合开发,由于没有微信公众号和混合开发的经验,混合开发不太现实,公司没有考虑这个,⽽jssdk有其他公众号平台的公司配合,所以就看看技术上能不能实现。
技术上要考虑的就是,能不能在项⽬中引⼊jssdk,然后当⽤户在微信端打开的时候,就能够通过jssdk来调⽤微信的扫⼀扫功能。
由于公司和公众号平台公司还没谈好,⾸先⽤微信公众号测试平台来做⼀下测试,开始漫长的填坑之路。
⾸先,jssdk是需要后台配合的,后台我⽤nodejs写,⽤的是express框架,先引⽤微信提供的⼀个三⽅库,wechat来通过微信的接⼝配置信息验证,端⼝号只⽀持80端⼝的
var express = require('express')
var app = express()
var wechat = require('wechat')
app.get('/weixin', wechat('wechat',function (req, res, next) {
console.log('true');
}));
var server = app.listen(80,function () {
var host = server.address().address
var port = server.address().port
console.log('服务已启动在http://%s:%s',host,port)
})
其中url是我⾃⼰把内⽹端⼝地址映射到公⽹上的地址。
token是⾃⼰在后台约定好的。
如果服务启动起来,端⼝映射也成功了,点击提交就会提⽰配置成功,否则会提⽰有错误。
接下来需要开始获取access_token和 jsapi_ticket 来进⾏签名
access_token需要APPID和appsecret来获取,通过"https:///cgi-bin/token?
grant_type=client_credential&appid="+APPID+"&secret="+appsecret地址来获得,其中APPID和appsecret是你⾃⼰公众号⾥⾯提供的
获取到access_token以后,通过'https:///cgi-bin/ticket/getticket?
access_token='+JSON.parse(result).access_token+'&type=jsapi'地址来获取
jsapi_ticket,JSON.parse的result是"https:///cgi-bin/token?
grant_type=client_credential&appid="+APPID+"&secret="+appsecret这个地址中获取的的返回信息。
通常情况下,access_token需要缓存,因为access_token⼀天只能请求2000次。
但本次只是测试⽤,就没有将它缓存起来了
具体代码:
var sign = require('./sign')
app.post('/test/getSignature', function (req, res) {
var token = 'wechat',
appsecret = 'xxxxxxxxxxxxxxx', //你申请的
APPID ='xxxxxxxxxxxxxx',//你申请的id
url = '', //JS接⼝安全域名参与签名⽤的
Res = res;
//发送https get请求获取 access_token;
if(!access_token){
https.get("https:///cgi-bin/token?grant_type=client_credential&appid="+APPID+"&secret="+appsecret, function(res) { var datas = [];
var size = 0;
res.on('data', function (data) {
datas.push(data);
size += data.length;
});
res.on("end", function () {
var buff = Buffer.concat(datas, size);
var result = buff.toString();
access_token = JSON.parse(result).access_token
console.log(JSON.parse(result).access_token);
// 获取 jsapi_ticket //异步嵌套是不合理的不推荐这样使⽤promise
https.get('https:///cgi-bin/ticket/getticket?access_token='+JSON.parse(result).access_token+'&type=jsapi',function(res){ var datas = [];
var size = 0;
res.on('data', function (data) {
datas.push(data);
size += data.length;
res.on('end',function(){
var buff = Buffer.concat(datas, size);
var result = buff.toString()
console.log(JSON.parse(result).ticket);
var config = sign(JSON.parse(result).ticket,url);//当前要调⽤js-sdk的url
config.appId = APPID;
console.log(config);
Res.json(config);
});
}).on('error',function(e){
console.log("Got error: " + e.message);
})
});
}).on('error', function(e) {
console.log("Got error: " + e.message);
});
} else {
https.get('https:///cgi-bin/ticket/getticket?
access_token='+ access_token +'&type=jsapi',function(res){
var datas = [];
var size = 0;
res.on('data', function (data) {
datas.push(data);
size += data.length;
});
res.on('end',function(){
var buff = Buffer.concat(datas, size);
var result = buff.toString()
console.log(JSON.parse(result).ticket);
var config = sign(JSON.parse(result).ticket,url);//当前要调⽤js-sdk的url
config.appId = APPID;
console.log(config);
Res.json(config);
});
})
}
});
其中sign是⼀个签名的函数⽂件,⾥⾯⾃动⽣成nonceStr,timestamp字段,然后通过签名⽣成signature,时间戳需要精确到秒,⽽不是毫秒,
url需要包含?后⾯的但不包含#后⾯的内容
具体代码如下:
var createNonceStr = function () {
return Math.random().toString(36).substr(2, 15);
};
var createTimestamp = function () {
return parseInt(new Date().getTime() / 1000) + '';
};
var raw = function (args) {
var keys = Object.keys(args);
keys = keys.sort()
var newArgs = {};
keys.forEach(function (key) {
newArgs[key.toLowerCase()] = args[key];
});
var string = '';
for (var k in newArgs) {
string += '&' + k + '=' + newArgs[k];
}
string = string.substr(1);
return string;
};
var sign = function (jsapi_ticket, url) {
var ret = {
jsapi_ticket: jsapi_ticket,
nonceStr: createNonceStr(),
timestamp: createTimestamp(),
};
var string = raw(ret);
jsSHA = require('jssha');
shaObj = new jsSHA(string, 'TEXT');
ret.signature = shaObj.getHash('SHA-1', 'HEX');
return ret;
};
module.exports = sign;
到此,后台获取前端需要的wx.config的所有字段完成。
然后前端开始请求后台的接⼝,需要注意的是,前端的地址需要添加到安全域名中,为此我映射了第⼆个端⼝到公⽹
然后需要在vue项⽬中引⼊jssdk,微信为了⽅便⽤户使⽤,将官⽅的jssdk发布到了npm上,有⼀个叫weixin-js-sdk的,但我们需要使⽤的不是这个,⽹上很多在vue中引⽤的是这个,但是这个是为commonjs发布的版本,只能通过require引⼊,很多⼈发现在vue中引⼊import wx from 'weixin-js-sdk',console.log(wx)会出现undefined,实际为了⽅便es6使⽤,官⽅发布了⼀个weixin-jsapi,这个才是我们能在vue中引⽤的jssdk。
我也在这⾥被坑了很久。
然后拿到后台返回的配置参数,通过wx.config来验证配置后,在wx.ready⾥⾯就可以调⽤jssdk提供的api了,具体代码:
import wx from 'weixin-jsapi'
export default {
data () {
return {
videoSrc: ''
}
},
mounted () {
http.POST('/xxxx/xxxxxxxxx').then((data) => {
console.log(wx)
wx.config({
debug: true,
appId: data.appId, // 必填,公众号的唯⼀标识
timestamp: data.timestamp, // 必填,⽣成签名的时间戳,精确到秒
nonceStr: data.nonceStr, // 必填,⽣成签名的随机串
signature: data.signature, // 必填,签名
jsApiList: ['scanQRCode']
})
}).catch(() => {
alert('failed')
})
},
methods: {
handleQR () {
wx.ready(() => {
console.log('ininin')
wx.scanQRCode({
needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
scanType: ["qrCode","barCode"], // 可以指定扫⼆维码还是⼀维码,默认⼆者都有
success: function (res) {
var result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果
}
});
})
}
}
}。