shopify_api 4.9.0 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +8 -0
- data/.travis.yml +0 -4
- data/CHANGELOG +25 -0
- data/README.md +36 -14
- data/lib/shopify_api/limits.rb +1 -2
- data/lib/shopify_api/resources/abandoned_checkout.rb +7 -0
- data/lib/shopify_api/resources/access_scope.rb +5 -0
- data/lib/shopify_api/resources/api_permission.rb +9 -0
- data/lib/shopify_api/resources/asset.rb +8 -8
- data/lib/shopify_api/resources/billing_address.rb +1 -1
- data/lib/shopify_api/resources/checkout.rb +24 -1
- data/lib/shopify_api/resources/custom_collection.rb +3 -3
- data/lib/shopify_api/resources/{customer_invite_message.rb → customer_invite.rb} +0 -0
- data/lib/shopify_api/resources/graphql.rb +22 -0
- data/lib/shopify_api/resources/image.rb +2 -2
- data/lib/shopify_api/resources/inventory_item.rb +6 -0
- data/lib/shopify_api/resources/inventory_level.rb +55 -0
- data/lib/shopify_api/resources/line_item.rb +9 -1
- data/lib/shopify_api/resources/location.rb +4 -0
- data/lib/shopify_api/resources/o_auth.rb +8 -0
- data/lib/shopify_api/resources/order.rb +7 -2
- data/lib/shopify_api/resources/payment.rb +7 -0
- data/lib/shopify_api/resources/ping.rb +3 -0
- data/lib/shopify_api/resources/ping/conversation.rb +18 -0
- data/lib/shopify_api/resources/ping/message.rb +9 -0
- data/lib/shopify_api/resources/product.rb +4 -4
- data/lib/shopify_api/resources/shipping_line.rb +1 -1
- data/lib/shopify_api/resources/shipping_rate.rb +7 -0
- data/lib/shopify_api/resources/shop.rb +4 -4
- data/lib/shopify_api/session.rb +1 -1
- data/lib/shopify_api/version.rb +1 -1
- data/shopify_api.gemspec +2 -1
- data/test/abandoned_checkouts_test.rb +29 -0
- data/test/api_permission_test.rb +9 -0
- data/test/checkouts_test.rb +67 -4
- data/test/detailed_log_subscriber_test.rb +3 -2
- data/test/fixtures/abandoned_checkout.json +184 -0
- data/test/fixtures/abandoned_checkouts.json +186 -0
- data/test/fixtures/checkout.json +160 -0
- data/test/fixtures/checkouts.json +25 -49
- data/test/fixtures/inventory_level.json +7 -0
- data/test/fixtures/inventory_levels.json +24 -0
- data/test/fixtures/order_with_properties.json +373 -0
- data/test/fixtures/payment.json +7 -0
- data/test/fixtures/payments.json +9 -0
- data/test/fixtures/ping/conversation.json +1 -0
- data/test/fixtures/ping/message.json +1 -0
- data/test/fixtures/shipping_rates.json +12 -0
- data/test/inventory_level_test.rb +59 -0
- data/test/location_test.rb +14 -0
- data/test/order_test.rb +13 -1
- data/test/payment_test.rb +19 -0
- data/test/ping/conversation_test.rb +39 -0
- data/test/session_test.rb +11 -11
- data/test/shipping_rate_test.rb +17 -0
- data/test/test_helper.rb +7 -5
- data/test/variant_test.rb +4 -1
- metadata +49 -10
- data/lib/shopify_api/resources/discount.rb +0 -11
- data/test/discount_test.rb +0 -52
- data/test/fixtures/discount.json +0 -17
- data/test/fixtures/discount_disabled.json +0 -17
- data/test/fixtures/discounts.json +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 55a5fb52fc6aa176717a301e7a52d015b54a7128
|
4
|
+
data.tar.gz: 7318df185fd7cfe2272a3b5078900beea9831eb4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b0eeef0481961159424da00239ac3f9bfbc4709ccc169f592bdd4a385c15ea27a1efe2cd083737c5a36a13d2be8a6687cd5b44b4ad0d69903a1cbcf34440414
|
7
|
+
data.tar.gz: 2b0c63f6db528a3c721c2ddf9e30ed5e79976e8570c0ec7a9f03bfde173c90230e5af3979b16f7a49a001ab9ce90ad4d68920d03e291487340215506c9d70653
|
data/.rubocop.yml
ADDED
data/.travis.yml
CHANGED
@@ -2,7 +2,6 @@ language: ruby
|
|
2
2
|
sudo: false
|
3
3
|
|
4
4
|
rvm:
|
5
|
-
- '2.0'
|
6
5
|
- 2.3.1
|
7
6
|
- 2.4.0-preview1
|
8
7
|
|
@@ -15,9 +14,6 @@ gemfile:
|
|
15
14
|
- Gemfile_ar_master
|
16
15
|
|
17
16
|
matrix:
|
18
|
-
exclude:
|
19
|
-
- rvm: '2.0'
|
20
|
-
gemfile: Gemfile_ar_master
|
21
17
|
fast_finish: true
|
22
18
|
allow_failures:
|
23
19
|
- rvm: 2.4.0-preview1
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,28 @@
|
|
1
|
+
== Version 5.0.0
|
2
|
+
|
3
|
+
* Added `ShopifyAPI::AbandonedCheckout`
|
4
|
+
* Added support for X-Shopify-Checkout-Version header on `ShopifyAPI::Checkout`
|
5
|
+
* Added `ShopifyAPI::ShippingRate`
|
6
|
+
* Added support for Checkout::complete endpoint
|
7
|
+
|
8
|
+
== Version 4.12.0
|
9
|
+
|
10
|
+
* Added support for the GraphQL API
|
11
|
+
|
12
|
+
== Version 4.11.0
|
13
|
+
|
14
|
+
* Added `ShopifyAPI::InventoryItem`
|
15
|
+
* Added `ShopifyAPI::InventoryLevel`
|
16
|
+
* Added `#inventory_levels` method to `ShopifyAPI::Location`
|
17
|
+
|
18
|
+
== Version 4.10.0
|
19
|
+
|
20
|
+
* Added `ShopifyAPI::AccessScope`
|
21
|
+
|
22
|
+
== Version 4.9.1
|
23
|
+
|
24
|
+
* Fix a bug with custom properties for orders
|
25
|
+
|
1
26
|
== Version 4.9.0
|
2
27
|
|
3
28
|
* Added `ShopifyAPI::PriceRule`
|
data/README.md
CHANGED
@@ -10,6 +10,13 @@ The Shopify API gem allows Ruby developers to programmatically access the admin
|
|
10
10
|
|
11
11
|
The API is implemented as JSON over HTTP using all four verbs (GET/POST/PUT/DELETE). Each resource, like Order, Product, or Collection, has its own URL and is manipulated in isolation. In other words, we’ve tried to make the API follow the REST principles as much as possible.
|
12
12
|
|
13
|
+
## ⚠️ Breaking change notice for version 5.0.0 ⚠️
|
14
|
+
The [Abandoned Checkout API](https://help.shopify.com/en/api/reference/orders/abandoned_checkouts) is now accessed through the `ShopifyAPI::AbandonedCheckout` resource. If you were previously accessing the Abandoned Checkout API through the `ShopifyAPI::Checkout` resource, you will need to update your code after upgrading from version 4.x.x or earlier.
|
15
|
+
|
16
|
+
Going forward, the `ShopifyAPI::Checkout` resource is used to access the [Checkout API](https://help.shopify.com/en/api/reference/sales_channels/checkout), which can be used to create new checkouts.
|
17
|
+
|
18
|
+
For more details, [please see this issue](https://github.com/Shopify/shopify_api/issues/471).
|
19
|
+
|
13
20
|
## Usage
|
14
21
|
|
15
22
|
### Requirements
|
@@ -19,7 +26,7 @@ All API usage happens through Shopify applications, created by either shop owner
|
|
19
26
|
* Shop owners can create applications for themselves through their own admin: https://docs.shopify.com/api/authentication/creating-a-private-app
|
20
27
|
* Shopify Partners create applications through their admin: http://app.shopify.com/services/partners
|
21
28
|
|
22
|
-
For more information and detailed documentation about the API visit
|
29
|
+
For more information and detailed documentation about the API visit https://developers.shopify.com/
|
23
30
|
|
24
31
|
#### Ruby version
|
25
32
|
|
@@ -39,15 +46,6 @@ Or install via [gem](http://rubygems.org/)
|
|
39
46
|
gem install shopify_api
|
40
47
|
```
|
41
48
|
|
42
|
-
#### Rails 5
|
43
|
-
|
44
|
-
shopify_api is compatible with Rails 5 but since the latest ActiveResource release (4.1) is locked on Rails 4.x, you'll need to use the unreleased master version:
|
45
|
-
|
46
|
-
```ruby
|
47
|
-
gem 'shopify_api'
|
48
|
-
gem 'activeresource', github: 'rails/activeresource'
|
49
|
-
```
|
50
|
-
|
51
49
|
### Getting Started
|
52
50
|
|
53
51
|
ShopifyAPI uses ActiveResource to communicate with the REST web service. ActiveResource has to be configured with a fully authorized URL of a particular store first. To obtain that URL you can follow these steps:
|
@@ -230,6 +228,30 @@ gem install shopify_cli
|
|
230
228
|
shopify-cli help
|
231
229
|
```
|
232
230
|
|
231
|
+
## GraphQL
|
232
|
+
|
233
|
+
This library also supports Shopify's new [GraphQL API](https://help.shopify.com/api/graphql-admin-api)
|
234
|
+
via a dependency on the [graphql-client](https://github.com/github/graphql-client) gem.
|
235
|
+
The authentication process (steps 1-5 under [Getting Started](#getting-started))
|
236
|
+
is identical. Once your session is activated, simply construct a new graphql
|
237
|
+
client and use `parse` and `query` as defined by
|
238
|
+
[graphql-client](https://github.com/github/graphql-client#defining-queries).
|
239
|
+
|
240
|
+
```ruby
|
241
|
+
client = ShopifyAPI::GraphQL.new
|
242
|
+
|
243
|
+
SHOP_NAME_QUERY = client.parse <<-'GRAPHQL'
|
244
|
+
{
|
245
|
+
shop {
|
246
|
+
name
|
247
|
+
}
|
248
|
+
}
|
249
|
+
GRAPHQL
|
250
|
+
|
251
|
+
result = client.query(SHOP_NAME_QUERY)
|
252
|
+
result.data.shop.name
|
253
|
+
```
|
254
|
+
|
233
255
|
## Threadsafety
|
234
256
|
|
235
257
|
ActiveResource is threadsafe as of version 4.1 (which works with Rails 4.x and above).
|
@@ -241,14 +263,14 @@ If you were previously using Shopify's [activeresource fork](https://github.com/
|
|
241
263
|
Download the source code and run:
|
242
264
|
|
243
265
|
```bash
|
244
|
-
|
266
|
+
bundle install
|
267
|
+
bundle exec rake test
|
245
268
|
```
|
246
269
|
|
247
270
|
## Additional Resources
|
248
271
|
|
249
|
-
API
|
250
|
-
|
251
|
-
Ask questions on the forums: http://ecommerce.shopify.com/c/shopify-apis-and-technology
|
272
|
+
* [API Reference](https://help.shopify.com/api/reference)
|
273
|
+
* [Ask questions on the forums](http://ecommerce.shopify.com/c/shopify-apis-and-technology)
|
252
274
|
|
253
275
|
## Copyright
|
254
276
|
|
data/lib/shopify_api/limits.rb
CHANGED
@@ -39,8 +39,7 @@ module ShopifyAPI
|
|
39
39
|
# @return {Integer}
|
40
40
|
#
|
41
41
|
def credit_limit(scope=:shop)
|
42
|
-
|
43
|
-
@api_credit_limit[scope] ||= api_credit_limit_param(scope).pop.to_i - 1
|
42
|
+
api_credit_limit_param(scope).pop.to_i - 1
|
44
43
|
end
|
45
44
|
alias_method :call_limit, :credit_limit
|
46
45
|
|
@@ -42,7 +42,7 @@ module ShopifyAPI
|
|
42
42
|
prefix_options, query_options = split_options(prefix_options) if query_options.nil?
|
43
43
|
"#{prefix(prefix_options)}#{collection_name}.#{format.extension}#{query_string(query_options)}"
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
# find an asset by key:
|
47
47
|
# ShopifyAPI::Asset.find('layout/theme.liquid', :params => {:theme_id => 99})
|
48
48
|
def self.find(*args)
|
@@ -57,7 +57,7 @@ module ShopifyAPI
|
|
57
57
|
resource
|
58
58
|
end
|
59
59
|
end
|
60
|
-
|
60
|
+
|
61
61
|
# For text assets, Shopify returns the data in the 'value' attribute.
|
62
62
|
# For binary assets, the data is base-64-encoded and returned in the
|
63
63
|
# 'attachment' attribute. This accessor returns the data in both cases.
|
@@ -65,28 +65,28 @@ module ShopifyAPI
|
|
65
65
|
attributes['value'] ||
|
66
66
|
(attributes['attachment'] ? Base64.decode64(attributes['attachment']) : nil)
|
67
67
|
end
|
68
|
-
|
68
|
+
|
69
69
|
def attach(data)
|
70
70
|
self.attachment = Base64.encode64(data)
|
71
71
|
end
|
72
|
-
|
72
|
+
|
73
73
|
def destroy
|
74
74
|
connection.delete(element_path(prefix_options.merge(:asset => {:key => key})), self.class.headers)
|
75
75
|
end
|
76
|
-
|
76
|
+
|
77
77
|
def new?
|
78
78
|
false
|
79
79
|
end
|
80
|
-
|
80
|
+
|
81
81
|
def method_missing(method_symbol, *arguments) #:nodoc:
|
82
82
|
if %w{value= attachment= src= source_key=}.include?(method_symbol)
|
83
83
|
wipe_value_attributes
|
84
84
|
end
|
85
85
|
super
|
86
86
|
end
|
87
|
-
|
87
|
+
|
88
88
|
private
|
89
|
-
|
89
|
+
|
90
90
|
def wipe_value_attributes
|
91
91
|
%w{value attachment src source_key}.each do |attr|
|
92
92
|
attributes.delete(attr)
|
@@ -1,4 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ShopifyAPI
|
2
4
|
class Checkout < Base
|
5
|
+
self.primary_key = :token
|
6
|
+
headers['X-Shopify-Checkout-Version'] = '2016-09-06'
|
7
|
+
|
8
|
+
def complete
|
9
|
+
post(:complete)
|
10
|
+
end
|
11
|
+
|
12
|
+
def ready?
|
13
|
+
return false unless persisted?
|
14
|
+
|
15
|
+
reload
|
16
|
+
[200, 201].include?(ShopifyAPI::Base.connection.response.code.to_i)
|
17
|
+
end
|
18
|
+
|
19
|
+
def payments
|
20
|
+
Payment.find(:all, params: { checkout_id: id })
|
21
|
+
end
|
22
|
+
|
23
|
+
def shipping_rates
|
24
|
+
ShippingRate.find(:all, params: { checkout_id: id })
|
25
|
+
end
|
3
26
|
end
|
4
|
-
end
|
27
|
+
end
|
@@ -6,14 +6,14 @@ module ShopifyAPI
|
|
6
6
|
def products
|
7
7
|
Product.find(:all, :params => {:collection_id => self.id})
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
def add_product(product)
|
11
11
|
Collect.create(:collection_id => self.id, :product_id => product.id)
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
def remove_product(product)
|
15
15
|
collect = Collect.find(:first, :params => {:collection_id => self.id, :product_id => product.id})
|
16
16
|
collect.destroy if collect
|
17
17
|
end
|
18
|
-
end
|
18
|
+
end
|
19
19
|
end
|
File without changes
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'graphql/client'
|
3
|
+
require 'graphql/client/http'
|
4
|
+
|
5
|
+
module ShopifyAPI
|
6
|
+
# GraphQL API.
|
7
|
+
class GraphQL
|
8
|
+
def initialize
|
9
|
+
uri = Base.site.dup
|
10
|
+
uri.path = '/admin/api/graphql.json'
|
11
|
+
@http = ::GraphQL::Client::HTTP.new(uri.to_s) do
|
12
|
+
define_method(:headers) do |_context|
|
13
|
+
Base.headers
|
14
|
+
end
|
15
|
+
end
|
16
|
+
@schema = ::GraphQL::Client.load_schema(@http)
|
17
|
+
@client = ::GraphQL::Client.new(schema: @schema, execute: @http)
|
18
|
+
end
|
19
|
+
|
20
|
+
delegate :parse, :query, to: :@client
|
21
|
+
end
|
22
|
+
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
module ShopifyAPI
|
2
2
|
class Image < Base
|
3
3
|
init_prefix :product
|
4
|
-
|
4
|
+
|
5
5
|
# generate a method for each possible image variant
|
6
6
|
[:pico, :icon, :thumb, :small, :compact, :medium, :large, :grande, :original].each do |m|
|
7
7
|
reg_exp_match = "/\\1_#{m}.\\2"
|
8
8
|
define_method(m) { src.gsub(/\/(.*)\.(\w{2,4})/, reg_exp_match) }
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
def attach_image(data, filename = nil)
|
12
12
|
attributes['attachment'] = Base64.encode64(data)
|
13
13
|
attributes['filename'] = filename unless filename.nil?
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShopifyAPI
|
4
|
+
class InventoryLevel < Base
|
5
|
+
|
6
|
+
# The default path structure in ActiveResource for delete would result in:
|
7
|
+
# /admin/inventory_levels/#{ inventory_level.id }.json?#{ params }, but since
|
8
|
+
# InventroyLevels are a second class resource made up of a Where and a What
|
9
|
+
# (Location and InventoryItem), it does not have a resource ID. Here we
|
10
|
+
# redefine element_path to remove the id so HTTP DELETE requests go to
|
11
|
+
# /admin/inventory_levels.json?#{ params } instead.
|
12
|
+
#
|
13
|
+
def self.element_path(prefix_options = {}, query_options = nil)
|
14
|
+
prefix_options, query_options = split_options(prefix_options) if query_options.nil?
|
15
|
+
"#{prefix(prefix_options)}#{collection_name}.#{format.extension}#{query_string(query_options)}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def destroy
|
19
|
+
load_attributes_from_response(
|
20
|
+
self.class.delete('/', location_id: location_id, inventory_item_id: inventory_item_id)
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
def connect(relocate_if_necessary: nil)
|
25
|
+
body = { location_id: location_id, inventory_item_id: inventory_item_id }
|
26
|
+
body[:relocate_if_necessary] = relocate_if_necessary unless relocate_if_necessary.nil?
|
27
|
+
load_attributes_from_response(
|
28
|
+
self.class.post(:connect, {}, body.to_json)
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
def set(new_available, disconnect_if_necessary: nil)
|
33
|
+
body = {
|
34
|
+
location_id: location_id,
|
35
|
+
inventory_item_id: inventory_item_id,
|
36
|
+
available: new_available
|
37
|
+
}
|
38
|
+
body[:disconnect_if_necessary] = disconnect_if_necessary unless disconnect_if_necessary.nil?
|
39
|
+
load_attributes_from_response(
|
40
|
+
self.class.post(:set, {}, body.to_json)
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
def adjust(available_adjustment)
|
45
|
+
body = {
|
46
|
+
location_id: location_id,
|
47
|
+
inventory_item_id: inventory_item_id,
|
48
|
+
available_adjustment: available_adjustment
|
49
|
+
}
|
50
|
+
load_attributes_from_response(
|
51
|
+
self.class.post(:adjust, {}, body.to_json)
|
52
|
+
)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -1,6 +1,14 @@
|
|
1
1
|
module ShopifyAPI
|
2
|
-
class LineItem < Base
|
2
|
+
class LineItem < Base
|
3
3
|
class Property < Base
|
4
|
+
def initialize(*args)
|
5
|
+
attributes = args[0] || {}
|
6
|
+
persisted = args[1] || false
|
7
|
+
super
|
8
|
+
rescue NameError
|
9
|
+
attributes = attributes.to_hash
|
10
|
+
self
|
11
|
+
end
|
4
12
|
end
|
5
13
|
end
|
6
14
|
end
|
@@ -1,8 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This resource is deprecated and will be removed in a future version of this gem.
|
4
|
+
# Use ShopifyAPI::ApiPermission.destroy instead
|
5
|
+
|
1
6
|
module ShopifyAPI
|
2
7
|
class OAuth < Base
|
3
8
|
self.collection_name = 'oauth'
|
4
9
|
|
5
10
|
def self.revoke
|
11
|
+
warn '[DEPRECATED] ShopifyAPI::OAuth#revoke is deprecated and will be removed in a future version. ' \
|
12
|
+
'Use ShopifyAPI::ApiPermission#destroy instead.'
|
13
|
+
|
6
14
|
delete(:revoke)
|
7
15
|
end
|
8
16
|
end
|