uni-app中使用微信JSSDK

发布于 2021-03-21  3015 次阅读


最近在业务上遇到一个问题:在一个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."&timestamp=".$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) {
		 // 要做的事情
	   }
	});
}

等风来,不如追风去。