H5如何拉起微信扫一扫
项目开发中有很多场景需要拉起微信扫一扫,在这里主要记录下开发过程中遇到的一些问题,以及解决方案。仅供参考
官方api:
https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html
前端内容:
1.npm下载 / 导入相关JS
npm install weixin-js-sdk在需要调用JS接口的页面引入如下JS文件,(支持https):[http://res.wx.qq.com/open/js/jweixin-1.2.0.js](http://res.wx.qq.com/open/js/jweixin-1.2.0.js)2.引用(全局)main.js
import wx from "weixin-js-sdk";3.配置
1.从后端获取参数,通过config接口注入权限验证配置
WEIXIN_JSDK() {const url = encodeURIComponent(location.href.split("#")[0]); //获取当前页面路由http.fetchGet(`后端接口$ {url}`).then(data = >{let a = data.data.data;wx.config({debug: false,// 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。appId: a.appid,// 必填,公众号的唯一标识timestamp: a.timestamp,// 必填,生成签名的时间戳nonceStr: a.noncestr,// 必填,生成签名的随机串signature: a.signature,// 必填,签名jsApiList: ["scanQRCode", "getLocation"] // 必填,需要使用的JS接口列表});});},
2.调起扫一扫接口
wx.ready(function() {wx.scanQRCode({// 微信扫一扫接口desc: "scanQRCode desc",needResult: 1,// 默认为0,扫描结果由微信处理,1则直接返回扫描结果,scanType: ["qrCode", "barCode"],// 可以指定扫二维码还是一维码,默认二者都有success: function(res) {const getCode = res.resultStr; // 当needResult 为 1 时,扫码返回的结果} else {}},fail: function(res) {Toast(res.errMsg);}});});
后端内容:
1.获取参数
public function renew() {//获取ticket$ticket = $this->get_access_token($pay['app_id'],$pay['secret']);//生成JSSDK实例$opt['app_id'] = $pay['app_id'];$opt['jsapi_ticket'] = $ticket['ticket'];$opt['url'] = '此处填写你的当前地址url';$wx = $this->configuration($opt);$data['wx'] = $wx;return ajax_return($data,'成功',0);}public function get_access_token($appid,$secret) {//获取已存储d的token,token值2小时失效,需要自己存储$token = DB::name('wxtoken')->value('token');//获取ticket$get_jsapi_ticket = $this->get_jsapi_ticket($token);$get_jsapi_ticket = json_decode($get_jsapi_ticket,true);//如果token失效,就重新获取if($get_jsapi_ticket['errcode'] == 40001 || $get_jsapi_ticket['errcode'] == 42001 ) {$get_url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$secret;$data = $this->curl($get_url);$data = json_decode($data,true);DB::name('wxtoken')->where('id',1)->update(['token'=>$data['access_token']]);$get_jsapi_ticket = $this->get_jsapi_ticket($data['access_token']);}return($get_jsapi_ticket);}//获取ticketpublic function get_jsapi_ticket($token) {$get_ticket_url="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=".$token."&type=jsapi";$data = $this->curl($get_ticket_url);return($data);}//生成随机字符串private function createNonceStr($length = 16) {$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";$str = "";for ($i = 0; $i < $length; $i++) {$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);}return $str;}//返回配置config数据public function configuration($option) {//签名算法$timestamp=time();//时间戳$noncestr =$this->createNonceStr();//拼接$signature原型$ping="jsapi_ticket=".$option['jsapi_ticket']."&noncestr=".$noncestr."×tamp=".$timestamp."&url=".$option['url'];//加密生成signature$signature=sha1($ping);$signPackage = array("appID" => $option['app_id'],"noncestr" => $noncestr,"timestamp"=> $timestamp,"signature"=> $signature,"jsapi_ticket"=> $option['jsapi_ticket']);//返回参数return($signPackage);}
问题解决方法及原因
1.签名失效
– 首先利用js校验工具
http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 去校验下签名是否正确
– 再确认页面url是否正确(location.href.split(‘#’)[0]),包括’http(s)://’部分,以及’?’后面的GET参数部分,但不包括’#’hash后面的部分
– appId是否正确,config 中的 appid 与用来获取 jsapi_ticket 的 appid
以上是签名失效的检查顺序,并且要确保项目开发的安全域名已经在公众号内配置。
2.spa单页面应用,服务端渲染index页面返回客户端,本地页面切换不存在服务端刷新,因此,在需要调起扫一扫的页面传递的url与服务端url不一致,当强制刷新页面时,服务端的url与当前页面一致,因此可以成功获取。
解决方法 再进入该页面后强制刷新一次(reload)
当然要要标记下首次进入才需要刷新,否则会造成很对不必要的刷新
3.ios的签名要在入口页获取,解决了签名失效的问题
其他
1.安卓在当前页面注入config,获取签名
2.公众号确认是否配置安全域名

评论
