背景介绍
最近为客户做的一个微信H5中要求在页面里生成二维码(是每次ID生成不同的二维码)。之前在ThinkPHP3.2项目中一直使PHPQrCode,但这个H5项目是基于ThinkCMF(ThinkPHP5.0内核)开发的,在开发过程中我发现JQuery也有生成二维码插件(Jquery.qrcode),所以决定用JS来生成二维码。
用JQuery Qrcode生成二维码
把插件JS文件放到项目JS文件夹后参考官网的示例代码,两分钟搞定。
<!-- HTML代码 -->
<div class="divOne" style="width: 120px;height: 120px;"></div>
<!-- JS代码 -->
$('.divOne').qrcode({text: 'http://www.xxx.com/demo', width: 120, height: 120});
存在问题
JS生成的二维码在微信客户端无法呼出“长按识别图片中二维码”菜单——因为二维码图片是用Canvas渲染出来 的微信不能识别。
用endroid-qrcode生成二维码
发现JS生成的二维码微信无法识别后,改回用PHP来生成二维码。在TP官网上有人说PHPQrCode这个插件太老了,所以使用endroid-qrcode。参考github上该插件的说明文档,使用composer在项目里安装好插件,然后在controller里引入插件生成二维码图片。
// 在controller头部添加引用声明
use Endroid\QrCode\QrCode;
// 这段代码有点啰嗦,生成图片在项目中的路径和绝对路径
$file_name = "{$this->id}.png";
// 计算记录对应的子文件路径(防止每个文件夹内保存的图片数量超过系统限制)
$sub_dir = num_divide_dir_path($this->id);
$local_dir = "/upload/qrcode/{$sub_dir}";
$local_path = $local_dir."/".$file_name;
$full_dir = ROOT_PATH."public".$local_dir;
$full_path = $full_dir."/".$file_name;
if(!file_exists($full_path)){
if(!is_dir($full_dir)){
mkdir($full_dir, 0777, true);
}
// 这是生成图片的主要方法
$qrCode = new QrCode($share_url);
$qrCode->writeFile($full_path);
}
//把图片路径传到view页面
$this->assign("qrcode_img", $local_path);
存在问题
本地一切运行正常后部署到服务器后发现QrCode在服务器上运行报错。经过排查发现原来是因为QrCode只能运行在PHP5.6以上版本,而服务器上的PHP版本是5.5。
用phpqrcode生成二维码
服务器是ubuntu 14.04,PHP版本是5.5.9-1ubuntu4.20,考虑到服务器上已有多个PHP项目运行,不敢冒然升级服务器。所以决定改用phpqrcode。把phpqrcode包放到thinkcmf根目录的simplewind/extend里。
$file_name = "{$this->id}.png";
// 计算记录对应的子文件路径(防止每个文件夹内保存的图片数量超过系统限制)
$sub_dir = num_divide_dir_path($this->id);
$local_dir = "/upload/qrcode/{$sub_dir}";
$local_path = $local_dir."/".$file_name;
$full_dir = ROOT_PATH."public".$local_dir;
$full_path = $full_dir."/".$file_name;
if(!file_exists($full_path)){
if(!is_dir($full_dir)){
mkdir($full_dir, 0777, true);
}
// 这是生成图片的主要方法
import('phpqrcode.phpqrcode',EXTEND_PATH);
\QRcode::png("http://www.baidu.com", $full_path);
}
//把图片路径传到view页面
$this->assign("qrcode_img", $local_path);
存在问题
经过调试发现\QRcode::png方法已执行,但无法在本地还是服务器上运行都没有生成二维码图片。而在本地TP3.2项目中测试发现可以正常生成图片。所以怀疑phpqrcode和ThinkCMF或ThinkPHP5.0不兼容。
再次用JQuery Qrcode生成二维码
当发现使用endroid-qrcode和phpqrcode都存在问题后,最后又决定使用JS来生成二维码图片。因为之前使用JQuery Qrcode已经可以生成二维码了,所以只需要解决微信识别二维码问题就可以。
最终找到了一个解决方法——把JQuery Qrcode生成的Canvas内容赋值给一个Img控件的src,而把Canvas隐藏起来。
<!-- HTML代码 -->
<img id="qrImg" class="qrcode-img img-responsive" src=""/>
<div class="divOne" style="width: 120px;height: 120px;display: none;"></div>
<!-- JS代码 -->
var qrcode= $('.divOne').qrcode({text: '{$sign_package["share_url"]}'});
var canvas = qrcode.find('canvas').get(0);
$('#qrImg').attr('src',canvas.toDataURL('image/jpg'));
绕了一大圈,最后还是用JQuery Qrcode搞定。
PS:网上有人说JQuery Qrcode生成的二维码识别不了是因为JQuery Qrcode默认生成二维码是用canvas来渲染,建议把rander参数设置成table就可以。但我本地测试把rander测试成table生成的二维码图片微信也不能自动识别。
插件 | 实现语言 | 优点 | 不足 |
---|---|---|---|
JQuery Qrcode | JS | 前端页面生成,不需要服务器上保存生成图片 | 直接生成的二维码微信无法识别,需要把生成图片赋值给Image控件的src才可以被微信识别 |
endroid-qrcode | PHP | 服务器端PHP生成,插件比较新; | PHP版本5.6+ |
phpqrcode | PHP | 服务器端PHP生成 | 插件比较老;不兼容ThinkPHP5.0或ThinkCMF |
参考引用