package coach_client import ( "context" "crypto/tls" "fmt" "time" "github.com/bytedance/sonic" "github.com/cloudwego/hertz/pkg/app/client" "github.com/cloudwego/hertz/pkg/network/standard" "github.com/cloudwego/hertz/pkg/protocol" "github.com/corpix/uarand" ) type XMacHeader string const ( XMac_Coach XMacHeader = "e6d4b3d780db4251bc4b6b54f41ee7b0" XMac_Outlet XMacHeader = "b55d4769f3e768630046291ee2ee26f0" ) type CN struct { c *client.Client xmac XMacHeader } func CNClient(xmac XMacHeader) (cli *CN, err error) { cli = new(CN) clientCfg := &tls.Config{ InsecureSkipVerify: true, } cli.c, err = client.NewClient( client.WithTLSConfig(clientCfg), client.WithDialer(standard.NewDialer()), ) cli.xmac = xmac return } type CNData interface { ItemListData } type CNResponse[data CNData] struct { Data data `json:"data"` Msg string `json:"msg"` Rid string `json:"rid"` StatusCode string `json:"statusCode"` } type ItemListData struct { Count int `json:"count"` CurrentPage int `json:"currentPage"` Items []CNItem `json:"items"` Size int `json:"size"` TotalPages int `json:"totalPages"` } type CNItem struct { Code string `json:"code"` DiscountRateMin float64 `json:"discountRateMin"` Id int `json:"id"` Images []struct { Imgs []struct { Config string `json:"config"` Img string `json:"img"` Position int `json:"position"` Resource string `json:"resource"` Type int `json:"type"` } `json:"imgs"` ItemPropId int `json:"itemPropId"` } `json:"images"` ListPrice float64 `json:"listPrice"` SalePrice float64 `json:"salePrice"` SkuMaxPrice float64 `json:"skuMaxPrice"` Stock int `json:"stock"` Style string `json:"style"` Title string `json:"title"` } func (c *CN) ListItems(_ctx context.Context, page, size int) (ItemListData, error) { req, resp := protocol.AcquireRequest(), protocol.AcquireResponse() defer func() { protocol.ReleaseRequest(req) protocol.ReleaseResponse(resp) }() page = max(page, 1) size = max(size, 50) req.SetRequestURI("https://ec-api.coach.com.cn/api/v2/item/search") req.SetMethod("GET") req.SetHeader("X-Ma-C", string(c.xmac)) req.SetHeader("User-Agent", uarand.GetRandom()) req.SetQueryString(fmt.Sprintf("scope=shop&pageNo=%d&pageSize=%d", page, size)) ctx, cancel := context.WithTimeout(_ctx, time.Second*30) defer cancel() err := c.c.Do(ctx, req, resp) if err != nil { return ItemListData{}, err } var respData CNResponse[ItemListData] if err = sonic.Unmarshal(resp.Body(), &respData); err != nil { return ItemListData{}, err } if respData.StatusCode != "100010" { return ItemListData{}, fmt.Errorf("status code: %s, msg: %s", respData.StatusCode, respData.Msg) } return respData.Data, nil }