shopify_api 3.2.1 → 3.2.2
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 +4 -4
- data/CHANGELOG +5 -0
- data/Gemfile.lock +3 -2
- data/lib/shopify_api/cli.rb +20 -19
- data/lib/shopify_api/session.rb +4 -1
- data/lib/shopify_api/version.rb +1 -1
- data/shopify_api.gemspec +4 -2
- data/test/checkouts_test.rb +9 -0
- data/test/cli_test.rb +24 -24
- data/test/fixtures/checkouts.json +186 -0
- data/test/fixtures/order.json +297 -0
- data/test/fixtures/orders.json +299 -0
- data/test/fixtures/script_tag.json +10 -0
- data/test/fixtures/script_tags.json +18 -0
- data/test/fixtures/webhook.json +10 -0
- data/test/fixtures/webhooks.json +18 -0
- data/test/order_test.rb +24 -40
- data/test/script_tag_test.rb +30 -0
- data/test/session_test.rb +4 -4
- data/test/webhook_test.rb +21 -0
- metadata +31 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4b7258c4c1368bc212523e4f8454567e21d46737
|
4
|
+
data.tar.gz: 3ab24e5dba88ffb8172b7b4b9f9b72029fefe208
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b3f0a8efebafd6e97a057c5e87de87a1fc81be1a587c4471c5c2129589d0ecbae0ba2b7398b5ecc6e6b4986e2cd1a2f9c85bbb090209e7438d7c31d42b885ab8
|
7
|
+
data.tar.gz: e38505ed41e9ae8bd00377483b57cf8a8b62dfff37eb218193cc620665309e978668193ede11b824cb2e7bf3bcbd820e85b4b5eb88a49539c6167eef7bb6e22e
|
data/CHANGELOG
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
shopify_api (3.2.
|
4
|
+
shopify_api (3.2.2)
|
5
5
|
activeresource (>= 3.0.0)
|
6
|
-
thor (
|
6
|
+
thor (~> 0.18.1)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
@@ -44,6 +44,7 @@ PLATFORMS
|
|
44
44
|
DEPENDENCIES
|
45
45
|
activeresource (~> 4.0.0)
|
46
46
|
fakeweb
|
47
|
+
minitest (~> 4.0)
|
47
48
|
mocha (>= 0.9.8)
|
48
49
|
rake
|
49
50
|
shopify_api!
|
data/lib/shopify_api/cli.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
require 'thor'
|
2
2
|
require 'abbrev'
|
3
|
+
require 'yaml'
|
3
4
|
|
4
5
|
module ShopifyAPI
|
5
6
|
class Cli < Thor
|
6
7
|
include Thor::Actions
|
7
|
-
|
8
|
+
|
8
9
|
class ConfigFileError < StandardError
|
9
10
|
end
|
10
11
|
|
@@ -15,7 +16,7 @@ module ShopifyAPI
|
|
15
16
|
puts prefix + c
|
16
17
|
end
|
17
18
|
end
|
18
|
-
|
19
|
+
|
19
20
|
desc "add CONNECTION", "create a config file for a connection named CONNECTION"
|
20
21
|
def add(connection)
|
21
22
|
file = config_file(connection)
|
@@ -35,7 +36,7 @@ module ShopifyAPI
|
|
35
36
|
default(connection)
|
36
37
|
end
|
37
38
|
end
|
38
|
-
|
39
|
+
|
39
40
|
desc "remove CONNECTION", "remove the config file for CONNECTION"
|
40
41
|
def remove(connection)
|
41
42
|
file = config_file(connection)
|
@@ -46,7 +47,7 @@ module ShopifyAPI
|
|
46
47
|
no_config_file_error(file)
|
47
48
|
end
|
48
49
|
end
|
49
|
-
|
50
|
+
|
50
51
|
desc "edit [CONNECTION]", "open the config file for CONNECTION with your default editor"
|
51
52
|
def edit(connection=nil)
|
52
53
|
file = config_file(connection)
|
@@ -60,7 +61,7 @@ module ShopifyAPI
|
|
60
61
|
no_config_file_error(file)
|
61
62
|
end
|
62
63
|
end
|
63
|
-
|
64
|
+
|
64
65
|
desc "show [CONNECTION]", "output the location and contents of the CONNECTION's config file"
|
65
66
|
def show(connection=nil)
|
66
67
|
connection ||= default_connection
|
@@ -72,7 +73,7 @@ module ShopifyAPI
|
|
72
73
|
no_config_file_error(file)
|
73
74
|
end
|
74
75
|
end
|
75
|
-
|
76
|
+
|
76
77
|
desc "default [CONNECTION]", "show the default connection, or make CONNECTION the default"
|
77
78
|
def default(connection=nil)
|
78
79
|
if connection
|
@@ -90,15 +91,15 @@ module ShopifyAPI
|
|
90
91
|
puts "There is no default connection set"
|
91
92
|
end
|
92
93
|
end
|
93
|
-
|
94
|
+
|
94
95
|
desc "console [CONNECTION]", "start an API console for CONNECTION"
|
95
96
|
def console(connection=nil)
|
96
97
|
file = config_file(connection)
|
97
|
-
|
98
|
+
|
98
99
|
config = YAML.load(File.read(file))
|
99
100
|
puts "using #{config['domain']}"
|
100
101
|
ShopifyAPI::Base.site = site_from_config(config)
|
101
|
-
|
102
|
+
|
102
103
|
require 'irb'
|
103
104
|
require 'irb/completion'
|
104
105
|
ARGV.clear
|
@@ -110,15 +111,15 @@ module ShopifyAPI
|
|
110
111
|
end
|
111
112
|
|
112
113
|
private
|
113
|
-
|
114
|
+
|
114
115
|
def shop_config_dir
|
115
116
|
@shop_config_dir ||= File.join(ENV['HOME'], '.shopify', 'shops')
|
116
117
|
end
|
117
|
-
|
118
|
+
|
118
119
|
def default_symlink
|
119
120
|
@default_symlink ||= File.join(shop_config_dir, 'default')
|
120
121
|
end
|
121
|
-
|
122
|
+
|
122
123
|
def config_file(connection)
|
123
124
|
if connection
|
124
125
|
File.join(shop_config_dir, "#{connection}.yml")
|
@@ -126,35 +127,35 @@ module ShopifyAPI
|
|
126
127
|
default_symlink
|
127
128
|
end
|
128
129
|
end
|
129
|
-
|
130
|
+
|
130
131
|
def site_from_config(config)
|
131
132
|
protocol = config['protocol'] || 'https'
|
132
133
|
api_key = config['api_key']
|
133
134
|
password = config['password']
|
134
135
|
domain = config['domain']
|
135
|
-
|
136
|
+
|
136
137
|
ShopifyAPI::Base.site = "#{protocol}://#{api_key}:#{password}@#{domain}/admin"
|
137
138
|
end
|
138
|
-
|
139
|
+
|
139
140
|
def available_connections
|
140
141
|
@available_connections ||= begin
|
141
142
|
pattern = File.join(shop_config_dir, "*.yml")
|
142
143
|
Dir.glob(pattern).map { |f| File.basename(f, ".yml") }
|
143
144
|
end
|
144
145
|
end
|
145
|
-
|
146
|
+
|
146
147
|
def default_connection_target
|
147
148
|
@default_connection_target ||= File.readlink(default_symlink)
|
148
149
|
end
|
149
|
-
|
150
|
+
|
150
151
|
def default_connection
|
151
152
|
@default_connection ||= File.basename(default_connection_target, ".yml")
|
152
153
|
end
|
153
|
-
|
154
|
+
|
154
155
|
def default?(connection)
|
155
156
|
default_connection == connection
|
156
157
|
end
|
157
|
-
|
158
|
+
|
158
159
|
def no_config_file_error(filename)
|
159
160
|
raise ConfigFileError, "There is no config file at #{filename}"
|
160
161
|
end
|
data/lib/shopify_api/session.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
|
2
2
|
module ShopifyAPI
|
3
3
|
|
4
|
+
class ValidationException < StandardError
|
5
|
+
end
|
6
|
+
|
4
7
|
class Session
|
5
8
|
cattr_accessor :api_key
|
6
9
|
cattr_accessor :secret
|
@@ -74,7 +77,7 @@ module ShopifyAPI
|
|
74
77
|
return token if token
|
75
78
|
|
76
79
|
unless self.class.validate_signature(params) && params[:timestamp].to_i > 24.hours.ago.utc.to_i
|
77
|
-
raise "Invalid Signature: Possible malicious login"
|
80
|
+
raise ShopifyAPI::ValidationException, "Invalid Signature: Possible malicious login"
|
78
81
|
end
|
79
82
|
|
80
83
|
code = params['code']
|
data/lib/shopify_api/version.rb
CHANGED
data/shopify_api.gemspec
CHANGED
@@ -25,15 +25,17 @@ Gem::Specification.new do |s|
|
|
25
25
|
s.license = 'MIT'
|
26
26
|
|
27
27
|
s.add_dependency("activeresource", [">= 3.0.0"])
|
28
|
-
s.add_dependency("thor", ["
|
29
|
-
|
28
|
+
s.add_dependency("thor", ["~> 0.18.1"])
|
29
|
+
|
30
30
|
if s.respond_to?(:add_development_dependency)
|
31
31
|
s.add_development_dependency("mocha", ">= 0.9.8")
|
32
32
|
s.add_development_dependency("fakeweb")
|
33
|
+
s.add_development_dependency("minitest", "~> 4.0")
|
33
34
|
s.add_development_dependency("rake")
|
34
35
|
else
|
35
36
|
s.add_dependency("mocha", ">= 0.9.8")
|
36
37
|
s.add_dependency("fakeweb")
|
38
|
+
s.add_dependency("minitest", "~> 4.0")
|
37
39
|
s.add_dependency("rake")
|
38
40
|
end
|
39
41
|
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class CheckoutsTest < Test::Unit::TestCase
|
4
|
+
test "get all should get all orders" do
|
5
|
+
fake 'checkouts', :method => :get, :status => 200, :body => load_fixture('checkouts')
|
6
|
+
checkout = ShopifyAPI::Checkout.all
|
7
|
+
assert_equal 450789469, checkout.first.id
|
8
|
+
end
|
9
|
+
end
|
data/test/cli_test.rb
CHANGED
@@ -10,7 +10,7 @@ class CliTest < Test::Unit::TestCase
|
|
10
10
|
`rm -rf #{@test_home}`
|
11
11
|
ENV['HOME'] = @test_home
|
12
12
|
@cli = ShopifyAPI::Cli.new
|
13
|
-
|
13
|
+
|
14
14
|
FileUtils.mkdir_p(@shop_config_dir)
|
15
15
|
File.open(config_file('foo'), 'w') do |file|
|
16
16
|
file.puts valid_options.merge('domain' => 'foo.myshopify.com').to_yaml
|
@@ -20,11 +20,11 @@ class CliTest < Test::Unit::TestCase
|
|
20
20
|
file.puts valid_options.merge('domain' => 'bar.myshopify.com').to_yaml
|
21
21
|
end
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
def teardown
|
25
25
|
`rm -rf #{@test_home}`
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
test "add with blank domain" do
|
29
29
|
`rm -rf #{@shop_config_dir}/*`
|
30
30
|
$stdout.expects(:print).with("Domain? (leave blank for foo.myshopify.com) ")
|
@@ -33,9 +33,9 @@ class CliTest < Test::Unit::TestCase
|
|
33
33
|
$stdin.expects(:gets).times(3).returns("", "key", "pass")
|
34
34
|
@cli.expects(:puts).with("\nopen https://foo.myshopify.com/admin/api in your browser to get API credentials\n")
|
35
35
|
@cli.expects(:puts).with("Default connection is foo")
|
36
|
-
|
36
|
+
|
37
37
|
@cli.add('foo')
|
38
|
-
|
38
|
+
|
39
39
|
config = YAML.load(File.read(config_file('foo')))
|
40
40
|
assert_equal 'foo.myshopify.com', config['domain']
|
41
41
|
assert_equal 'key', config['api_key']
|
@@ -43,7 +43,7 @@ class CliTest < Test::Unit::TestCase
|
|
43
43
|
assert_equal 'https', config['protocol']
|
44
44
|
assert_equal config_file('foo'), File.readlink(@default_symlink)
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
test "add with explicit domain" do
|
48
48
|
`rm -rf #{@shop_config_dir}/*`
|
49
49
|
$stdout.expects(:print).with("Domain? (leave blank for foo.myshopify.com) ")
|
@@ -52,58 +52,58 @@ class CliTest < Test::Unit::TestCase
|
|
52
52
|
$stdin.expects(:gets).times(3).returns("bar.myshopify.com", "key", "pass")
|
53
53
|
@cli.expects(:puts).with("\nopen https://bar.myshopify.com/admin/api in your browser to get API credentials\n")
|
54
54
|
@cli.expects(:puts).with("Default connection is foo")
|
55
|
-
|
55
|
+
|
56
56
|
@cli.add('foo')
|
57
|
-
|
57
|
+
|
58
58
|
config = YAML.load(File.read(config_file('foo')))
|
59
59
|
assert_equal 'bar.myshopify.com', config['domain']
|
60
60
|
end
|
61
|
-
|
61
|
+
|
62
62
|
test "list" do
|
63
63
|
@cli.expects(:puts).with(" bar")
|
64
64
|
@cli.expects(:puts).with(" * foo")
|
65
|
-
|
65
|
+
|
66
66
|
@cli.list
|
67
67
|
end
|
68
|
-
|
68
|
+
|
69
69
|
test "show default" do
|
70
70
|
@cli.expects(:puts).with("Default connection is foo")
|
71
|
-
|
71
|
+
|
72
72
|
@cli.default
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
75
|
test "set default" do
|
76
76
|
@cli.expects(:puts).with("Default connection is bar")
|
77
|
-
|
77
|
+
|
78
78
|
@cli.default('bar')
|
79
|
-
|
79
|
+
|
80
80
|
assert_equal config_file('bar'), File.readlink(@default_symlink)
|
81
81
|
end
|
82
|
-
|
82
|
+
|
83
83
|
test "remove default connection" do
|
84
84
|
@cli.remove('foo')
|
85
|
-
|
85
|
+
|
86
86
|
assert !File.exist?(@default_symlink)
|
87
87
|
assert !File.exist?(config_file('foo'))
|
88
88
|
assert File.exist?(config_file('bar'))
|
89
89
|
end
|
90
|
-
|
90
|
+
|
91
91
|
test "remove non-default connection" do
|
92
92
|
@cli.remove('bar')
|
93
|
-
|
93
|
+
|
94
94
|
assert_equal config_file('foo'), File.readlink(@default_symlink)
|
95
95
|
assert File.exist?(config_file('foo'))
|
96
96
|
assert !File.exist?(config_file('bar'))
|
97
97
|
end
|
98
|
-
|
98
|
+
|
99
99
|
private
|
100
|
-
|
100
|
+
|
101
101
|
def valid_options
|
102
102
|
{'domain' => 'snowdevil.myshopify.com', 'api_key' => 'key', 'password' => 'pass', 'protocol' => 'https'}
|
103
103
|
end
|
104
|
-
|
104
|
+
|
105
105
|
def config_file(connection)
|
106
106
|
File.join(@shop_config_dir, "#{connection}.yml")
|
107
107
|
end
|
108
|
-
|
109
|
-
end
|
108
|
+
|
109
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
{
|
2
|
+
"checkouts": [
|
3
|
+
{
|
4
|
+
"buyer_accepts_marketing": false,
|
5
|
+
"cart_token": "68778783ad298f1c80c3bafcddeea02f",
|
6
|
+
"closed_at": null,
|
7
|
+
"completed_at": null,
|
8
|
+
"created_at": "2012-10-12T07:05:27-04:00",
|
9
|
+
"currency": "USD",
|
10
|
+
"email": "bob.norman@hostmail.com",
|
11
|
+
"gateway": null,
|
12
|
+
"id": 450789469,
|
13
|
+
"landing_site": null,
|
14
|
+
"note": null,
|
15
|
+
"referring_site": null,
|
16
|
+
"shipping_lines": [
|
17
|
+
{
|
18
|
+
"title": "Free Shipping",
|
19
|
+
"price": "0.00",
|
20
|
+
"code": "Free Shipping",
|
21
|
+
"source": "shopify"
|
22
|
+
}
|
23
|
+
],
|
24
|
+
"source": null,
|
25
|
+
"source_identifier": null,
|
26
|
+
"source_name": "web",
|
27
|
+
"source_url": null,
|
28
|
+
"subtotal_price": "398.00",
|
29
|
+
"taxes_included": false,
|
30
|
+
"token": "2a1ace52255252df566af0faaedfbfa7",
|
31
|
+
"total_discounts": "0.00",
|
32
|
+
"total_line_items_price": "398.00",
|
33
|
+
"total_price": "409.94",
|
34
|
+
"total_tax": "11.94",
|
35
|
+
"total_weight": 400,
|
36
|
+
"updated_at": "2012-10-12T07:05:27-04:00",
|
37
|
+
"line_items": [
|
38
|
+
{
|
39
|
+
"applied_discounts": [
|
40
|
+
|
41
|
+
],
|
42
|
+
"compare_at_price": null,
|
43
|
+
"fulfillment_service": "manual",
|
44
|
+
"gift_card": false,
|
45
|
+
"grams": 200,
|
46
|
+
"id": 49148385,
|
47
|
+
"line_price": "199.00",
|
48
|
+
"price": "199.00",
|
49
|
+
"product_id": 632910392,
|
50
|
+
"properties": null,
|
51
|
+
"quantity": 1,
|
52
|
+
"requires_shipping": true,
|
53
|
+
"sku": "IPOD2008RED",
|
54
|
+
"tax_lines": [
|
55
|
+
|
56
|
+
],
|
57
|
+
"taxable": true,
|
58
|
+
"title": "IPod Nano - 8GB",
|
59
|
+
"variant_id": 49148385,
|
60
|
+
"variant_title": "Red",
|
61
|
+
"vendor": "Apple"
|
62
|
+
},
|
63
|
+
{
|
64
|
+
"applied_discounts": [
|
65
|
+
|
66
|
+
],
|
67
|
+
"compare_at_price": null,
|
68
|
+
"fulfillment_service": "manual",
|
69
|
+
"gift_card": false,
|
70
|
+
"grams": 200,
|
71
|
+
"id": 808950810,
|
72
|
+
"line_price": "199.00",
|
73
|
+
"price": "199.00",
|
74
|
+
"product_id": 632910392,
|
75
|
+
"properties": null,
|
76
|
+
"quantity": 1,
|
77
|
+
"requires_shipping": true,
|
78
|
+
"sku": "IPOD2008PINK",
|
79
|
+
"tax_lines": [
|
80
|
+
|
81
|
+
],
|
82
|
+
"taxable": true,
|
83
|
+
"title": "IPod Nano - 8GB",
|
84
|
+
"variant_id": 808950810,
|
85
|
+
"variant_title": "Pink",
|
86
|
+
"vendor": "Apple"
|
87
|
+
}
|
88
|
+
],
|
89
|
+
"name": "#450789469",
|
90
|
+
"note_attributes": [
|
91
|
+
{
|
92
|
+
"name": "custom engraving",
|
93
|
+
"value": "Happy Birthday"
|
94
|
+
},
|
95
|
+
{
|
96
|
+
"name": "colour",
|
97
|
+
"value": "green"
|
98
|
+
}
|
99
|
+
],
|
100
|
+
"discount_codes": [
|
101
|
+
{
|
102
|
+
"code": "TENOFF",
|
103
|
+
"amount": "10.00"
|
104
|
+
}
|
105
|
+
],
|
106
|
+
"abandoned_checkout_url": "https://checkout.local/orders/690933842/2a1ace52255252df566af0faaedfbfa7?recovered=1",
|
107
|
+
"tax_lines": [
|
108
|
+
{
|
109
|
+
"price": "11.94",
|
110
|
+
"rate": 0.06,
|
111
|
+
"title": "State Tax"
|
112
|
+
}
|
113
|
+
],
|
114
|
+
"billing_address": {
|
115
|
+
"address1": "Chestnut Street 92",
|
116
|
+
"address2": "",
|
117
|
+
"city": "Louisville",
|
118
|
+
"company": null,
|
119
|
+
"country": "United States",
|
120
|
+
"first_name": "Bob",
|
121
|
+
"last_name": "Norman",
|
122
|
+
"latitude": "45.41634",
|
123
|
+
"longitude": "-75.6868",
|
124
|
+
"phone": "555-625-1199",
|
125
|
+
"province": "Kentucky",
|
126
|
+
"zip": "40202",
|
127
|
+
"name": "Bob Norman",
|
128
|
+
"country_code": "US",
|
129
|
+
"province_code": "KY"
|
130
|
+
},
|
131
|
+
"shipping_address": {
|
132
|
+
"address1": "Chestnut Street 92",
|
133
|
+
"address2": "",
|
134
|
+
"city": "Louisville",
|
135
|
+
"company": null,
|
136
|
+
"country": "United States",
|
137
|
+
"first_name": "Bob",
|
138
|
+
"last_name": "Norman",
|
139
|
+
"latitude": "45.41634",
|
140
|
+
"longitude": "-75.6868",
|
141
|
+
"phone": "555-625-1199",
|
142
|
+
"province": "Kentucky",
|
143
|
+
"zip": "40202",
|
144
|
+
"name": "Bob Norman",
|
145
|
+
"country_code": "US",
|
146
|
+
"province_code": "KY"
|
147
|
+
},
|
148
|
+
"customer": {
|
149
|
+
"accepts_marketing": false,
|
150
|
+
"created_at": "2014-03-07T16:12:37-05:00",
|
151
|
+
"email": "bob.norman@hostmail.com",
|
152
|
+
"first_name": "Bob",
|
153
|
+
"id": 207119551,
|
154
|
+
"last_name": "Norman",
|
155
|
+
"last_order_id": null,
|
156
|
+
"multipass_identifier": null,
|
157
|
+
"note": null,
|
158
|
+
"orders_count": 0,
|
159
|
+
"state": "disabled",
|
160
|
+
"total_spent": "0.00",
|
161
|
+
"updated_at": "2014-03-07T16:12:37-05:00",
|
162
|
+
"verified_email": true,
|
163
|
+
"tags": "",
|
164
|
+
"last_order_name": null,
|
165
|
+
"default_address": {
|
166
|
+
"address1": "Chestnut Street 92",
|
167
|
+
"address2": "",
|
168
|
+
"city": "Louisville",
|
169
|
+
"company": null,
|
170
|
+
"country": "United States",
|
171
|
+
"first_name": null,
|
172
|
+
"id": 207119551,
|
173
|
+
"last_name": null,
|
174
|
+
"phone": "555-625-1199",
|
175
|
+
"province": "Kentucky",
|
176
|
+
"zip": "40202",
|
177
|
+
"name": null,
|
178
|
+
"province_code": "KY",
|
179
|
+
"country_code": "US",
|
180
|
+
"country_name": "United States",
|
181
|
+
"default": true
|
182
|
+
}
|
183
|
+
}
|
184
|
+
}
|
185
|
+
]
|
186
|
+
}
|