本期分享背景:微信小程序在发布初期是没有什么入口的,之后的一段时间,才确定了由线下扫二维码进入。今天的分享内容由猫眼前端技术团队-小程序业务组提供。团队在一次线下投放二维码进行促销活动的过程中,经历了一些波折,这里总结并与大家分享一下!
本期主讲大咖:曹宇,2015年加入美团,之后随猫眼独⽴。⽬前负责猫眼电影选座交易业务的Web前端和小程序业务。属于准全栈工程师,习惯多角度思考业务和需求,关注工程质量、工程效率相关工具和理论的推⼴。
本期分享主要介绍一下4点:
- ⼩程序码和二维码的约束(纯技术分享)
- 产出物料后改需求
- 优惠券和用户触达通知
- 线上监控发现的问题
⼩程序码和二维码的约束
小程序码生成:
方案A:getWXACode
参数:path: 'pages/movie/index?arg=foo'
限制:长度128字节,数量10w个
方案A是,调用微信文档中的 getWXACode API 生成小程序码,参数path可以传入带query参数的路径,整个path的长度限制为128字节,生成小程序码的数量限制是10w个,超过10w后,微信会绝句接口请求,提示超量。使用时要注意场景是否适用。
小程序码生成:
方案B:getWXACodeUnlimit
参数:path: 'pages/movie/index' 和 scene: 'arg=foo'
限制:path不能加参数,scene参数32个字符,不限数量
方案B是,调用微信文档中的 getWXACodeUnlimit API 生成小程序码,这个二维码生成数量没有限制,但是path部分不能带参数,这就限制了很多业务场景,这个限制导致它只能在一个固定的落地页。不带参数,我们无从知道用户是从哪里扫过来的,也就无从定制特定使用场景的特色。在大规模投放场景下,只能使用这个方法
(小程序)二维码生成:
方案C:createWXAQRCode
参数:path: 'pages/movie/index?arg=foo'
限制:长度128字节,数量10w个
方案C是,调用微信文档中的 createWXAQRCode API 生成(小程序)二维码,参数及限制和方案A基本一样,但是这个二维码可以用微信以外的一般扫码程序来扫,你会发现它的地址是https://mp.weixin.qq.com/a/~xxxxxxxxxxx~这种,这里应该是微信内部对path做了一个转换,有兴趣的可以查阅相关资料,这里就不做拓展了。
上面介绍了一些⼩程序码和二维码的形式以及它们支持的一些东西,它们本身存储了一些信息,本质上和url差不多,url本身也可以理解为一种输入,所以这些也需要我们前端去控制,去处理⼩程序码和二维码背后的那个字符串,综上总结功能如下:
作为连接线上和线下的入口
页面路径 + 参数 ~= url
⼩程序的⼀种输入形式,类似点击 触控...
线下扫码1分购
业务流程
电影院扫码(通过易拉宝展示二维码)
支付1分钱领5元选座券 + 5元卖品券
线上⽀付,购买电影票、爆米花、甜品、饮料时使用
需求阶段1
单价约束: 优惠劵成本是和影院分摊的
总价约束: 每家影院可领取的数量有限
需求阶段1 —— 初步解决方案
活动落地页增加影院参数
⽣成二维码加上相关参数
每家影院二维码不同
例如:path: 'pages/onecent/index?cinema=15280'
需求阶段1 —— 遇到的问题
2000家影院的地推物料如何正确生产出来
并如期正确的送达
解析:此次活动,猫眼有2000家影院参与,预计至少打印4000份二维码,因为每家影院可能投放多个易拉宝。这种物料一般是由总部统一制作,多数公司很在意自己的品牌,不会允许各个影院自己随便处理。总部制作好,需要邮寄到各个城市,所以必须保证正确的打印与正确的邮寄,而这种人工集中处理的方式,出错是必然的,因为二维码必须扫过之后,才能知道是哪家影院的二维码,很容易出错,假使出问题的概率按1%计算,也有20多家会出问题,所以整体印刷出来后在邮寄的方案肯定是行不通的
需求阶段1 —— 新的解决方案
批量生产物料模板,寄送多份
二维码独立推送
影院自行印刷并粘贴二维码
提供设计素材,定制物料
解析:猫眼会统一印刷一些没有二维码的模板,因为整体物料除了二维码部分,其他部分是一样的,然后在批量邮寄二维码,如果某家影院的二维码出现问题,总部可以把设计素材的电子版发给影院,影院的后台可以推送二维码,并可以自己打印二维码,粘贴上即可,基本没有什么差异。
实际效果:
需求阶段2
领取优惠券后, 期望能点击后退
解析:一般二维码扫进来后,之后一个活动页,用户领取了优惠券后,返回就直接退出了,再次扫进来还是活动页,这就导致了用户领取了优惠券,但是不知道去哪里消费。所以希望载用户点击后退的时候,能去到一个可以消费优惠券的场景。
需求如图所示,需要在左上角出现一个返回按键:
需求阶段2 —— 初步解决方案
扫码后,先跳转到首⻚,再重定向到活动页
例子:path: 'pages/movie/index?go=pages/onecent/ index?cinema=15280'
或自定义导航栏
解析:第一种方案中'pages/movie/index'为首页,后面部分为跳转目标,这种方案导致二维码又变了,而且参数变长了,会有一些麻烦和风险。第二种方法是完全自定义导航栏,相当于页面变成了全屏的,只是右上角浮出来小程序的关闭与菜单按钮,这是就可以自己控制屏幕左上角的操作布局了。这个方案有一些限制,比如使用了自定义导航栏,那整个小程序所有的页面,就都是自定义的了。最后猫眼采用了第一种方案。
需求阶段2 —— 遇到的问题
已经打印的二维码物料都没用了
需要重新生成⼆维码
重新让影院印刷二维码并粘贴
解析:因为路径改变了,所以二维码也变了,相当于之前所有电子版和打印版的二维码全部失效,这种走步一看一步的方式肯定会出问题的。
需求阶段2 —— 问题的分析
期望能控制后退
期望可以后退到非⾸页的地址
⼀家影院在不同⼊口放置的二维码效果如何
参数越来越多,长度超限怎么办
解析:产出物料后改需求是常态。
如果想后退到非首页,路径变更,又会导致二维码的更改;如果是同一家影院放在不同的地方,想知道具体效果如何,还是要在二维码上继续增加参数;这种需求越多,参数就会越多,最后可能就会达到参数长度的限制。频繁的变更二维码不仅麻烦,最终还可能触及方案A的10w个数量限制。
需求阶段2 —— 新的解决方案
使用短网址服务,客户端:
⼊口 path: 'pages/jump?id=3a5fc8'
前端请求 wx.request()
后端响应结果 { path: 'pages/movie/index?go=pages/onecent/ index?cinema=15280&utm_source=foo' }
前端重定向 wx.redirectTo()
使用短网址服务,管理端:
创建短网址 API (响应给前端)
批量查询 修改 API(满足频繁更改二维码需求)
类别(对不同活动进行区分)
附加信息 :Map 结构(比如影院id,后退页面地址,埋点等)
解析:猫眼提供了一个jump页面,这个页面提供了所有二维码的入口,并提供一个唯一id标识,此方案需要前端,后端及PM一起协商,后端去存储所有短网址的信息,前端使用id去后端请求返回一个长的path,这个path是不受二维码长度限制的,因为它不是二维码本身。拿到path后,前端就可以重定向到指定页面了,这样也解决了后退多样化的需求,埋点的需求可以通过,比如上面的 &utm_source=foo 参数,来进行控制。
综上即实现了扫描同一个二维码,返回不同的路径(后端控制)。
使用短网址服务,更多:
体验问题
扫普通链接二维码打开小程序
链接http://m.maoyan.com/jump?id=3a5fc8
pages/jump?id=3a5fc8
解析:最终我们生成的二维码短网址,后面的id是不变的,我们只需要在后台更改对应id下的小程序行为,最终来控制小程序的行为。这个方案解决了需求,但是也产生了一个问题,它多了一个中间层jump页面,一般jump页面是空白的,最多加一个loading改善一下体验,中间层jump页面多了一次请求,可能会多消耗一点时间,进入页面相应的会慢一点。一般的解决办法是:首次进入就是这么慢,然后将响应数据保存起来,第二次扫进来就会更快一些,缓存方面的技巧这里不做扩展。此方案的一个进阶场景是生成普通的二维码,链接如http://m.maoyan.com/jump?id=3a5fc8,这个传统二维码使用任何扫码工具都可以扫描,小程序管理后台提供一个功能,支持扫普通链接打开小程序,只需要经过一些配置即可。
达成扫码,⼩结:
需求是多变的
物料产出后难以修改
短网址服务方案
优惠券和用户触达通知
用户扫码领取了优惠券后,不一定会立刻使用,我们不会等用户来购票,我们期望可以通知领取了优惠券的用户。
微信支付及预充值代金券
首先,介绍一下微信支付的优惠券体系
曝光⼊口:消息列表 "微信支付" 服务号
时机:领取通知 和 到期通知(设置提前通知的时间很重要)
优惠形式:满减,
商品限制
,预算限制提供服务:防刷,对账,下载消耗记录
解析:我们想投放微信支付的优惠券时,首先需要充值,比如5元的优惠券投放100个,至少需要充值500元,这对公司的现金会有要求,pm考虑到这一点。前端需要注意的主要是商品限制这一块,在调微信支付的时候,需要将商品的标记或分类传过去,否则不能使用优惠券。
⾃建优惠券系统
在使用微信的优惠券时,需要先垫付资金,可能会对公司的现金流产生影响,所以有的公司会考虑自建一套优惠券系统。猫眼使用的是微信提供的优惠券,但是也对自建优惠券系统做了调研分析如下
曝光⼊口:消息列表 "服务通知"
时机:⾃由,提前收集formId/prepayId,7天内通知
问题:客诉,合规性问题
优惠形式,防刷,对账,消耗记录
解析:通知入口可以使用微信的消息列表"服务通知",这个通知一般是随时可以发送,但是使用时也有一些约束,我们每发一个服务通知,必须要有一个凭证。这个凭证可以是用户点击一个按钮,提交一个表单产生的formId作为凭证,这个凭证只能使用1次;或者是用户支付成功,返回一个prepayId作为凭证,这个凭证可以使用3次。这两个凭证的有效期都是7天,这是前端需要特别注意的。前端需要刻意的在一些地方去收集formId,否则可能遇到想通知用户领取优惠券,但是发不出去通知的场景。一般要尽量多收集一些,因为需求比较多变,可能由之前的发送2个通知,到发送3个,4个,还有别的通知等等。当我们发送多个通知的时候,可能会遇到客户的投诉,这就会导致消息发送不成功,如果一起工作的pm不了解这些,一定要即时告知有这个风险,如果业务流程特别依赖服务通知,那么一定不要做任何可能违规的事情。自己做优惠券,那么优惠形式,防刷,对账,消耗记录都需要自己做,这对后端来说,工作量是很大的。自建优惠券系统,要做的事情是比较多的,如果是初创公司,不想在这方面有额外的投入的话,最好是直接用微信支付提供的优惠券服务,这会省很多事。
线上监控发现的问题
无法完成登录
猫眼优惠券项目上线后,一直在观察服务本身是否有意外情况。猫眼对多数的异步调用都做了监控,发现了一个无法完成登录的问题,比如 wx.getUserInfo() 校验 signature 不一致时,微信认为可能存在通讯问题,这次调用是失败的。实际的情况是,在某种场景下,校验永远是失败的,比如:微信 + android 5.x以下,用户昵称中含emoji时。这是这种场景下微信本身存在的一个问题,目前没有什么解决方案,只能等android 5.x版本消失就没问题了。当前的处理办法是,发现符合上述特征时,暂时忽略略签名检查,用户昵称的大概还是能获取到的,作为展示没有太大问题。
所有微信接口调用可能失败
通过node调用微信的所有接口时,有时可能会超时,比如获取用户的昵称,头像这些东西,用户点击授权,⼩程序端可能会出现卡顿,等了好久后,提示网络错误。这种情况是偶发的,约 0.5%,猫眼的日活基本在百万以上,最高在300w左右或更高,这种场景下,0.5%就牵涉到了很多用户了,一般用户遇到卡顿,可能会认为小程序有问题,导致这个用户可能就会流失了。经过调研,确定为网络线路稳定性问题,因为猫眼的机房在北京,小程序的机房在上海。目前有一个解决方案是,在使用api.weixin.qq.com这个域名出现问题时,可以使用api2.weixin.qq.com在试一试,即做一个容灾方案。具体到猫眼本身是,做了一个延迟重试策略,这个功能上线后,使用成功率的变化为 99.5% => 99.99% 的提升。
监控工具推荐
Central Application Tracking
猫眼使用的是自己的监控工具,名为 cat。这个工具是在和大众点评合并之后,大众点评技术团队分享的一套监控系统,为开源项目。之前在使用其他监控系统时,遇到的问题是,我们期望在遇到异常是,一定要对异常进行一个分类,需要知道异常的规模是什么样的,其他的监控系统,要么是在大规模报警的时候就崩溃了,要么就是只做日志,不做分类,导致了我们"只见树木,不见森林"。使用 cat,可以精确的控制分类,吞吐量特别大,满足了我们前端和node端的监控需要,有兴趣的可以去github上了解一下。
以上,由猫眼线下扫码1分购谈起,分享了靠谱的线下扫码活动需要技术团队提供哪些⽀支撑,这就是这次活动的内容。