package woocommerce import ( "context" "encoding/json" "strconv" "time" ) const ( defaultListPerPage = 50 maxListPerPage = 100 ) type OrderBilling struct { Email string `json:"email"` FirstName string `json:"first_name"` LastName string `json:"last_name"` } type OrderLineItem struct { ID int `json:"id"` Name string `json:"name"` ProductID int `json:"product_id"` VariationID int `json:"variation_id"` Quantity int `json:"quantity"` Total string `json:"total"` SKU string `json:"sku"` MetaData json.RawMessage `json:"meta_data"` } type Order struct { ID int `json:"id"` Status string `json:"status"` Currency string `json:"currency"` Total string `json:"total"` CustomerID int `json:"customer_id"` DateCreated string `json:"date_created"` DateCreatedGMT string `json:"date_created_gmt"` Billing OrderBilling `json:"billing"` LineItems []OrderLineItem `json:"line_items"` Raw json.RawMessage `json:"-"` } type ProductReview struct { ID int `json:"id"` ProductID int `json:"product_id"` Status string `json:"status"` Reviewer string `json:"reviewer"` ReviewerEmail string `json:"reviewer_email"` Review string `json:"review"` Rating int `json:"rating"` DateCreated string `json:"date_created"` DateCreatedGMT string `json:"date_created_gmt"` ProductName string `json:"product_name"` Raw json.RawMessage `json:"-"` } func clampPerPage(perPage int) int { if perPage <= 0 { return defaultListPerPage } if perPage > maxListPerPage { return maxListPerPage } return perPage } // ListOrdersPage fetches one page of WooCommerce orders. func (c *Client) ListOrdersPage(ctx context.Context, page, perPage int, modifiedAfter string) ([]Order, []byte, error) { perPage = clampPerPage(perPage) if page <= 0 { page = 1 } q := map[string]string{ "page": strconv.Itoa(page), "per_page": strconv.Itoa(perPage), "orderby": "date", "order": "desc", } if modifiedAfter != "" { q["modified_after"] = modifiedAfter } raw, err := c.do(ctx, "GET", "/orders", q, nil) if err != nil { return nil, nil, err } var out []Order if err := json.Unmarshal(raw, &out); err != nil { return nil, nil, err } // Keep full payload slices aligned with unmarshaled rows. var rawItems []json.RawMessage _ = json.Unmarshal(raw, &rawItems) for i := range out { if i < len(rawItems) { out[i].Raw = rawItems[i] } } return out, raw, nil } // ListProductReviewsPage fetches one page of WooCommerce product reviews. func (c *Client) ListProductReviewsPage(ctx context.Context, page, perPage int) ([]ProductReview, []byte, error) { perPage = clampPerPage(perPage) if page <= 0 { page = 1 } q := map[string]string{ "page": strconv.Itoa(page), "per_page": strconv.Itoa(perPage), "orderby": "date", "order": "desc", } raw, err := c.do(ctx, "GET", "/products/reviews", q, nil) if err != nil { return nil, nil, err } var out []ProductReview if err := json.Unmarshal(raw, &out); err != nil { return nil, nil, err } var rawItems []json.RawMessage _ = json.Unmarshal(raw, &rawItems) for i := range out { if i < len(rawItems) { out[i].Raw = rawItems[i] } } return out, raw, nil } func parseWooTime(vals ...string) *time.Time { layouts := []string{ time.RFC3339, "2006-01-02T15:04:05", "2006-01-02 15:04:05", } for _, v := range vals { if v == "" { continue } for _, layout := range layouts { if t, err := time.Parse(layout, v); err == nil { u := t.UTC() return &u } } } return nil }