
小程序项目往往节奏快、迭代频繁,后端接口如果一开始没有统一规范,后期维护成本会指数级上升。前端开发者需要对接多个接口,每个接口的返回格式、字段命名、错误码都不一样,联调效率极低;测试人员无法建立标准化的用例模板;新成员接手项目时,光理解接口约定就要花大量时间。更严重的是,不规范的接口在上线后暴露问题,往往需要前后端同时修改,甚至影响已发布版本的兼容性,导致被迫重写。
接口设计规范的核心价值在于:降低沟通成本、减少返工、提升可维护性、保障系统稳定性。它不是束缚创造力的条条框框,而是团队协作的共同语言。
每个接口只负责一个明确的业务功能,避免一个接口干多件事。比如 "获取用户信息" 和 "更新用户信息" 应该拆成两个接口,而不是用一个接口通过参数区分。单一职责让接口语义清晰,调用方容易理解,也便于后续独立扩展和维护。
接口设计应该围绕资源展开,而不是围绕操作动作。用名词描述资源,用请求方法表达操作意图,这是 RESTful 风格的核心思想。资源可以是实体(如用户、订单、商品),也可以是抽象概念(如会话、通知、配置)。
整个系统的接口在命名风格、参数格式、返回结构、错误处理上必须保持一致。一致性不是某个接口的事情,而是全局约定。一旦确定了规范,所有新接口都必须遵守,历史接口在迭代时逐步对齐。
接口一旦上线被调用,就不能随意修改。新增字段通常是安全的,但删除字段、修改字段含义、改变返回结构都属于破坏性变更。需要变更时,应该通过版本号机制引入新版本,同时保留旧版本一段时间,给调用方升级的窗口。
接口返回的数据应该刚好满足业务需求,不多不少。返回过多冗余字段会增加网络传输量和前端解析成本,也可能泄露敏感信息;返回字段不足则会导致前端需要多次请求,增加交互复杂度。设计时应结合实际页面需求,精准定义返回字段。
资源路径统一使用名词复数,例如:
用户列表:/users
单个用户:/users/{id}
订单列表:/orders
订单详情:/orders/{id}
复数形式让集合和单个资源的关系一目了然,也避免了单复数混用造成的不一致。
如果资源之间存在从属关系,应该在 URL 中体现层级:
某用户的地址列表:/users/{userId}/addresses
某订单的商品明细:/orders/{orderId}/items
层级不宜过深,一般不超过三级。过深的层级会让 URL 变得冗长,也增加了路由匹配的复杂度。如果层级过深,考虑将子资源提升为独立资源,通过查询参数关联。
URL 路径中统一使用小写字母,多单词之间用连字符(-)分隔,而不是下划线或驼峰命名。例如:
推荐:/user-profiles
不推荐:/userProfiles、/user_profiles、/UserProfiles
查询参数的命名同样遵循小写加下划线或连字符的风格,整个系统统一即可。
URL 代表资源,不应该包含操作动词。操作意图由请求方法表达。例如:
推荐:GET /users(获取用户列表)
不推荐:GET /getUsers、POST /queryUsers
对于无法用标准资源表达的操作(如登录、注册、支付、退款),可以使用动名词形式的子资源路径,例如 /auth/login、/payments/{id}/refund,但这类接口应尽量少,并在团队内统一约定。
表格
| 方法 | 语义 | 幂等性 | 安全性 |
|---|---|---|---|
| GET | 获取资源 | 是 | 是 |
| POST | 创建资源 | 否 | 否 |
| PUT | 全量更新资源 | 是 | 否 |
| PATCH | 部分更新资源 | 否 | 否 |
| DELETE | 删除资源 | 是 | 否 |
GET:用于查询,不应该修改服务端数据。请求参数放在 URL 查询字符串中,不应该携带请求体。
POST:用于创建新资源,请求体包含创建所需的数据。返回新建资源的标识或完整信息。
PUT:用于全量替换资源,请求体包含资源的完整数据。如果资源不存在,部分系统允许创建,但建议明确约定。
PATCH:用于部分更新,请求体只包含需要修改的字段。比 PUT 更节省传输量,也更符合实际业务场景。
DELETE:用于删除资源。删除可以是物理删除,也可以是逻辑删除(修改状态标记),但接口语义对调用方应该一致。
幂等性意味着同一个请求执行一次和执行多次的效果相同。在网络不稳定的环境下,客户端可能会重试请求,如果接口不具备幂等性,就可能导致重复创建、重复扣款等严重问题。
GET、PUT、DELETE 天然幂等。
POST 不天然幂等,需要通过业务手段保证。例如创建订单时,可以要求客户端传入唯一请求标识,服务端根据标识判断是否重复请求。
PATCH 的幂等性取决于具体操作,如果是设置字段值则幂等,如果是增量计算则不幂等。
对于关键写操作接口,建议在设计时就考虑幂等性方案,避免上线后出现数据不一致。
路径参数(Path):用于标识资源,如 /users/{id} 中的 id。必须是资源的唯一标识。
查询参数(Query):用于筛选、排序、分页等控制,如 ?page=1&size=20&status=active。
请求体(Body):用于提交创建或更新的数据,格式统一为 JSON。
请求头(Header):用于传递鉴权信息、内容类型、客户端版本等元数据。
列表接口必须支持分页,参数命名和格式统一。常见方案:
页码分页:page(页码,从 1 开始)、size(每页条数)
游标分页:cursor(上一页最后一条的标识)、size(每页条数)
页码分页适合数据量不大、需要跳页的场景;游标分页适合数据量大、实时性要求高的场景,避免深分页性能问题。无论选择哪种,整个系统保持一致。
分页返回结果中应包含总条数、当前页、每页条数等元信息,方便前端构建分页控件。
筛选参数直接使用字段名作为查询参数,支持多条件组合。例如 ?status=active&role=admin。
排序参数统一使用 sort,多个字段用逗号分隔,升降序用前缀或单独参数控制。例如 ?sort=-created_at,name 表示按创建时间降序、名称升序。
后端必须对所有入参进行严格校验,不能依赖前端校验。校验内容包括:
类型校验:数字不能传字符串,日期格式必须正确
范围校验:数值在合理范围内,枚举值在允许列表中
长度校验:字符串长度不超过字段限制
格式校验:手机号、邮箱、身份证等格式正确
必传校验:必填字段不能为空
业务校验:结合业务逻辑的校验,如库存是否充足、状态是否允许操作
校验失败时返回明确的错误信息,指出哪个字段有什么问题,方便前端定位和提示用户。
所有接口的响应体使用统一的 JSON 结构,包含业务状态码、提示信息和数据三部分:
{
"code": 0,
"message": "success",
"data": {}
}
code:业务状态码,0 表示成功,非 0 表示各类业务错误。与 HTTP 状态码配合使用。
message:面向开发者的提示信息,成功时为 "success",失败时说明错误原因。
data:实际返回的业务数据,可以是对象、数组或 null。
这种统一结构让前端可以用统一的拦截器处理响应,减少每个接口单独处理的重复代码。
列表接口的 data 中包含列表数据和分页信息:
{
"code": 0,
"message": "success",
"data": {
"list": [],
"pagination": {
"page": 1,
"size": 20,
"total": 156,
"total_pages": 8
}
}
}
分页信息的字段命名与请求参数对应,保持一致。
响应数据中的字段名统一使用小写下划线命名(snake_case),与 URL 和查询参数风格一致。例如:
推荐:user_name、created_at、order_status
不推荐:userName、CreatedAt、orderStatus
如果前端框架偏好驼峰命名,可以在网关层或前端拦截器统一转换,但后端接口规范保持统一风格。
所有时间字段使用 ISO 8601 格式,带时区信息,例如 2026-08-26T14:30:00+08:00。或者使用 Unix 时间戳(毫秒级),整个系统统一即可。
不建议使用 2026/08/26 14:30:00 这类非标准格式,不同语言解析时容易出问题。
字段值为空时,根据字段类型返回对应的空值:
字符串为空:返回 "" 或 null,系统统一
数字为空:返回 null,不要返回 0(0 可能是有效值)
布尔值为空:返回 null 或默认值,根据业务确定
数组为空:返回 [],不要返回 null
对象为空:返回 {} 或 null,系统统一
列表为空时返回空数组 [],这一点尤其重要,前端遍历空数组不会报错,遍历 null 会崩溃。
正确使用 HTTP 状态码,不要所有接口都返回 200。
200 OK:请求成功,用于 GET、PUT、PATCH、DELETE 的成功响应。
201 Created:资源创建成功,用于 POST 的成功响应,响应头中包含新资源的位置。
204 No Content:操作成功但无返回内容,用于 DELETE 等不需要返回数据的场景。
400 Bad Request:请求参数错误,校验失败。
401 Unauthorized:未认证,缺少或无效的身份凭证。
403 Forbidden:已认证但无权限访问该资源。
404 Not Found:资源不存在。
405 Method Not Allowed:请求方法不被允许。
409 Conflict:资源冲突,如重复创建、状态冲突。
422 Unprocessable Entity:请求格式正确但业务逻辑无法处理。
429 Too Many Requests:请求过于频繁,触发限流。
500 Internal Server Error:服务端内部错误。
502 Bad Gateway:网关错误。
503 Service Unavailable:服务不可用。
504 Gateway Timeout:网关超时。
HTTP 状态码表达的是协议层面的结果,业务层面的细分错误需要通过业务状态码表达。业务状态码建议分段设计,便于归类和维护:
表格
| 码段 | 含义 |
|---|---|
| 0 | 成功 |
| 1000-1999 | 通用错误(参数校验、格式错误等) |
| 2000-2999 | 认证与授权错误 |
| 3000-3999 | 用户模块错误 |
| 4000-4999 | 订单模块错误 |
| 5000-5999 | 支付模块错误 |
| ... | 按业务模块继续划分 |
每个业务状态码对应唯一的错误含义,在系统中维护一份错误码字典,前后端共同参照。错误码一旦定义就不要随意更改含义,可以新增但不要复用。
错误响应中除了状态码,还应该提供对开发者友好的错误信息,以及对用户友好的提示。建议结构:
{
"code": 4001,
"message": "用户昵称不能为空",
"data": null,
"details": [
{
"field": "nickname",
"issue": "required"
}
]
}
details 字段用于参数校验类错误,详细列出每个字段的问题,方便前端精准定位和展示。
小程序接口的鉴权通常基于令牌机制。用户登录后,服务端签发访问令牌和刷新令牌,客户端在后续请求的请求头中携带访问令牌:
Authorization: Bearer <access_token>
访问令牌有效期较短(如 2 小时),降低泄露风险。
刷新令牌有效期较长(如 30 天),用于在访问令牌过期后获取新的访问令牌。
刷新令牌应该支持轮换机制,每次使用后签发新的刷新令牌,旧的失效,防止重放攻击。
除了登录鉴权,还需要对接口进行细粒度的权限控制。不同角色的用户能访问的接口范围不同,能操作的数据范围也不同。
接口级权限:某个角色能否调用某个接口。
数据级权限:某个用户能否访问某条具体数据,只能访问自己的数据还是所在组织的所有数据。
权限校验应该在统一的中间件或拦截器中完成,避免在每个业务代码中重复实现。
密码等敏感信息不允许明文存储,必须使用加盐哈希算法加密。
接口返回中不应该包含密码、密钥、令牌等敏感字段。
手机号、身份证号、银行卡号等个人敏感信息在返回时应该脱敏处理,如手机号显示为 138****1234。
日志中不允许记录敏感信息的明文。
SQL 注入:使用参数化查询或 ORM 框架,禁止拼接 SQL。
XSS 防护:对用户输入的富文本内容进行过滤和转义。
CSRF 防护:对于基于 Cookie 的鉴权,使用 CSRF Token 机制。
接口限流:对登录、注册、发送验证码等敏感接口进行限流,防止暴力破解和资源消耗。
请求签名:对于关键接口,可以要求客户端对请求参数进行签名,服务端验证签名,防止参数被篡改。
HTTPS:所有接口必须通过 HTTPS 传输,禁止明文 HTTP。
接口上线后,随着业务迭代,不可避免地需要修改。如果直接修改已有接口,可能导致正在使用旧版本的客户端出现异常。特别是小程序,用户不一定会及时更新,旧版本客户端可能长期存在。因此,需要通过版本管理机制,在引入新接口的同时保留旧接口,给客户端升级留出时间。
常见的版本号放置方式有三种:
URL 路径:/v1/users、/v2/users。最直观,推荐使用。
查询参数:/users?version=1。不够直观,不推荐。
请求头:Accept: application/vnd.example.v1+json。符合 REST 规范但不够直观,适合对 REST 纯度要求高的团队。
推荐使用 URL 路径方式,简单明了,便于网关路由和日志分析。
小版本迭代(新增字段、新增接口):不需要升级版本号,保持向前兼容。
大版本变更(删除字段、修改字段含义、改变返回结构、改变业务逻辑):需要升级版本号。
旧版本维护:新版本发布后,旧版本至少保留一个迭代周期,期间只修复安全问题,不再增加新功能。
废弃通知:在废弃旧版本前,通过接口响应头或业务通知告知客户端,引导升级。
版本数量控制:同时维护的版本不宜过多,一般不超过 3 个,过多会增加维护成本。
接口响应时间应该有明确的目标。一般来说:
简单查询接口:响应时间控制在 100ms 以内。
复杂查询接口:响应时间控制在 500ms 以内。
写操作接口:响应时间控制在 300ms 以内。
超过 1 秒的接口需要优化,超过 3 秒的接口必须优化或改为异步处理。
响应时间应该从客户端视角测量,包含网络传输和服务端处理的总时间。
所有查询条件涉及的字段必须建立合适的索引,避免全表扫描。
避免在循环中执行数据库查询,使用批量查询代替。
复杂查询可以使用冗余字段、预计算表等方式优化读取性能。
分页查询避免使用深分页(如 OFFSET 100000),使用游标分页或延迟关联优化。
写操作注意事务范围,避免长事务占用连接资源。
读多写少的数据(如配置信息、字典数据、商品详情)应该使用缓存,减少数据库压力。
缓存可以使用内存缓存(适合单实例)或分布式缓存(适合多实例)。
缓存必须设置合理的过期时间,避免数据长期不一致。
更新数据时注意缓存失效策略,可以采用更新数据库后删除缓存的模式,避免缓存与数据库不一致。
对于热点数据,注意缓存击穿、缓存雪崩、缓存穿透问题,采取相应的防护措施。
耗时操作(如发送短信、生成报表、调用第三方服务)不应该阻塞主流程,应该使用异步队列处理。
接口先返回受理成功,后台异步执行,客户端通过轮询或回调获取结果。
异步任务需要有重试机制和失败处理,确保最终一致性。
响应体较大时启用 Gzip 或 Brotli 压缩,减少传输量。
列表接口避免一次性返回过多数据,通过分页控制单次返回量。
图片等大文件不应该通过接口返回,应该使用对象存储和 CDN,接口只返回访问地址。
接口文档是前后端协作的桥梁。没有文档或文档不及时更新,联调时只能靠口头沟通和猜,效率极低,也容易出错。好的接口文档应该在接口开发的同时编写,与代码保持同步更新。
每个接口的文档应该包含以下内容:
接口名称:简洁描述接口功能。
接口描述:详细说明接口的用途、业务场景、注意事项。
请求方法:GET、POST、PUT、PATCH、DELETE。
请求路径:完整的 URL,包含路径参数。
请求参数:路径参数、查询参数、请求体参数,每个参数包含名称、类型、是否必填、说明、示例值。
请求示例:完整的请求示例,包含请求头和请求体。
响应参数:响应体中每个字段的名称、类型、说明。
响应示例:完整的成功响应示例和失败响应示例。
错误码:该接口可能返回的业务错误码列表及含义。
变更记录:接口的修改历史,包含版本、日期、修改内容。
推荐使用自动化文档工具,从代码注释或注解中生成文档,减少手动维护的工作量。常见的方案包括基于 OpenAPI 规范的工具链。文档应该可以在线访问,支持搜索和调试功能。
接口修改时必须同步更新文档,代码合并时将文档更新作为检查项。
文档中应该标注接口的状态:开发中、已上线、已废弃。
废弃的接口文档应该保留,但明确标注废弃时间和替代方案。
后端开发者在提交代码前必须完成接口自测,确保接口功能正常、参数校验完整、错误处理正确。自测内容包括:
正常流程测试:传入正确参数,验证返回结果符合预期。
参数校验测试:传入缺失、错误、越界的参数,验证返回正确的错误信息。
边界条件测试:测试空数据、最大数据量、特殊字符等边界情况。
权限测试:未登录、无权限的用户调用接口,验证返回正确的权限错误。
性能测试:简单评估接口响应时间,确保没有明显的性能问题。
在前后端并行开发时,后端接口尚未完成,前端可以基于接口文档使用 Mock 数据进行开发。Mock 数据应该与最终接口的返回结构完全一致,确保前端代码在接口完成后只需切换地址即可正常运行。
联调前,后端提供可访问的测试环境地址和接口文档。
联调时,前后端保持沟通,遇到问题及时定位是前端问题还是后端问题。
问题修复后,后端及时部署到测试环境,前端重新验证。
联调完成后,双方确认所有接口功能正常,进入测试阶段。
接口必须记录访问日志,包含请求方法、路径、参数、响应状态码、响应时间、客户端标识等信息。
错误日志必须记录完整的错误堆栈和上下文信息,便于排查问题。
日志中不允许记录敏感信息明文。
提供链路追踪能力,通过唯一请求标识串联一次请求经过的所有服务和日志。
接口上线前,对照以下清单逐项检查,避免遗漏:
接口功能符合需求文档,业务逻辑正确
接口命名、参数、返回格式符合团队规范
所有入参进行了校验,错误信息明确
接口鉴权和权限控制正确
敏感数据已脱敏,无敏感信息泄露
接口性能达标,无慢查询和性能瓶颈
数据库索引合理,无全表扫描
缓存策略合理,无缓存一致性问题
接口具备幂等性(关键写操作)
接口文档完整且与实现一致
接口自测通过,覆盖正常和异常场景
日志记录完整,便于排查问题
有版本管理方案,后续迭代可平滑升级
有监控告警,接口异常时能及时发现
后端接口设计规范是小程序开发中不可忽视的基础工作。它不是一次性的文档,而是贯穿整个项目生命周期的实践准则。从接口设计、开发、测试到上线、迭代、维护,每个环节都需要遵循规范。
规范的价值在项目初期可能不明显,甚至会让人觉得 "束缚手脚"。但随着项目规模扩大、团队成员增加、迭代次数增多,规范带来的收益会越来越明显:沟通更顺畅、返工更少、维护更容易、系统更稳定。
不要等上线了才发现接口设计有问题,那时候重写的成本是初期的数倍甚至数十倍。在项目启动的第一天,就应该确立接口设计规范,并在整个开发过程中严格执行。规范越早定,后面的路越顺。