Files
zt-closet-backend/.codebuddy/plans/api-v1层完整实现_e89004bd.md
2026-09-11 01:41:52 +08:00

9.7 KiB
Raw Permalink Blame History

name, overview, todos
name overview todos
api-v1层完整实现 实现 internal/routers/api/v1 全部 HTTP handler 并在 router.go 完成中间件与路由接线,调用已完成的 service 层;同时修复阻断运行的中间件/启动初始化问题,形成可跑通的 RESTful 接口。
id content status
fix-infra 修复 middleware(requestid uuid 导入、JWTAuth 封禁判断反转与缓存回落 DB)、main.go 初始化 global.Tracer/CosClient 与运势任务、dto 列表字段补 form tag completed
id content status dependencies
handlers-user-basic 实现 user/quota/horoscope/goods 四个 handler(登录/刷新/信息/额度/运势/商品) completed
fix-infra
id content status dependencies
handlers-clothes-outfit 实现 clothes(含 multipart 上传)与 outfit 两个 handler,覆盖增删改查与公开 completed
fix-infra
id content status dependencies
handlers-community 实现 closet/collect/like/notification 四个 handler(分享、收藏、点赞、通知) completed
fix-infra
id content status dependencies
handlers-order-ai 实现 order(含微信支付/退款回调按规范返回)与 airecommend 两个 handler completed
fix-infra
id content status dependencies
wire-router 在 router.go 接线中间件链与 /api/v1 公开/鉴权路由,添加 /ping,go build 与 go vet 全量验证 completed
handlers-user-basic
handlers-clothes-outfit
handlers-community
handlers-order-ai

产品概述

为"衣柜/穿搭"微信小程序后端补齐 HTTP 接口层(api/v1):将已完成的 service 业务逻辑通过 Gin handler 暴露为 RESTful 接口,并完成路由与中间件接线,形成可跑通的完整后端服务。

核心功能

  • 用户与登录:微信登录、刷新 Token、获取/修改个人信息
  • 衣物管理:上传(含图片处理)、状态查询、详情、修改、删除、列表
  • 穿搭管理:创建、详情、修改、删除、列表、公开设置
  • 衣柜分享:创建、详情(访客/属主)、我的分享列表、取消
  • 社区互动:点赞/取消、点赞状态与计数、收藏/取消、收藏列表
  • 消息通知:列表、详情、标记已读、未读数
  • 商品与订单:商品查询/列表、下单、订单列表、取消、退款申请、微信支付/退款回调
  • 额度与运势:额度概览与流水、今日运势
  • AI 推荐:发起 AI 穿搭推荐、保存到我的搭配

接口约定

  • 统一前缀 /api/v1;成功返回 {code:0,msg,data},失败按业务错误码返回。
  • 登录、刷新 Token、商品查询、微信回调为公开接口;其余需登录鉴权。
  • 微信支付/退款回调按微信规范返回受理结果。

技术栈

  • 语言/框架:Go 1.27 + Gin(沿用现有项目),复用 pkg/app(统一响应)、pkg/errcode(业务错误码)、internal/middleware(JWT/CORS/日志/追踪/RequestID)。
  • 依赖注入:handler 结构体持有对应 internal/service,构造函数注入,与 service/dao 现有风格一致。

实现思路

新增 internal/routers/api/v1 下按业务域拆分的 handler,并在 router.go 完成中间件与路由接线。handler 只负责:请求绑定与校验、path param 覆盖标识字段、从 context 取 userID、调用 service、统一响应转换;业务逻辑与归属校验(AuthZ)保持在 service 层,handler 不重复实现。

统一 handler 模式:

  1. resp := app.NewResponse(c)
  2. 绑定:JSON 用 ShouldBindJSON,GET query 用 ShouldBindQuery,失败返回 errcode.InvalidParams.WithDetails(err.Error())
  3. REST 路径标识(uuid/code/orderNo 等)用 c.Param(...) 覆盖 req 对应字段
  4. middleware.GetUserID(c.Request.Context()) 取 userID
  5. 调 service,错误 resp.ToErrorResponse(e),成功 resp.ToResponse(out)

关键技术决策

  • 同层静态路由与参数路由共存:Gin v1.12 支持 /notification/unread 与 /notification/:uuid、/order/refund 与 /order/:orderNo/cancel 共存,无需拆分前缀,保持 URL 语义清晰。
  • 微信回调独立处理:回调不走 JWT,handler 读 c.GetRawData() 原始报文传 service(service 已做 V3 验签/GCM 解密),按微信规范返回 {"code":"SUCCESS"}(200)或 {"code":"FAIL","message":...}(非 200),避免微信重复回调。
  • 文件上传:/clothes/upload 用 c.FormFile("file") 取 *multipart.FileHeader 传 service。

实现要点(防回归)

本次需一并修复阻断 api 层编译/运行的既有问题,否则接口无法跑通:

  • middleware/requestid.go:修复非法导入 import "uuid" → github.com/google/uuid,调用 uuid.New().String()(当前该文件导致 middleware 包无法编译)。
  • middleware/lzcwyjwt.go:
  • 修复封禁判断反转:if userInfo.Status == 1 → 应为 != 1 时拒绝(1=正常),避免正常用户被拦、禁用用户放行。
  • 缓存未命中(redis.Nil)回落 DB(mysqldao.UserDao.UserGetByID),成功回填 redisdao.UserInfoSet,仍失败再拒绝,避免缓存过期导致合法用户被锁死。
  • main.go 运行期初始化(当前缺失,直接运行会 nil panic):
  • global.Tracer = otel.Tracer(global.OtelSetting.ServiceName)(otel 默认 no-op provider 返回合法非 nil tracer,DAO 的 global.Tracer.Start 依赖它)。
  • global.CosClient, _ = cos.NewCosClient()(衣物上传 upload.FileUploadCos 依赖)。
  • 启动运势兜底:tokenhub.EnsureTodayFortunes() 与 tokenhub.StartFortuneScheduler()。
  • dto 补 form tag(GET query 筛选可用的最小调整):OutfitListRequest.IsPublic/Source、GoodsListRequest.GoodsType、ClosetShareListRequest.Status 当前仅 json tag,需补 form tag 才能 ShouldBindQuery 绑定。
  • 不打印 token/密钥;绑定错误文本作为 details 返回可接受,不泄露内部实现。

架构与数据流

请求 → Gin 中间件链(Recovery → RequestID → OTel → Slog → CORS)→ [公开路由 / JWTAuth 鉴权组] → v1 handler(绑定+取 userID)→ service(业务+AuthZ)→ dao/redis/pkg → 统一响应。

目录结构

zt-closet-backend/
├── main.go                                   # [MODIFY] 初始化 global.Tracer / global.CosClient;启动运势定时任务与启动兜底
├── internal/
│   ├── dto/
│   │   ├── outfit.go                         # [MODIFY] OutfitListRequest.IsPublic/Source 补 form tag
│   │   ├── goods.go                          # [MODIFY] GoodsListRequest.GoodsType 补 form tag
│   │   └── closet.go                         # [MODIFY] ClosetShareListRequest.Status 补 form tag
│   ├── middleware/
│   │   ├── requestid.go                      # [MODIFY] 修复 uuid 导入路径
│   │   └── lzcwyjwt.go                        # [MODIFY] 修复封禁状态判断反转 + 缓存未命中回落 DB 回填
│   └── routers/
│       ├── router.go                         # [MODIFY] 中间件链接线 + /api/v1 公开与鉴权路由注册 + /ping
│       └── api/v1/
│           ├── user.go                       # [NEW] UserHandler:WxLogin/RefreshToken/InfoGetBySelf/ProfileUpdate
│           ├── quota.go                      # [NEW] QuotaHandler:Info/FlowList
│           ├── horoscope.go                  # [NEW] HoroscopeHandler:Today
│           ├── clothes.go                    # [NEW] ClothesHandler:Upload/List/Get/Status/Update/Delete
│           ├── outfit.go                     # [NEW] OutfitHandler:Create/Get/Update/Delete/List/Public
│           ├── closet.go                     # [NEW] ClosetShareHandler:Create/Detail/List/Cancel
│           ├── collect.go                    # [NEW] CollectHandler:Collect/List
│           ├── like.go                       # [NEW] LikeHandler:Like/GetByTarget
│           ├── notification.go               # [NEW] NotificationHandler:List/Unread/Get/Read
│           ├── goods.go                      # [NEW] GoodsHandler:GetByCode/List(公开)
│           ├── order.go                      # [NEW] OrderHandler:Create/List/Cancel/RefundApply/PayNotify/RefundNotify
│           └── airecommend.go                # [NEW] AIRecommendHandler:Create/Save

路由清单(前缀 /api/v1)

公开:POST /user/wxlogin、POST /user/refresh-token、GET /goods、GET /goods/:code、POST /order/pay/notify、POST /order/refund/notify 鉴权(JWTAuth):

  • GET /user/info、PUT /user/profile
  • GET /quota/info、GET /quota/flow
  • GET /horoscope/today
  • POST /clothes/upload、GET /clothes、GET /clothes/:uuid、GET /clothes/:uuid/status、PUT /clothes/:uuid、DELETE /clothes/:uuid
  • POST /outfit、GET /outfit、GET /outfit/:uuid、PUT /outfit/:uuid、DELETE /outfit/:uuid、PUT /outfit/:uuid/public
  • POST /closet-share、GET /closet-share、GET /closet-share/:uuid、POST /closet-share/:uuid/cancel
  • POST /collect、GET /collect
  • POST /like、GET /like/:targetUUID
  • GET /notification、GET /notification/unread、GET /notification/:uuid、POST /notification/:uuid/read
  • POST /order、GET /order、POST /order/:orderNo/cancel、POST /order/refund
  • POST /ai-recommend、POST /ai-recommend/save

SubAgent

  • code-explorer
  • Purpose:实现阶段如需核对个别 service 方法签名或 dto 字段(如回调 body 读取、multipart 字段名、path param 与 dto 字段映射),快速跨文件确认,避免签名臆测。
  • Expected outcome:handler 与 service 签名、dto 绑定一次性对齐,减少编译期返工。