shopify_api 4.9.0 → 5.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.github/CODEOWNERS +1 -0
- data/.github/probots.yml +2 -0
- data/.gitignore +3 -0
- data/.rubocop.yml +8 -0
- data/.travis.yml +0 -4
- data/CHANGELOG +63 -0
- data/README.md +36 -14
- data/lib/active_resource/detailed_log_subscriber.rb +25 -2
- data/lib/shopify_api/connection.rb +5 -3
- 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 +27 -1
- data/lib/shopify_api/resources/collection_publication.rb +10 -0
- data/lib/shopify_api/resources/currency.rb +6 -0
- 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 +16 -4
- 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 +42 -0
- data/lib/shopify_api/resources/ping/delivery_confirmation_details.rb +10 -0
- data/lib/shopify_api/resources/ping/message.rb +8 -0
- data/lib/shopify_api/resources/product.rb +4 -4
- data/lib/shopify_api/resources/product_publication.rb +10 -0
- data/lib/shopify_api/resources/publication.rb +5 -0
- 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/resources/smart_collection.rb +6 -2
- data/lib/shopify_api/resources/tender_transaction.rb +6 -0
- data/lib/shopify_api/session.rb +1 -1
- data/lib/shopify_api/version.rb +1 -1
- data/service.yml +8 -0
- data/shopify_api.gemspec +4 -1
- data/test/abandoned_checkouts_test.rb +29 -0
- data/test/api_permission_test.rb +9 -0
- data/test/checkouts_test.rb +72 -4
- data/test/collection_publication_test.rb +40 -0
- data/test/currency_test.rb +21 -0
- data/test/detailed_log_subscriber_test.rb +19 -1
- 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/collection_publication.json +11 -0
- data/test/fixtures/collection_publications.json +13 -0
- data/test/fixtures/currencies.json +25 -0
- 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/failed_delivery_confirmation.json +1 -0
- data/test/fixtures/ping/message.json +1 -0
- data/test/fixtures/ping/successful_delivery_confirmation.json +1 -0
- data/test/fixtures/product_publication.json +11 -0
- data/test/fixtures/product_publications.json +13 -0
- data/test/fixtures/publications.json +9 -0
- data/test/fixtures/shipping_rates.json +12 -0
- data/test/fixtures/smart_collection_products.json +155 -0
- data/test/fixtures/tender_transactions.json +52 -0
- data/test/inventory_level_test.rb +59 -0
- data/test/location_test.rb +14 -0
- data/test/order_test.rb +29 -1
- data/test/payment_test.rb +19 -0
- data/test/ping/conversation_test.rb +71 -0
- data/test/ping/message_test.rb +23 -0
- data/test/product_publication_test.rb +40 -0
- data/test/publication_test.rb +12 -0
- data/test/session_test.rb +11 -11
- data/test/shipping_rate_test.rb +17 -0
- data/test/smart_collection_test.rb +25 -0
- data/test/tender_transaction_test.rb +18 -0
- data/test/test_helper.rb +8 -5
- data/test/variant_test.rb +4 -1
- metadata +102 -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
|
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
|
|
@@ -3,8 +3,13 @@ module ShopifyAPI
|
|
|
3
3
|
include Events
|
|
4
4
|
include Metafields
|
|
5
5
|
|
|
6
|
-
def close
|
|
7
|
-
|
|
6
|
+
def close
|
|
7
|
+
load_attributes_from_response(post(:close, {}, only_id))
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def open
|
|
11
|
+
load_attributes_from_response(post(:open, {}, only_id))
|
|
12
|
+
end
|
|
8
13
|
|
|
9
14
|
def cancel(options = {})
|
|
10
15
|
load_attributes_from_response(post(:cancel, {}, options.to_json))
|
|
@@ -14,8 +19,15 @@ module ShopifyAPI
|
|
|
14
19
|
Transaction.find(:all, :params => { :order_id => id })
|
|
15
20
|
end
|
|
16
21
|
|
|
17
|
-
def capture(amount = "")
|
|
18
|
-
|
|
22
|
+
def capture(amount = "", currency: nil)
|
|
23
|
+
capture_transaction = {
|
|
24
|
+
amount: amount,
|
|
25
|
+
kind: "capture",
|
|
26
|
+
order_id: id,
|
|
27
|
+
}
|
|
28
|
+
capture_transaction[:currency] = currency if currency
|
|
29
|
+
|
|
30
|
+
Transaction.create(capture_transaction)
|
|
19
31
|
end
|
|
20
32
|
|
|
21
33
|
class ClientDetails < Base
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ShopifyAPI
|
|
4
|
+
module Ping
|
|
5
|
+
class Conversation < Base
|
|
6
|
+
self.prefix = "/admin/api/ping-api/v1/"
|
|
7
|
+
|
|
8
|
+
def send_message(message_attrs)
|
|
9
|
+
message = ShopifyAPI::Ping::Message.new(
|
|
10
|
+
message_attrs.merge(conversation_id: id)
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
message.save
|
|
14
|
+
message
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def successful_delivery(message_id:, delivery_timestamp:)
|
|
18
|
+
delivery_details = ShopifyAPI::Ping::DeliveryConfirmationDetails.new(
|
|
19
|
+
delivery_attrs(message_id, delivery_timestamp).merge(delivered: true)
|
|
20
|
+
)
|
|
21
|
+
delivery_details.save
|
|
22
|
+
delivery_details
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def failed_delivery(message_id:, delivery_timestamp:, details:)
|
|
26
|
+
delivery_details = ShopifyAPI::Ping::DeliveryConfirmationDetails.new(
|
|
27
|
+
delivery_attrs(message_id, delivery_timestamp).merge(delivered: false, details: details)
|
|
28
|
+
)
|
|
29
|
+
delivery_details.save
|
|
30
|
+
delivery_details
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def delivery_attrs(message_id, delivery_timestamp)
|
|
34
|
+
{
|
|
35
|
+
conversation_id: id,
|
|
36
|
+
message_id: message_id,
|
|
37
|
+
confirmation_timestamp: delivery_timestamp,
|
|
38
|
+
}
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ShopifyAPI
|
|
4
|
+
module Ping
|
|
5
|
+
class DeliveryConfirmationDetails < Base
|
|
6
|
+
self.prefix = "/admin/api/ping-api/v1/conversations/:conversation_id/messages/:message_id/"
|
|
7
|
+
self.collection_name = "delivery_confirmation"
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -13,19 +13,19 @@ module ShopifyAPI
|
|
|
13
13
|
format % prices.min
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
def collections
|
|
18
18
|
CustomCollection.find(:all, :params => {:product_id => self.id})
|
|
19
19
|
end
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
def smart_collections
|
|
22
22
|
SmartCollection.find(:all, :params => {:product_id => self.id})
|
|
23
23
|
end
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
def add_to_collection(collection)
|
|
26
26
|
collection.add_product(self)
|
|
27
27
|
end
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
def remove_from_collection(collection)
|
|
30
30
|
collection.remove_product(self)
|
|
31
31
|
end
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
module ShopifyAPI
|
|
2
|
-
# Shop object. Use Shop.current to receive
|
|
2
|
+
# Shop object. Use Shop.current to receive
|
|
3
3
|
# the shop.
|
|
4
4
|
class Shop < Base
|
|
5
5
|
def self.current(options={})
|
|
@@ -11,13 +11,13 @@ module ShopifyAPI
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def add_metafield(metafield)
|
|
14
|
-
raise ArgumentError, "You can only add metafields to resource that has been saved" if new?
|
|
14
|
+
raise ArgumentError, "You can only add metafields to resource that has been saved" if new?
|
|
15
15
|
metafield.save
|
|
16
16
|
metafield
|
|
17
17
|
end
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
def events
|
|
20
20
|
Event.find(:all)
|
|
21
21
|
end
|
|
22
|
-
end
|
|
22
|
+
end
|
|
23
23
|
end
|
|
@@ -3,8 +3,12 @@ module ShopifyAPI
|
|
|
3
3
|
include Events
|
|
4
4
|
include Metafields
|
|
5
5
|
|
|
6
|
-
def products
|
|
7
|
-
|
|
6
|
+
def products(options = {})
|
|
7
|
+
if options.present?
|
|
8
|
+
Product.find(:all, from: "/admin/smart_collections/#{id}/products.json", params: options)
|
|
9
|
+
else
|
|
10
|
+
Product.find(:all, params: { collection_id: id })
|
|
11
|
+
end
|
|
8
12
|
end
|
|
9
13
|
|
|
10
14
|
def order(options={})
|
data/lib/shopify_api/session.rb
CHANGED
|
@@ -51,7 +51,7 @@ module ShopifyAPI
|
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
def validate_signature(params)
|
|
54
|
-
params = params.with_indifferent_access
|
|
54
|
+
params = (params.respond_to?(:to_unsafe_hash) ? params.to_unsafe_hash : params).with_indifferent_access
|
|
55
55
|
return false unless signature = params[:hmac]
|
|
56
56
|
|
|
57
57
|
calculated_signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new(), secret, encoded_params_for_signature(params))
|
data/lib/shopify_api/version.rb
CHANGED
data/service.yml
ADDED
data/shopify_api.gemspec
CHANGED
|
@@ -23,14 +23,17 @@ Gem::Specification.new do |s|
|
|
|
23
23
|
s.summary = %q{ShopifyAPI is a lightweight gem for accessing the Shopify admin REST web services}
|
|
24
24
|
s.license = "MIT"
|
|
25
25
|
|
|
26
|
-
s.required_ruby_version = ">= 2.
|
|
26
|
+
s.required_ruby_version = ">= 2.1"
|
|
27
27
|
|
|
28
28
|
s.add_runtime_dependency("activeresource", ">= 3.0.0")
|
|
29
29
|
s.add_runtime_dependency("rack")
|
|
30
|
+
s.add_runtime_dependency("graphql-client")
|
|
30
31
|
|
|
31
32
|
s.add_development_dependency("mocha", ">= 0.9.8")
|
|
32
33
|
s.add_development_dependency("fakeweb")
|
|
33
34
|
s.add_development_dependency("minitest", ">= 4.0")
|
|
34
35
|
s.add_development_dependency("rake")
|
|
35
36
|
s.add_development_dependency("timecop")
|
|
37
|
+
s.add_development_dependency("pry")
|
|
38
|
+
s.add_development_dependency("pry-byebug")
|
|
36
39
|
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'test_helper'
|
|
3
|
+
|
|
4
|
+
class AbandonedCheckoutsTest < Test::Unit::TestCase
|
|
5
|
+
def setup
|
|
6
|
+
super
|
|
7
|
+
|
|
8
|
+
@expected_checkouts = JSON.parse(load_fixture('abandoned_checkouts'))['checkouts']
|
|
9
|
+
@expected_checkout_id = JSON.parse(load_fixture('abandoned_checkout'))['checkout']['id']
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
test ":create creates a checkout" do
|
|
13
|
+
fake 'checkouts', method: :post, status: 201, body: load_fixture('abandoned_checkout')
|
|
14
|
+
|
|
15
|
+
checkout = ShopifyAPI::AbandonedCheckout.create
|
|
16
|
+
|
|
17
|
+
assert_equal @expected_checkout_id, checkout.id
|
|
18
|
+
assert_equal true, checkout.attributes.include?(:abandoned_checkout_url)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
test "get all checkouts indexed by token" do
|
|
22
|
+
fake 'checkouts', method: :get, status: 200, body: load_fixture('abandoned_checkouts')
|
|
23
|
+
|
|
24
|
+
checkouts = ShopifyAPI::AbandonedCheckout.all
|
|
25
|
+
|
|
26
|
+
assert_equal @expected_checkout_id, checkouts.first.id
|
|
27
|
+
assert_equal @expected_checkouts.size, checkouts.size
|
|
28
|
+
end
|
|
29
|
+
end
|