WORKBUDDY 技能包

给页面加一道卡密门
但别做成「用一次就作废」

静态站 / 单文件 H5 的付费门。一张码绑一台手机:同一台手机随便进,换手机才拦。

先讲一个真实的坑

买家投诉:明明付了钱,退出来就进不去了

规则是「核销即一次性 + 本地存会话」,看起来最安全。实际发生的是:

买家进过一次 → 会话存在浏览器里 → 退出重开 → 碰上一次网络波动 → 前端把本地凭证抹了 → 只好重输同一张码 → 服务端只看到「这张码核销过了」→ 回一句「已经被用过了」。

买家钱付了、码在手上、门进不去,而且没有任何自救路径。

这套规则防不到任何人 —— 你自己在后台一查就知道码有没有被转手; 它唯一稳定做到的事,是把正常买家锁在门外。

正确的规则:码认设备,不认次数

场景结果
首次输码放行 · 核销 + 把这串码绑到本机标识上
同一台手机再来放行 · 长期可反复进入,不报「已用过」
换一台手机403 · 不放行,也不改动已有绑定
买家换了手机客服一条命令解绑一次,买家在新手机上输码即改绑
别家产品的码401 · 拒绝,且不把那张码烧成已用

判定顺序(顺序本身就是设计)

1
码不在库里 → 无效计入限流
2
前缀不是本站产品 → 拒绝计入限流
必须放在核销状态判断之前,否则拿别家码来探,会先把那张码烧掉
3
还没核销 → 核销 + 绑本机 + 发会话
4
已核销 → 分五种
设备指纹或设备盐命中 → 放行(只读,零 KV 写)
码里没有设备字段 + 带了设备 → 收编(救升级前的老码)
管理员标记可改绑 + 设备不同 → 改绑一次
完全没带设备标识 → 409 已用(兼容没升级的旧页面)
其余 → 403 换设备了刻意不计限流
为什么「换设备被拒」不能计入失败限流
它意味着调用方手上有一条真实存在且有效的码 —— 不是枚举探测,记进限流挡不到任何人。 而买家指纹万一漂了会反复重试,本来就已经被挡在门外了,再叠一个「一小时不许再试」是纯粹的雪上加霜。

装法

技能包(约 96 KB,零第三方依赖)
下载 kv-access-gate.zip
Windows 可直接双击打开 zip,不会乱码

解压后把 kv-access-gate 整个文件夹放进 ~/.workbuddy/skills/,重启对话即可。 之后跟 AI 说一句「用 kv-access-gate 给我这个页面加卡密验证门」就行。

Windows 路径是 C:\Users\<用户名>\.workbuddy\skills\。

想手动跑,四条命令:

node 初始化.js "<工作区>/访问验证系统"
node tools/同步产品配置.js
node tools/生成卡密.js SJ 1000
node tools/导入卡密到KV.js --product SJ
node tools/接入验证门.js "<你的产品目录>" --out "<部署包目录>"
node tools/部署.js "<部署包目录>" <Pages项目名>
node tools/验收-设备绑定.js

本地先自测(不用云账户、不用联网)

node assets/tools/自测-设备绑定逻辑.js

58 项断言,覆盖 17 组场景:首次核销 / 同机重进 / 指纹或盐任一命中 / 换机拦截且不篡改绑定 / 会话回访与续签 / 老码收编 / 旧客户端兼容 / 改绑一次 / 产品绑定 / 归一化 / 脏标识 / 限流 / 并发抢码 / 请求方法。

改完服务端函数先跑这个,30 秒知道有没有改坏 —— 不用先部署到线上再拿买家当小白鼠。

14 个脚本,各管一段

脚本干什么
产品配置.js唯一需要手改的文件。产品表、前缀、域名都在这
初始化.js铺骨架 + 环境自检(Node 版本 / wrangler / 配置 / 凭证)
同步产品配置.js把产品表写进服务端函数。加产品只需改一处
生成卡密.js出一批码,两份文件:卡券库导入 + KV 导入
导入卡密到KV.js批量写进 KV,写完抽一张回读确认
接入验证门.js自动找入口 / 改写 / 插门 / 拷函数
升级验证门.js门或函数改了,替换已存在的部署包(各保留自己的前缀)
部署.js建项目 + 绑 KV + 设环境变量 + 部署
验收-线上五项.js接口活着 / 门在 / 核销隔离 / 产品绑定 / 归一化
验收-设备绑定.js同机重进 / 换机拦截 / 老码收编 / 旧客户端兼容
自测-设备绑定逻辑.js本地 58 项,不用联网
解绑设备.js换手机售后。标可改绑 + 作废旧会话
清限流.js把自己从「尝试次数过多」里放出来
_公共.js产品表解析 / 凭证 / 云 API / wrangler

七条死规矩

① 前端只在「明确失效码」时清本地凭证
网络类错误(请求抛错、5xx、限流 429)一律保留凭证,让买家点一下重试。 「任何非正常响应就清凭证」正是上面那个坑的根因。
② 本地凭证 localStorage + Cookie 双写
各 App 的内置浏览器对 localStorage 处理不一致,有的关掉页面就清。单靠它会丢凭证。
③ 设备指纹刻意排除浏览器型号、UA 版本、Canvas 指纹
同一台手机用内置浏览器和系统浏览器打开,必须是同一台。 而 Canvas / 字体指纹会被 Safari、Firefox 逐会话随机化,拿它当判据会把正常买家误判成换设备。 误伤比挡不住严重得多。
④ 前端传上来的设备标识一律清洗后再存
只收小写字母数字与短横、长度上限 64,脏值当没传。防脏数据把正常设备全判成「换了设备」。
⑤ 同设备重进走只读快路径,零 KV 写
KV 免费版每天只有 1000 次写。不这么做,正常买家的回访会把额度啃光。
⑥ 升级前已核销的老码要自动收编
不然发新版的那一刻,所有已售出、已核销的买家全部被锁死。这是必须有的兼容措施。
⑦ 产品表只有一个真源
散着写迟早不一致,那就会出现「买一个产品的码在别的产品页面上也能用」——等于买一个用全部。

几个会浪费你一整个下午的坑

还有一条:永远不要用普通接口去读写 KV。
那个接口发的是 JSON 且会自动序列化,写字符串进去会多套一层引号;读的时候响应体就是值本身、没有 result 字段。 必须用纯文本写入 / 直接读文本那两个函数。