微信小程序生态11—一个二维码同时支持微信、钉钉、支付宝扫码打开小程序

一、前言

大家有没有好奇过饭店扫码点餐的时候,小程序是如何打开的?商家是怎么确认桌号的?为什么有的码微信可以扫,支付宝也可以扫?

本篇文章将会给大家介绍:如何使用二维码实现一码多扫 。

二、微信、钉钉、支付宝扫码打开小程序的规则设定

1. 微信

官方文档地址:developers.weixin.qq.com/miniprogram...

(1)打开方式

官方文档如下:

  • 从2017年5月开始,微信客户端支持二维码规则根据"子路径匹配"。如原有二维码链接为 www.qq.com/a/123456 ,其中12345为业务参数,则可配置规则 www.qq.com/a/ 实现扫码打开小程序。

解释和补充一下:

  • 微信小程序扫码需要一个域名且支持http/https,不能随便乱输入,也就是说配置IP地址是不行的;
  • 必须要按照它的规则来配置链接,否则打不开。这里有个隐藏问题,一个规则只能打开一个页面,规则与页面是一一对应的,而规则的上限为100个;
  • 扫码时,微信不会调用你的服务器接口,它会直接打开小程序。但是配置规则时需要你添加校验文件,我的做法是自己写个与规则一致的接口直接返回校验文件的内容,这个接口功能不仅如此,后面会详细概述;

(2)完整的配置界面

2. 钉钉

官方文档地址:open.dingtalk.com/document/or...

(1)打开方式

钉钉小程序的打开方式很简单,是通过小程序schema打开的,配置如下:

perl 复制代码
dingtalk://dingtalkclient/action/open_micro_app?corpId=%s&appId=%s&page=%s

(2)注意事项

  • 该链接是一个通用链接,想要打开指定小程序需要配置appid参数;
  • 钉钉小程序是有企业区分的,也就是A企业下的小程序,如果用户不在A企业中是无法打开的,这个问题我会在下文中单独介绍;
  • 由于页面路径中存在"/"符号,所以schema中的参数需要进行转义,否则会报错;

3. 支付宝

官方文档地址:opendocs.alipay.com/mini/03cj40

(1)打开方式

支付宝小程序也是通过schema配置打开,配置如下:

perl 复制代码
alipays://platformapi/startapp?appId=%s&page=%s

三、微信、钉钉、支付宝扫码如何携带参数

1. 微信

(1)参数携带

  • 第一种,通过路径携带参数,例如http://www.qq.com/123456,其中123456就可以当做参数

  • 第二种,通过"?"携带参数,例如http://www.qq.com/aa?param1=111

(2)页面获取参数

js 复制代码
Page({
  onLoad(query) {
    const q = decodeURIComponent(query.q) // 获取到二维码原始链接内容
    const scancode_time = parseInt(query.scancode_time) // 获取用户扫码时间 UNIX 时间戳
  }
})

2. 钉钉

直接放在page上,例如:dingtalk://dingtalkclient/action/open_micro_app?appid=xxx&param1=111

3. 支付宝

同钉钉

四、 微信、钉钉、支付宝扫码的特点

  • 钉钉、支付宝小程序扫码的原理一样,使用schema就可以打开小程序,而微信小程序是使用规则匹配的方式;

  • 钉钉小程序有企业隔离的问题,如果用户不在当前企业下,是打不开小程序的;

  • 钉钉、支付宝小程序的schema较长,不建议使用schema生成二维码,否则码会很密不容易扫描;

  • 微信小程序在配置扫码规则时已经确定了是哪个小程序,而钉钉和支付宝是通过AppID参数的方式确定;

  • 微信小程序配置扫码规则时需要校验文件,而钉钉、支付宝小程序不需要;

  • 整体来说,钉钉、支付宝小程序实现较为简单,微信小程序扫码实现起来较为复杂;

五、实现多码合一

1. 扫码的原理

在实现扫码功能之前,我们需要先知道扫码的原理。在微信、支付宝、钉钉这些超级APP中,都内置了一个专属浏览器。而二维码的本质就是一个链接,扫码的动作就是在浏览器中输入这个链接然后点击搜索。

那么根据这个原理,我们可以得出一个结论:扫码的动作是可以直接调用后台接口的。所以我们只需要统一这几个端的扫码接口,那么就可以实现一码多扫了。

2. 功能实现

(1)实现思路

通过第一章节我们知道,钉钉和支付宝的打开逻辑简单,配置好schema就行;而微信只在配置的时候调用一次接口,所以返回校验文件内容。实现思路是:

(2)后台代码

java 复制代码
/**
  * 扫码打开各类小程序
  *
  * @param pathValue 路径参数
  * @param param1  参数1
  * @param param2  参数2
  *              
  * @return
  */
  @GetMapping("/scan/{pathValue}")
  public Object scan(
            @PathVariable(name = "pathValue") String pathValue,
            @RequestParam(required = false) String param1,
            @RequestParam(required = false) String param2) {
    //如果是微信校验文件的请求,一般是http://www.test.com/scan/xxx.txt格式
    //此时该参数会占用pathValue参数
    if (pathValue.contains(".txt")) {
        //直接返回对应的校验文件内容
        return "xxx";
    }
    //如果是钉钉或支付宝的请求,则生成schema
    ModelAndView modelAndView = new ModelAndView("scan");
    
    //获取钉钉小程序的AppId,可以写在配置文件中
    String dingAppId = "xxx";
    //获取钉钉组织corpId,可以写在配置文件中
    String corpId = "xxx";
    //生成钉钉的schema
    String dingTalkSchema = "dingtalk://dingtalkclient/action/open_micro_app?corpId="+corpId+"&appId=" + dingAppId + "&page=pages/Index/index?param1=" + param1 + "&param2=" + param2;
    modelAndView.addObject("dingTalkSchema", dingTalkSchema);
      
    //获取支付宝小程序的AppId,可以写在配置文件中
    String alipayAppId = "xxx";
    //生成支付宝的schema
    String alipaySchema = "alipays://platformapi/startapp?appId=" + alipayAppId + "&page=pages/Index/index?param1=" + param1 + "&param2=" + param2;
    modelAndView.addObject("dingTalkSchema", alipaySchema);

    return modelAndView;
}

(3)scan.vm模板

js 复制代码
<script>
    window.dingTalkSchema = '${dingTalkSchema}'
    window.alipaySchema = '${alipaySchema}'
    //判断当前浏览器内核
    var userAgentStr = window.navigator.userAgent;
    if (/AlipayClient/.test(userAgentStr)) {
        console.log('Alipay(支付宝)');
        window.location.href = window.alipayPage
    } else if (/DingTalk/.test(userAgentStr)) {
        console.log('DingTalk(钉钉)');
        window.location.href = window.dingTalkPage
    }
</script>

除微信小程序外(微信小程序使用路径匹配的方式打开),其他小程序都通过判断当前浏览器内核重定向到不同小程序打开url。

(4)解决钉钉小程序企业隔离问题

上面有说道,如果用户不在目标企业下,是打不开该小程序的。所以为了优化用户的体验问题,我们可以修改一下流程:

这个流程可以全部通过js代码实现,逻辑如下:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <!-- 方案二 ,该方法依赖jquery库-->
    <script src="https://g.alicdn.com/dingding/dingtalk-jsapi/2.10.3/dingtalk.open.js"></script>
    <script>

    </script>
</head>
<style>
</style>
<body>
</body>
<script>
    window.corpId = '${corpId}'
    window.appId = '${appId}'
    window.page = '${page}'
    dd.ready(function () {
        dd.runtime.permission.requestAuthCode({
            corpId: window.corpId,
            onSuccess: function (result) {
                dd.biz.navigation.replace({
                    url: "dingtalk://dingtalkclient/action/open_micro_app?corpId=" + window.corpId + "&appId=" + window.appId + "&page=" + window.page,
                    onSuccess: function (res) {
                        // 调用成功时回调
                        console.log(res)
                    },
                    onFail: function (err) {
                        // 调用失败时回调
                        console.log(err)
                    }
                });
            },
            onFail: function (err) {
                //目前只能使用文字进行判断
                if (err.errorMessage.indexOf('用户不在当前企业') != -1) {
                    dd.biz.navigation.replace({
                        url: "https://wx-in-i.dingtalk.com/invite-page/weixin.html?bizSource=____source____&corpId=" + window.corpId,
                        onSuccess: function (res) {
                            // 调用成功时回调
                            console.log(res)
                        },
                        onFail: function (err) {
                            // 调用失败时回调
                            console.log(err)
                        }
                    });
                } else {
                    dd.biz.navigation.replace({
                        url: "dingtalk://dingtalkclient/action/open_micro_app?corpId=" + window.corpId + "&appId=" + window.appId + "&page=" + window.page,
                        onSuccess: function (res) {
                            // 调用成功时回调
                            console.log(res)
                        },
                        onFail: function (err) {
                            // 调用失败时回调
                            console.log(err)
                        }
                    });
                }
            }
        })
    });
</script>
</html>

那么将钉钉小程序的打开URL换成当前页面

js 复制代码
if (/DingTalk/.test(userAgentStr)) {
      console.log('DingTalk(钉钉)');
      window.location.href = "xxx.html"
}
相关推荐
我不是外星人3 分钟前
浅谈我对 AI 发展的看法
前端·ai编程·claude
码不停蹄的玄黓15 分钟前
Spring Bean 生命周期
java·后端·spring
西安邮电大学27 分钟前
分治算法详细讲解
java·后端·其他·算法·面试
老马聊技术39 分钟前
AI对话功能之SpringBoot整合Vue3
vue.js·人工智能·spring boot·后端
甲维斯44 分钟前
测一波Kimi K2.7,消耗一周配额!
前端·人工智能·游戏开发
Dick5071 小时前
ROS2 多机器人通用 Driver 层复盘:BaseRobotDriver 到多平台 Mock 切换实现
前端·javascript·机器人
武子康1 小时前
调查研究-174 什么是“红丸主义“:它为什么吸引人,又为什么容易把人带偏?
后端
神奇小汤圆1 小时前
白嫖DeepSeek V4 Pro!免费无限用,还能接入Claude-Code
后端
码不停蹄的玄黓1 小时前
SpringBoot 全局异常处理器实现
java·spring boot·后端
xiaofeichaichai1 小时前
前端安全 XSS 与 CSRF
前端·安全·xss