微信服务号 扫一扫功能开发
2020-05-27 本文已影响0人
narcissus灬
扫一扫需要调用微信的js-sdk JS_SDK文档
前端部分
-
微信公众平台配置
绑定域名
必须配置安全域名后才能使用js-sdk
-
引入js文件
引入js文件
可以通过npm i weixin-js-sdk
,或者使用链接的形式
-
通过config接口注入权限验证配置
image.png
可以在项目开始的时候先设置wx.config
配置,也可以在需要使用js-sdk
的页面配置。
配置参数来源后台的处理
-
打开扫一扫
微信扫一扫
openScan(){
wx.ready(() => {
wx.scanQRCode({
needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
scanType: ['qrCode','barCode'], // 可以指定扫二维码还是一维码,默认二者都有
success: res => {
console.log(res)
},
error: err => {
console.log(err)
if(err.errMsg.indexOf('function_not_exist') > 0){
alert('版本过低请升级')
}
},
})
})
}
后台部分
- 微信公众平台配置ip白名单
- “微信公众平台-开发-基本配置”页面中先启用
AppSecret
需要管理员启用。 - 启用
AppSecret
后,会有一个IP白名单配置,今天白名单添加 -
access_token
需要缓存,建议通过Redis进行缓存。
- 缓存access_token
const setAccessToken = async () => {
try {
let url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appid}&secret=${secret}`
let res = await axios.get(url)
await Redis.setAsync('access_token', res.data.access_token, 3600)
return res.data.access_token
} catch (error) {
console.log(error)
throw { errmsg: '获取access_token异常' }
}
}
- 读取access_token
const getAccessToken = async () => {
let res = null
try {
res = await Redis.getAsync('access_token')
if (res == null) {
res = await setAccessToken()
return res
} else {
return res
}
} catch (error) {
res = await setAccessToken()
return res
}
}
- 缓存
jsapi_ticket
const setJsapiTicket = async () => {
try {
let accessToken = await getAccessToken()
let url = `https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${accessToken}&type=jsapi`
let res = await axios.get(url)
await Redis.setAsync('jsapi_ticket', res.data.ticket, 3600)
return res.data.ticket
} catch (error) {
console.log(error)
throw { errmsg: '获取jsapi_ticket异常', errdata: error }
}
}
- 获取
jsapi_ticket
const getJsapiTicket = async () => {
let res = null
try {
res = await Redis.getAsync('jsapi_ticket')
if (res === null) {
res = await setJsapiTicket()
return res
} else {
return res
}
} catch (error) {
res = await setJsapiTicket()
return res
}
}
- 进行签名
签名检验连接
签名检验
- 签名算法实现
目前已经获取到了jsapi_ticket
,还需要使用js-sdk功能的页面路径url
const jsSHA = require('jssha')
// `obj`转`string`,需要对`key`进行排序并转为小写通过 `&` 连接
const obj2str = args => {
let keys = Object.keys(args)
keys = keys.sort()
let str = ''
keys.forEach(k => {
str += `&${k.toLowerCase()}=args[k]`
})
return str.substr(1)
}
const sign = (jsapi_ticket, url) => {
let ret = {
jsapi_ticket: jsapi_ticket,
nonceStr: createNonceStr(), // 随机字符串,由开发者随机生成
timestamp: createTimestamp(), // 由开发者生成的当前时间戳
url: url,
}
let string = raw(ret)
// let string = `jsapi_ticket=${ret.jsapi_ticket}&noncestr=${ret.nonceStr}×tamp=${ret.timestamp}&url=${ret.url}`
let shaObj = new jsSHA('SHA-1', 'TEXT') // npm i jssha
shaObj.update(string)
ret.signature = shaObj.getHash('HEX')
return ret
}
- 给前台返回数据
最终返回的参数
{
appId: "appId",
nonceStr: "nonceStr",
signature: "signature",
timestamp: "timestamp",
url: "url"
}
const { getJsapiTicket } = require('../../lib/wx')
const sign = require('./sign')
const { AppId } = require('../../env')
router.post('/wx/config', async (req, res) => {
try {
let url = req.body.url
let jsapi_ticket = await getJsapiTicket()
let wxConfig = sign(jsapi_ticket, url)
delete wxConfig.jsapi_ticket
delete wxConfig.url
wxConfig.appId = AppId
return res.json(wxConfig)
} catch (error) {
res.status(500).json(error)
}
})