From 6849fad720ebcf6457bf337d8ca67c55da4d4419 Mon Sep 17 00:00:00 2001 From: Bastian de Byl Date: Thu, 23 Feb 2023 00:05:01 -0500 Subject: [PATCH] initial commit --- .gitignore | 3 ++ example.go | 32 +++++++++++++ go.mod | 3 ++ snipcart/helper.go | 39 ++++++++++++++++ snipcart/orderstatus.go | 13 ++++++ snipcart/snipcart.go | 99 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 189 insertions(+) create mode 100644 .gitignore create mode 100644 example.go create mode 100644 go.mod create mode 100644 snipcart/helper.go create mode 100644 snipcart/orderstatus.go create mode 100644 snipcart/snipcart.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b593205 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.json +*.sum +config/* \ No newline at end of file diff --git a/example.go b/example.go new file mode 100644 index 0000000..521e834 --- /dev/null +++ b/example.go @@ -0,0 +1,32 @@ +package main + +import ( + "flag" + "log" + + "github.com/debyltech/go-snipcart/snipcart" +) + +const ( + configFile = "config.json" +) + +func main() { + snipcartApiKey := flag.String("key", "", "Snipcart API Key") + flag.Parse() + + if *snipcartApiKey == "" { + log.Fatal("missing -key flag") + } + + snipcartProvider := snipcart.NewSnipcartProvider(*snipcartApiKey) + + response, err := snipcartProvider.GetOrdersByStatus(snipcart.Processed) + if err != nil { + log.Fatal(err) + } + + for k, v := range response.Items { + log.Printf("%v: %v\n", k, v) + } +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..f1c85be --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/debyltech/go-snipcart + +go 1.20 diff --git a/snipcart/helper.go b/snipcart/helper.go new file mode 100644 index 0000000..f34c66a --- /dev/null +++ b/snipcart/helper.go @@ -0,0 +1,39 @@ +package snipcart + +import ( + "fmt" + "net/http" +) + +type URLQuery struct { + Key string + Value string +} + +func JSONGet(uri string, authName string, authValue string, queries []URLQuery) (*http.Response, error) { + client := &http.Client{} + + request, err := http.NewRequest("GET", uri, nil) + if err != nil { + return nil, err + } + request.Header.Set("Accept", "application/json") + request.Header.Set("Authorization", fmt.Sprintf("%s %s", authName, authValue)) + + if len(queries) > 0 { + q := request.URL.Query() + + for _, query := range queries { + q.Add(query.Key, query.Value) + } + + request.URL.RawQuery = q.Encode() + } + + response, err := client.Do(request) + if err != nil { + return nil, err + } + + return response, nil +} diff --git a/snipcart/orderstatus.go b/snipcart/orderstatus.go new file mode 100644 index 0000000..7d1d4fb --- /dev/null +++ b/snipcart/orderstatus.go @@ -0,0 +1,13 @@ +package snipcart + +type OrderStatus string + +const ( + Processed OrderStatus = "Processed" + Disputed = "Disputed" + Shipped = "Shipped" + Delivered = "Delivered" + Pending = "Pending" + Cancelled = "Cancelled" + Dispatched = "Dispatched" +) diff --git a/snipcart/snipcart.go b/snipcart/snipcart.go new file mode 100644 index 0000000..a94f645 --- /dev/null +++ b/snipcart/snipcart.go @@ -0,0 +1,99 @@ +package snipcart + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "strconv" +) + +const ( + defaultLimit = 50 + apiUri = "https://app.snipcart.com" + ordersPath = "/api/orders" +) + +var ( + orderUri = apiUri + ordersPath +) + +type SnipcartProvider struct { + SnipcartKey string + AuthBase64 string + Limit int +} + +type SnipcartItem struct { + UUID string `json:"uniqueId"` + ID string `json:"id"` + Name string `json:"name"` + Quantity float64 `json:"quantity"` + Weight string `json:"weight"` + TotalWeight float64 `json:"totalWeight"` + CustomFieldsJSON string `json:"customFieldsJson"` +} + +type SnipcartOrder struct { + Token string `json:"token"` + Invoice string `json:"invoiceNumber"` + Status string `json:"status"` + TotalWeight float64 `json:"totalWeight"` + Email string `json:"email"` + Name string `json:"shippingAddressName"` + Address1 string `json:"shippingAddressAddress1"` + Address2 string `json:"shippingAddressAddress2"` + City string `json:"shippingAddressCity"` + Province string `json:"shippingAddressProvince"` + Country string `json:"shippingAddressCountry"` + PostalCode string `json:"shippingAddressPostalCode"` + Phone string `json:"shippingAddressPhone"` + Items []SnipcartItem `json:"items"` +} + +type SnipcartOrders struct { + TotalItems int + Items []SnipcartOrder +} + +func NewSnipcartProvider(snipcartApiKey string) SnipcartProvider { + return SnipcartProvider{ + SnipcartKey: snipcartApiKey, + AuthBase64: base64.StdEncoding.EncodeToString([]byte(snipcartApiKey + ":")), + } +} + +func (s *SnipcartProvider) GetOrders() (*SnipcartOrders, error) { + return s.GetOrdersByStatus("") +} + +func (s *SnipcartProvider) GetOrdersByStatus(status OrderStatus) (*SnipcartOrders, error) { + if s.Limit == 0 { + s.Limit = defaultLimit + } + + queries := []URLQuery{ + {Key: "limit", Value: strconv.Itoa(s.Limit)}, + } + + if status != "" { + queries = append(queries, URLQuery{Key: "status", Value: string(status)}) + } + + response, err := JSONGet(orderUri, "Basic", s.AuthBase64, queries) + if err != nil { + return nil, err + } + if response.Status != "200 OK" { + return nil, fmt.Errorf("unexpected response received: %s", response.Status) + } + + defer response.Body.Close() + + var orders SnipcartOrders + err = json.NewDecoder(response.Body).Decode(&orders) + if err != nil { + return nil, err + } + + return &orders, nil +}