一个(相对)完整的抽奖活动,都需要考虑哪些东西?
首先附上文章整体大纲结构:
(右击,在新标签页中打开即可查看大图)
抽奖活动,应该算是最古老的运营活动之一了,无论线上还是线下,商场还是超市,大转盘都无处不在。
然而,在微信红包出现以后,抽奖活动便发生了质的飞跃,因为用户抽到的红包可以直接发放到零钱中,这可是真金白银的活动,而且立马可以体验到好处,刺激反馈非常实时。所以,基于微信的红包抽奖想不火都不行。
早在 2015 年初的时候,我司的运营同学策划了基于微信服务号的『天天大抽奖』活动,在那样的蛮荒时期,朋友圈活动还不会打击得特别严厉,因此借助于此固化活动,我们获得了数百万粉丝留存。
当然,关于留存的部分,就不只是发钱这么简单了,还需要结合其他促销活动一起才能留住真正的优质用户。
曾经在很长的一段时间内,业界并未见到类似的微信抽奖活动,所以有好几家公司试图出巨资(数十万)购买我们的全套抽奖活动系统。
这至少说明,基于服务号的完善的抽奖系统,是具有一定价值的。当然,作为公司来讲,我们不会去赚这些小钱,毕竟我们不是程序外包公司 ~
那么,本篇我们就来探讨一下,一个(相对)完整的抽奖活动,都需要考虑哪些东西。
1. 平台的选择
首先我们来说一下平台的选择,目前我们可以选择的主流平台大致有 PC、H5(移动端网页版)、APP、微信平台的服务号、微信小程序、阿里平台的天猫、手淘应用,甚至支付宝小程序等。
至于具体选用哪个平台,要基于自身用户群体的分布,以及研发团队的技术积累,还要考虑一些新兴的处于风口的平台类型,比如微信小程序。
这里简单带过一些平台上可能产生的差异:
1.1 PC
PC 上需要考虑的主要是不能直接发红包的问题,电脑上的抽奖活动存在好多年,除了抽取积分、卡券、实物等,没有什么实质性的变化。
另外一点就是大量的兼容性问题,比如圆形的转盘动画在低级 IE 浏览器就很难实现,所以之前许多抽奖活动都是用 flash 解决方案。
1.2 H5
除了兼容性问题少了一点(真的吗?)外,其他与 PC 特性差异不大。
1.3 APP
众所周知,APP 版本在各个应用市场存在审核时间的问题,但如果固话活动不经常修改,且变动部分都能由运营热更新实现的话,也是个不错的选择。因为原生 APP 可以实现更多流畅的交互体验,更多炫酷的效果。
1.4 微信服务号
这是我认为的最佳选择,撒钱真的很方便!而且开发也不复杂,服务号开发文档非常完善。
1.5 天猫、手淘应用
在淘宝开放平台上可以作为独立开发者(ISV)创建应用,然后授权给其他店铺使用,做得好还可以赚钱。不过,同样的问题就是,在成本一样的情况下,任何其他的奖品都没有微信红包诱惑大。
目前笔者在淘宝开放平台还没有看到第三方应用的发放红包接口,即使有这种接口,作为第三方的应用,商户资金管理和审计也比较复杂,店铺不会把这种发放资金的能力交给第三方应用开发者的。
1.6 微信小程序
微信小程序目前只有支付能力,即收钱的能力,暂时还没有开放发钱的能力。不过如果一定要在小程序里玩,可以考虑通过 unionid 打通小程序和服务号的用户,在用户中奖时获取该用户在对应服务号下的 openid 再调用服务号的红包发放接口发放红包。
1.7 支付宝小程序:你说啥?
本文的案例始于 2015 年,彼时服务号方兴未艾,微信也将许多资源倾向于服务号的能力扩展,就像现如今的小程序一样,大家都没有想好怎么玩。
所以,对于微信服务号这个平台,我们除了要做基本的『服务』之外,也希望尝试更多的玩法,加之微信红包接口已经开放,故,基于微信服务号开发的『天天抽大奖』活动应运而生。
2. 前期准备
2.1 服务号认证
抽奖活动至少需要服务号获得网页授权能力,这也意味着必须使用通过了微信认证的服务号才能玩得起来。而微信认证只针对个体工商户、企事业单位、政府组织等。这意味着你只要要能使用其中一种资质的证明材料。
而对于一般的企业型账户,获取微信认证需要通过对公账户打款进行注册主体验证,也就是说至少要有对公账户。
当然,对于正规的企业来讲,这些都不是问题,正常走流程跟公司申请对公账户打款即可。
另外,每次认证需要缴纳 300 元 费用,详见微信文档。
2.2 服务商平台
既然要做红包抽奖,那必须要有钱可以发放。服务商平台(https://pay.weixin.qq.com/)就是你可以充钱的地方,同样,申请服务商平台也需要提交对应资质,所有关于用户支付、企业打款、红包等功能均在此管理。对于开发人员来讲,发放用户红包还需要在此平台下载证书部署到服务器。
另外,大家可以参考下前一阵 @Javen 的 chat 《微信支付接入的那点事儿》,里面有详细的支付接入流程。
3. 界面设计 & 前端开发
3.1 界面设计
抽奖活动的界面设计主要要提现欢快热烈的活动氛围,但也不宜天马行空随意发挥,因为我们后面还有代码实现和运营的问题。比如整个页面的背景结构如果过于复杂,或者由于动效缘故要拆成若干部分,那么在更换抽奖活动主题的时候,就要做更多的改动。
3.2 转盘
对于抽奖动画我们也有很多选择,比如圆盘(指针转,圆盘转)、滚球、方盘跑马灯等。所有你在游乐场、澳门赌场等看到的抽奖玩法,都可以想办法移植到活动中来。
这里值得一提的是,前一段时间京东凹凸实验室开发了一款推金币领券的游戏活动,其 3D 效果异常逼真,以至于被微信给屏蔽了 … 感兴趣的读者可以搜索『凹凸实验室』公众号查看相关文章。
3.3 动画时机
这是个前端开发问题。对于动画执行的时机,最简单的实现就是先去请求服务器,拿到抽奖结果之后再执行动画。缺点就是,网络慢或者服务器响应慢的时候可能会有短暂等待。
当然,也可以用有趣的进度条或者加载动画等缩短用户对这个时间的感知。类似的,先执行动画,当动画结束后再去请求服务器也是差不多一样的效果,当动画结束之后,也可能有短暂的等待时间需要处理。
而最接近真实世界的方式,就是当用户点击抽奖时动画就启动,当获取到抽奖结果时动画就结束。显然,这事儿没那么简单。
首先,动画都是有过渡效果的,拿到抽奖结果后不可能戛然而止。其次,如果在请求抽奖结果的过程中网络卡顿一直拿不到结果怎么办?如果中间服务器报错了怎么办?请求没有响应要不要再尝试几次?在这个过程中动画怎么处理?
最后,假设我们对外宣称是『100% 中奖』,那么多次尝试之后服务器确实没有响应,转盘或指针要落在哪里?什么?落在最便宜的奖品吗?那么服务器没有记录可查,用户截屏过来要奖品,你给还是不给?
这里我们的策略是:用户点击抽奖则转盘开始转动,且开始请求抽奖结果。转盘从开始转动到最后结束分为三个阶段,即加速 → 匀速 → 减速。
尝试多次请求或或网络延迟等问题,都可以在匀速阶段处理,如出现问题则适当延长匀速时间,对于用户来说只是感觉转盘转动比较久而已,想想《盗梦空间》中的陀螺。
那么,如果最后真的报错了呢?你可以考虑让指针停在两个奖品中间,但是这样仍然会有争议。首先是太像 BUG,其次用户会说他一定会得到两侧的某个奖品,只是你这个东西出错了停在了中间。
所以,最保险的方案,就是永远不要宣称『100% 中奖』,永远保留『谢谢参与』用来兜底。
3.4 排行榜
多数情况下,抽奖界面上都会有个类似排行榜的模块,用来展示中奖用户和诱人的奖品。这里在界面上没有太多东西,不过是各种循环滚动动画、展示用户昵称头像等,如果是手机号,记得在 CGI 层面打码,不要泄露用户隐私就好。
3.5 用户信息收集
基本的表单提交需要前端的验证,对于抽奖业务中的实物奖品,则需要类似地址选择组件搜集用户收件地址。更严格一点,手机号需要验证码来验证真实性,确保能够联系到用户。
再进一步,可以利用 GPS 定位能力,自动获取用户所在区域,只需要补充详细地址即可。现在许多快递公司或者有外送服务的服务号,都实现了类似功能,具体不再展开。
4. 接口设计
对于接口的设计,首先要考虑平台是否有需要整合的基础能力,比如公司主站的登录态与微信授权打通等,这里每个公司具体业务不同,不便展开讨论,我们只讨论一下抽奖强相关的接口设计。
4.1 微信网页授权
基于服务号的微信网页授权可以获取用户在该服务号下的 openid,作为用户在该服务号下的唯一标识,具体可以查看服务号开发文档。
至于 openid 是否作为用户的唯一标识,有许多种处理方法,一般还是建议自己维护一套用户 id 系统,不要直接暴露 openid 为好。
起码在数据库中,int 的查找要比 string 快。至于具体的授权流程以及 token 维护等,则是微信服务号开发的内容,不展开。
4.2 授权后操作
微信授权只是获取 openid 或其他用户信息的第一步,根据自身业务的需要,可能还需要用户继续注册或绑定手机等,才能真正算是你的用户。
在本文的案例中,我们也曾尝试过不要求用户注册,只要简单的授权即可抽奖的活动,但事实证明,这会带来许多问题。
一来只用 openid 标识用户,容易被羊毛党刷单,二来如果对于价值比较高的有价产品,可能还是希望他注册。而注册之后还要绑定之前的抽奖结果,而这个过程就可能带来安全风险。
因此,经过一段时间的尝试和权衡,我们把抽奖活动改成了必须先关注和绑定手机才能抽奖的形式。虽然参与度会有所下降,但也避免了许多不必要的麻烦。
对于授权后的绑定手机,手机登录还是帐号密码登录,是否需要验证码等,请参考自身平台的用户体系建设。
4.3 抽奖主接口
抽奖主接口主要用来获取中奖状态、奖品信息等。这个接口将会是承受压力最大的一个接口,因为总会有人试图单独刷这个接口,所以所有的防御机制都要体现在这个接口上,具体我们后面再聊。
对于接口吐出的信息多少也是要严格控制的,比如奖品的库存、中奖概率等信息。基本上,如果是简单的抽奖,那么这个接口只需要告诉用户是否中奖即可,也可以加上剩余抽奖资格等信息。
4.4 获取可抽奖次数
一般情况下,抽奖资格的获取可以混合到抽奖主接口中,不过也有一些场景需要单独判断抽奖资格,即是否允许抽奖以及能抽几次。比如用户刚刚进入抽奖界面时,或者执行了 “关注”,“绑定” 等操作后刷新资格的时候。
另外,部分安卓手机可能会缓存页面,如果在下一步操作中改变了抽奖资格(次数,积分变化等),再直接点击左上角返回,次数可能就不会变化。
因此,最好再抽奖动作之前先强制更新一下抽奖资格,而不是直接等待抽奖主接口返回不能抽奖的错误,因为这样会导致用户看到界面上有资格,但是每次点了之后又不能抽。这种情况下,还不如一次就让用户死心,如果真有投诉就如实相告,告诉用户手机有缓存问题。
4.5 更新奖品状态
如果你的奖品设置了领取状态(抽奖领奖动作分离 / 注册前抽奖 / 微信卡包领取状态 / 优惠券领取状态) ,那么还需要一个更新奖品状态的接口,用来修改奖品的领取状态。
举个例子,如果你用了微信卡包的 API 去实现发券功能,那么用户会进入微信实现的卡券领取界面,在这个界面用户也可以选择不领取,当然你也可以就此视为用户放弃。
但如果你希望再给用户开放领取入口,比如在类似 “我的奖品” 这样的页面再次领取的话,就需要判断用户是否领过此卡券。
而当用户终于点击了领取,把卡券放到自己的微信卡包之后,微信会执行一个回调函数,在这里,你可以去更新用户的奖品状态并关闭领取入口了。
4.6 关联用户
这个接口只在一种情况下使用,即 “未注册” 之前允许抽奖,“注册” 之后领奖的情况。注意这里的 “未注册” 和 “注册” 都加了双引号,是因为这两个词对于不同的平台不同的业务意义也不同,需要您自己去界定,什么是注册,什么是未注册。
关联用户有一定的风险,尤其是对于价值比较高的奖品。因为你只能根据某个特定的条件来判定注册前后两个账户是否真的是同一个人。比如通过 openid 判定注册前后用了同一个微信号;再比如用特定算法生成的机器码判定注册前后是同一台设备等。
以 openid 为例,如果每个用户进来,我们都使用微信授权接口去微信那里授权,势必会有严重的性能瓶颈,因为微信的接口对于我们来说是外部接口。更严重的情况,还有可能达到微信 API 的每日调用上限,导致全部 API 无法使用。
因此,我们最初的简易版方案并没有每次都去授权获取 openid,而是缓存了第一次授权的 openid,且没有其他辅助的 ukey 来综合校验,导致用户在抽奖的时候,我们实际上并不能确认这是个真实的用户,甚至不能确认这是个真实存在的微信号的 openid,只能说明这段字符串符合 openid 的长度。
这个漏洞的可乘之机是要刷微信红包,如果不是真实的 openid,是无法收到微信红包的。所以,羊毛党来刷红包的时候,一定用的是真实的 openid,因此这个 bug 不能造成太大的伤害。不过我们还是及时加入了 ukey 验证。
并且,对于抽中后再来实名关联的用户,也会再次验证其微信账户是否有疑似作弊行为,这就是为什么所有活动都要加上 “最终解释权归 xx 所有” 的缘故,因为总有羊毛党来捣乱。
注意,羊毛党一般都是有大量真实微信号在手里的,这种大量真实微信号的操作,是无法通过简单手段识别出来的。
4.7 运营文案接口
该接口是否需要以及其复杂的程度,取决于您的业务需要,即抽奖活动在线时有多少需要实时运营的内容。比如用户欢迎语、抽奖成功 / 失败后的引导语等等,重点是如何能与自身的运营系统结合,方便运营同学使用。
4.8 清除缓存
抽奖活动往往有类似排行榜,参与人数等信息的展示。对于访问量较大的抽奖活动,这种信息一定是有缓存方案的,不可能每次都去查询数据库实时计算。
那么,既然有缓存,就有清除缓存操作,有时可能还涉及到冷启动造数据等,后面我们再详细讲解。
对于排行榜的刷新时间也是要权衡的,缓存久的话缓存利用率高,但是用户如果真抽中了,发现没有上排行榜,定会对系统产生怀疑。
因此,缓存时间不宜过长,或可采用表面方案,如果用户中奖,则直接在页面中处理排行榜的展示效果,用户可以直接看到自己进入了排行榜。
当缓存再次刷新时,即使排名顺序有变化,或者被挤出排行榜,就都是正常的展示了。而对于定期清理缓存的机制,可以使用 linux 系统自带的 crontab 或其他常驻的 deamon 脚本均可。
4.9 日志记录
除了用户抽奖本身的记录之外,一般还需要记录其他一些重要信息。比如,微信红包接口属于外部接口,因此调用微信红包接口的返回内容就最好记录一下方便定位,否则有的时候会很难确定问题。
比如扩容多台机器,但有个别机器的 CA 证书没有带上,导致微信红包接口调用失败。
再比如微信商户平台中余额不足,导致发放失败等,都需要通过日志记录。这些错误是不方便直接展示给用户的,因此在用户侧一般是直接告知未抽中即可。
4.10 其他功能页
根据业务需要,抽奖活动可能还包含我的奖品、抽奖规则、抽奖结束页,通用错误页等,这些页面基本上只需要考虑运营内容和经常变化的逻辑即可。
比如新增了奖品类型,在我的奖品页要怎么展示;如果有新的活动主题,是否方便修改之前的奖品图标风格等。
4.11 页面入口权限控制
在抽奖活动的各个阶段,可能需要对某些页面入口进行统一控制,具体可以通过活动时间,资格等手段控制。
唯一需要注意的是,最好设计成页面和相关异步接口可以统一开关,否则经常容易犯的低级错误就是,页面虽然不能访问,但是接口仍然可以单独调用。
另外,即使是你记着要把所有接口都关掉,但是每次全部要手动修改全部接口,就不是很方便了。
5. 逻辑层设计
逻辑层的设计,大体与前面的接口设计对应,这里只单独拿出一些值得讨论的点说一下。
5.1 用户体系
前面也提到过标识用户的重要性,明确标识用户而不只是依赖微信的 openid 体系,可以一定程度上防止刷单。另外,手机号注册基本算是终极方案,但是用户参与成本也高很多,需要权衡。
一个相对折中的方案是,使用与 openid 有映射关系的用户体系,这样方便用户绑定微信,且在微信上可以实现 “自动登录” 的效果。微信开放平台提供了 unionId 体系,可以帮助打通各个服务号 / 小程序等的用户。
如果要实现跟手机号绑定,那就需要自己建立一套手机号与各个平台 openid 的对应关系。
或者单纯只有服务号的 openid 与自建用户体系的对应关系,向用户派发 uid + ukey 来识别用户,而不是直接使用 openid 作为用户标识。
5.2 抽奖资格
抽奖资格可以通过多种方式实现,例如通过其他活动派发抽奖次数,甚至免费赠送抽奖次数,或者通过自建用户体系的积分体系实现抽奖资格。
与之对应的,抽奖动作则是消耗对应的抽奖次数或消耗某种积分,比如招商银行的信用卡积分抽奖。对于自建用户体系的积分抽奖,可以通过打卡签到,电商购物等获得。
而对于其他活动渠道获得的抽奖次数,则需要抽奖系统对外提供增加次数的能力,如果多个活动共用或多种获取渠道共用,则还要区分该资格来自哪个渠道。
增加次数接口如果是对外暴露的,则有被多加的风险,因此不建议前端直接使用 ajax 异步调用新增次数,而是要把新增次数的逻辑混合在活动的逻辑中,经过严格的判断再在 CGI 层面处理完成。
如果是新用户进来默认赠送次数的,则一定会导致羊毛党使用大量帐号刷单。对于这种活动的奖品和概率设置,必然是要尽量降低成本,降低概率,这样即使是羊毛党也不会使我们造成过大损失。
羊毛党其实是无法完全杜绝的,因为在系统层面看来,很多时候就是大量的真实用户。所以我们只能在成本和风险上进行控制和权衡,无法完全避免,也不能误伤太多真实用户。
5.3 奖品类型
上文讨论的奖品类型,主要都围绕微信红包和微信卡券。这两种虚拟商品都是基于微信平台的实现,相对比较容易。
如果您的抽奖活动还需要派发其他奖品,比如商家自己实现的优惠券、邮寄实物奖品、各种会员卡体验名额等,则需要结合自身业务实现发放接口,再供抽奖系统调用。
同样,仍然需要注意实际发放资格的判断是否完善,以及如何判断刷单和作弊等。
5.4 抽奖概率算法
从发放奖品的大体倾向来看,一般有两种玩法。
一种是尽快把奖品都抽完,即土豪要尽量保证奖品发完。这种抽奖有时效性,虽然先来后到对概率没影响,但是晚了可能奖品被抽完;另外一种是,尽量保证更多的人次参与,奖品不要太快消耗。
这种抽奖参与人次分布相对均匀,但是对于单次活动,且没有手动调整抽奖概率的情况下,不能保证奖品都被抽完。
第一种场景的典型例子,就是公司年会,奖品固定人数固定,且要求在晚会上必须抽完。这种场景下抽奖的概率是需要系统动态计算的,根据已知的库存和原始概率,如果人次达到某个阈值还没有抽完就自动增加一点点概率。
当然,这种情况也可以用奖品来抽人,比如先固定本次抽取 iPhoneX,再来随机是哪个人。什么?伪随机数不够随机?who cares~
现场抽奖重要的是公平透明,如果用了复杂的抽奖系统反倒不能服众,搞不好来个现场 review 代码,所以即使是伪随机数的抽奖,也比复杂系统强。
再说第二种,它的特点就是同样的奖品数量消耗较慢,那么对于长期固化的活动来说,一定是希望最小的成本获得最多的参与。即使是时效非常短的抽奖活动,也没有非要把奖品都送出去的道理。
因此,这个场景下不会让系统动态调整概率,而是采用人工控制概率的方式。对于单个抽奖用户来说,中奖区间是恒定的,即使抽了很多次,也不会扩大中奖概率。
这样也可以防止恶意刷单,一切能够通过数量提升中奖概率的活动,最后都可能被刷单,除非你不在乎这些成本。
人工控制还有个好处就是,发现刷单后可以及时调整概率防止损失扩大,另外如果奖品发放变慢,也可以人工提升概率保持活跃度。
5.5 连续不中补偿(必中)
如果你的抽奖活动也是固化活动,会有一大波忠实粉丝定期参与,那么为了保证粉丝的活跃度,可能要对运气一直不好的用户有些补偿。比如连续抽奖 N 次都不中的,我们要补发某些奖品给用户。补发逻辑没有什么特别,
只是要在用户身上记录一个连续不中的次数。不过,值得注意的是,如果多个抽奖活动的连续不中次数不能共用,那就要扩展多个存储字段来区分了。
对于这些只需要判定而不需要用来排序的字段,可以统一用一个扩展字段,以 JSON 的形式存在数据表中,避免频繁修改 DB 结构。
此外,如果配合管理系统,让运营同学去新建抽奖活动和新增奖品,那么就要明确标识出到底哪个奖品可以作为连续不中自动发放的。要么用明显的标记和提示,要么单独一个字段设置这种通用奖品。
如果由于提示不明显,把 188 元 现金当成了连续不中补偿,那就有点过于土豪了。
5.6 连续不中提升中奖概率(权重提升)
接 5.5,如果你只希望连续不中的用户提升一定的中奖概率的话,实现思路就又不同了。中奖概率本身这个事,分散到多个奖品上面,就不是简单的可以提升概率的问题了。
所以,更简单的做法是,把用户抽奖时获得的随机数扩大范围。比如我的概率范围相当于 1-10000 的随机数,如果用户获得的是 3000 这个随机数,那么 10% 的概率相当于 1000 个单位,因此给用户提升 10% 的中间概率可以粗略地转化为:在 2500 – 3500 之间如果有命中奖品中奖区间,就都算中奖。
5.7 默认奖品设置
上文 3.3 中说过,最好始终保留 “谢谢参与” 兜底,那么如果运营要求本次活动一定要所有都有奖品呢?
如果说用户投诉,截图直接索取奖品都能接受呢?这时,之前设定的谢谢参与的位置,就要变成普通的奖品,从而导致一切跟不中奖相关的逻辑以及判定条件都可能要修改。
所以,如果你担心有这种需求变更的风险,最好把所有的奖品位置都设计成可以作为普通奖品,也可以作为特殊位置(谢谢参与,没有奖品等)。
5.8 奖品库存判断
一般来说,库存都是整数单位,但每次操作的数量未必是 1 个 / 件 / 积分 / 元。假设你的奖品涵盖积分、微信红包、优惠券等。
那么,抽奖资格可能是 10 积分每次,所以用户账户中必须有 10 积分以上才可抽奖;如果是次数抽奖,一般来说用户账户中只要 1 次资格就可以抽奖。
奖品库存的判断也类似,微信红包的限制是每次至少发放 1 元,一般金额的存储不建议用 float,因为会产生精度问题。所以我们一般以分为单位存储,那么如果想发放红包,则该奖品的库存至少要大于等于 100(分)才可发放。
综上,对于不同类型的奖品,是要考虑资格和库存判断标准的不同的,这里可以采用配置文件的方式将可能的奖品类型和判断标准列出即可,方便修改。
5.9 微信红包逻辑
目前的微信红包,需要通过用户在该服务号下的 openid 发放(可以不关注),这里最好为所有的红包发放逻辑设置全局开关,用来在遇到重大安全隐患时临时手动关闭有价奖品。微信的红包接口需要一个唯一的业务 ID,这里可能出现的坑就是大并发时业务 ID 重复。
因此,如果并发不是很大可以采用毫秒级时间戳 +uid,如果不能满足需求还可以继续加入随机数,或者使用一定长度的 UUID+uid,只要注意别超过业务 ID 本身的长度限制即可。
这里一定要加入 uid 是由于商户平台的资金流水只包含用户的 openid,不方便与自身的用户体系对应,所以在业务 ID 中混入 uid 方便查询信息。当然,也可以使用红包接口的扩展字段记录用户信息。
5.10 实物奖品逻辑
这里的实物奖品是个通用的类型,对于一切无法通过程序直接发放给用户,或者用户不能直接通过页面领取的,都可以归为实物奖品。
典型的例子就是,某个活动希望用户抽的是支付宝红包,那么在微信平台上显然这是不可能的。
因此,如果一定要走支付宝红包,可以采用抽中红包口令,但不能防止用户直接把口令发给别人。或者是抽中后,让用户输入支付宝账户,然后再想办法人肉或批量操作转账。
对于其他实物奖品也类似,需要邮寄的要留下地址电话,需要领取码的要在抽中后的接口内再返回领取码。
总之,这里每次新增一种奖品,就可能新增一部分开发工作量,因为设计情况较多无法提前兼容。
5.11 抽奖记录
用户的抽奖记录要尽可能记录更多的信息,因为每天都会有用户以各种理由找客服投诉(除非你不给投诉入口)。
其间不乏许多无理取闹直接来骗奖品的用户,比如在移动端转盘动画旋转的的时候拖动手机让转盘暂停,或者干脆用 PhotoShop 合成中奖状态的。
这时候,我们唯一能依赖的就是用户的抽奖记录了,只要记录中不存在或者记录异常,就可以坚决判定本次中奖是假的。例如,用户当时的中奖随机数,奖品信息的快照(当时的文案、库存等)等。
而对于用户自身的抽奖记录,即 “我的奖品” 页面的展示,则要考虑大量不中的情况下,“谢谢参与” 是否要隐藏。
如果谢谢参与要隐藏,那么按照 5.7 中的要求如果这个位置变成了普通奖品,又要以什么样的判断依据来决定是展示还是隐藏。
5.12 排行榜展示
上文 4.8 讲了排行榜的缓存清除,这里我们讨论下排行榜的构成。看似简单的排行榜,其实并不简单。首先,除非你的奖品非常丰厚,中奖概率非常高,所有人皆大欢喜。
否则,如果排行榜是自然生成且按时间倒序,那么一定是满满的谢谢参与或者微不足道的小奖品。排行榜的作用并不是真的要排行,而是吸引用户参与,营造气氛。
所以,排行榜上要尽量放 “大奖” 的用户抽奖记录才有吸引力,比如前五名都中了 iPhoneX,虽然用户未必真信,但是氛围效果还是达到了。
综上,排行榜的构成不是简单的抽奖记录倒序,而是按照一定的奖品配比生成的。因此,不同的活动不同的奖品就要考虑排行榜配比不同的问题,这里也可以通过配置文件来实现。
5.13 风险控制
风险控制包含很多方面,对于整个系统的全流程都有涉及。最基本的 DB 层面的事务处理,运营系统的金额控制,有价奖品总开关等,这些细节将会分散在各个章节。
5.14 活动类逻辑
这里的活动指作为一个运营活动的一些基本逻辑判断,比如用户属性判断(VIP/ 等级 / 活动资格) ,抽奖次数来源 / 渠道 / 限制判断 ,抽奖活动判断(区分活动 / 上下线时间) ,时效性活动(会员日半价抽奖) ,强制判断关注 / 强制判断分享等,具体暂不展开。
6. 数据层设计
数据层面的设计要包含上文提到的所有想关信息字段,大体上与业务逻辑是对应的,对于简单的抽奖活动,可能单表即可搞定。而要满足上文提到的大部分逻辑,那么该系统至少要包含以下数据表:
奖品表主要包含:活动 ID(平台维度 / 活动维度) ,概率(区间 / 百分比),奖品基本信息(名称 / 描述 / 库存 / 图片 / 领券码 / 现金范围等) ,各种运营文案 / 按钮设置 / 跳转链接等。
用户表(依据数据量分表) 主要包含: 用户基础信息(依赖平台用户体系),用户扩展信息(抽奖次数 / 签到 / 分享次数 / 评论 / 点赞 / 连续不中次数 / 手机号 / 收货地址等) 。
抽奖记录表(依据数据量分表) 主要包含: 抽奖记录表(用户基础信息冗余 / 奖品信息冗余 / 抽奖动作快照 / 抽奖随机数) ,抽奖记录归档表(无需展示的抽奖记录定期归档) 。
数据统计相关(独立系统) ,用户行为上报 ,管理员操作日志 等。
由于具体的表设计较少有共性可言,因此不再赘述,具体的表结构我也不粘贴了,大致思路都是类似的。
7. 运维相关
抽奖系统如果真的火了的话,会对服务器造成非常大的压力。现在无论大小公司,许多都已经采用云服务来实现,既可以方便地扩容,承受更大业务量,也可以拥有更安全的保障,更专业的服务。
7.1 服务器选择
如果采用阿里云的服务,一般是 SLB(负载均衡)+ECS(云服务器)+RDS(云存储)+CDN(内容分发网络)组合。
这里不推荐用云服务器自建的数据库服务,一来性能有限,二来要自己写守护进程防止数据库挂掉,最后,还要自己实现各种备份脚本,成本高又不可靠,真的不如直接购买云服务。
抽奖活动推送期间,我们大概使用 5-10 台 ECS 来承接抽奖活动流量,即使真的有压力,也可以快速扩容。
7.2 数据表索引
对于高并发的活动 DB,索引的重要性就非常突出了。平时做些小网站小打小闹可能根本不需要建立数据库索引,而在高并发的时候,一切问题都会被放大。
因此,关键数据表,关键查询,组合查询等,都要提前建立好索引。而复杂的联表查询,如能转换成两次单表查询,则效率更高。
类似用户表和抽奖记录表这种有可能单表数据量过大的情况,可以提前考虑分表,比如给用户按 uid 分 100 张表。
7.3 数据缓存
常用的缓存方案有许多,对于排行榜、总人数这种需求,建议采用 Redis 缓存,因为其用法简单,查询速度快,与各种语言结合友好。
需要注意的是 Redis 服务器的账户和访问权限问题,初次使用的同学很可能不设置 Redis 的账户和端口,那么你的缓存就很有可能被其他人直接读取甚至写入。
7.4 基础服务监控(独立系统)
每个公司都有自己的基础服务监控系统,或多或少。那么抽奖活动也尽量接入这些系统,比如可用性监控,服务器性能,接口访问量 / 失败量 / 告警等。
如果本身没有类似的系统,那么也可以针对抽奖单独开发一些监控功能,但成本会相对较高了。
7.5 安全
安全 是个大课题,我也不是专家,简单说一下抽奖业务常用的一些方案吧。比如,基本的防刷机制 可能包括:Nginx 动态封 IP ,缓存层限制操作频次(防止高并发写入) ,数据层限制操作数量与频次 ,薅羊毛的度 等等。
再比如,第三方登录校验合法性 ,验证是否合法的 openid 等。此外,一定程度上的学费总是难免的,没有杀死我们的只会让我们更强大(健壮)。
7.6 应急预案
除了前面说到的这些安全问题,有时候还会有一些 “飞来横祸”,比如微信忽然把活动 URL 封了,分享到朋友圈后别人看不到。
在早期的应急预案中,我们可以考虑使用 Nginx Rewrite 路径随机串躲避,类似 https://xxx.yourname.com/Er52d6z/lottery 的形式。
还可以提前准备多个域名共存,可以实时切换,类似 https://xxx.yourname0.com/lottery,https://xxx.yourname1.com/lottery,https://xxx.yourname2.com/lottery 等。
这种方案实现成本略高一点,要准备多个域名,切代码可以无缝切换,比较麻烦的就是微信 JS Api 的安全域名设置,最多只能三个,所以还是要慎重。
最后想说的是,这些方案现在都不管用了,因为只要微信判断你某段时间通过诱导分享获得了大量用户,那就直接删用户。比如搞个活动本来只拉来了 1w 用户,然后被微信判定诱导分享,损失 2w 用户,劳民伤财还亏了 1w 用户 …
对于这种情况,一般没地方说理去。目前已知的唯一办法,就是活动不要搞太热烈,细水长流比较好。
8. 活动管理后台
活动管理后台可繁可简,如果在抽奖业务之前已经有了部分运营机制和能力,且能方便地用在抽奖系统就最好。
如果不能,那么可以考虑开发通用的活动管理平台,或者针对抽奖系统订制完善的运营平台。
这里简单罗列一下,抽奖的管理后台可能要考虑到哪些能力。
8.1 操作日志查询
奖品库存,概率等属于敏感操作,是必须要有操作日志的。至于具体操作的人员通过什么来识别,可以考虑使用内部的帐号系统,或手机号等。权限控制 + 日志记录 都是必不可少,否则很可能钱都不知道怎么没的。
另外,对于大一点的企业可能还有审计需求,审计公司会要求你实现这些记录功能,作为年终审计的依据。
8.2 平台选择
前面上文说过可能存在多个平台的抽奖活动,即使只是服务号抽奖,也可能存在多个服务号的切换问题,这些都是管理后台需要考虑的。
多个平台共存的情况下,针对不同的平台也会有个性化设置,比如奖品数量可能在不同平台有差别。例如 PC 抽 8 个,H5 抽 6 个这种情况。
8.3 创建活动 / 设置奖品 / 概率 / 运营字段 / 是否需要关注分享 / 奖品信息即时修改
创建活动要考虑多平台,多服务号的交互设计;设置奖品主要考虑奖品类型对奖品设置的影响;
概率可以采用百分比,也可以直接设置中将区间,比如使用 1-10000 的数字来界定抽奖概率。至于运营字段和是否需要关注、是否需要分享等细节,就有业务自己决定了。
奖品信息的增改查是基本操作,删除一般只改变数据状态,保留记录流水。
8.4 发布操作
保存和发布操作要尽可能做成两步,即存在 “预发布” 状态,或者只保存,不发布的状态。
发布的时候需要注意的是,如果奖品的图片不是跟着每条奖品信息一起的单张小图,那么就要保证全部奖品信息和独立的奖品图片(转盘,背景等)同时生效。
否则这个抽奖操作可能就不是 “所见即所得”,抽到了现金可能实际发了积分。
8.5 用户信息查询 / 抽奖记录查询 / 紧急拉黑
在用户投诉过来的时候,我们首先要验证用户的真实身份,以及他对应的抽奖记录是否存在。
比如通过用户的手机号来查询用户抽奖记录,或者客服系统接入用户体系,从客服聊天窗口可以获得用户的 openid 或 uid 等信息,也可以根据这些信息来查询。
最后一招,还可以根据用户的 “我的奖品” 界面判断:如果用户拒绝提供 “我的奖品” 界面截图,那说明他自己都看不到记录,纯是骗子。
如果他能提供记录,那么至少可以通过抽奖记录的时间戳来查询抽奖记录。在秒级时间节点上同步抽奖的人数毕竟有限,查出后再通过奖品等信息进行筛查,一般是骗不到我们的。
8.6 冷启动相关设置(排行榜 / 参与人数)
排行榜问题前面已经多次提到过,这里说说冷启动,即初始排行榜的生成。有人会说,这不是造假吗?但是,血淋淋的事实是,如果排行榜上一条记录没有,很多人都会直接关掉。
相反,即使明知道排行榜有可能是假的,大家也愿意相信。毫不夸张的说,大部分抽奖活动都有这个冷启动过程。
最简单的办法,是让大量的内部用户抽,只是不发奖。但是微信红包想不发就比较麻烦,要关掉红包接口,还要让他能获得抽中的记录展示。
所以,最理想的情况,是用一批内部可信的真实用户信息,根据每次活动的排行榜奖品配比,直接写入抽奖记录并生成排行榜缓存。
这样在下次刷新缓存的时候,大奖仍然屹立不倒。而当有外部真实用户抽中大奖的时候,也可以一样按照配比刷新到排行榜上方。
参数人数由于只是个数字,比较好处理。只需要给出一个初始的数值,后面每次抽奖的人次累加上去即可。
注意,所有这种需要冷启动的数字,都不能使用数据库实时 count,否则只能用一次,再更新就会变回真实的数字。因此,数据库只管累加,而不要管之前是多少就好了。
8.7 数据需求
每个运营活动都有许多数据需求,从基本的 PV/UV,到最细节的用户行为分析。对于抽奖活动,可能需要统计实时抽奖人数 / 次数,甚至同时在线人数。
另外,对于每个活动,每日每周可能都会有报表需求。因此,如果有独立的报表平台支持,就非常完美了。
8.8 奖品补发工具
如果投诉的用户经过我们验证,真的是系统出了问题,那么就需要一个方便的途径去给用户补发奖品。
比如微信红包,可以在管理后台直接调用红包接口把钱补发给用户,积分也一样。而实物奖品,则是正常走邮寄流程发货了。
8.9 权限管理
同数据管理一样,最好是有独立的权限管理系统可以接入,如果没有,那就只能自己开发个简单的版本。或者以抽奖活动为契机,为公司开发一套完善的权限管理系统。
一个基本的权限系统要包含:系统管理、角色管理,权限管理等等,另外还有权限的申请与审批(可能结合 OA 系统),要做到权责分明,出了问题有据可查。对于没有权限的,最好直接提示权限申请入口或申请途径。
9. 运营相关
一款成功的活动,需要投入大量的人力物力进行开发和运营。而对于固化的长期活动,更是需要体现运营功力的地方。
抽奖活动初期,如果只是疯狂砸钱的话,是毫无疑问可以拉到粉丝的,但运营的意义就是在有限资金下获得更好的效果,只砸钱谁不会呢?
而通过砸钱过来的用户,如何能通过后续活动巩固养成,使其成为我们真正的留存用户,就没有那么简单了。
9.1 诱导关注
我们先来了解一下什么是诱导关注。根据《微信公众平台运营规范》第 3.3.2 诱导关注为:通过外链、公众号群发或二维码等方式,以奖励或其他方式,强制或诱导用户关注公众号的行为。
奖励的方式包括但不限于:实物奖品、虚拟奖品(积分、信息)等。若违反相关协议,微信会根据公众帐号违规情况,对公众帐号限制或禁止使用全部或部分功能、帐号封禁 / 注销等相应处罚(http://kf.qq.com/faq/120911VrYVrA150916bYvUJR.html)。
是不是很可怕?大体上就是不能通过奖励强制或诱导用户关注公众号,常见的就是先抽红包再关注领现金的骗局。所以,我们是关注之后再抽,而且直接发钱。但是,树大难免招风,带有诱导关注的活动小打小闹没关系,微信不会注意到。一旦做大,就有风险,请大家自行把握。
9.2 冷启动
前面已经讲过排行榜的冷启动和人工干预问题,其实冷启动还包括初始没有流量时如何引流。不过对于实实在在的现金抽奖,初次流量获取相对容易,我们每天发一两万元给用户,就不信没人来。
9.3 可运营字段设计
可运营字段设计包括:主题、转盘、按钮文案、提示语,跳转链接等等,需要提前与运营同学沟通好可能出现的运营位,再结合已有的运营系统看看怎样方便接入。
当然,无论最初想得多周全,上线后也总是要缝缝补补继续增加需要运营的部分,所以,把这种事情当作常态就好。
9.4 多平台共用 / 多活动并存 / 多版本并存 / 多状态切换
当你的业务涉及多个平台,多个活动,多个版本的时候,在系统设计上就要考虑更多的多平台运营之间的差异,以及各种切换问题。
9.5 客服对接
对于抽奖活动来说,客服的压力是比较大的,相应的开发也会消耗很多经历用来查记录,确认 BUG,核实信息等。后来,我们开发了一系列的运营工具,从用户信息查询、抽奖记录查询、到补发积分、补发优惠券,甚至各种批量补发工具,都可以很方便地应对这些日常投诉。
期间最典型的例子是截图造假,用户只发个疑似 “中奖” 的截图过来要奖品,这时只需要查一下是否真的有抽奖记录即可。另外,客服的话术也要约定好,各种情况下要统一话术,否则就会有纠纷。
9.6 沉迷设计
抽奖系统一定程度上是要考虑沉迷设计的,通过适当的定期鼓励来促进参与度。本文的例子中我们只实现了连续不中的必中逻辑,对于经常参与的用户会有定期的奖励回馈。更复杂的沉迷设计并不适用于 web 端抽奖这种相对低频的游戏操作。
9.7 审计需求
跟钱打交道的业务,安全是第一位的。安全除了包含程序上的安全,还有人为因素,比如误操作等。此外,如果有内部人员恶意操作等,也是要有据可查的。
因此,所有具有权限的人员操作流水,包括时间和结果等都要记录在案。尤其是对于有价物品的发放日志,补发积分、红包、优惠券等操作记录。对于公司年底审计的时候,也需要提供各种操作流水给审计公司。
本文为@运营喵原创,运营喵专栏作者。