# 0x00:写在前面
甲方是某地区的一个农商银行,由于新网点开业需要做一个活动网站,接入到自己的公众号内进行推广,以配合线下的活动同步进行,需要实现微信登录、在线点播视频,抽奖、奖品发放等功能,但距离甲方的活动上线的时间只有7天左右,所以还需要考虑是否能在这个时间区间内实现所有的需求。

经过需求的梳理,以及参考类似的产品过后,列出了可能会遇到一些技术上的难点(没有实现过的需求)例如对接一些微信的API、视频在线点播、微信红包自动发放等。但这些都是在可以接受的范围内的,查文档查案例,边学边做,顺便也可以将近期所学得的知识点用在该项目当中来。
# 0x01:目录
[TOC]
# 0x02:需求分析
甲方给出的活动流程如下:
1. 前三天进行推文和长图传播,最终弄实现形式是H5(包括微电影+抽奖)
2. 三天三部微电影,观看完整视频后可获得一次(仅有一次)抽奖机会,奖品大多数是红包
3. 并生成二维码进行分享传播,别人扫你的二维码可增加人气值和最多一次的抽奖机会
4. 人气值在最后一天体现,每天的H5要有人气值的排行榜。
5. 第四天做答案揭晓,并在朋友圈做广告推广(推广这块由另一位老板负责)根据排行榜抽取最终的大奖
开发周期:`7` 天时间实现所有需求,第 `8` 天早上上线,活动持续 `4` 天时间,第 `11` 天下午活动结束。

# 0x03:需求整理

1. 用户点击【开启新起点】按钮,浏览企业信息
2. 观看一部微电影视频,观看结束后提示用户获得一次抽奖机会
3. 抽奖成功,显示当前的抽奖结果,在【我的奖品】内可以查看抽奖记录
4. 引导用户点击【生成邀请海报】点击保存海报图片,引导用户分享到朋友圈或者微信好友
5. 成功邀请好友进入到页面,用户额外获得一次抽奖机会,邀请者人气值增加,用户每邀请成功一个用户,都会获取一定的人气值,但抽奖机会只能额外增加一次。
6. 点击【活动锦囊】查看当前人气排行榜,以及自己的积分数量和排名
# 0x04:业务流程总结
捋清楚项目中一些核心的功能实现流程
## 微信登录授权流程

1. 用户进入活动页面,为用户重定向至微信授权页面,等待用户选择 “同意” 或 "拒绝" 授权。
2. 用户同意授权,微信授权服务会自动重定向到 `redirect_uri` 中的 `URL`,也就是我们的后端的用户登录接口,并且会携带用户的 `tempcode`
3. 后端的用户登录接口接收到 `tempcode` 并使用 `tempcode` 去获取用户的 `access_token` 等信息,获取成功后微信会返回 `access_token` 以及用户的 `openid`、`unionid` 等信息(公众号需要绑定微信开发平台才能获取到`unionid`,`unionid` 可以作为该微信号的唯一标识)
4. 携带 access_token 获取该用户的微信信息,并添加或者更新到数据库内。
5. 生成JWT令牌,为用户重定向至活动主页,并在重定向时携带生成的 `JWT` 令牌信息。
## 用户在线点播视频流程

1. 由于在线点播视频使需要携带 `playauth` 才能进行播放,后端使用 `spring task` 开启定时任务,每隔一段时间向阿里云 `vod` 服务获取新的 `playauth`(playauth 默认的过期时间为7200秒,所以我们需要提前一些时间去更新)
2. 用户点击播放视频,向后端接口请求该视频的播放信息,例如视频ID、视频标题、描述信息、playauth等
3. 后端接收到请求后,首先校验用户携带的JWT令牌是否合法。
4. 令牌校验失败,则会响应的效应的信息到前端,前端再要求用户重新信息授权登录。
5. 令牌校验通过,返回指定视频的播放信息到前端。
6. 前端播放器携带获取到的视频 `id` 以及 `playauth` 访问阿里云VOD服务,获取该视频的播放流。
7. 接收视频的流数据,播放视频。
8. 每个一段时间向后端发送当前视频的播放进度,后端接收到请求后做相应的记录,并且响应当前的记录状态到前端
9. 后端以用户首次提交进度作为播初始提交时间,当检测到用户当前提交的播放进度符合要求时,对比用户第一次与最后一次提交的时间的差来判断用户是否存在作弊行为。
10. 用户完成当天的视频观看任务,增加一次抽奖机会。
## 抽奖流程

1. 用户点击抽奖,显示腾讯滑块验证码,要求用户通过该验证码后才能进行下一步操作。
2. 滑块通过,将滑块验证码的行为数据加密后发送到腾验证码服务进行校验
3. 腾讯验证码服务返回校验后的信息到前端,但此时前端还无法判断用户是否通过了校验
4. 前端将收到的验证信息发送到后端服务,后端首先会校验用户的 `jwt` 令牌是否合法(防止接口薅羊毛的人恶意调用)令牌校验通过后将接收到验证信息后再次向验证码服务请求校验。
5. 验证码服务返回校验结果,校验失败则返回响应的结果到前端,前端收到后要求用户重新通过验证码后才能进行后续的操作。
6. 验证码校验成功,根据预设的概率来计算抽奖等级,如果抽到的是现金红包,则为用户重定向至红包的领取页面。
## 用户分享海报增加积分流程

1. 用户 `A` 进入海报分享页面,前端以携带用户 `ID` 的链接作为参数生成一个二维码,点击生成海报,生成图片。
2. 用户 `B` 扫描用户 `A` 分享海报中的二维码,访问用户 `A` 的分享链接并且要求用户B进行微信授权。
3. 用户 `B` 同意授权,在微信授权接口的 `state` 参数中携带用户A的 `userid` 作为 `friendid`,并重定向至后端登录接口
4. 后端接口获取用户 `B` 的微信信息,根据用户的 `openid` 判断该用户是否为新注册的用户,如果是则根据携带的`friendid` 为用户 `A` 增加一次邀请积分。
5. 生成 `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 端快速接入腾讯验证码,适用于每次都需要进行人机验证的场景(登录、注册、下发短信、活动等)[接入文档](https://cloud.tencent.com/document/product/1110/36841) |
| 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:个人职责
- 负责与甲方对接、讨论需求
- 数据库设计
- 后端业务功能实现
- 项目部署、交付、运维
前端页面设计与实现的工作由 [邓老板](https://bangyid.cn/) 负责
# 0x08:开发流程总结

# 0x09:最终实现效果
## 微信登录授权

## 视频在线点播

## 抽奖

## 自动发放红包
用户抽中现金红包后,后端返回一个重定向的请求,为用户重定向至红包代发平台的领取地址,领取成功后,代发平台又为用户重定向至我们的中奖页面,并显示用户的中奖金额,如下图
<img src="https://qnoss.codeyee.com/202020292240-r.png" style="zoom:50%;" />
同时用户的微信消息中会收到一个服务通知,如下图所示
<img src="https://qnoss.codeyee.com/202020292243-Q.png" style="zoom:50%;" />
点击服务通知可以看到红包代发平台的领取消息,并且我们可以自定义一些活动的信息
<img src="https://qnoss.codeyee.com/202020292243-f.png" style="zoom:50%;" />
点击领取红包,红包会自动存入我们的微信零钱当中,如下图
<img src="https://qnoss.codeyee.com/202020292243-k.png" style="zoom: 33%;" />
## 积分排行榜

# 0x0A:项目总结
- 过度的需求分析以及伪代码设计,这样做虽然逻辑能够严谨,但并不适用这种完成周期较短的项目,最终可能会导致某个功能整体的实现时间变得更长。解决方案是:分析需求后简单的罗列步骤,尽快的开始具体的代码编写,开发过程中可以进行单元测试。
- 项目完成周期过短,甲方对页面效果要求高,且还未确定最终的页面效果、文案(开发两天后,该项目甲方所要求的页面效果的平面图在项目上线的前一天还在变动,预期的规划跟不上甲方的变化)
- 未在活动前收集用户联系方式或要求用户先关注公众号,导致在活动结束后无法通知未关注公众号的用户填写收货信息。
- 项目中使用了 `nginx` 的一些模块来限制 `IP` 的某个时间内的 [请求频率 ](https://www.jianshu.com/p/88edc4a0cba9),再配合 `iptables` 进行访问控制、部署goaccess等监控工具实施监控日志信息,还有 [行为验证码](https://007.qq.com/)、令牌校验等机制(使用滑块等行为验证码可以大幅度的提高羊毛党的成本,也能最大程度的减少用户体验的损耗)上线后被羊毛党使用爬虫脚本、代理池等手段来高频的访问我们的后端接口,导致我们服务器的大部分带宽被占用,好在部署实施监控的工具,并编写shell脚本实时对高频访问的IP进进行ACL,使得网站能够正常运行。
- 没有坚持每天都对当天完成的进度进行复盘总结,原因是在后续的几天时间里面,全天时间都花在了需求讨论和实现上,每天都是忙到晚上11点左右才回宿舍,已经再无精力去做总结,给出的解决方案是在往后的项目开发中,每天分段对开发的进度和情况进行复盘,例如午饭后、晚饭后、睡觉前,对每个时间段进行总结,从而减少复盘时的焦虑。
- 严格控制项目的完成周期,把控进度,预知风险,如果周期较短按最低需求先实现(避免过渡追求细节的习惯)保证能够顺利交付,产品顺利上线后再做优化和迭代。
再次感谢 [邓老板](https://bangyid.cn/) 的陪同作战150多个小时,上线当天两个人熬夜通宵之后还坚持了两天两夜(40多个小时)没有休息,项目的最后能够顺利交付离不开队友的积极配合与支持,虽然上线当天还是出了一些状况,但是整体来说还是很好,通过本次项目也收获到了不少实际开发中的经验。

# 0x0B:其他
## 微信网页授权的 “坑”
day4的上午,开始对微信登录的逻辑进行分析,查阅微信开放平台对于网站应用开发的文档,预期是使用之前审核通过的 “网站应用” 进行相关的开发
经过测试后发现,在开放平台提供给 “网站应用” 文档内的 "微信登录开发指南" 只能实现PC端的二维码扫码登录,而并不适用于移动端H5的需求(移动端的需求应该是打开网页后直接弹出授权请求)
PC端扫码后提示授权
<img src="https://qnoss.codeyee.com/20200627_[项目笔记] 某农商银行开业活动网站/image2.png" alt="image-20200617075421112" style="zoom:50%;" />
移动端直接提示授权
<img src="https://qnoss.codeyee.com/20200627_[项目笔记] 某农商银行开业活动网站/image3.png" alt="image-20200617075552275" style="zoom: 67%;" />
经过资料的查阅,以及在询问经验丰富的大哥,最后在 `segmentfault` [提出的问题](https://segmentfault.com/q/1010000022943900) 得到了答复,最终确认了移动端 `H5` 网站要想实现微信登录授权,必须通过微信公众号来进行,而微信开发平台上的 “网站应用” 只适用于PC端网站进行扫码登录。微信为每个用户提供了公众平台的 [测试账号](https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login) ,但API操作上有次数和频率的限制,并不适用于投入生产使用。
下午,最后还是把甲方的公众号权限要了过来,交付相关的权限后查阅 [微信开放文档](https://developers.weixin.qq.com/doc/offiaccount/Message_Management/One-time_subscription_info.html) 进行相关流程的测试,最终实现了微信登录授权到信息获取的全过程,满足了该项目的需求,接下来是对整个后端的登录、校验流程的设计。整个下午都在使用思维导图对流程进行设计,没有进行实际的编码操作。
晚上,继续完善了登录流程的设计,整打算进行实际的编码,然后想到跟邓老板先讨论一下这个登录设计逻辑有无问题,经过分析后发现,设计的流程当中需要频繁的访问微信的授权 `API` 获取用户信息,且根据我们的需求,有更高效的方案,经过2个多小时的讨论后,最终决定使用 `JWT` 来实现无状态的令牌校验,既能防止用户对令牌进行篡改,也能实现令牌自动失效的需求,而无需再将令牌储存到 `redis` 内进行过期校验。
## 使用goaccess实时分析、监控nginx日志
参考文档
https://blog.csdn.net/liyyzz33/article/details/89945844
配置实时刷新
https://www.jianshu.com/p/b134995ae16c
效果图

[项目总结] 某农商银行的开业线上活动网站