Install go-shopify v4
masterTo install the latest major version (v4), use the following command:
go get github.com/bold-commerce/go-shopify/v4Then, import it in your Go code using:
import "github.com/bold-commerce/go-shopify/v4"repository·master·Indexed 19 days ago
https://github.com/bold-commerce/go-shopifyA Go library for interacting with the Shopify API. It supports OAuth flows for public apps, basic authentication for private apps, and provides a structured way to interact with Shopify resources. Features include client configuration for API versions and retries, webhook request verification, and services for managing abandoned checkouts, application charges, blog articles, and API permissions.
To install the latest major version (v4), use the following command:
go get github.com/bold-commerce/go-shopify/v4Then, import it in your Go code using:
import "github.com/bold-commerce/go-shopify/v4"Testing is performed using docker and docker-compose.
Using Make (Recommended):
make: Builds the go-shopify:latest container.make test: Runs tests inside the container.make clean: Removes the build container and coverage output.make coverage: Generates and opens coverage.html.Manual Commands:
docker-compose build testdocker-compose run --rm testsdocker-compose run --rm dev sh -c 'go test -coverprofile=coverage.out ./... && go tool cover -html coverage.out -o coverage.html'If an endpoint is not implemented in the library, you can use the client.Get method to fetch data into your own custom structs. You must define models that match the expected JSON structure from Shopify.
type Webhook struct {
Id int `json:"id"`
Address string `json:"address"`
}
type WebhooksResource struct {
Webhooks []Webhook `json:"webhooks"`
}
func FetchWebhooks() ([]Webhook, error) {
path := "admin/webhooks.json"
resource := new(WebhooksResource)
client, _ := goshopify.NewClient(app, "shopname", "token")
// resource gets modified by the Get call
err := client.Get(path, resource, nil)
return resource.Webhooks, err
}If you do not have a permanent access token, you can use the goshopify.App struct to manage the OAuth flow.
ApiKey, ApiSecret, RedirectUrl, and Scope.app.AuthorizeUrl(shopName, state) to generate the URL for redirection.app.VerifyAuthorizationURL(r.URL) to validate the signature, then call app.GetAccessToken(ctx, shopName, code) to retrieve the permanent token.// Create an app
app := goshopify.App{
ApiKey: "abcd",
ApiSecret: "efgh",
RedirectUrl: "https://example.com/shopify/callback",
Scope: "read_products,read_orders",
}
// 1. Generate Authorize URL
authUrl := app.AuthorizeUrl(shopName, state)
// 2. In callback, verify and get token
if ok, _ := app.VerifyAuthorizationURL(r.URL); !ok {
// handle invalid signature
}
ctx := context.TODO()
token, err := app.GetAccessToken(ctx, shopName, code)To handle large sets of customers, use ListWithPagination. This method returns a slice of Customer objects and a *Pagination object. If pagination.NextPageOptions is not nil, you can pass those options back into a subsequent ListWithPagination call to retrieve the next page of results.
// Manual pagination loop example
options := interface{}(nil)
for {
customers, pagination, err := client.CustomerService.ListWithPagination(ctx, options)
if err != nil {
break
}
// Process customers...
if pagination.NextPageOptions == nil {
break
}
options = pagination.NextPageOptions
}When Shopify sends a request to your CallbackUrl, your server must respond with a ShippingRateResponse object. This object contains an array of ShippingRate objects that customers will see at checkout.
ShippingRate Fields:
ServiceName: The name of the rate (e.g., "Expedited Mail").Description: A description of the rate (e.g., "Includes tracking").ServiceCode: A unique code for the rate (e.g., "expedited_mail").Currency: The currency of the rate.TotalPrice: The total price in the currency's smallest unit (e.g., cents). This uses decimal.Decimal.PhoneRequired: Whether the customer must provide a phone number.MinDeliveryDate / MaxDeliveryDate: Optional time bounds for the rate validity.response := goshopify.ShippingRateResponse{
Rates: []goshopify.ShippingRate{
{
ServiceName: "Standard Shipping",
Description: "3-5 business days",
ServiceCode: "standard",
Currency: "USD",
TotalPrice: decimal.NewFromFloat(500), // $5.00
},
},
}The Order struct represents a full Shopify order. Key fields include:
Id: The unique identifier for the order.LineItems: A slice of LineItem objects containing product details, quantities, and prices.TotalWeight: Total weight of the order.FinancialStatus: The current payment status (OrderFinancialStatus).FulfillmentStatus: The current shipping status (OrderFulfillmentStatus).Customer: Pointer to the Customer resource.TotalPrice: The total price of the order using decimal.Decimal for precision.TaxLines: A slice of TaxLine objects describing taxes applied.To fulfill specific quantities of items within a Fulfillment Order, use the LineItemByFulfillmentOrder and LineItemByFulfillmentOrderItemQuantity structures. This is common in newer Shopify API workflows.
Fields:
LineItemByFulfillmentOrder.FulfillmentOrderId: The ID of the fulfillment order.LineItemByFulfillmentOrder.FulfillmentOrderLineItems: A list of items and the quantities to fulfill.LineItemByFulfillmentOrderItemQuantity.Id: The line item ID.LineItemByFulfillmentOrderItemQuantity.Quantity: The amount to fulfill.When Shopify calls your carrier service callback URL, it sends a ShippingRateRequest. This request contains the context needed to calculate rates.
Request Structure:
Rate: A ShippingRateQuery containing:Origin: The starting ShippingRateAddress.Destination: The target ShippingRateAddress.Items: A list of LineItem objects being shipped.Currency: The requested currency.Locale: The requested locale.Address Fields:
For API-created carrier services, you should primarily use these fields in ShippingRateAddress:
Address1, Address2, City, Province, Zip (via PostalCode), Country.Note: Other fields like Address3, Fax, or CompanyName may be present for specific legacy providers but are typically null for standard API integrations.
// The incoming payload from Shopify will unmarshal into:
goshopify.ShippingRateRequestThe PriceRule struct provides helper methods to set various prerequisite conditions for a discount rule. These methods handle the internal creation of prerequisite sub-structs and can also clear them by passing nil.
SetPrerequisiteSubtotalRange(greaterThanOrEqualTo *string) error: Sets the minimum subtotal required for the rule to apply. The string must be a valid decimal value. Returns an error if the string is not a valid decimal.SetPrerequisiteQuantityRange(greaterThanOrEqualTo *int): Sets the minimum quantity required for the rule to apply.SetPrerequisiteShippingPriceRange(lessThanOrEqualTo *string) error: Sets the maximum shipping price allowed for the rule to apply. The string must be a valid decimal value. Returns an error if the string is not a valid decimal.SetPrerequisiteToEntitlementQuantityRatio(prerequisiteQuantity *int, entitledQuantity *int): Sets the ratio between required items and entitled items (e.g., for 'Buy X, Get Y' rules).// Example: Setting a subtotal prerequisite
val := "50.00"
err := priceRule.SetPrerequisiteSubtotalRange(&val)
// Example: Setting a quantity prerequisite
qty := 2
priceRule.SetPrerequisiteQuantityRange(&qty)
// Example: Setting a Buy X Get Y ratio
pReq := 1
eEnt := 1
priceRule.SetPrerequisiteToEntitlementQuantityRatio(&pReq, &eEnt)To interact with the Shopify Admin API, you must create a Client instance. You can do this using NewClient (which returns an error) or MustNewClient (which panics on error).
Both functions require an App configuration and the shop's domain (e.g., "theshop.myshopify.com" or just "theshop"), along with an access token.
Note that each store requires its own Client instance because the baseURL is set on a per-store basis.
app := goshopify.App{
ApiKey: "your_api_key",
ApiSecret: "your_api_secret",
}
// Using NewClient
client, err := goshopify.NewClient(app, "theshop", "your_access_token")
if err != nil {
// handle error
}You can run the project's test suite within a Docker container using the provided test service in docker-compose.yml. This service builds the image from the current directory and executes go test -v -cover ./... inside the container, mapping the local source code to /go/src/github.com/bold-commerce/go-shopify to ensure tests run against your local changes.
docker-compose up test