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);
}
//获取ticket
public 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.公众号确认是否配置安全域名
评论