https://github.com/is-Xiaoen/CampusHub
上面是github链接,跟朋友写的一个开源项目,基于 go-zero
微服务框架构建的校园活动发布、报名、签到平台。采用 Clean Architecture 设计,支持分布式事务、全文搜索、实时通讯。
大家感兴趣觉得还不错的欢迎点点 star !有什么需要改进的地方欢迎大家指出!
阶段1:报名阶段
1.1 报名前检查
-
输入:用户ID、活动ID
-
检查项:
-
查询用户当前信誉积分
-
如果积分 < 60,直接拒绝报名,返回错误信息:"信誉积分不足,无法报名"
-
-
输出:检查结果(通过/拒绝)
1.2 创建报名记录
-
操作:
-
在数据库中创建报名记录
-
记录字段:用户ID、活动ID、报名时间、状态(已报名/已核销/已取消)
-
设置初始状态为"已报名"
-
1.3 生成票据码
-
生成规则:
-
票据码格式:
TICKET_{活动ID}_{用户ID}_{时间戳}_{随机字符串} -
时间戳:Unix时间戳(秒级)
-
随机字符串:8位随机字符(字母+数字)
-
-
存储:将票据码与报名记录关联存储
1.4 生成TOTP密钥
-
操作:
-
为每个报名记录生成唯一的TOTP密钥
-
密钥格式:Base32编码的随机字符串(16-32字符)
-
存储密钥到数据库(加密存储)
-
-
TOTP参数:
-
算法:HMAC-SHA1
-
时间步长:30秒
-
位数:6位数字
-
1.5 生成二维码
-
二维码内容:
{ "ticket_code": "TICKET_xxx", "user_id": "用户ID", "activity_id": "活动ID", "timestamp": 时间戳, "signature": "签名(可选,用于防篡改)" } -
格式:JSON字符串,然后转换为二维码图片
-
返回:二维码图片(Base64编码或URL)
阶段2:活动准备阶段
2.1 定时任务:活动开始前24小时检查
-
触发时机:活动开始前24小时
-
检查逻辑:
-
查询所有状态为"已报名"的记录
-
检查报名是否有效(例如:用户是否取消、活动是否取消等)
-
如果报名无效,扣减用户信誉积分5分
-
更新报名状态为"制备无效"
-
阶段3:核销阶段
3.1 核销时间窗口
-
开启时间:活动开始前30分钟
-
关闭时间:活动结束后1小时
-
验证逻辑:
-
当前时间 < 活动开始时间 - 30分钟:拒绝核销
-
当前时间 > 活动结束时间 + 1小时:拒绝核销
-
在时间窗口内:允许核销
-
3.2 组织者扫描二维码
-
输入:二维码内容(JSON格式)
-
解析:
-
解析JSON获取票据码、用户ID、活动ID、时间戳
-
验证时间戳是否在有效期内(例如:5分钟内)
-
验证签名(如果使用)
-
3.3 获取当前TOTP动态码
-
操作:
-
根据票据码查询报名记录
-
获取存储的TOTP密钥
-
计算当前时间窗口的TOTP动态码
-
公式:
TOTP = HMAC-SHA1(密钥, 当前时间/30) % 1000000(6位数字)
-
3.4 验证TOTP动态码
-
输入:组织者扫描二维码时获取的TOTP码(从二维码中解析或用户手动输入)
-
验证:
-
计算当前时间窗口的TOTP码
-
计算前一个时间窗口的TOTP码(容错处理,允许30秒误差)
-
计算后一个时间窗口的TOTP码(容错处理)
-
如果输入的TOTP码与任一计算结果匹配,验证通过
-
3.5 防重复核销(幂等性设计)
-
检查逻辑:
-
查询报名记录的核销状态
-
如果状态为"已核销":
-
返回核销信息(核销时间、核销人)
-
返回HTTP 200状态码(幂等性:重复请求返回相同结果)
-
-
如果状态为"已报名":
- 继续执行核销流程
-
3.6 执行核销
-
操作:
-
使用数据库事务确保原子性
-
更新报名记录状态为"已核销"
-
记录核销时间
-
记录核销操作人(组织者ID)
-
提交事务
-
3.7 核销成功响应
-
返回信息:
-
核销成功
-
用户信息(姓名、头像等)
-
核销时间
-
活动信息
-
阶段4:活动结束后处理
4.1 定时任务:活动结束后1小时检查
-
触发时机:活动结束后1小时
-
检查逻辑:
-
查询所有状态为"已报名"但未核销的记录
-
对每个未核销的记录:
-
扣减用户信誉积分10分
-
更新记录状态为"未参加"
-
记录扣分原因和时间
-
-
TOTP 核心算法实现
1. 生成TOTP密钥(Ba2se3)
- 计算时间步长,通过时间步长来刷新验证码,然后核销,如果时间步长不一样说明totp码不同,说明过期了,会核销失败
2. HMAC计算(为时间步长"签名")
将时间步长和TOTP密钥混合, 生成一个不可预测的,唯一的哈希值,防止密钥泄露导致伪造,并保证时间步长相似,但是也毫无关联,导致哈希冲突
3. 动态截断
从32字节的HMAC哈希中,动态选择4个字节作为生成验证码的种子,并确保这个种子足够随机,无法预测,防止固定位置攻击
4. 生成验证码
这一步坐了,取模运算------把最大数压缩到六位,保证最后是六位数字,然后验证码输出
防止重复核销(幂等性设计)
1. 表结构层,唯一索引
2. redis层面:分布式锁(并发控制),涉及到悲观锁
https://github.com/is-Xiaoen/CampusHub
github链接,跟朋友写的一个开源项目,基于 go-zero 微服务框架构建的校园活动发布、报名、签到平台。采用 Clean Architecture 设计,支持分布式事务、全文搜索、实时通讯。 大家感兴趣觉得还不错的欢迎点点 star !有什么需要改进的地方欢迎大家指出!