nodejs二维码扫描—实现兑换码自动核销
背景
该文章主要是为了实现在没有扫码器的情况下,怎么识别分辨是哪个用户用扫一扫扫描的二维码。设计由来:主要是公司项目有个功能是一个关于将类似于优惠券的兑换码生成二维码后,用户需要向商家展示二维码,由商家扫描二维码进行核销。这样就涉及的如何判断是商家扫描的而不是普通用户扫描的?
实现概述
用户点击优惠券->后台会返回相应的二维码(带有相应产品的信息)->用户/商户扫描二维码->进行微信网页授权->进入后台进行微信openid验证,判断是否为商户用户(提前将商户的微信openid保存下来,供本次核对商户信息)->为商户(进行核销)/普通用户(只显示兑换码信息等普通信息)
开发环境
1.nodejs
相关依赖
1.qr-image(其实还有个用户量很多的node-qrcode,但是实现本功能比较繁琐,所以选择了小众的qr-image):主要是为了动态显示二维码,无需后台保存二维码图片。
2.微信网页授权:用于识别是哪个用户扫描的二维码。
微信网页授权
第一步:用户同意授权,获取code
在确保微信公众账号拥有授权作用域(scope参数)的权限的前提下(服务号获得高级接口后,默认拥有scope参数中的snsapi_base和snsapi_userinfo),引导关注者打开如下页面:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect 若提示“该链接无法访问”,请检查参数是否填写错误,是否拥有scope参数对应的授权作用域权限。(如果想让微信回调自己的路由时同时带有自己的参数,可以在回调路由里添加自己的参数,再进行url编码,这样即可带有自己的参数回调回来,具体实现可看下方实现)
第二步:通过code换取网页授权access_token
首先请注意,这里通过code换取的是一个特殊的网页授权access_token,与基础支持中的access_token(该access_token用于调用其他接口)不同。公众号可通过下述接口来获取网页授权access_token。如果网页授权的作用域为snsapi_base,则本步骤中获取到网页授权access_token的同时,也获取到了openid,snsapi_base式的网页授权流程即到此为止。
尤其注意:由于公众号的secret和获取到的access_token安全级别都非常高,必须只保存在服务器,不允许传给客户端。后续刷新access_token、通过access_token获取用户信息等步骤,也必须从服务器发起。
请求方法
获取code后,请求以下链接获取access_token: https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
第三步:拉取用户信息(需scope为 snsapi_userinfo)
如果网页授权作用域为snsapi_userinfo,则此时开发者可以通过access_token和openid拉取用户信息了。
请求方法
http:GET(请使用https协议) https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
该调用,主要是为了获取用户的详细信息用于后台的核对,分辨是自己后台中的商户还是普通用户。
干货代码
第一步客户端请求
//bms.js
router.get("/QRcode",BMSServer.qrcode);
//bmsserver.js
//获取用户传过来的获取兑换码请求
qrcode:function(req,res){
let pid=req.body.pid;//用户告知是哪个商品(即优惠券ID)
res.render(renderPath+'qrcode',{
pid:pid});
},
//qrcode.ejs
<!DOCTYPE html>
<html>
<head>
<link rel='stylesheet' href='/stylesheets/style.css'/>
</head>
<body>
<h1 style="position:absolute;left:43%;top:5%">优惠券二维码</h1>
<img src="/Data/create_qrcode?url=https://xxxx.xxxxx.xxxx/xxx/qrcodeInfo&pid=<%=pid%>" style="width: 100%;height:100%;margin-top:10%"/>
</body>
</html>
第二步后台接收到第一步img标签的src请求
//1.由img标签的src请求create_qrcode请求返回二维码
//data.js
router.get("/create_qrcode",DataServer.create_qrcode);
//dataserver.js
create_qrcode: