Files
xiaotutongxue/backend/xt-server
lovife eb352e3537 feat(qrcode): M1-06 填报二维码(接入真实微信小程序)
学生端的入口终于通了:班主任把码发到班级群,学生扫码进填报页。
这条 E2E 是本仓库唯一打外网的测试 —— 真实调微信生成小程序码并取回图片。

交付:
· GET /tasks/{id}/qrcode?type=MINI[&orgId]  (§7.12)
· GET /qrcodes/{scene}  匿名图片接口(<img src> 带不了 Authorization 头,
  必须匿名。图里只有一串场景值,不含学生信息)
· 微信小程序凭据接入 + access_token 与二维码的 Redis 缓存

微信账号(已实测确认,不是靠猜):
· wxf01d3fa60f87f0b7 是【小程序】:小程序码可生成、小程序订阅消息可用、
  公众号的用户管理接口返回 48001(交叉验证)
· wx5d3ae5c1c21fef24 是【公众号测试号】:做不了小程序码,但能做网页授权
  + JS-SDK —— 正好是「H5 保底」需要的能力。两条路都有号了

三处刻意的设计:
1) access_token 走 Redis 缓存(TTL 7000 秒,比官方 7200 少 200 避开边界)。
   token 获取接口有日调用限额(约 2000 次),每次生成码都取一次,
   几十个班一起用就会撞限额 —— 表现是"早上还能用,下午全班的码都生成不出来"。
2) 同一个 scene 的图缓存 30 天:图是一样的,而生成接口本身也有日限额,
   列表页每渲染一次就可能请求一次。
3) 微信 errcode 翻译成人话:40164(IP 不在白名单)与 40001(appsecret 错)
   是完全不同的排查方向,只给一个数字等于让运维从错的方向查起。

匿名图片接口**只读缓存、绝不现场调微信**:否则任何人都能用构造出来的 scene
刷爆当天额度,而额度用完是全租户的码都生成不出来 —— 等于整个填报入口瘫痪。

开发期 env-version 设成 develop(配置项 WX_MP_ENV_VERSION)。这个小程序若尚未
发布,用 release 生成的码扫开提示「小程序未发布」,而接口不会报错 ——
只会让人以为"码生成得不对"。

本轮踩的 3 个坑,都是"假设错了但不报错":
1) 微信返回的是 JPEG 不是 PNG。探测脚本按 PNG 魔数判断,把一次成功报成了失败
   (接口 200、91KB、看着一切正常)。服务代码里按 Content-Type/是不是图片判断。
2) 业务错误返回 HTTP 200 —— 项目约定只有 401/403/429/5xxxx 才占用真 HTTP 状态码,
   业务码在响应体的 code 里(ErrorCode.httpStatus())。我的 E2E 按 HTTP 状态码判
   业务失败,于是把"业务失败"当成了"成功"。
3) 我写的断言又一次恒为真:check(..., "max-age" in (...) or True, "")。
   这与上一轮刚记进摘要的"断言要能真的失败"是同一类错 —— 说明那条教训我只是
   写下来了,没有真的在写断言时自查。已改成真的读响应头来判。
   另外 fetch_* 辅助函数成功时返回 err=None,而断言在成功路径上写 err[:120],
   把"本该通过的用例"崩掉了;已改成成功时返回空串。

⚠️ 凭据位置与安全:
app-secret 放在 application-dev.yml(会入库),用 ${WX_MP_APP_SECRET:...} 形式,
test/prod 必须用环境变量覆盖。它与 jwt/crypto/rsa 那几把自研密钥性质不同:
那几个泄露只影响本系统,appsecret 泄露等于别人能以这个小程序身份调用所有接口。
生产环境务必单独申请凭据 + 走环境变量。

已知缺口:
· shortUrl 恒为 null:短链需要短链服务,而「H5 保底」路线还没定。
  不返回一个"其实很长"的链接冒充短链 —— 字段叫 shortUrl 却给 80 个字符,
  会让调用方以为可以直接打印。
· 图存在 Redis,没走对象存储(后端还没接 MinIO,容器在跑代码没接)。
· 小程序正式使用还需两步人工操作:服务器域名白名单加 API 域名、确认小程序已发布。
· 前端还没有二维码入口(属 M1-07~M1-10)。

验收:e2e-m1-qrcode.py 32/32(真实调微信);七条 E2E 合计 358 项断言全通过。
2026-09-29 10:08:02 +08:00
..