二维码 | 如何实现一码多用

本人查阅了许多资料,网上大部分的描述都比较模棱两可,我这里就将我的想法分享出来提供大家学习。

在这里实现一码多用的功能指的是 同个二维码在不同端扫出的结果不一样 例如微信扫跳出 微信小程序,支付宝扫跳出 支付宝小程序,内部APP扫码跳 内部页面等等。

1、实现流程

1.1、流程图
image
1.2、详细流程步骤

1、 是生成二维码,链接是前端H5界面的链接

2、 用户扫一扫的时候就会根据扫码的APP进行判断,其中微信扫一扫如果要 跳转小程序 的话需要在 微信公众平台 配置,而且小程序 暂不支持个人类型小程序开启此功能。相关配置操作如下:

  • 微信公众平台链接 https://mp.weixin.qq.com/wxamp/devprofile/

  • 配置二维码规则跳转二维码

    image
    image
    image

  • 二维码规则: 微信api里说的很清楚了
    1、二维码规则的域名须通过ICP备案的验证。
    2、支持http、https、ftp开头的链接(如:http://wx.qq.comhttps://wx.qq.com/mp/https://wx.qq.com/mp?id=123)。
    3、一个小程序帐号可配置不多于10个二维码前缀规则。

  • 前缀占用规则:
    开发者可选择是否占用符合二维码匹配规则的所有子规则。如选择占用,则其他帐号不可申请使用满足该前缀匹配规则的其他子规则。
    如:若开发者A配置二维码规则:https://wx.qq.com/mp?id=123,并选择“占用所有子规则“,其他开发者将不可以配置满足前缀匹配的子规则如https://wx.qq.com/mp?id=1234

3、内置APP需要在扫码端进行判断对应扫码内容并进行处理。如果识别到对应的 H5页面带有对应的参数 就跳转到 对应APP内部页面,如果是其他页面则跳转至单页面,展示复制并打开浏览器即可查看网站/展示对应的内容,这样就实现了APP扫码跳转功能。

2、后端实现

2.1、准备工作
image
2.2、代码实现
  • 根据内容安装依赖包后,我们开始封装生成二维码服务类
<?php

namespace app\common\service;
use Endroid\QrCode\ErrorCorrectionLevel;
use Endroid\QrCode\QrCode;
use think\Hook;

class QrcodeService
{
    /**
     * 生成二维码
     * @param string $content 生成二维码的内容
     * @param int $userId 用户ID,默认为0
     * @param string $logoImg 中间logo的图片本地路径
     * @param int $logoWidth 中间logo的宽度
     * @param int $logoHeight 中间logo的长度
     * @return mixed
     * @throws \Endroid\QrCode\Exception\InvalidPathException
     */
    public function create($content, $userId = 0, $logoImg = 0, $logoWidth = 50, $logoHeight = 50)
    {
        if(!$logoImg) $logoImg = ASSETS_PATH . 'img/qrcode.png';

        $qrCode = new QrCode($content);
        $qrCode->setSize(300);
        $qrCode->setWriterByName('png');
        $qrCode->setMargin(10);
        $qrCode->setEncoding('UTF-8');
        $qrCode->setErrorCorrectionLevel(ErrorCorrectionLevel::HIGH());
        $qrCode->setForegroundColor(['r' => 0, 'g' => 0, 'b' => 0, 'a' => 0]);
        $qrCode->setBackgroundColor(['r' => 255, 'g' => 255, 'b' => 255, 'a' => 0]);
//        $qrCode->setLabel('Scan the code', 16, __PUBLIC__.'/../assets/fonts/noto_sans.otf', LabelAlignment::CENTER());
        $qrCode->setLogoPath($logoImg); //设置LOGO
        $qrCode->setLogoSize($logoWidth, $logoHeight);
        $qrCode->setRoundBlockSize(true);
        $qrCode->setValidateResult(false);
        $qrCode->setWriterOptions(['exclude_xml_declaration' => true]);

        // Directly output the QR code
        header('Content-Type: ' . $qrCode->getContentType());

        // Save it to a file
        $dir = 'qrCode/' . date('Ymd', time()) . '/';
        if (!file_exists($dir)) mkdir($dir, 0777, true);

        //文件名称
        $dirUrl = $dir . 'qrCode.png';
        $url = PUBLIC_PATH . $dirUrl;
        if ($userId) $url = PUBLIC_PATH . $dir . $userId . '-qrCode.png';

        //写入本地
        $qrCode->writeFile($url);

        //保存到OSS
        $urlOss = Hook::listen("upload_oss", $url, null, true);

        //删除本地图片和文件夹
        if (file_exists($url)) {
            unlink($url);
            rmdir($dir);
        }
        return $urlOss;
    }

}

上面代码可以根据自己业务需求进行修改,我这里将二维码生成后 上传到OSS

  • 创建个人二维码
<?php

namespace app\api\controller;

use app\common\controller\Api;
use app\common\service\QrcodeService;
use app\common\service\RedisService;
use app\common\service\WeChatService;

/**
 * 二维码接口
 * @package app\api\controller
 */
class Code extends Api
{ 
    public function createSelfQrCode()
    {
        $redis = RedisService::connect();
        $user = $this->auth->getUser();
        $userId = $user['id'];
        $avatar = $user['avatar'];

        //判断Redis是否存在
        $imgUrl = $redis->get(RedisService::SU_QRCODE_SELF_USER . $userId);
        if (!$imgUrl) {
            //调用中转页面,type=1 个人二维码
            $h5Domain = db('sulink_setting')->where('id', 1)->value('h5_domain');
            $path = $h5Domain . 'pages/index/info/index?user_id=' . $userId . '&type=1';
            $imgUrl = (new QrcodeService)->create($path, $userId);

            //存一次Redis
            $redis->set(RedisService::SU_QRCODE_SELF_USER . $userId, $imgUrl);
        }

        $this->success(MSG_OK, [
            'is_enterprise_certification' => $user['is_enterprise_certification'],
            'is_certification' => $user['is_certification'],
            'company' => $user['company'],
            'username' => $user['username'],
            'avatar' => $avatar,
            'qrcode' => $imgUrl,
        ]);
    }
}

这里我将二维码存到redis中,RedisService是服务类,SU_QRCODE_SELF_USER 为键值的常量。

3、前端实现

3.1、APP内置扫一扫

// 允许从相机和相册扫码
uni.scanCode({
    success: function (res) {
        console.log('条码类型:' + res.scanType);
        console.log('条码内容:' + res.result);
    }
});
 
// 只允许通过相机扫码
uni.scanCode({
    onlyFromCamera: true,
    success: function (res) {
        console.log('条码类型:' + res.scanType);
        console.log('条码内容:' + res.result);
    }

  • 我们只要识别对应的 res.result 如果是H5页面的链接就直接跳转到对应的内部APP页面即可

4、一码多用第二种方法

如果我们要处理其他端的话,可以添加一个 前端界面(需要部署到服务器)去判断和跳转,不过这样我们需要每次将这个页面部署成一个可访问的h5网站,如下流程图:

4.1、流程图
image
4.2、代码实现
<script>
    //拆分链接后面的参数方法
    let newObj = {};
    function getQueryVariable(variable) {
        var query = window.location.search.substring(1);
        var vars = query.split("&");
        console.log(vars);
        for (var i = 0; i < vars.length; i++) {
            var pair = vars[i].split("=");
            newObj[pair[0]] = pair[1];
        }
        return (false);
    }

    getQueryVariable();
    let u = navigator.userAgent;
    if (u != null && u.contains("AlipayClient")) {
        // "来自支付宝";
        if (newObj.type == 1) {//跳转个人页
            window.location.href = 'http://192.168.2.198:8080/#/pages/index/info/index?uid=' + newObj.uid
        }
    } else if(u != null && u.contains("MicroMessenger")) {
        // "来自微信";
    } else if(u.contains("Android")) {
         // "Android移动客户端";
    } else if(u.contains("iPhone")) {
         // "iPhone移动客户端";
    } else if(u.contains("iPad")) {
         // "iPad客户端";
    } else if(u.contains("Window")) {
        // "PC端";
    } else if(u.contains("MY_APP_iOS/1.0.0")) {
         //  "App端";
    } else if(u.contains("miniProgram")) {
        // "微信小程序端";
    } else {
         // "其他客户端";
    }

</script>

其中 getQueryVariable 是获取拆分链接后面的参数方法,获取的参数存在对象 newObj 中。

  • 相关 user-agent 对应的类型如下:
  • 1、Android 系统下不同手机中微信的user-agent
Mozilla/5.0 (Linux; Android 7.1.1; MI 6 Build/NMF26X; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 MQQBrowser/6.2 TBS/043807 Mobile Safari/537.36 MicroMessenger/6.6.1.1220(0x26060135) NetType/WIFI Language/zh_CN
Mozilla/5.0 (Linux; Android 7.1.1; OD103 Build/NMF26F; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.49 Mobile MQQBrowser/6.2 TBS/043632 Safari/537.36 MicroMessenger/6.6.1.1220(0x26060135) NetType/4G Language/zh_CN
Mozilla/5.0 (Linux; Android 6.0.1; SM919 Build/MXB48T; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.49 Mobile MQQBrowser/6.2 TBS/043632 Safari/537.36 MicroMessenger/6.6.1.1220(0x26060135) NetType/WIFI Language/zh_CN
Mozilla/5.0 (Linux; Android 5.1.1; vivo X6S A Build/LMY47V; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.49 Mobile MQQBrowser/6.2 TBS/043632 Safari/537.36 MicroMessenger/6.6.1.1220(0x26060135) NetType/WIFI Language/zh_CN
Mozilla/5.0 (Linux; Android 5.1; HUAWEI TAG-AL00 Build/HUAWEITAG-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.49 Mobile MQQBrowser/6.2 TBS/043622 Safari/537.36 MicroMessenger/6.6.1.1220(0x26060135) NetType/4G Language/zh_CN
  • 2、iPhone 系统下的微信 user-agent
Mozilla/5.0 (iPhone; CPU iPhone OS 9_3_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Mobile/13F69 MicroMessenger/6.6.1 NetType/4G Language/zh_CN
Mozilla/5.0 (iPhone; CPU iPhone OS 11_2_2 like Mac OS X) AppleWebKit/604.4.7 (KHTML, like Gecko) Mobile/15C202 MicroMessenger/6.6.1 NetType/4G Language/zh_CN
Mozilla/5.0 (iPhone; CPU iPhone OS 11_1_1 like Mac OS X) AppleWebKit/604.3.5 (KHTML, like Gecko) Mobile/15B150 MicroMessenger/6.6.1 NetType/WIFI Language/zh_CN
Mozilla/5.0 (iphone x Build/MXB48T; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.49 Mobile MQQBrowser/6.2 TBS/043632 Safari/537.36 MicroMessenger/6.6.1.1220(0x26060135) NetType/WIFI Language/zh_CN
  • 3、微信内置浏览器与小程序中的 user-agent主要区别是小程序多了一个miniProgram
# 安卓系统中小程序 User Agent
Mozilla/5.0 (Linux; Android 7.1.1; MI 6 Build/NMF26X; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 MQQBrowser/6.2 TBS/043807 Mobile Safari/537.36 MicroMessenger/6.6.1.1220(0x26060135) NetType/4G Language/zh_CN MicroMessenger/6.6.1.1220(0x26060135) NetType/4G Language/zh_CN miniProgram
# 安卓系统中微信内置浏览器 User Agent
Mozilla/5.0 (Linux; Android 7.1.1; MI 6 Build/NMF26X; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 MQQBrowser/6.2 TBS/043807 Mobile Safari/537.36 MicroMessenger/6.6.1.1220(0x26060135) NetType/4G Language/zh_CN
  • 4、PC端的user-agent
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36

PS : 谢谢大家的观赏,有什么问题欢迎在留言区留言。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,802评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,109评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,683评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,458评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,452评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,505评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,901评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,550评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,763评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,556评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,629评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,330评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,898评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,897评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,140评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,807评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,339评论 2 342