活动抽奖的创意方式(“盲盒抽奖”创意营销活动实践)

当无服务器和低代码两种不同的技术交叉在同一个业务中,会表现出怎样的价值?本文以Serverless Devs做过的一个创意营销活动“盲盒抽奖”为例,告诉你Serverless和low code是如何匹配来满足一个业务需求的。

前言

线上H5创意动漫结合线下实体奖励是互联网营销活动的常用手段。为了抓住关键的时间节点,活动从策划到落地的周期一般都比较短,短时间内落地上线服务对做技术开发的同学来说是不小的挑战。

尤其是当需求更多的时候,比如增加后台管理、关键前端访问数据埋点等,挑战往往会加倍。对于开发来说,除了完成核心业务需求,往往还需要关注非业务需求之外的其他情况,比如系统访问安全性、高并发流量响应、可观察的系统运行指标等等。

以往这种需求往往需要产品、前端、后端、设计、测试、运营、运维等多个角色的参与。,使得投入产出比降低,活动可持续性较差。今天有了无服务器+低代码的技术,我们可以大大降低做这种活动的成本,让它成为一个持续的活动,从而大大提高运营效果。

实际只投入了3.5人的无服务器Devs盲盒抽奖,完成了活动策划、产品设计、前端实施、系统部署、运维等活动。并且借助Serverless的服务能力,很容易满足系统访问安全、高并发流量、系统可观测性等这些非业务挑战。功能的完善和效率的提升,让这次运营取得了非常好的效益,活动服务的模板沉淀为后续类似活动打下了良好的基础。

“盲盒抽取”的整体流程如下:

  • 需求(包括业务逻辑和交互逻辑)
  • 设计草案
  • 低代码实现前端
  • 代码无服务器服务
  • 联合调试测试
  • 在线部署
  • 主动问题修复
  • 备份磁盘
  • 应用效果预览:



    “1分钟无服务器极速部署盲盒”抽奖活动现已结束,但有兴趣的同学仍可体验:https://developer.aliyun.com/adc/series/serverless2.

    架构预览:



    的这种部署架构不使用阿里云API网关,而是直接使用函数计算自定义运行时作为托管形式。这是因为这个需求的特殊性,我们是“自行部署,自行绘制”,实际上就是说端侧访问是去中心化的,端侧访问的服务比较单薄,只有数据处理接口调用和提供静态渲染服务,然后一个集中式的逻辑后台处理中奖概率和管理奖品。



    如果是做自己的集中式活动后台,建议参考以下架构模式,采用API gateway作为流量入口。方便进行更多的安全限制和更灵活的扩展。

    实现解析

    前端交互的低代码实现

    这个前端实现使用低级代码来工作hype4。hype4的具体用法这里就不详细描述了。感兴趣的同学可以自行搜索一下。

    设计稿除了裁剪出需要的图纸,还会实现和Flash一样的动画效果,最后添加js代码实现界面访问、场景切换等能力。整个过程会比全编码快很多,尤其是动态效率比纯手写高2-3倍。

    数据层中的无服务器服务

    如架构所示,这里的数据层其实就是我们理解的SSF,这一层只做数据转发和静态渲染。代码实现比较简单,采用express框架,然后以函数计算自定义运行时的形式部署。

    目的是该服务不仅可以托管静态内容,还可以进行动态数据转发。值得注意的是,用户的信息获取也是在这一层实现的。



    这里得到的是阿里云用户的accountId,方便对齐中奖信息,发放奖品。这个参数对于普通开发者来说没有太大意义。

    我们会提前在后台部署抽奖。接下来,每个用户部署完这层服务后,会接入自己部署的服务,然后将uid等基本信息发送到抽奖后台,发起抽奖。最后,返回获胜结果被传送到前端显示器。作为管理员,可以通过后台操作设置奖品和概率。

    后台抽奖逻辑的实现

    后端服务由Python Web framework: Django实现。主要方法有:

    1.获取用户的uid信息并验证uid信息,以确保:

  • uid信息的准确性
  • 客户端服务是通过无服务器Devs开发工具部署的;
  • 2.建立当天的奖金池;

    3.初步确定用户获奖信息;

    4.查看用户的中奖信息;

    5.将最终结果返回给客户端;

    基本流程

    1.在本地,用户通过无服务器的Devs开发者工具将盲盒抽奖的客户端服务部署到用户自己的账户;

    在部署期间,需要给用户颁发一个临时域名(这个临时域名需要用户的uid)。在发布临时域名的过程中,无服务器Devs会生成部分客户端令牌,并记录在无服务器Devs的后端服务中。这个令牌实际上是识别用户身份的重要标志;

    (如果用户在Yaml声明不使用系统自动发布的域名信息,可能无法成功参与本次活动)。

    2.用户部署完成后,会返回一个由无服务器Devs发布的临时域名,供用户学习和测试。

    3.接下来,用户通过浏览器打开临时域名,就可以看到抽奖的相关页面,用户点击就可以抽奖了。

    4.用户点击抽奖操作后,会在用户账号下发起对无服务器服务的请求,无服务器服务会根据用户的uid信息处理相关信息,向本次活动的后台无服务器服务发起真实的抽奖请求;

    5.当这个活动的后端无服务器服务收到用户的抽奖请求时,它会:

  • 获取用户账户下的无服务器服务发起抽奖请求时发送的uid信息;
  • 利用获取的uid信息匹配临时域名分配系统中的数据,确定用户本次使用了临时域名分配系统并分配了相应的域名;
  • 实现彩票运营;
  • 彩票核心的实现

    在抽奖操作过程中,也对目前的系统做了初步的评估,为小规模的抽奖活动设置了简单易实现的抽奖功能:



    在这一部分,Django项目的实现方法:

    @csrf_exempt

    定义奖品(请求):

    uid =请求。post . get(& # 34;uid & # 34,无)

    如果不是uid:

    return JSON response({ & # 34;错误& # 34;: "Uid是必需的。"})


    temp _ url = & # 34& lt获取uid的合法性和有效性是一个重要的判断依据>:?uid = & # 34+字符串(uid)

    if JSON . loads(urllib . request . urlopen(temp _ URL))。阅读()。解码(& # 34;utf-8 & # 34;))["回应& # 34;] == '0':

    return JSON response({ & # 34;错误& # 34;: "Uid是必需的。"})


    token = randomStr(10)

    #获得今日大奖

    奖品= {}

    for eve _ prize in prize model . objects . filter(date = time . strftime(& # 34;% Y-% m-% d & # 34;,time.localtime())):

    奖品[eve_prize.name] = {

    "伯爵& # 34;:eve_prize.count,

    "利率& # 34;:eve_prize.rate

    }

    #建立一个彩票池

    prize_list = []

    对于evePrize,eveInfo in prizes.items():

    temp_prize_list = [evePrize,]* int((100 * eve info[& # 39;利率& # 39;]))

    奖品列表=奖品列表+临时奖品列表

    none_list = [None,] * (100 - len(prize_list))

    奖品列表=奖品列表+无列表

    pre _ prize = random . choice(prize _ list)

    #数据仓库

    尝试:

    user model . objects . create(uid = uid,

    token =令牌,

    pre_prize=pre_prize,

    结果=假)

    除了:

    尝试:

    如果不是UserModel.objects.get(uid=uid)。结果:

    return JSON response({ & # 34;结果& # 34;: "0"})

    除了:

    及格

    return JSON response({ & # 34;错误& # 34;: "每个人只能参加一次。"})

    如果不是预奖:

    return JSON response({ & # 34;结果& # 34;: "0"})

    user _ id = user model . objects . get(uid = uid,token=token)。编号

    users _ count = user model . objects . filter(pre _ prize = pre _ prize,id__lt=user_id,date = time . strftime(& # 34;% Y-% m-% d & # 34;,time.localtime()))。计数()

    #获奖的最终判决

    如果users _ count & gt= prices . get(pre _ prize,{})。获取(& # 34;伯爵& # 34;, 0):

    十大创意抽奖方式

    return JSON response({ & # 34;结果& # 34;: "0"})

    user model . objects . filter(uid = uid,token=token)。更新(结果=真)


    return JSON response({ & # 34;结果& # 34;: {

    "token & # 34:令牌,

    "奖品& # 34;:pre_prize

    }})

    系统安全设置

    当用户赢得奖品时,系统将生成一个令牌。令牌和uid的组合是判断用户是否中奖的重要依据。这可能会涉及到一个问题:有uid的情况下需要添加什么token进行组合判断?其实原因很简单。如果提交中奖信息和查询中奖信息都是直接通过uid处理,那么很有可能用户会通过遍历等方式非法获取其他用户提交的信息,而这部分信息很有可能涉及到用户提交的接收地址等。所以为了安全起见,增加了一个令牌,一定程度上提高了被暴力穿越的复杂程度。而这部分方法也很简单:

    @csrf_exempt

    定义信息(请求):

    uid =请求。get . get(& # 34;uid & # 34,无)

    令牌=请求。get . get(& # 34;token & # 34,无)

    如果[uid,token]中没有:

    return JSON response({ & # 34;错误& # 34;: "Uid和令牌是必需的。"})

    user infor = user model . objects . filter(uid = uid,token=token)

    if userInfor.count() == 0:

    return JSON response({ & # 34;错误& # 34;: "尚未找到任何信息。"})

    如果不是userInfor[0]。结果:

    return JSON response({ & # 34;错误& # 34;: "目前还没有找到中奖信息。"})

    if request.method = = & # 34获取& # 34;:

    返回JsonResponse({

    "结果& # 34;: {

    "奖品& # 34;:userInfor[0]。预奖,

    "姓名& # 34;:userInfor[0]。姓名,

    "电话& # 34;:userInfor[0]。电话,

    "地址& # 34;:userInfor[0]。地址

    }

    })

    elif request.method = = & # 34邮政& # 34;:

    名称=请求。post . get(& # 34;姓名& # 34;,无)

    电话=请求。post . get(& # 34;电话& # 34;,无)

    地址=请求。post . get(& # 34;地址& # 34;,无)

    如果[姓名、电话、地址]中没有:

    return JSON response({ & # 34;错误& # 34;: "姓名、电话和地址是必填项。"})

    userInfor.update(name=name,

    电话=电话,

    地址=地址)

    return JSON response({ & # 34;结果& # 34;: "保存成功。"})

    整个过程是:

  • 通过用户的uid和令牌获取相关用户信息;
  • 如果请求方法是GET方法,则直接返回用户的获奖信息(指接收信息)。
  • 如果请求方法是POST方法,则允许用户修改中奖信息(指接收信息);
  • 其他安全补充剂:

  • 如何保证用户令牌等信息的唯一性和不可伪造性,在浏览器端不容易实现,因为用户可能会更换浏览器,但在函数计算平台的函数服务中,用户实现起来相对容易。因此,在域名发布阶段,记录指定时间段内发布的域名信息,然后在后期进行比对,以确保用户真正通过无服务器Devs开发者工具部署项目,发布临时域名,并在指定时间内参与活动。(当然,如果用户已经注册了多个阿里云账号参与该活动,这个时间是允许的)
  • 如何保证奖品不会超发?这部分系统采用了一个比较笨的方法,但也是小平台比较容易的方法,就是先给用户一个奖品标签,然后根据数据库中用户奖品的时间顺序位置来判断最终的中奖信息。比如用户获得了一个机械键盘,这是机械键盘在数据库中的第六个位置,但是机械键盘总共只有五个,那么这个时候,就会是正确的。(当然这种方式对于小规模的活动是可以的,但是对于大规模的活动是不可取的,因为无论用户是否中奖都会导致数据库的很多读写操作,这在一定程度上是不合理的)。
  • 中奖后,用户提交了奖品邮寄信息。如何保证这些信息的安全,防止被他人暴力穿越,也是一个值得关注的问题。这里增加了一个随机令牌,增加了被暴力遍历的复杂度,进一步保证了安全性。
  • 部署准备工作

    这种部署不需要域名,只需要使用函数计算生成的自定义域名,仍然需要安装无服务器Devs工具。这一次,你只需要打开函数计算。

    操作步骤

    彩票后台的一些模板还在准备中,只演示了前端和数据层服务的部署。

    步骤1:密钥配置

    见无服务器devs阿里云关键配置。

    第二步:初始化

    使用无服务器devs命令行工具执行:

    初始盲盒游戏

    引导操作:



    步骤3:构建部署

    修改相关的配置信息并执行s deploy



    效果查看

    功能部署:



    页面效果:



    抽奖部分的申请模板正在准备中,后续会统一在这个申请模板里给大家展示。

    结语

    经过以上实践,我想再次和大家拓展一下低代码无服务器的话题。以下部分将以理论为主,希望能给读者带来不一样的收获。

    无服务器+从开发人员的角度看代码低

    就我个人而言,明确的结论是,我并不排斥两者的兼容,但我真的希望两者的结合能进一步让我的工作更加高效和安全。

    我在这次活动中最大的感受就是,如果低代码平台可以无缝连接无服务器就好了。比如我在low-code上调用的接口,只能在测试前在线搭建和发送,这种自然集成的平台优势会很明显。另外,前端发布构建后,还得和后端接口组装。如果这是一个统一的平台,完成需求后可以一键发布,会省很多事。不过这里也有一个矛盾,因为我也担心一旦low code的前端和Serverless的后端耦合在一起,会变得不灵活,被服务提供商锁定。

    从供应商的角度看,无服务器+低代码

    可以看到,云服务商的无服务器化和低代码服务商正在相互融合。例如,低代码平台的领导者outsystem早在2016年就开始使用AWS服务,如Lambda,为他们的客户提供原生APP服务的构建。

    Trillo是一个低代码平台,以无服务器和模型驱动的应用程序为主要服务,帮助他们的用户构建基于谷歌云服务架构的无服务器服务和前端应用程序。当然,国内外各种云厂商也没闲着。Azure将其低代码产品Power Apps整合到无服务器的能力中,形成无服务器的Power Apps,充分融合了两者的优势。

    Aws前端集成交给了合作伙伴,他们更专注于服务端的无服务器集成,推出了Step Functions Workflow Studio产品,将无服务器与几乎所有自己的产品串联起来。

    腾讯在国内推出了微低码平台,也是以无服务器+低码为主。在小程序场景中,各厂商的跟进也显示了对这一领域的重视。

    搭建无服务器+低代码平台的想法

    无服务器+低代码平台的价值比较明确,其关键词是效率、安全、成本。那么要搭建这样一个平台,我们需要做哪些考虑呢?

    首先,从平台能力来说,我们应该能够从前到后覆盖一个应用开发的所有方面。例如:

  • 数据建模
  • 数据API
  • 使用无服务器构建后端应用程序逻辑
  • 部署支持长期运行的后端服务
  • 可扩展的外部服务集成
  • 文件存储器
  • 逻辑排列
  • 各种安全功能,如身份验证、权限控制等。
  • UI编排
  • CI/CD
  • 应用可观测量
  • 这里可以简单讨论一下这个平台的功能设计,基于云厂商的基础设施建设相应的能力。



    有一些与低代码能力相关的相关开源产品,可以在这里分享给大家:

  • Ui页面构建https://github.com/alibaba/designable
  • 数据库建模https://gitee.com/robergroup/chiner
  • 流程编排https://github.com/i5ting/imove
  • 另外,无服务器Devs的Iac能力可以考虑在与云基础设施的连接上,尤其是目前与FC的集成已经比较成熟,管理功能的全生命周期非常方便。

    当然,以上只是作者的一些想法,我知道要实现这样的系统并不容易,这里也只是参考。

    追求生产率的提高一直是企业生产的重要课题。无服务器和低代码在各自的技术领域有独立的分工,但也有共同的提高生产力的特点。学会同时掌握和利用好这两个生产力工具,对于从事信息行业的学生来说,可能是一个重要的竞争力。

    作者|谢晗&姜瑜

    原文链接:https://developer.aliyun.com/article/866362? UTM _ content = g _ 1000322916

    本文为阿里云原创内容,未经允许不得转载。

    您可以还会对下面的文章感兴趣

    使用微信扫描二维码后

    点击右上角发送给好友