通过短信中的链接打开小程序

在开发小程序的过程中,我遇到了这样的一个需求,通过短信中的链接打开一个h5,这个h5可以实现点击跳转小程序,或者扫码跳转,并且将链接上的参数填充到小程序界面上。下面来描述一下我的开发步骤及实现方案。

这个需求大部分的功能是基于 h5 页面实现的,所以首先进行对 h5 页面的攻破。样式部分不多说,开始攻破两大功能点。

1. 通过点击按钮跳转小程序

点击按钮跳转即通过链接实现跳转,这里使用了小程序官方 api - urlscheme.generate

在这个api中提到获取 URL Scheme 需要 access_token。

access_token,是小程序全局唯一后台接口调用凭据。需要通过官方 api - auth.getAccessToken 去调取,文档中提示 access_token 有效期是 2个小时,所以我将获取的 access_token 存储在 redis 中,并设定过期时间,避免反复调用造成 access_token 刷新,产生不必要的冲突。

下面是获取 accessToken 的代码实现:

const getAccessToken = (appId, appSecret) => {
    return new Promise((resolve, reject) => {
        // 从 redis 中查找是否有 accessToken,如果 accessToken 过期,则获取不到 accessToken
        getRedisData(appId).then((accessToken) => {
            if (!!accessToken) {
                // 有 accessToken 则直接返回
                resolve(accessToken);
            } else {
                // 没有则通过接口重新获取 accessToken
                request({
                    url: `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appId}&secret=${appSecret}`,
                    method: 'GET',
                    timeout: 5000
                }, (err, response, body) => {
                    body = JSON.parse(body);
                    if (err || !body) reject({errCode: -10, errInfo: err.toString()});
                    if (body.access_token) {
                        let accessToken = body.access_token;
                        // 获取后将 accessToken 存储在 redis 中,并设定过期时间,如果过期,则获取不到 accessToken
                        setRedisDataEx(appId, accessToken, body.expires_in);
                        resolve(accessToken);
                    } else {
                        reject({errCode: body.errcode, errInfo: body.errmsg});
                    }
                });
            }
        });
    });
}

下面是获取 URL Scheme 代码实现:

const getGenerateScheme = (req, res) => {
    let { tenantCode, ...rest } = req.body;
    // rest 为文档中的剩余参数
    let cfg = config[tenantCode]; // cfg中 存储了小程序的 appId 及 appSecret
    if (!cfg) return res.send(getErrInfo(errCode.ERR_PARAMETER_UNAVAILABLE, 'tenantCode'))
    
    let { appId, appSecret } = cfg
    getAccessToken(appId, appSecret).then((accessToken) => { // 获取 accessToken
        const params = {
            ...rest
        }
        request({
            url: `https://api.weixin.qq.com/wxa/generatescheme?access_token=${accessToken}`,
            method: 'POST',
            timeout: 5000,
            headers: {
                'content-type': 'application/json',
            },
            body: JSON.stringify(params)
        }, (err, response, body) => {
            body = JSON.parse(body);
            if (err || !body) return res.send({errCode: -10, errInfo: err.toString()});
            if (body.openlink) {
                // 获取跳转链接 openlink
                let openlink = body.openlink;
                return res.send({errCode: 0, result: openlink});
            } else {
                return res.send({errCode: body.errcode, errInfo: body.errmsg});
            }
        });
    }).catch((err) => {
        return res.send(err);
    });
}

上述代码中 rest,即为文档中的参数。

调用 getGenerateScheme 接口后即可获得 URL Scheme,如:weixin://dl/business/?t=LcoXo1wSXIq

iOS系统支持识别URL Scheme,可在短信等应用场景中直接通过Scheme跳转小程序。
Android系统不支持直接识别URL Scheme,用户无法通过Scheme正常打开小程序,我们需要使用H5页面中转,再跳转到Scheme实现打开小程序,跳转代码示例如下:

location.href = 'weixin://dl/business/?t=LcoXo1wSXIq
该跳转方法可以在打开H5时立即调用,也可以在用户触发事件后调用。

2. 通过生成的二维码图片扫码跳转小程序

生成二维码需要用到官方 api - wxacode.getUnlimited
下面是获取带参小程序二维码图片代码:

const getWxaCode = (req, res) => {
    let { tenantCode, ...rest } = req.body;
    // rest 为文档中的剩余参数
    let cfg = config[tenantCode];
    if (!cfg) return res.send(getErrInfo(errCode.ERR_PARAMETER_UNAVAILABLE, 'tenantCode'))
    
    let { appId, appSecret } = cfg; // cfg中 存储了小程序的 appId 及 appSecret
    getAccessToken(appId, appSecret).then((accessToken) => { // 获取 accessToken
        const params = {
            ...rest
        }
        request({
            url: `https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=${accessToken}`,
            method: 'POST',
            timeout: 5000,
            headers: {
                'content-type': 'image/jpeg',
            },
            encoding: null,
            body: JSON.stringify(params)
        }, (err, response, body) => {
            if (err || !body) return res.send({errCode: -10, errInfo: err.toString()});
            if (body) {
                const type = response.headers['content-type'];
                const img = `data:${type};base64,${body.toString('base64')}`;
                return res.send({errCode: 0, result: img});
            }
        });
    }).catch((err) => {
        return res.send(err);
    });
    
}

这里返回的 body 是 图片 Buffer 文件,Buffer是一个像Array的对象,但它主要用于操作字节,也就是二进制数据,它的元素为16进制的两位数,即0到255的数值。

request 发送请求的编码格式 encoding,会默认为 UTF-8,而对于不能识别的byte串会解码成�,通过将encoding设为null,也就不对原始数据编码,保持原始的二进制图片数据,即可得到 Buffer 文件的正确格式。

获取到 Buffer 文件后我又将其转换成 base64 的格式,以便前端直接使用。

至此这个 h5 的功能基本完成点击 链接 看看效果吧!如果如要通过短信发送打开,那么将长链接转换成短链接通过短信发送出去即可。

3. 接收跳转参数

通过接口获取的链接及二维码,在跳转时会将其余参数转换成页面 ? 后面的部分,形如 page='pages/index/index?foo=bar'。我们可以在小程序的 App.onLaunch、App.onShow 和 Page.onLoad 的回调函数中获取到。


本文首发于我的博客 mogii'blog 欢迎大家光临~

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

推荐阅读更多精彩内容