现在二维码的使用场景越来越广泛,如网页端为了兼容手机浏览,会为PC端网站每个页生成唯一的二维码,如在浏览我们站点文章时,在这部分是可以查看到生成的手机端的二维码的,如下图:
本文不介绍网页如何无限生成二维码的技术,只讲微信小程序通过调用wxacode.getUnlimited生成无限小程序码的功能实现。
因为微信小程序官方文档对本人来说可能是写得比较高深,以至于经常还得配合很多文档才能理解,再一个本文不是针对云开发的,如果使用云开发可以另查其他相关文章。
好,进入实战,先看最后实现的场景载图:
在订单中到店自取时选择货到付款时,需要用到核销码的功能,如下图:
有些系统开发会直接使用一串数字实现,如美团的就是用数字和二维码相结合,但美团只是生成二维码,并没有使用小程序码功能,为什么美团不用小程序码,而使用二维码呢,因为美团开发有独立的核销系统,所以用二维码加数字更符合他们的场景使用,好,还是言归正题。
点击核销码时,弹出微信小程序的二维码,如下图:
开发SAAS类型的小程序,这样的优势还是比较明显,在后台设置了有核销功能权限的用户,就可以通过扫小程序码对此订单进行核销操作,当然微信小程序码更大的用途还不止如此。
使用场景讲完,再进行实现方法讲解,所使用的开发环境是阿里云ecs服务器主机、系统nginx/1.18、搭建宝塔面板、PHP版本7.3、MYSQL5.5。
在申请小程序码时,首先要使用微信的token令牌,和令牌使用方式和大部分API区别不大,令牌大概2小时的使用期限,所以不是每次申请小程序调用都去获取令牌,像令牌的管理,应该不写在场景里,可以单独的开发个页,然后通过自动化执行命令,如2小时就更新一次,这个实现起来非常简单,这里不作详细说明,在本文就直接把令牌管理也放在代码里了。
首先我们要建一个数据表来存放令牌,名称就叫wzjm_wx_token吧,然后三个字段,id(int 4), token_str(text),token_time(varchar 32),数据表创建命令如下:
CREATE TABLE `wzjm_wx_token` (
`id` INT( 4 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`token_str` TEXT NULL ,
`token_time` VARCHAR( 32 ) NULL
) ENGINE = MYISAM CHARACTER SET utf8 COLLATE utf8_estonian_ci;
申请令牌的接口是:auth.getAccessToken,调用参数与方法介绍微信官方文档有了,大家就去查官方的资料,但微信官方没实现的案例,我们就写实例。
代码如下:
/*
读数据库代码略
*/
//生成小程序码
$time=time();
$token_time=time();//这里改成取数据表的token_time
$appid="XXXX";//微信小程序appid
$secret=""XXXX;//微信小程序secret
if($time>=($token_time+6000))
{
//token过期,这里为什么使用6000秒,而不使用7200秒呢,反正系统给的调用次数足够,但如果使用7200秒是极容易产生BUG的。
$url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$secret;
$curl = curl_init ( ) ;
//设置抓取的url
curl_setopt ( $curl , CURLOPT_URL , $url) ;
//设置头文件的信息作为数据流输出
curl_setopt ( $curl , CURLOPT_HEADER , 0 ) ;
//设置获取的信息以文件流的形式返回,而不是直接输出。
curl_setopt ( $curl , CURLOPT_RETURNTRANSFER , 1 ) ;
//执行命令
$data = curl_exec ( $curl ) ;
//关闭URL请求
curl_close ( $curl ) ;
//显示获得的数据
$data_info = json_decode($data,true);
if($data_info['access_token']<>"")
{
$up_date=array();
$up_date['ewm_token']=$data_info['access_token'];
$up_date['ewm_time']=time();
/*
更新数据库代码略,可以自己补充
*/
}
else
{
//提示异常
exit();
}
//token过期
}
通过以上代码,令牌管理基本可以了,如果要统一更新也更加简单了,写好分析加条每隔一段时间自动化执行命令即可。
令牌代码实现后,就可以申请小程序码了。
像订单核销场景,需要针对每个订单添加一个小程序码的字段,如果不做保存,每次使用时都去申请这样会造成比较占用系统的资源。
继续看代码:
$token="XXXXXX";//这是上段代码取得的token值
$url="https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=".$token;
$ewm_list=array();
$ewm_list['scene']='id='.$id;//小程序传参
$ewm_list['page']='pages/index/welcome';//扫码时进入小程序的页面
$ewm_list['width']=215;//小程序码的宽度和高度
$ewm_str = json_encode($ewm_list);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $ewm_str);
$data=curl_exec($ch);
curl_close($ch);
$ts=array();//提示信息
$data_str= json_decode($data,true);
if($data_str['errcode'])
{
//这个判断一定要加,不然返回错异常的时候,也会生成不可以用的小程序码
$ts['user_zt']="300";
$ts['user_info']="生成二维码异常";
echo json_encode($login_info);
exit();
}
else
{
$path = 'userfiles/ewm';//图片本地保存路径
if(!file_exists($path))
{
//检查是否有该文件夹,如果没有就创建,并给予权限
mkdir($path, 0700);
}
$path = $path.'/ewm_'.$id.'.jpg';
//保存到服务器
if(file_put_contents($path, $data))
{
/*
更新订单中的小程序码字段,这里略过
*/
}
else
{
$ts['user_zt']="300";
$ts['user_info']="生成二维码异常";
echo json_encode($ts);
exit();
}
//保存到服务器
//生成小程序码,返回给小小程序
$ts['ewmimg']=$system_url."/wx/".$path;
$ts['user_zt']="200";
echo json_encode($ts);
exit();
}
最后到小程序上的逻辑实现,先看wxml关键代码:
<view class="btn-pay" catchtap="showewm" data-id="{{item.id}}">核销码view>
<view class="ewm-box" hidden='{{ewmflag}}'>
<view class="ewm-img-box">
<image src="{{ewmimg}}" class="ewm-img">image>
view>
<view class="btn-list">
<view class="btn-close" bindtap="closeewm">
关闭
view>
view>
view>
<view class='mask' hidden='{{maskFlag}}'>view>
wxss代码:
.btn-pay{
width: 160rpx;
border-radius: 30rpx;
height: 60rpx;
line-height: 60rpx;
text-align: center;
border: 1px solid #dadada;
margin-left: 20rpx;
}
.ewm-box{
width: 650rpx;
height: 700rpx;
position: fixed;
left: 50rpx;
top: 50%;
margin-top: -350rpx;
z-index: 9999;
background: #FFFFFF;
border-radius: 30rpx;
}
.ewm-img-box{
width: 430rpx;
height: 430rpx;
margin: 40rpx auto;
}
.ewm-img{
width: 430rpx;
height: 430rpx;
}
.btn-list {
position: absolute;
left: 0;
top: 550rpx;
display: flex;
justify-content: center;
width: 100%;
z-index: 99999;
}
.btn-close {
width: 30%;
height: 60rpx;
line-height: 60rpx;
text-align: center;
border-radius: 30rpx;
border: 1px solid #999;
color: #666;
}.mask {
position: fixed;
width: 100%;
height: 100%;
top: 0px;
background: rgba(0, 0, 0, 0.6);
overflow: hidden;
z-index: 9998;
}
微信JS代码:
Page({
data: {
ewmflag:true,
maskFlag:true,
ewmimg:'',
},
showewm:function(e){
var id = e.currentTarget.dataset.id;
var that=this;
that.setData({
ewmflag:false,
maskFlag:false,
});
wx.showLoading({
title: '加载中',
});
wx.request({
url: '取小程序码的服务器网页地址',
data: {
id:id,
},
success: function (res) {
if (res.data['user_zt'] == '200') {
that.setData({
ewmimg: res.data['ewmimg'],
});
}
},
complete: function () {
wx.hideLoading();
}
});
},
closeewm:function(){
var that=this;
that.setData({
ewmflag:true,
maskFlag:true,
})
},
})
至止,关键部分的代码实例已完成,当然在实际场景中还需要添加各类事件的逻辑需要处理,非主要功能的逻辑代码都删除了。
在开发生成小程序这代码部分,当时出了点BUG,生成的图片就是一个小方格图标,排查了很久没能找到原因,中途显示器出现太热出现少量花点,休息了一下,等冷却后再次重写才见到小程序码,所以那个生成小方格的迷到现在还不知道是什么原因造成。
最后开发时,如果还没发布的小程序是不可以生成小程序的