微信跳转外部浏览器

之前在做公司的h5项目时,搞了一个从微信跳转外部浏览器的功能,用户点击按钮就可以直接跳转。

目前比较常见的处理方式都是弹出一个遮罩层,提示用户点击右上角在浏览器中打开,这种操作对于目标用户(老年人)来说比较复杂了点,所以没有采用。

实现原理

客户端发起HTTP请求,后端接受到请求后,判断Header中的user-agent字段,如果判断用户是在微信中打开的链接,则返回206状态码和附件的头信息,微信会因为头部是下载处理,自动跳出到外部浏览器。

后端接口逻辑


@client.route("/readmi/download_app", methods=['GET'])
def download_app():
    response = make_response()
    user_agent = request.headers.get('User-Agent')
    # 微信内置浏览器
    if 'MicroMessenger' in user_agent:
        response.status = "206 Partial Content"
        response.headers.set('Content-Disposition', 'attachment; filename="load.doc"')
        response.headers.set('Content-Type', 'charset=utf-8')
        response.headers.set('Content-Range', 'bytes 0-1/1')
        response.headers.set('Content-Length', '0')
    else:
        response.status = "302"
        download_url = '落地页链接'
        # 添加参数
        args = request.args
        if len(args) > 0:
            download_url += '?'
            for arg_item in args.items():
                download_url += '{0}={1}&'.format(arg_item[0], arg_item[1])
            download_url = download_url[:-1]
        # 重定向到下载页面
        response.headers.set('Location', download_url)
    return response

206状态码

http 2xx 范围内的状态码就表明“客户端发送的请求已经被服务器接受并且被成功处理”。

206 状态码表示请求已成功,并且主体包含所请求的数据区间,该数据区间是在请求的 Range 首部指定的,主要用于断点续传功能。

这里其实不用206状态码也可以,市面上卖这种服务的提供的接口都是返回的200状态码

被封禁危险

由于微信官方是禁止了这种从微信直接跳转到外部浏览器的功能,所以如果有用户投诉或被腾讯安全网址安全中心检测到,现在这种跳转方式就有可能会被微信封掉域名。域名防封这方面还没有研究出解决方案

跳转至app

完成跳出微信的功能后,产品经理接着又来了个跳转到app的需求。

跳转到app本来是可以在微信内简单实现,但是微信还是限制了不能随便跳转到App,只有存在他们官方设置的白名单里的app才能直接跳转,所以只能是先跳转到外部浏览器,然后通过scheme协议跳转。相关代码:

var albumAppScheme = 'android://xxx' // 安卓端定义一个scheme
// 判断如果是安卓系统并且是非微信端(一般是从微信跳转到外部浏览器的情况),尝试打开App
if(isAndroid) {
    if(!isWeixin) {
        // 非微信端就尝试直接打开app
        url = albumAppScheme
        openApp(url)
    }
}

function openApp(url) {
    var iframe = document.createElement("iframe");
        iframe.style.display = "none";
        iframe.src = url;
        document.body.appendChild(iframe);
}

这篇之前是在项目组内部分享时写的,现在同步到自己的博客上来记录一下。