bold-commerce / go-shopify Goto Github PK
View Code? Open in Web Editor NEWThis project forked from getconversio/go-shopify
Go client for the Shopify API
License: MIT License
This project forked from getconversio/go-shopify
Go client for the Shopify API
License: MIT License
From @sudomake on December 19, 2017 21:1
We should add order refunds.
https://help.shopify.com/api/reference/refund
Copied from original issue: getconversio#56
Admin REST APIs that would be beneficial to implement:
Would be nice to see following methods as a result:
client := goshopify.NewClient(app, tenant, token)
cancelInput := goshopify.OrderCancelInput{
OrderID: 1, // shopify id of order
// rest of fields are optional fields documented in request parameters section of docs
}
if err := client.Order.Cancel(cancelInput); err != nil {
// handle error
}
closeInput := goshopify.OrderCloseInput{
OrderID: 1, // shopify id of order
// rest of fields are optional fields documented in request parameters section of docs
}
if err := client.Order.Close(closeInput); err != nil {
// handle error
}
Thoughts?
While working with the Metafields API cleitn exposed by this package, I noticed that we're currently unable to work with Metafields on Shopify version 2021-07 since there was a breaking change to the model.
This is a blocker for some work of ours, but the change to this library can be non-breaking and transparently support both the old and new approaches.
func (r *RecurringApplicationChargeServiceOp) Update(chargeID, newCappedAmount int) (
*RecurringApplicationCharge, error) {
path := fmt.Sprintf("%s/%d/customize.json?recurring_application_charge[capped_amount]=%d",
recurringApplicationChargesBasePath, chargeID, newCappedAmount)
resource := &RecurringApplicationChargeResource{}
err := r.client.Put(path, nil, resource)
return resource.Charge, err
}
the newCappedAmount should be the type decimal instead of an int.
however the change would be break the original interface.
I am making calls to Product.List but after sometime I think I am hitting the api limits set by Shopify.
How do I know that it is a RateLimitError from the err of Product,List call? And how do I access the RetryAfter attribute?
Because a string's default is ""
and it cannot be set to nil
Shopify creates the asset from ""
instead of the URL given to Src
currenty in variants.go the field InventoryQuantity is marked as "omitempty". Zero is an empty value in go so this field would not be sent to shopify. so you are not able to sent zero values.
Is this project still active?
Problem
SinceId is an int64 but the API documentation tells you to pass since_id=0 to work with paginated results. I found a problem in the smartcollections end point where it sorts by alpha title on default so in order to force an id sort you have to to use since_id=0 properly and have to initialize that param to force the id sort. With omitempty on SinceID the marshaler will consider this empty and not send the param even if you explicitly set it to int64(0) since obviously omitempty considers zero an empty int64 type. Also, if you don't set the param the struct will still initialize with zero and you dont want to pass since_id=0 ALL the time so you can't just remove omitempty.
Workaround
Initialize SinceID as int64(1) as it is basically the same thing for all intents and purposes but is not technically not what the api documents as the proper method and could trip up a developer.
Fix?
Possibly just document as a limitation on the struct field
i know how to Count Product Count
but i dont know how to Create New Customer
Please let me know
Hello,
I received the warning from shopify that I am using deprecated API for the pagination. Is there a way to do cursor-based pagination for orders? I looked at the commit history and it looks like only products can do that at the moment, is that not supported for orders yet?
What is the plan to add presentment price in the variant object
"presentment_prices": [
{
"price": {
"currency_code": "USD",
"amount": "199.99"
},
"compare_at_price": null
},
{
"price": {
"currency_code": "EUR",
"amount": "158.95"
},
"compare_at_price": null
},
{
"price": {
"currency_code": "GBP",
"amount": "143.00"
},
"compare_at_price": null
},
{
"price": {
"currency_code": "JPY",
"amount": "22400"
},
"compare_at_price": null
}
]
Received an email from Shopify that paging is deprecated and to use the cursor. April 1, 2020 looks to be the cutoff so it's still a way out. Will cursor-based paging be supported?
From @orian on June 8, 2018 7:59
It should be possible to add context.Context
to requests. It's particularly useful for a request we want to control a timeout, so one can use context.WithTimeout()
.
Not sure about how to make it as the current implementation assumes that options is just query.Values
.
The go' standard way is to pass context as first argument.
Copied from original issue: getconversio#93
This is a reference to getconversio#71 from the old project. We would like to support these, but the existing MR needs some work to be merged in.
When I try to run go mod tidy
I get an error:
github.com/bold-commerce/go-shopify tested by
github.com/bold-commerce/go-shopify.test imports
gopkg.in/jarcoal/httpmock.v1: no matching versions for query "latest"
Do you have any suggestion for resolving this issue?
As the title, struct RefundLineItem is missing property subtotal.
https://help.shopify.com/en/api/reference/orders/order#properties
I just created a pull request #29
How to access to shopfront API? I want to create checkout.
Fulfillment Receipt is an array not object
Shopify has support for AWS EventBridge(here), which can be used to integrate webhook delivery.
When trying to use the current Create method like this:-
resp, err := c.Webhook.Create(goshopify.Webhook{
Address: "arn:aws:events:ap-south-1::event-source/aws.partner/shopify.com/xxxxxx7/somecustomrule",
Topic: "orders/create",
Format: "json",
})
The response received is address: is invalid
The official node api has a DeliveryMethod
field
Any plan to support abandoned checkouts? It's an important feature for many apps.
https://shopify.dev/docs/admin-api/rest/reference/orders/abandoned-checkouts
Hi,
It looks like most Shopify changes are not being added. Is this being actively maintained?
Thanks
From Shopify's REST API Doc on Fulfillments:
notify_customer
: Whether the customer should be notified. If set to true, then an email will be sent when the fulfillment is created or updated. For orders that were initially created using the API, the default value is false. For all other orders, the default value is true.Whether the customer should be notified. If set to true, then an email will be sent when the fulfillment is created or updated. For orders that were initially created using the API, the default value is false. For all other orders, the default value is true.
The associated PR #56 removes omitempty
from the JSON tag because it prevents false
from being sent, and thus the default behavior from being overriden.
Hello,
Having used this library a bit I don't see why all the input options for operations on endpoints take interface{}
as input. It makes sense for the underlying CreateAndDo
request helper but for user code calling something like Product.List()
or Product.Count()
why isn't it taking a pointer(optionally nil) to CountOptions
or ListOptions
? I don't believe these can be customized or that you'd have any reason to pass in other data.
Perhaps I've overlooked something but any confirmation on this one way or the other would be great. I'm contemplating a patch to switch to proper types and also potentially add context support as a v4 upgrade.
This is a reference to: getconversio#86 from the old project.
We would like this feature in go-shopify, but we need tests and likely further changes to ensure that it will work.
Change the value_type
property to type in
your metafield resource.
shopify.dev
Hi there,
I'm consistently getting the following error whenever I attempt to create or change a variant using this library:
Write requests to inventory_quantity and inventory_quantity_adjustment are no longer supported. Please use the Inventory Levels API.
For reference, here is a snippet of code where I'm attempting the change:
ok := YesNoPrompt("Update Shopify Price?", true)
if ok {
fmt.Println("Updating Shopify Price")
currentVariant, err := client.Variant.Get(foundVariantID, nil)
assertNoErr(err)
// update price of local variant
currentVariant.Price = &shopifyPrice
// update remote variant
newVar, err := client.Variant.Create(foundProductID, *currentVariant)
assertNoErr(err)
fmt.Printf("New variant price is: %v\n", newVar.Price.String())
// verify update
}```
I'm about to do this refactor and PR it but wanted to document why you would want to do this. There is a limitation of using the package level variable globalApiPathPrefix
. If you call goshopify.NewClient
using WithVersion
it will always set all previous Clients to the last version passed. The global string should be refactored to a Client.pathPrefix and a first pass refactor could be
path := fmt.Sprintf("%s/%s.json", globalApiPathPrefix, locationsBasePath)
// becomes
path := fmt.Sprintf("%s/%s.json", s.client.pathPrefix, locationsBasePath)
but I would prefer the prefix was prepended in Client.CreateAndDo
so you don't have to worry about it at the service level since the client should really dictate where all calls are going and you shouldn't be able to re-path which api version you're using in the Services but could be convinced otherwise. This is the version I will PR so if @gordcurrie or somebody else wants to stop me before I get there then please respond.
e.g. of how to recreate this
func newStableShopifyClient() *goshopify.Client {
return goshopify.NewClient(shopifyApp, shopifyName, "")
}
func newVersionedShopifyClient(version string) *goshopify.Client {
return goshopify.NewClient(shopifyApp, shopifyName, "", goshopify.WithVersion(version))
}
_ = newStableShopifyClient()
fmt.Println(goshopify.MetafieldPathPrefix("test", 1234))
_ = newVersionedShopifyClient("2019-04")
fmt.Println(goshopify.MetafieldPathPrefix("test", 1234))
returns something like this
admin/test/1234/metafields
admin/api/2019-04/test/1234/metafields
From @apkrieg on April 30, 2018 15:56
app := goshopify.App{
ApiKey: "abcd",
ApiSecret: "efgh",
RedirectUrl: "https://example.com/shopify/callback",
Scope: "read_products,read_orders",
}
should look like:
app := goshopify.App{
APIKey: "abcd",
APISecret: "efgh",
RedirectURL: "https://example.com/shopify/callback",
Scope: "read_products,read_orders",
}
I understand the backwards compatibility thing, but maybe we can start working on version 2.X.X and fix this?
Cites:
https://github.com/golang/lint/blob/master/lint.go#L749
Copied from original issue: getconversio#78
Line 245 in f29f869
How is my code working now:
import (
goshopify "github.com/bold-commerce/go-shopify"
"net/url"
)
func NewClient(app goshopify.App, shopName string, token string) (*goshopify.Client, error){
_, err := url.Parse(shopName)
if err != nil {
return nil, err
}
return app.NewClient(shopName, token), nil
}
I think it would be right:
func (a App) NewClient(shopName, token string, opts ...Option) (*Client, error) {
return NewClient(a, shopName, token, opts...)
}
func NewClient(app App, shopName, token string, opts ...Option) (*Client, error) {
baseURL, err := url.Parse(ShopBaseUrl(shopName))
if err != nil {
return nil, err
}
//.....
}
Or:
func (a App) NewClient(shopName url.URL, token string, opts ...Option) (*Client, error) {
return NewClient(a, shopName, token, opts...)
}
func NewClient(app App, shopName url.URL, token string, opts ...Option) (*Client, error) {
baseURL := shopName
//.....
}
I was trying out product pagination parsing, and ended up having to change the link parsing regex for the code to work:
Here's the regex in your code:
Line 17 in fa02f85
And the example from the Shopify docs:
#...
Link: "<https://{shop}.myshopify.com/admin/api/2019-07/products.json?page_info=hijgklmn&limit=3>; rel=next"
#...
The quotes around (previous|next)
are nowhere to be seen in the docs, so either the Shopify docs are wrong (I haven't tried against their live API yet), or the regex is invalid. Just removing the quote seems to make my tests pass against the Shopify docs example.
From @baorv on July 17, 2018 10:45
Should support Draft Order.
https://help.shopify.com/en/api/reference/orders/draftorder
Copied from original issue: getconversio#103
According to public doc of Shopify [1], ProductID is unsigned int 64, however, Product in the lib has int64 [2]. This diff would be not only in Product but the other models as well.
This can be critical difference once the value exceeds range of int64. (although not sure how it is realistically exceeded)
[1] https://shopify.dev/docs/admin-api/rest/reference/products/product?api[version]=2020-01
An unsigned 64-bit integer that's used as a unique identifier for the product. Each id is unique across the Shopify system. No two products will have the same id, even if they're from different shops.
[2] https://github.com/bold-commerce/go-shopify/blob/master/product.go#L43
From @sudomake on October 25, 2017 18:14
Looking at the docs for a Customer Address, it looks very similar to a Billing Address and Shipping Address for an [Order](https://help.shopify.com/api/reference/order#Order properties)
The differences are:
Would you like to keep the types separate or combine these into one type?
Copied from original issue: getconversio#50
Hi all ✋
I'm very enjoying to use go-shopify.
By the way, is there any plan to support the PriceRule resource ❓
The search results for this repository indicate that the implementation of PriceRule was proposed once in #59.
(But it seems closed and didn't incorporate into the codebase. 😢 )
So, is there any plan to support the PriceRule resource or would you let me support it?
🙏
From @ckeyes88 on July 17, 2018 16:39
Currently, string values on any of the data structs have the omitempty
tag associated with them. Because of this, if I try to set a string value to it's nil
value ""
, json.Unmarshal
and json.Marshal
leave off that attribute. This is a problem when trying to update a string field that I want to unset.
Steps to reproduce (using a variant as example):
v.InventoryManagement = "shopify"
v.InventoryManagement = ""
shopify.Variant.Updated(v)
Expected: The returned updated variant should have v.InventoryManagement == ""
and that variant should no longer be set to have shopify track inventory.
Actual: The returned updated variant has v.InventoryManagement == "shopify"
and that variant has no changes to it's inventory management in the admin console.
Proposed fix: Convert the string values to string pointers so that they can be explicitly nil-able.
If I'm thinking about the problem incorrectly, I'd love some feedback on how to unset string properties.
Copied from original issue: getconversio#104
From the shopify docs:
A unique numeric identifier, of up to 32 digits, for the product.
Each id is unique across the Shopify system.
No two products will have the same id, even if they're from different shops.
largest int64 (8 bytes)
9223372036854775807 = 19 digits
if its uint64, you can get to 20 digits
It is probably better to represent the Id's as strings or some custom type.
For tests that register responders with query params. We should get them to use httpmock's new RegisterResponderWithQuery
See https://github.com/jarcoal/httpmock/blob/3be5f16b70eb0ec7d421ca2689144c0c5f3c2ca1/transport.go#L200.
While working with the PriceRules API client exposed by this package, I noticed that we are currently unable to specify PriceRule prerequisites (minimum purchase eligibility, minimum quantity eligibility, maximum shipping eligibility, etc)
This is a blocker for some work of ours, but would also pose a breaking change due to the rename of the types.
I've opened two PRs to illustrate some options and capture any pointed discussion, anything more general can be captured here in the comments.
From @orian on June 8, 2018 6:27
For some objects Shopify is using a global ID space and recently the threshold of 2^31-1 has been exceeded.
The Go's int size is at least 32 bits, but not guaranteed to be bigger (e.g. int64
).
I propose to switch all int
ids into int64
.
Copied from original issue: getconversio#92
the latest shopify order is support for total_tip_received
column
Could you support for this column total_tip_received
in your repo?
Hi All,
I'm trying to find all metafields for a Customer that has a specific namespace
and key
Basically, this cURL request
curl --location --request GET 'https://{{store_domain.com}}/admin/api/2022-01/metafields.json?namespace={{namespace}}&key={{key}}' \
--header 'X-Shopify-Access-Token: {{access_token}}'
In my code I'm using the Customer.ListMetafields
method like so:
metafield, err := client.Customer.ListMetafields(shopifyID, goshopify.Metafield{
Namespace: "{{namespace}}",
Key: "{{key}}",
})
if err != nil {
lib.CheckError("failed to get Shopify metafield", err)
}
But instead of getting a filtered list of Metafields I'm getting all of the customer's metafields. Is this an issue with the package or am I just doing something silly?
Does go-shopify need work with shopify.com service ?
i have noticed requested_fulfillment_service_id
having int
or null value but not a string value.
is there any indication/instance that this field is string instead?
Adding an option WithClient
that will allow to add custom configuration for the http client for example override the transport to add monitoring.
I'm willing to open an PR, if it's decided to move forward with this idea.
I am not able to download the latest version using go get. I am always getting the below version.
github.com/bold-commerce/go-shopify v2.3.0+incompatible
Steps I took to install are:
go mod init
go run main.go
Manually trying to install latest version gives errors
go get github.com/bold-commerce/[email protected]
go get github.com/bold-commerce/[email protected]: github.com/bold-commerce/[email protected]: invalid version: module contains a go.mod file, so major version must be compatible: should be v0 or v1, not v3
Any ideas on how to get this fixed?
I am trying to grab all of my products from Shopify, which number over 200. When I attempt to use ListWithPagination
, the NextPageOptions
and PrevPageOptions
are both nil
. In particular, I have
var prodList [][]goshopify.Product
ops := interface{}(goshopify.ProductListOptions{
ListOptions: goshopify.ListOptions{
Page: 1,
Limit: 50,
},
})
for true {
prods, page, err := client.Product.ListWithPagination(ops)
check(err)
prodList = append(prodList, prods)
if page.NextPageOptions == nil {
break
}
ops = interface{}(page.NextPageOptions)
}
Using a debugger, I find that page
only contains nil
values, and the loop breaks immediately. I currently get around this situation by using Product.List
and iterating until it returns an empty Product
slice, although I don't know how safe this is. I have
var prodList [][]goshopify.Product
ops := goshopify.ProductListOptions{
ListOptions: goshopify.ListOptions{
Page: 1,
Limit: 50,
},
}
for true {
prods, err := client.Product.List(ops)
check(err)
prodList = append(prodList, prods)
if len(prods) == 0 {
break
}
ops.ListOptions.Page++
}
This does work and pulls all products from Shopify.
VerifyWebhookRequest should handle errors with the header being blank etc.
AuthorizeUrl
does not handle errors. If url.Parse
returns an error then a panic occurs trying to access a nil pointer. This can occur if the shopName
contains invalid web address characters like a space.
func (app App) AuthorizeUrl(shopName string, state string) string {
shopUrl, _ := url.Parse(ShopBaseUrl(shopName)) // error here is unhandled
shopUrl.Path = "/admin/oauth/authorize" // panic occurs here on nil pointer
query := shopUrl.Query()
query.Set("client_id", app.ApiKey)
query.Set("redirect_uri", app.RedirectUrl)
query.Set("scope", app.Scope)
query.Set("state", state)
shopUrl.RawQuery = query.Encode()
return shopUrl.String()
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.