最近在业务上遇到一个问题:在一个H5页面中需要打开微信的扫码界面。在uni-app中,有原生的扫码方法,但是很遗憾的是,这个方法不支持H5。因此就需要用到微信的JSSDK了。
在网上找了一堆,给的方法也是五花八门。要么就是代码都是错的,要么就是没有后端代码。于是乎只能自己动手丰衣足食。
关于appid还有怎么安装JSSDK这些就不再赘述了,直接在uni-app的官网就能找到。我采用的方法是npm安装Jweixin-module。但是看DCloud论坛中有人说这样安装的话有一些模块已经过时了,因此或许可以尝试先npm安装Jweixin-moudle,之后将js替换成微信官方最新的。
由于JSSDK有严格的认证机制,因此需要进行服务端的配置。我直接使用的纯原生php来搭建的服务,因为自己的博客服务器用的不是thinkphp,而且这个认证功能也没有非常复杂,没必要杀鸡用牛刀,对于服务器本身就配置好了thinkphp框架或者flask 框架这些的,把代码改一下即可。
后端代码:
<?php
header('access-control-allow-credentials:true');
header('access-control-allow-origin:'.$_SERVER['HTTP_ORIGIN']);
header('Access-Control-Max-Age: 1800');
header('Access-Control-Allow-Methods:GET,POST,PUT,POST');
header('Access-Control-Allow-Headers:x-requested-with,content-type');
error_reporting(1);
function guid() //生成随机字符串nonceStr用
{
if (function_exists('com_create_guid')) {
return com_create_guid();
} else {
mt_srand((double)microtime() * 10000);
$charid = md5(uniqid(rand(), true));
$uuid = substr($charid, 0, 8)
. substr($charid, 8, 4)
. substr($charid, 12, 4)
. substr($charid, 16, 4)
. substr($charid, 20, 12);
return $uuid;
}
}
function curl_get($url){ //get方法,用于获取accessToken和Jsapi-token
//初始化
$curl = curl_init();
//设置抓取的url
curl_setopt($curl, CURLOPT_URL, $url);
//设置头文件的信息作为数据流输出
// curl_setopt($curl, CURLOPT_HEADER, 1);
//设置获取的信息以文件流的形式返回,而不是直接输出。
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
//执行命令
$data = curl_exec($curl);
// echo curl_getinfo($curl, CURLINFO_HTTP_CODE); //输出请求状态
curl_close($curl);
return $data;
}
function renewTicket(){ //获取Jsapi-token
try {
$accessJson = json_decode(curl_get("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET")); //此处补上你的appid和appsecret
$accessToken = $accessJson->access_token;
$ticketJson = json_decode(curl_get("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" . $accessToken . "&type=jsapi"));
$ticketdata = array();
$ticketdata["ticket"] = $ticketJson->ticket;
$ticketdata["exp"] = time() + $ticketJson->expires_in;
$ticketFile = fopen('__Tickets', 'w'); //**重要** 请自行将__Tickets更名为随机字符串或不易被猜测的文件名,下同,另请注意Linux的读写权限分配,否则会出现无法写入新的tickets的情况
$ToWrite = json_encode($ticketdata);
fwrite($ticketFile, $ToWrite);
fclose($ticketFile);
return $ticketJson->ticket;
}catch (Exception $e){
echo $e;
}
}
function GetJsapi(){
$ticketfile = fopen('__Tickets',"r");
$tickets = json_decode(fread($ticketfile,filesize('__Tickets')));
fclose($ticketfile);
if(time()<$tickets->exp){
return $tickets->ticket;
}else{
return renewTicket();
}
}
$jsapi_ticket = GetJsapi();
$timestamp = time();
$nonce = guid();
$url = $_GET["url"];
$ret = array();
$ret["timestamp"] = $timestamp;
$ret["nonceStr"] =$nonce;
$tmpStr = "jsapi_ticket=".$jsapi_ticket.'&noncestr='.$nonce."×tamp=".$timestamp.'&url='.$url;
$tmpStr = sha1($tmpStr);
$ret["signature"] = $tmpStr;
echo json_encode($ret);
服务器的返回是一个json格式:
{
"timestamp":1616332427,
"nonceStr":"e5a4f4994472631a9f7299e358449fd9",
"signature":"9d85562617da3bf9ed729005079ab91f3d845556"
}
在uni-app端,在onLoad()下,先向服务器请求签名:
async getsign(){
this.url = location.href.split('#')[0]
uni.request({
url:"你的服务地址",
method:"GET,",
data:{
"url":this.url
},
success:((res)=>{
console.log(res.data),
this.retdata = res.data;
})
})
}
之后进行config:
jweixin.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: "APPID", // 必填,公众号的唯一标识
timestamp: this.retdata.timestamp , // 必填,生成签名的时间戳
nonceStr: this.retdata.nonceStr, // 必填,生成签名的随机串
signature: this.retdata.signature,// 必填,签名
jsApiList: ['scanQRCode'] // 必填,需要使用的JS接口列表
}),
jweixin.ready(function(){
jweixin.checkJsApi({
jsApiList: ['scanQRCode'], // 需要检测的JS接口列表,所有JS接口列表见附录2,
success: function(res) {
console.log("success"+res);
},
fail: function(res){
console.log("fail"+res);
}
});
})
,
jweixin.error(function(res){
// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
console.log(res,'接口验证失败')
});
之后就可以进行操作了,例如我这里需要用的扫码:
scanqr(){
var jweixin = require('jweixin-module');
jweixin.scanQRCode({
needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
scanType: ["qrCode","barCode"], // 可以指定扫二维码还是条形码,默认二者都有
success: function (res) {
// 要做的事情
}
});
}

Comments | NOTHING