Files
wxmp_backend/docs/api-contract-v1.md
T

7.4 KiB
Raw Blame History

wxmp_backend API 契约 v1

本文档是小程序前端 wechat_wc 与后端 wxmp_backend 共同遵守的接口契约。 后端 Swagger 只展示实现,本文档才是前后端开发、评审、联调的依据。 契约变更必须升版本号(v2...),禁止在同一版本内悄悄改字段或语义。

1. 通用约定

  • 基础路径:/api,例如 POST /api/auth/login
  • 默认鉴权:除 @Public() 外所有接口要求 Authorization: Bearer <accessToken>
  • 统一响应:{ code, message, data },成功 code: 0,失败 code 等于 HTTP 状态码。
  • 请求体校验:ValidationPipe 白名单模式,多余字段直接 400。
  • 金额:数据库用 Decimal(10,2),对外 JSON 统一输出 number(两位小数精度的整数元)。
  • 分页:列表接口统一响应 { list, total, page, pageSize }
  • 时间:统一 ISO 8601 UTC 字符串。
  • 幂等:下单等写接口支持客户端 requestId,同一 requestId 只生效一次。
  • 错误码约定:
code 含义
400 参数校验失败
401 未登录 / token 失效
403 已登录但无权限访问他人资源
404 资源不存在
409 唯一冲突 / 重复操作
503 微信或依赖服务暂不可用

2. 认证与用户(已实现)

POST /api/auth/login

公开接口。请求体:{ code: string }wx.login 的 code)。

响应 data

{
  "accessToken": "jwt",
  "isNewUser": true,
  "nickname": null,
  "avatar": null
}

isNewUser=true 时前端引导补全昵称/头像。

POST /api/auth/register

公开接口。企业主体可选:换手机号注册,返回 { accessToken }

GET /api/users/me

返回当前用户。data 至少包含 idopenidnicknameavatar

PATCH /api/users/me

更新当前用户资料。请求体:{ nickname?: string, avatar?: string }

3. 商品与分类(R1,待实现)

GET /api/categories

公开接口。返回扁平分类列表,按 sort 升序。

GET /api/products

公开接口。查询参数:

参数 类型 说明
page number 默认 1
pageSize number 默认 20,上限 100
categoryId string 可选,分类过滤
keyword string 可选,名称/描述模糊搜索

仅返回 status=ON_SALE 的商品。

GET /api/products/:id

公开接口。返回单个在售商品;不存在返回 404。

ProductDTO

{
  id: string
  name: string
  categoryId?: string
  price: number
  originalPrice?: number
  leadTime: string
  subtitle?: string
  description?: string
  story?: string
  scene?: string
  tags: string[]
  specs: [string, string][]
  tone: [number, number, number]
  mask: { shape: 'rect' | 'circle', width: number, height: number, borderRadius?: number }
  images: string[]
  iconImg?: string
  status: 'ON_SALE'
  sort: number
}

4. 收货地址(R2,待实现完整 CRUD)

GET /api/addresses

返回当前用户地址列表,默认地址在前。

POST /api/addresses

请求体:

{
  name: string
  phone: string
  province: string
  city: string
  district: string
  detail: string
  isDefault?: boolean
}

isDefault=true 时事务内取消其他地址默认标记。

PATCH /api/addresses/:id

更新本人地址。isDefault 同样走默认地址事务。

PATCH /api/addresses/:id/default

设为默认;非本人资源返回 403。

DELETE /api/addresses/:id

删除本人地址;若删除的是默认地址,自动将最新一条设为默认。

注意:前端 AddressItem.region: string[] 与后端 province/city/district 的转换 只允许出现在前端 src/utils/api/address.ts

5. 设计清单(R2,待实现完整 CRUD)

GET /api/design-list

返回当前用户设计清单,按 createdAt 倒序。

POST /api/design-list

请求体:

{
  title: string
  items: {
    productId: string
    productName: string
    unitPrice: number
    count: number
    designData?: {
      stickers?: unknown[]
      category?: unknown
      imageSrc?: string
      imagePos?: { x: number; y: number; scale: number }
    }
  }[]
}

items 为服务端 JSON,需做结构白名单与大小校验(单条 ≤ 1MB)。

PATCH /api/design-list/:id

更新本人清单:itemstitle、状态迁移。

DELETE /api/design-list/:id

删除本人清单。批量删除建议 POST /api/design-list/batch-delete 请求体 { ids: string[] }

状态映射

前端显示 前端状态码 后端 DesignListStatus
待设计 undesigned DRAFT
设计中 designing SUBMITTED
生产中 processing PROCESSING
已下单 ordered DONE

orderedorderId != null 派生,前端不提交该状态。

6. 订单(R3,待实现)

POST /api/orders

请求体:

{
  designListId?: string
  addressId: string
  requestId?: string
  items: [{ productId: string, quantity: number }]
}

服务端职责:

  • 按 Product 真实价格与设计清单快照重算 totalAmount,忽略客户端金额。
  • prisma.$transaction 创建 Order + OrderItem + Payment(PENDING)。
  • 生成唯一 orderNorequestId 幂等,重复请求返回已创建订单。
  • 收货地址同步快照到 addressSnapshot,订单创建后不受地址变更影响。

响应 data

{
  id: string
  orderNo: string
  status: 'PENDING'
  totalAmount: number
  items: [{ productId, name, price, quantity }]
  addressSnapshot: object
  createdAt: string
}

GET /api/orders

参数:status(可选)、pagepageSize。只返回本人订单。

GET /api/orders/:id

仅本人可查,越权 403,不存在 404。

PATCH /api/orders/:id/confirm

确认收货,SHIPPED -> COMPLETED

POST /api/orders/:id/cancel

PENDING 可取消,PENDING -> CANCELLED

订单状态机

PENDING -> PAID -> PROCESSING -> SHIPPED -> COMPLETEDPENDING -> CANCELLED。 前端只读展示,状态迁移由后端与支付回调驱动。

7. 支付(R3,占位)

POST /api/payments/:orderId/pay

支付密钥未配置时返回:

{ "configured": false, "message": "支付未配置" }

不调用微信、不写成功记录、不使用默认商户参数。

POST /api/payments/notify

公开接口,保留原始 body 与 headers 签名;本版本不实现验签与落库。

8. 上传 / 词云 / 线稿(R4,待实现)

GET /api/upload/credentials?key=...

返回 COS STS 临时凭证或预签名 URL。小程序不得持有永久密钥。

POST /api/wordcloud/generate

multipart 请求:image(底图)+ names(文本名单)+ params?。 返回:

{ jobId: string }

GET /api/wordcloud/jobs/:id

{
  id: string
  status: 'queued' | 'running' | 'success' | 'failed'
  progress: number
  imageUrl?: string
  error?: string
}

仅本人可查;小程序使用轮询,不使用 SSE。

POST /api/sketch

multipartimage。返回处理后图片 URL;失败时前端降级本地灰度。

9. 契约维护规则

  • 前端与后端同名分支成对开发:feat/r1-catalogfeat/r2-address-designfeat/r3-order-payfeat/r4-upload-wordcloud
  • 每个 PR 必须同步更新本文档对应章节与前端 src/types
  • 契约字段只能增加(optional),不能改名、改类型、改语义;否则升版本。
  • 与 wordcloud 之间的契约见 docs/wordcloud-contract.md