package http import ( _ "embed" "time" "quyun/app/models" "quyun/app/requests" "quyun/database/fields" "quyun/database/schemas/public/model" "quyun/providers/wepay" "github.com/go-pay/gopay/wechat/v3" "github.com/gofiber/fiber/v3" "github.com/gofiber/fiber/v3/log" "github.com/pkg/errors" "github.com/samber/lo" ) type ListQuery struct { Keyword *string `query:"keyword"` } // @provider type posts struct { wepay *wepay.Client } type PostItem struct { model.Posts BoughtCount int64 `json:"bought_count"` } // List posts // @Router /api/posts [get] // @Bind pagination query // @Bind query query // @Bind user local func (ctl *posts) List(ctx fiber.Ctx, pagination *requests.Pagination, query *ListQuery, user *model.Users) (*requests.Pager, error) { cond := models.Posts.BuildConditionWithKey(query.Keyword) pager, err := models.Posts.List(ctx.Context(), pagination, cond, func(item model.Posts) model.Posts { item.Assets = fields.ToJson([]fields.MediaAsset{}) item.Content = "" return item }) postIds := lo.Map(pager.Items.([]model.Posts), func(item model.Posts, _ int) int64 { return item.ID }) if len(postIds) > 0 { postCntMap, err := models.Posts.BoughtStatistics(ctx.Context(), postIds) if err != nil { return pager, err } items := lo.Map(pager.Items.([]model.Posts), func(item model.Posts, _ int) PostItem { cnt := int64(0) if v, ok := postCntMap[item.ID]; ok { cnt = v } return PostItem{Posts: item, BoughtCount: cnt} }) pager.Items = items } return pager, err } // Show // @Router /api/posts/show/:id [get] // @Bind id path func (ctl *posts) Show(ctx fiber.Ctx, id int64) (*model.Posts, error) { return models.Posts.GetByID(ctx.Context(), id) } // Mine posts // @Router /api/posts/mine [get] // @Bind pagination query // @Bind query query func (ctl *posts) Mine(ctx fiber.Ctx, pagination *requests.Pagination, query *ListQuery) (*requests.Pager, error) { log.Infof("Fetching posts for user with pagination: %+v and keyword: %v", pagination, query.Keyword) return models.Users.PostList(ctx.Context(), 1, pagination, query.Keyword, func(item model.Posts) model.Posts { item.Assets = fields.ToJson([]fields.MediaAsset{}) item.Content = "" return item }) } // Buy // @Router /api/posts/buy/:id [get] // @Bind id path // @Bind user local func (ctl *posts) Buy(ctx fiber.Ctx, id int64, user *model.Users) (*wechat.JSAPIPayParams, error) { post, err := models.Posts.GetByID(ctx.Context(), id) if err != nil { return nil, errors.Wrapf(err, " failed to get post: %d", id) } // create order order, err := models.Orders.Create(ctx.Context(), user.ID, post.ID) if err != nil { return nil, errors.Wrap(err, "订单创建失败") } prePayResp, err := ctl.wepay.V3TransactionJsapi(ctx.Context(), func(bm *wepay.BodyMap) { bm. Expire(30 * time.Minute). Description(post.Title). OutTradeNo(order.OrderNo). Payer(user.OpenID) }) if err != nil { log.Errorf("wepay.V3TransactionJsapi err: %v", err) return nil, errors.Wrap(err, "微信支付失败") } return prePayResp.PaySignOfJSAPI() }