给微软中国做的第二场活动站点,页面比 2020 年那次还简单,身份这块复杂了:内部员工点了链接直接进,外部嘉宾现场扫码入场,最后要落进同一张签到表。
两条路
员工那条走 SSO。OA 里嵌的链接带加密票据,后端解出 mail_prefix,查身份表拿角色,跟 2019 年那套内部表单是一个路子,票据 5 分钟一次性。
嘉宾那条用钉钉扫码。现场立牌上一个二维码,扫完跳转带一个临时 code,后端拿 code 换用户信息,写一条 guest 记录,发一个 2 小时有效的临时凭证。不要求注册,也不收手机号。
两条路在签到表上合成一个结构:person_type、person_id、姓名、来源、签到时间、场次,6 个字段。报表按场次分 sheet 时,员工和嘉宾混在一起按签到时间排,不分开。
验签那个坑
钉钉回调带 timestamp 和签名,我们按常规拿 timestamp 加密钥算,一直验不过,返回 401。查了半天,那个 timestamp 是 13 位毫秒,而文档示例里按秒算的部分被我们照抄了。改成先除以 1000 再参与验签,通了。
顺手把时间容差设成 5 分钟,防止手机和服务器差得太多。重放靠一个 nonce 集合,Redis 存 10 分钟。
现场
5 月 16 号,9 点开门。前一个小时签到 400 多人,其中员工 100 多、嘉宾 300 出头。两套入口各走各的,签到台只用一台电脑看同一张表,不用切系统。
中间有个小插曲:一位嘉宾扫完码把页面关了,回来重扫,生成了第二条 guest 记录。后来按钉钉返回的唯一 userid 做了合并,重复的直接指向同一条,没影响统计。
两套身份怎么对上的
员工和嘉宾最后落进同一张签到表,但两边的 person_id 不是一套东西:员工是 mail_prefix,嘉宾是钉钉返回的 userid。报表里能混排,是因为我们没让这两列直接比,另加了一列 person_type 区分。第一版想统一成一个 id,做了半天发现没必要,还容易把外部嘉宾误判成内部人。
有个细节:员工里也有嘉宾家属,走的是员工入口但填了家属信息。这类在签到表上标成「员工带人」,统计到场人数时算 2,算员工出勤时算 1。客户自己定的规则,我们只负责把两列都留着,别在导出时替他们决定算哪个。
临时凭证那 2 小时
2 小时是照着活动时长定的,中间留了点余量。真有人散场后回来想再进场,凭证过期,扫码会提示「已结束,请联系签到台」,不再生成新记录。当天有 3 个人回来过,签到台手工放行,在备注里各写了一行。
钉钉那个 userid 合并,是活动当天中午加的。上午有位嘉宾重扫生成了两条,客服发现后我们改了逻辑:同一 userid 在同一场次只保留一条,后来的指向先来的。改动很小,赶在下午人最多之前上线,没再出现重复。
立牌和胶带
那天风大,门口立牌被吹歪过一次,行政拿胶带粘的。技术上的事没再出,倒是散场后有人问,能不能下次把二维码直接印在签到台桌面上,省得扶牌子。这条记进了活动复盘,没写进需求文档。
那份 7 列的 CSV 后来被客户拿去做了个简单的柱状图,按来源分两组,他们没让我们做图,自己拖的,挺好。那 3 个手工放行的备注,活动复盘时客户还专门看了一眼,说写清楚就行。胶带那截后来撕掉了,立牌收进库房。
导出
活动结束导了一份 CSV,7 列,按来源标了颜色,客户拿去对邀请名单。员工那部分不用对,本来就在名册里。
那天北京风挺大,立牌在门口被吹歪过一次,行政拿胶带粘了下。技术上的事没再出。

