fix(auth): 商品详情接口移至公开路由,修复未登录浏览触发登录弹窗

问题背景:
- 平台审核失败,原因:小程序页面未完整浏览即要求授权登录,属于登录规范不合规
- GET /api/app/products/:id 位于认证路由组,未登录用户访问返回 401,
  触发前端全局拦截器弹出"账号登录已过期"弹窗

修改内容:
1. router.go: 将 GET /products/:id 从 appAuthApiRouter(认证组)
   移至 appPublicApiRouter(公开组),允许未登录用户浏览商品详情
2. product.go: 针对公开端点增加安全加固
   - 增加商品 ID 参数校验(ParseInt 错误和 id<=0)
   - 将兜底错误信息从 validation.Error(err) 改为通用提示
     "商品信息获取失败",防止原始 DB 错误泄露给未认证请求

影响范围:
- 仅影响 GET /api/app/products/:id 端点
- GET /api/app/products(商品列表)仍保留在认证组
- 该 handler 不依赖 JWT session 上下文,移至公开组后功能无变化
- 返回数据仅包含商品元信息(名称、图片、价格、库存),不含用户敏感数据
This commit is contained in:
Zuncle 2026-03-26 14:35:25 +08:00
parent 58fd926b46
commit 53e5d81fa8
2 changed files with 7 additions and 3 deletions

View File

@ -121,7 +121,11 @@ type getAppProductDetailResponse struct {
func (h *productHandler) GetProductDetailForApp() core.HandlerFunc {
return func(ctx core.Context) {
idStr := ctx.Param("id")
id, _ := strconv.ParseInt(idStr, 10, 64)
id, err := strconv.ParseInt(idStr, 10, 64)
if err != nil || id <= 0 {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "无效的商品ID"))
return
}
d, err := h.product.GetDetailForApp(ctx.RequestContext(), id)
if err != nil {
if err.Error() == "PRODUCT_OFFSHELF" {
@ -132,7 +136,7 @@ func (h *productHandler) GetProductDetailForApp() core.HandlerFunc {
ctx.AbortWithError(core.Error(http.StatusOK, 20002, "商品缺货"))
return
}
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ServerError, validation.Error(err)))
ctx.AbortWithError(core.Error(http.StatusInternalServerError, code.ServerError, "商品信息获取失败"))
return
}
ptsDetail := h.user.CentsToPointsFloat(ctx.RequestContext(), d.Price)

View File

@ -462,6 +462,7 @@ func NewHTTPMux(logger logger.CustomLogger, db mysql.Repo) (core.Mux, func(), er
// 商城浏览(无需登录)
appPublicApiRouter.GET("/store/items", appapi.NewStore(logger, db, userSvc).ListStoreItemsForApp())
appPublicApiRouter.GET("/product_categories", appapi.NewProductCategory(logger, db).ListProductCategoriesForApp())
appPublicApiRouter.GET("/products/:id", appapi.NewProduct(logger, db, userSvc).GetProductDetailForApp())
}
// 公开接口路由组 (无需登录)
@ -514,7 +515,6 @@ func NewHTTPMux(logger logger.CustomLogger, db mysql.Repo) (core.Mux, func(), er
appAuthApiRouter.GET("/orders/:order_id", userHandler.GetOrderDetail())
appAuthApiRouter.POST("/orders/:order_id/cancel", userHandler.CancelOrder())
appAuthApiRouter.GET("/products", appapi.NewProduct(logger, db, userSvc).ListProductsForApp())
appAuthApiRouter.GET("/products/:id", appapi.NewProduct(logger, db, userSvc).GetProductDetailForApp())
appAuthApiRouter.GET("/lottery/result", activityHandler.LotteryResultByOrder())
// 需要黑名单检查的抽奖接口组