[项目总结] 为某银行开发一个开业线上活动的H5网站
0x00:写在前面
甲方给出的大致需求是做一个移动端 H5
的活动网站,需要实现微信登录、在线点播视频,抽奖、奖品发放等功能,但距离甲方的活动上线的时间只有7天左右,所以还需要考虑是否能在这个时间区间内实现所有的需求。
经过需求的梳理以及参考类似的产品过后,得出可能会遇到一些难点(没有动手实现过的需求)例如对接一些微信的API、视频在线点播、微信红包自动发放等。但这些都是在可以接收的范围内的,查文档查案例,边学边做,顺便也可以将近期所学得的知识点用在该项目当中来。0x02:需求分析
甲方给出的活动流程如下:
- 前三天进行推文和长图传播,最终弄实现形式是H5(包括微电影+抽奖)
- 三天三部微电影,观看完整视频后可获得一次(仅有一次)抽奖机会,奖品大多数是红包
- 并生成二维码进行分享传播,别人扫你的二维码可增加人气值和最多一次的抽奖机会
- 人气值在最后一天体现,每天的H5要有人气值的排行榜。
- 第四天做答案揭晓,并在朋友圈做广告推广(推广这块由另一位老板负责)根据排行榜抽取最终的大奖
开发周期:7
天时间实现所有需求,第 8
天早上上线,活动持续 4
天时间,第 11
天下午活动结束。
0x03:需求整理
- 用户点击【开启新起点】按钮,浏览企业信息
- 观看一部微电影视频,观看结束后提示用户获得一次抽奖机会
- 抽奖成功,显示当前的抽奖结果,在【我的奖品】内可以查看抽奖记录
- 引导用户点击【生成邀请海报】点击保存海报图片,引导用户分享到朋友圈或者微信好友
- 成功邀请好友进入到页面,用户额外获得一次抽奖机会,邀请者人气值增加,用户每邀请成功一个用户,都会获取一定的人气值,但抽奖机会只能额外增加一次。
- 点击【活动锦囊】查看当前人气排行榜,以及自己的积分数量和排名
0x04:业务流程总结
微信登录授权流程
- 用户进入活动页面,为用户重定向至微信授权页面,等待用户选择 “同意” 或 "拒绝" 授权。
- 用户同意授权,微信授权服务会自动重定向到
redirect_uri
中的URL
,也就是我们的后端的用户登录接口,并且会携带用户的tempcode
- 后端的用户登录接口接收到
tempcode
并使用tempcode
去获取用户的access_token
等信息,获取成功后微信会返回access_token
以及用户的openid
、unionid
等信息(公众号需要绑定微信开发平台才能获取到unionid
,unionid
可以作为该微信号的唯一标识) - 携带 access_token 获取该用户的微信信息,并添加或者更新到数据库内。
- 生成JWT令牌,为用户重定向至活动主页,并在重定向时携带生成的
JWT
令牌信息。
用户在线点播视频流程
- 由于在线点播视频使需要携带
playauth
才能进行播放,后端使用spring task
开启定时任务,每隔一段时间向阿里云vod
服务获取新的playauth
(playauth 默认的过期时间为7200秒,所以我们需要提前一些时间去更新) - 用户点击播放视频,向后端接口请求该视频的播放信息,例如视频ID、视频标题、描述信息、playauth等
- 后端接收到请求后,首先校验用户携带的JWT令牌是否合法。
- 令牌校验失败,则会响应的效应的信息到前端,前端再要求用户重新信息授权登录。
- 令牌校验通过,返回指定视频的播放信息到前端。
- 前端播放器携带获取到的视频
id
以及playauth
访问阿里云VOD服务,获取该视频的播放流。 - 接收视频的流数据,播放视频。
- 每个一段时间向后端发送当前视频的播放进度,后端接收到请求后做相应的记录,并且响应当前的记录状态到前端
- 后端以用户首次提交进度作为播初始提交时间,当检测到用户当前提交的播放进度符合要求时,对比用户第一次与最后一次提交的时间的差来判断用户是否存在作弊行为。
- 用户完成当天的视频观看任务,增加一次抽奖机会。
抽奖流程
- 用户点击抽奖,显示腾讯滑块验证码,要求用户通过该验证码后才能进行下一步操作。
- 滑块通过,将滑块验证码的行为数据加密后发送到腾验证码服务进行校验
- 腾讯验证码服务返回校验后的信息到前端,但此时前端还无法判断用户是否通过了校验
- 前端将收到的验证信息发送到后端服务,后端首先会校验用户的
jwt
令牌是否合法(防止接口薅羊毛的人恶意调用)令牌校验通过后将接收到验证信息后再次向验证码服务请求校验。 - 验证码服务返回校验结果,校验失败则返回响应的结果到前端,前端收到后要求用户重新通过验证码后才能进行后续的操作。
- 验证码校验成功,根据预设的概率来计算抽奖等级,如果抽到的是现金红包,则为用户重定向至红包的领取页面。
用户分享海报增加积分流程
- 用户
A
进入海报分享页面,前端以携带用户ID
的链接作为参数生成一个二维码,点击生成海报,生成图片。 - 用户
B
扫描用户A
分享海报中的二维码,访问用户A
的分享链接并且要求用户B进行微信授权。 - 用户
B
同意授权,在微信授权接口的state
参数中携带用户A的userid
作为friendid
,并重定向至后端登录接口 - 后端接口获取用户
B
的微信信息,根据用户的openid
判断该用户是否为新注册的用户,如果是则根据携带的friendid
为用户A
增加一次邀请积分。 - 生成
JWT
令牌信息,为用户B重定向至活动主页。
0x05:实现过程总结
具体的实现思路以及伪代码的过程都写在了思维导图中。
https://www.processon.com/view/link/5ee39247f346fb1ae55ef6d3
0x06:项目中用到的技术栈
前端
技术、框架 |
说明 |
---|---|
Vue |
前端框架,MVVM 模式的实现者 |
Vue CLI |
Vue 脚手架,基于 NodeJS |
Vue Router |
Vue 路由框架 |
Vuex |
Vue 全局状态管理框架 |
Webpack |
用于将Vue工程打包为单页应用进行部署 |
Axios |
前端 HTTP 框架 |
Vant UI |
VantUI 是有赞开源的一套基于 Vue 2.0 的 Mobile 组件库。通过 VantUI 组件库,可以快速搭建出风格统一的页面,提升开发效率。 |
SCSS |
Sass 是成熟、稳定、强大的CSS预处理器,而SCSS是Sass3版本当中引入的新语法特性,完全兼容 CSS3 的同时继承了Sass强大的动态功能。 |
TCaptcha.js |
用于Web 端快速接入腾讯验证码,适用于每次都需要进行人机验证的场景(登录、注册、下发短信、活动等)接入文档 |
Aliplayer.js |
阿里云播放器SDK |
Shake.js |
实现微信摇一摇功能,IOS端需要提供运动权限 |
Vueqr.js |
用于前端生成二维码 |
html2canvas |
指定dom生成图片流,用于生成图片分享。 |
后端
技术、框架 |
说明 |
---|---|
Spring Boot |
Spring Boot 是新一代 JavaEE 开发标准,本项目中使用 Spring boot 2.2.X 作为后端开发框架 |
Spring Task |
使用 Spring Task 对阿里云 vod 视频播放的认证信息进行定时更新,保证用户能够正常获取视频信息。 |
Mybatis Plus |
Mybatis-Plus(简称MP)是一个 Mybatis 的增强工具,用于简化 MyBatis 操作,一些常用的单表操作我们则直接使用Mp提供的API来进行,而复杂的多表操作我们任然是编写sql语句使用原生 Mybatis 来执行,们用到的版本是 3.3.2 , 依赖包内集成了 Mybatis 3.5.4 |
MyBatisGenerator |
Maven 插件,用于 MyBatis 相关代码生成 |
MybatisCodeHelper |
Intellij IDEA 插件,用于 MyBatis 相关代码生成 |
jjwt |
用于快速生成、校验JWT令牌。 |
Swagger2 |
自动生成接口文档,用于后端接口调试以及提供给负责前端的老板调试页面。 |
Maven |
项目依赖、版本管理 |
Docker |
容器化引擎。用于快速部署应用程序 |
Docker-maven-plugin |
maven打包插件,自动将maven项目打包为 docker 镜像 |
aliyun-java-sdk-vod |
提供阿里云视频点播服务的API的相关操作规范 |
tencentcloud-sdk-java |
用于快速接入腾讯云产品 API。本项目中用于接入腾讯滑块验证码 |
0x07:个人职责
- 负责与甲方对接、讨论需求
- 数据库设计
- 后端业务功能实现
- 项目部署、交付、运维
前端页面设计与实现的工作由 邓老板 负责
0x08:开发流程总结
0x09:最终实现效果
微信登录授权
视频在线点播
抽奖
自动发放红包
用户抽中现金红包后,后端返回一个重定向的请求,为用户重定向至红包代发平台的领取地址,领取成功后,代发平台又为用户重定向至我们的中奖页面,并显示用户的中奖金额,如下图
同时用户的微信消息中会收到一个服务通知,如下图所示
点击服务通知可以看到红包代发平台的领取消息,并且我们可以自定义一些活动的信息
点击领取红包,红包会自动存入我们的微信零钱当中,如下图
积分排行榜
0x0A:项目总结
- 过度的需求分析以及伪代码设计,这样做虽然逻辑能够严谨,但并不适用这种完成周期较短的项目,最终可能会导致某个功能整体的实现时间变得更长。解决方案是:分析需求后简单的罗列步骤,尽快的开始具体的代码编写,开发过程中可以进行单元测试。
- 项目完成周期过短,甲方对页面效果要求高,且还未确定最终的页面效果、文案(开发两天后,该项目甲方所要求的页面效果的平面图在项目上线的前一天还在变动,预期的规划跟不上甲方的变化)
- 未在活动前收集用户联系方式或要求用户先关注公众号,导致在活动结束后无法通知未关注公众号的用户填写收货信息。
- 上线前的安全策略没有准备妥当,例如可以使用
nginx
的一些模块来限制IP
的某个时间内的 请求频率,再配合iptables
进行访问控制,还有 行为验证码、令牌校验等机制(使用滑块等行为验证码可以大幅度的提高羊毛党的成本,也能最大程度的减少用户体验的损耗)但由于甲方的活动在几天内就要上线,我们需要在短时间内实现所有需求,没有多余的时间去考虑这些问题,当然,这也是因为我们这方面经验,否则这些在开始的时候就应该安排人手去着手准备,导致上线后被羊毛党使用爬虫脚本配合代理池来高频的访问我们的后端接口导致我们的带宽被占用,影响正常用的访问。 - 没有坚持每天都对当天完成的进度进行复盘总结,原因是在后续的几天时间里面,全天时间都花在了需求讨论和实现上,每天都是忙到晚上11点左右才回宿舍,已经再无精力去做总结,给出的解决方案是在往后的项目开发总,每天分段对开发的进度和情况进行复盘,例如午饭后、晚饭后、睡觉前,分段完成从而减少复盘时的焦虑。
- 完成周期以及合同纠纷问题。如果周期较短按最低需求先实现(避免扣细节的习惯)保证截至当天能够交付或者上线,产品顺利上线后再做优化和迭代。
再次感谢 邓老板 的陪同作战 150
多个小时(上线当天两个人连续作战 40
多个小时没有休息)项目最后能够顺利交付离不开队友的积极配合与支持,虽然上线当天还是出了一些状况,但是整体来说还是很好,通过本次项目也收获到了不少实际开发中的经验。
0x0B:其他
微信网页授权的 “坑”
day4的上午,开始对微信登录的逻辑进行分析,查阅微信开放平台对于网站应用开发的文档,预期是使用之前审核通过的 “网站应用” 进行相关的开发
经过测试后发现,在开放平台提供给 “网站应用” 文档内的 "微信登录开发指南" 只能实现PC端的二维码扫码登录,而并不适用于移动端H5的需求(移动端的需求应该是打开网页后直接弹出授权请求)
PC端扫码后提示授权
移动端直接提示授权
经过资料的查阅,以及在询问经验丰富的大哥,最后在 segmentfault
提出的问题 得到了答复,最终确认了移动端 H5
网站要想实现微信登录授权,必须通过微信公众号来进行,而微信开发平台上的 “网站应用” 只适用于PC端网站进行扫码登录。微信为每个用户提供了公众平台的 测试账号 ,但API操作上有次数和频率的限制,并不适用于投入生产使用。
下午,最后还是把甲方的公众号权限要了过来,交付相关的权限后查阅 微信开放文档 进行相关流程的测试,最终实现了微信登录授权到信息获取的全过程,满足了该项目的需求,接下来是对整个后端的登录、校验流程的设计。整个下午都在使用思维导图对流程进行设计,没有进行实际的编码操作。
晚上,继续完善了登录流程的设计,整打算进行实际的编码,然后想到跟邓老板先讨论一下这个登录设计逻辑有无问题,经过分析后发现,设计的流程当中需要频繁的访问微信的授权 API
获取用户信息,且根据我们的需求,有更高效的方案,经过2个多小时的讨论后,最终决定使用 JWT
来实现无状态的令牌校验,既能防止用户对令牌进行篡改,也能实现令牌自动失效的需求,而无需再将令牌储存到 redis
内进行过期校验。
使用goaccess实时分析、监控nginx日志
参考文档
https://blog.csdn.net/liyyzz33/article/details/89945844
配置实时刷新
https://www.jianshu.com/p/b134995ae16c
效果图
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 机器学习第4天:预测1立方米混凝土抗压强度
- 硬件笔记之GP106-90 3GB GTX1060 3GB魔改
- Java BigDecimal 的舍入模式(RoundingMode)详解
- 实际工程中加快 Java 代码编写的小提示
- CentOS7 离线安装软件并准备依赖包
- CentOS7 SkyWalking APM8.1.0 搭建与项目集成使用
- CentOS7 cassandra安装与测试
- Centos7 搭建DNS服务器
- CentOS7 fastdfs安装与测试
- CentOS7 jdk安装
- CentOS7 kafka安装
- Centos7 keepalived安装并监控mysql实现自动切换
- Centos7 mqtt集群安装
- CentOS7 mysql5.7安装并配置主主同步
- CentOS7 nginx安装并负载mysql