微信小程序后端接口设计备忘:从登录态、幂等到灰度发布

最近在规划一个自研微信小程序时,我把后端接口层重新梳理了一遍。项目规模不大,但越是个人项目,越容易因为“先跑起来再说”而把一些基础约定欠下来。等功能多了,再回头补登录态、幂等、审计和灰度,成本会变得很高。

这篇是我给自己写的一份备忘,目标不是追求大而全,而是用适合个人开发节奏的方式,先把最容易失控的部分定住。

1. 登录态不要只停留在“能拿到 openid”

很多小程序后端的第一步,是前端调用 wx.login() 拿到 code,然后服务端去微信侧换取 openidsession_key。这个流程本身没问题,但如果系统设计停在“库里有个 openid 字段”,后面就会遇到几个问题:

  1. 无法区分设备会话。
  2. 登录态刷新策略模糊。
  3. 服务端日志里缺少可追踪的用户会话标识。

我现在更倾向于把微信登录理解为“身份证明的上游输入”,而不是最终会话本身。服务端在拿到 openid 后,仍然要自己签发应用侧 session token,并且把 token 生命周期、刷新机制、失效策略设计清楚。

对个人项目来说,不一定要一上来就做复杂的 OAuth 体系,但至少要做到:

  1. 应用会话与微信 code 交换流程解耦。
  2. token 过期时间可配置。
  3. 敏感接口在服务端统一校验,不依赖前端状态判断。

2. 写接口时尽早考虑幂等

我以前做小程序时,最容易忽视的一件事就是重复点击。移动网络环境比桌面网页更容易出现超时重试、弱网抖动和用户反复点击提交按钮的情况。如果创建订单、保存记录、发起任务这些操作没有幂等保护,就很容易出现重复数据。

这次我给自己定的规则很简单:

  1. 只要是“有副作用”的写操作,都要先问一句:它是否可能被重复提交?
  2. 如果答案是可能,就给它设计幂等键。

幂等键不一定非要上复杂中间件。个人项目起步阶段,用请求头传一个 Idempotency-Key,配合数据库唯一约束和短期结果缓存,就能解决大部分问题。重点是思维上先意识到“重复请求不是边缘情况,而是默认要处理的情况”。

3. 返回结构统一比字段名优雅更重要

个人项目常见的演进路径是:先写一个接口,能返回数据就行;第二个接口复制前一个;第三个接口开始出现不同风格的错误码和 message 字段。等前端页面多起来,联调成本会明显上升。

所以我这次先把返回包格式固定下来:

  1. requestId:用于日志追踪。
  2. code:业务状态码。
  3. message:给前端展示或记录的可读信息。
  4. data:真正业务数据。

哪怕前期只有自己一个人开发,这种统一也很有价值。因为几周之后再回来看代码,“未来的自己”其实就已经像另一个协作者了。

4. 灰度和配置开关比想象中更早需要

以前我总觉得灰度发布是大团队才需要的能力。后来发现只要产品要上线给真实用户用,即使只有几十个用户,灰度依然非常有帮助。

最简单的灰度能力可以从配置中心思维开始,而不一定是完整平台:

  1. 某个功能是否对所有用户开放。
  2. 某个实验参数是否分组生效。
  3. 某个接口是否暂时降级到旧逻辑。

如果把这些判断都硬编码在业务逻辑里,后面会很难收拾。哪怕只是做一个数据库配置表,或者一份受控的远程配置,也比每次上线改代码再发版灵活很多。

5. 审计与日志从第一天就值得做

个人项目往往没有专门的运维体系,所以出问题时更依赖日志。我的经验是,日志不需要特别花哨,但一定要在关键链路上可串联。

我现在至少会记录这些信息:

  1. requestId
  2. 用户标识或匿名会话标识
  3. 接口耗时
  4. 核心参数摘要
  5. 下游调用结果

另外,对管理后台操作、配置变更、任务重试这类动作,我会额外留审计日志。原因很简单:一旦某条数据异常,先弄清“是谁在什么时候以什么方式改过它”,排查效率会高很多。

6. 当前阶段最适合个人项目的取舍

最后总结一下,我认为个人开发的小程序后端在第一阶段最值得优先做的是:

  1. 登录态独立成应用会话。
  2. 写操作具备基本幂等能力。
  3. 返回结构统一。
  4. 关键日志可追踪。
  5. 留出配置开关和灰度空间。

这些工作看起来不像业务功能那样“立刻可见”,但它们直接决定项目后面是轻松迭代,还是每加一个功能都担心把旧逻辑带崩。对长期维护的网站和后续小程序、小游戏来说,这些地基越早打,收益越大。