微信外网打开小程序(URL Scheme)


在之前我们只能在微信内的网页中使用微信的开发标签-小程序跳转按钮 打开小程序,只有这样一种单一的场景。

而在实际的业务中,我们希望在给用户发送的营销短信、邮件或其他渠道如APP打开小程序,以快速获取用户流量,完成引流、导购等目的。

近期微信支持URL Scheme打开小程序

首先我们先来看一下目前微信官方提供的两种打开微信小程序的方式以及相关适用场景

打开方式适用场景场景值使用方式备注官网链接
URL Scheme 短信、邮件、等微信外网页打开小程序 1065 location.href = 'weixin://dl/business/?t= *TICKET*' TICKET由服务端接口返回(openlink) https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/url-scheme/urlscheme.generate.html
微信内网页 1167 页面配置标签 需配置JS接口域名或云开发静态网站托管绑定的域名下网页 https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_Open_Tag.html

URL Scheme的获取

方案一通过服务端接口获取:

ps:怎样获取ACCESS_TOKEN,这里就不写了

请求地址:

POST https://api.weixin.qq.com/wxa/generatescheme?access_token=ACCESS_TOKEN

请求参数:

属性类型默认值必填说明
access_token string   接口调用凭证
jump_wxa Object   跳转到的目标小程序信息。
is_expire boolean false 生成的scheme码类型,到期失效:true,永久有效:false。
expire_time number   到期失效的scheme码的失效时间,为Unix时间戳。生成的到期失效scheme码在该时间前有效。最长有效期为1年。生成到期失效的scheme时必填。

  

 

 

 

 

  

jump_wxa 的结构:

属性类型默认值必填说明
path string   通过scheme码进入的小程序页面路径,必须是已经发布的小程序存在的页面,不可携带query。path为空时会跳转小程序主页。
query string   通过scheme码进入小程序时的query,最大1024个字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~

 

 

 

请求示例:

{
    "jump_wxa":
    {
        "path": "/pages/tab",
        "query": "xx=1&xxx=1"
    },
    "is_expire":true,
    "expire_time":1614059318
}

返回示例:

{
 "errcode": 0,
 "errmsg": "ok",
 "openlink":"weixin://dl/business/?t= *TICKET*",
}

请求代码:

    /**
     * 获取scheme(创建)
     * @param array $params
     * @return array
     * @throws Exception
     */
    public function generateScheme(array $params)
    {
        list($scene, $path, $query, $appid, $expire_time) = $this->getParams($params);


        //获取小程序实例
        $app = XXXX;

        $tag = $this->setTag($scene, $appid, $path, $query);
        //查询数据库/缓存
        $infoArr = $this->getSchemeByTag($tag);
        if ($infoArr) return $infoArr;

        /**
         * 请求微信接口
         */
        $is_expire = $expire_time ? true : false;   //到期失效:true,永久有效:false。
        $openlink = $this->wxGenerateScheme($is_expire, $expire_time, $path, $query, $app);

        //保存到数据库
        $this->create($params, $appid, $openlink, $tag, $is_expire);

        $returnArr = [
            'is_expire' => $is_expire,   
            'expire_time' => $expire_time,                  
            'tag' => $tag,
            'openlink' => $openlink,
            'appid' => $appid,
        ];
        $key = $this->setCacheKey($tag);
        $redis->setex($key, $this->setCacheTime($expire_time), json_encode($returnArr));
        return $returnArr;
    }

    /**
     * 通过标记获取openlink
     * @param $tag
     * @return array|mixed
     * @throws UserException
     */
    public function getSchemeByTag($tag)
    {
        $key = $this->setCacheKey($tag);
        if ($cache = $redis->get($key)) return json_decode($cache, true);
        
        $info = Scheme::find()->andWhere(['tag' => $tag])->one();
        if (empty($info)) return [];

        $returnArr = [
            'is_expire' => $info->is_expire,
            'expire_time' => $info->expire_time,
            'tag' => $tag,
            'openlink' => $info->openlink,
            'appid' => $info->appid,
        ];
        $redis->setex($key, $this->setCacheTime($info->expire_time), json_encode($returnArr));
        return $returnArr;
    }

    /**
     * 设置缓存时间,默认缓存360天
     * @param null $expire_time
     * @return float|int|null
     */
    protected function setCacheTime($expire_time = null)
    {
        return $expire_time ? $expire_time + 60 : mt_rand(3600 * 20 * 360, 3600 * 24 * 360);
    }

    /**
     * 设置唯一标签
     * @param $scene 场景
     * @param $appid
     * @param $path 小程序页面路径
     * @param $query 参数
     * @return string
     */
    protected function setTag($scene, $appid, $path, $query)
    {
        return md5($scene . $appid . $path . $query);
    }

    /**
     * 请求微信接口
     * @param $is_expire   生成的scheme码类型,到期失效:true,永久有效:false。
     * @param $expire_time 到期失效的scheme码的失效时间,为Unix时间戳。生成的到期失效scheme码在该时间前有效。最长有效期为1年。生成到期失效的scheme时必填。
     * @param $path        通过scheme码进入的小程序页面路径,必须是已经发布的小程序存在的页面,不可携带query。path为空时会跳转小程序主页。
     * @param $query       通过scheme码进入小程序时的query,最大1024个字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~
     * @param $app         小程序实例
     * @return mixed
     * @throws Exception
     */
    protected function wxGenerateScheme($is_expire, $expire_time, $path, $query, $app)
    {
        $arr = [
            'is_expire' => $is_expire,
            'expire_time' => $expire_time,
            'jump_wxa' => [
                'path' => $path,
                'query' => $query,
            ]
        ];
//这里使用了 EasyWeChat $server = new BaseClient($app); $result = $server->httpPostJson('https://api.weixin.qq.com/wxa/generatescheme', $arr); if ($result['errcode'] != 0) { $msg = $result['errmsg'] . ',errcode:' . $result['errcode']; throw new Exception($msg); } return $result['openlink']; }
Scheme保存表设计:
CREATE TABLE `cw_scheme` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `appid` varchar(255) NOT NULL DEFAULT '0' COMMENT 'appid',
  `scene` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8 NOT NULL COMMENT '场景',
  `tag` char(33) CHARACTER SET utf8mb4 COLLATE utf8 NOT NULL DEFAULT '' COMMENT '标记(唯一,md5(scene+appid+path+query))',
  `path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8 DEFAULT NULL COMMENT '通过scheme码进入的小程序页面路径,必须是已经发布的小程序存在的页面,不可携带query。path为空时会跳转小程序主页。',
  `query` varchar(1024) DEFAULT NULL COMMENT '通过scheme码进入小程序时的query,最大1024个字符,只支持数字,大小写英文以及部分特殊字符:!#$&''()*+,/:;=?@-._~',
  `is_expire` tinyint(1) unsigned DEFAULT '1' COMMENT '生成的scheme码类型,到期失效:1,永久有效:0。(注意这个是给微信接口的参数,业务系统不通过这个来判断)',
  `expire_time` int(10) unsigned DEFAULT NULL COMMENT '到期失效的scheme码的失效时间(业务系统通过这个来判断)',
  `openlink` varchar(255) NOT NULL COMMENT '微信返回',
  `created_at` bigint(20) DEFAULT NULL COMMENT '创建时间',
  `updated_at` bigint(20) DEFAULT NULL COMMENT '修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `appid_tag` (`appid`,`tag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8 COMMENT='scheme方法产生小程序码';

小程序URL Scheme的使用:

 生成的URL Scheme如下所示:weixin://dl/business/?t= *TICKET*

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

location.href = 'weixin://dl/business/?t= *TICKET*'
使用方式备注
Android location.href="weixin://dl/business/?t= *TICKET*" 只有一种方式
IOS 直接识别URL Scheme 或使用location.href方式 两种方式
 

 

 

 

But, 当我们进行短信,邮件等触达时,是无法确定用户所使用的的手机设备是IOS还是Android

So, 我们从实际的业务触发,都需要一个H5页面进行中转处理。

小程序唤起业务流程图

通过短信打开小程序:

一般我们在短信中发送出去的链接如下:

https://www.cnblogs.com/jxxiaocao?tag=68627b50710d465c3db3f6c3edbfc0c1

这时在h5页面可以通过tag请求 getSchemeByTag($tag) 接口来获取 openlink 就可以通过

location.href = 'weixin://dl/business/?t= *TICKET*'

 方法来打开小程序了(这里可以做一些过期等其他的判断处理)

当然也可以把openlink等包含在要发送的短信链接上,但总感觉这样不好

方案二云开发

文档地址:

https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/staticstorage/jump-miniprogram.html

适用场景:
非个人主体并且已认证的小程序,使用云开发静态网站托管的网页,可以免鉴权跳转任意合法合规的小程序