shoptet 0.0.2 → 0.0.7
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/README.md +2 -3
- data/lib/shoptet.rb +82 -42
- data/lib/shoptet/request.rb +11 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8facc56cfe2afc649cbad1f5094830d94d83f1f8d3d564e8886f17efe1b5bc87
|
4
|
+
data.tar.gz: 82c8517d218cc6182c54620e1161428d992a43e70364c23438fb0970bf303a6f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3ff366765e02c7fe423368d0afa62bda693811c96f4f681b490161274228d39e0713cca821d4d49768c17e5f7de51e80a291bad2473e5087ff3bf4f22ccf872b
|
7
|
+
data.tar.gz: c74cda5f867dd363950b031cd4995fdf9585b843e8f66b11bdd7ec4f5e8e3f728e8340d7cebf796756133b05b3b3678716994692a46b169454e680b8a357f516
|
data/README.md
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
# Shoptet
|
2
2
|
|
3
|
-
This is Ruby API wrapper for [Shoptet API](https://
|
4
|
-
|
5
|
-
This is currently under development and hasn't been released to Rubygems yet.
|
3
|
+
This is Ruby API wrapper for [Shoptet API](https://shoptet.docs.apiary.io) which provides access to e-shop data for addon developers.
|
6
4
|
|
7
5
|
# How to install
|
8
6
|
|
@@ -82,6 +80,7 @@ Also they accept hash with params which will be passed to Shoptet api. Through t
|
|
82
80
|
## Other
|
83
81
|
|
84
82
|
* `Shoptet#new_api_token` - this returns new api token created with oauth token
|
83
|
+
* `Shoptet::install` - TODO
|
85
84
|
|
86
85
|
## License
|
87
86
|
|
data/lib/shoptet.rb
CHANGED
@@ -1,23 +1,17 @@
|
|
1
1
|
require_relative 'shoptet/request'
|
2
2
|
|
3
3
|
class Shoptet
|
4
|
-
class Error < StandardError
|
5
|
-
#TODO: check that this works
|
6
|
-
attr_reader :additional_data
|
7
|
-
|
8
|
-
def initialize message, additional_data = {}
|
9
|
-
super(message)
|
10
|
-
@additional_data = additional_data
|
11
|
-
end
|
12
|
-
end
|
4
|
+
class Error < StandardError; end
|
13
5
|
class AddonSuspended < StandardError; end
|
6
|
+
class AddonNotInstalled < StandardError; end
|
7
|
+
class InvalidTokenNoRights < StandardError; end
|
14
8
|
|
15
9
|
DEFAULT_ON_TOKEN_ERROR = -> (api) do
|
16
10
|
api.api_token = api.new_api_token
|
17
11
|
end
|
18
12
|
|
19
13
|
def self.version
|
20
|
-
'0.0.
|
14
|
+
'0.0.7'
|
21
15
|
end
|
22
16
|
|
23
17
|
def self.ar_on_token_error(model)
|
@@ -37,20 +31,71 @@ class Shoptet
|
|
37
31
|
end
|
38
32
|
end
|
39
33
|
|
34
|
+
def self.install url, redirect_url, client_id, client_secret, code
|
35
|
+
data = {
|
36
|
+
'redirect_uri' => redirect_url,
|
37
|
+
'client_id' => client_id,
|
38
|
+
'client_secret' => client_secret,
|
39
|
+
'code' => code,
|
40
|
+
'grant_type' => 'authorization_code',
|
41
|
+
'scope' => 'api'
|
42
|
+
}
|
43
|
+
|
44
|
+
Shoptet::Request.post url, data
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.login_token url, code, client_id, client_secret, redirect_url
|
48
|
+
data = {
|
49
|
+
code: code,
|
50
|
+
grant_type: 'authorization_code',
|
51
|
+
client_id: client_id,
|
52
|
+
client_secret: client_secret,
|
53
|
+
redirect_uri: redirect_url,
|
54
|
+
scope: 'basic_eshop'
|
55
|
+
}
|
56
|
+
|
57
|
+
Shoptet::Request.post url, data
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.basic_eshop url, access_token
|
61
|
+
Shoptet::Request.get url, { 'Authorization' => "Bearer #{access_token}" }
|
62
|
+
end
|
63
|
+
|
40
64
|
attr_accessor :api_token
|
41
65
|
|
42
|
-
def initialize
|
66
|
+
def initialize oauth_url:, oauth_token:, shop_url:, client_id:, api_token: nil, on_token_error: nil
|
43
67
|
@oauth_url = oauth_url
|
44
68
|
@oauth_token = oauth_token
|
69
|
+
@shop_url = shop_url
|
70
|
+
@client_id = client_id
|
45
71
|
@api_token = api_token
|
46
72
|
@on_token_error = on_token_error || DEFAULT_ON_TOKEN_ERROR
|
47
73
|
end
|
48
74
|
|
75
|
+
def authorize_url redirect_url, state
|
76
|
+
query = {
|
77
|
+
client_id: @client_id,
|
78
|
+
state: state,
|
79
|
+
scope: 'basic_eshop',
|
80
|
+
response_type: 'code',
|
81
|
+
redirect_uri: redirect_url
|
82
|
+
}.to_query
|
83
|
+
|
84
|
+
URI("#{@shop_url}action/OAuthServer/authorize?#{query}").to_s
|
85
|
+
end
|
86
|
+
|
49
87
|
def shop_info api_params = {}
|
50
|
-
request 'https://api.myshoptet.com/api/eshop'
|
88
|
+
result = request 'https://api.myshoptet.com/api/eshop'
|
89
|
+
result['data']
|
51
90
|
end
|
52
91
|
|
53
|
-
def
|
92
|
+
def design_info api_params = {}
|
93
|
+
result = request 'https://api.myshoptet.com/api/eshop/design'
|
94
|
+
|
95
|
+
result['data']
|
96
|
+
end
|
97
|
+
|
98
|
+
def stocks api_params = {}
|
54
99
|
enumerize 'https://api.myshoptet.com/api/stocks', api_params
|
55
100
|
end
|
56
101
|
|
@@ -63,6 +108,11 @@ class Shoptet
|
|
63
108
|
enumerize uri, api_params
|
64
109
|
end
|
65
110
|
|
111
|
+
def stocks_movements warehouse_id, api_params = {}
|
112
|
+
uri = "https://api.myshoptet.com/api/stocks/#{warehouse_id}/movements"
|
113
|
+
enumerize uri, api_params
|
114
|
+
end
|
115
|
+
|
66
116
|
def product_categories api_params = {}
|
67
117
|
enumerize 'https://api.myshoptet.com/api/categories', api_params
|
68
118
|
end
|
@@ -93,20 +143,20 @@ class Shoptet
|
|
93
143
|
def order code, api_params = {}
|
94
144
|
uri = "https://api.myshoptet.com/api/orders/#{code}"
|
95
145
|
result = request assemble_uri(uri, api_params)
|
96
|
-
result.dig
|
146
|
+
result.dig 'data', 'order'
|
97
147
|
end
|
98
148
|
|
99
149
|
def product guid, api_params = {}
|
100
150
|
uri = "https://api.myshoptet.com/api/products/#{guid}"
|
101
151
|
result = request assemble_uri(uri, api_params)
|
102
|
-
result
|
152
|
+
result['data']
|
103
153
|
end
|
104
154
|
|
105
155
|
def new_api_token
|
106
156
|
headers = { 'Authorization' => "Bearer #{@oauth_token}" }
|
107
157
|
|
108
158
|
result = Shoptet::Request.get @oauth_url, headers
|
109
|
-
handle_errors result, @oauth_url
|
159
|
+
handle_errors result, @oauth_url, headers
|
110
160
|
|
111
161
|
result.fetch 'access_token'
|
112
162
|
end
|
@@ -130,32 +180,36 @@ class Shoptet
|
|
130
180
|
total_pages = first_page.dig('data', 'paginator', 'pageCount') || 0
|
131
181
|
other_pages = 2..total_pages
|
132
182
|
|
133
|
-
first_page.dig('data', data_key).each { y.yield _1
|
183
|
+
first_page.dig('data', data_key).each { y.yield _1 }
|
134
184
|
|
135
185
|
other_pages.each do |page|
|
136
186
|
uri = assemble_uri base_uri, filters.merge(page: page)
|
137
187
|
result = request uri
|
138
|
-
result.dig('data', data_key).each { y.yield _1
|
188
|
+
result.dig('data', data_key).each { y.yield _1 }
|
139
189
|
end
|
140
190
|
end
|
141
191
|
end
|
142
192
|
|
143
|
-
def request uri
|
193
|
+
def request uri, retry_on_token_error = true
|
144
194
|
headers = { 'Shoptet-Access-Token' => @api_token,
|
145
195
|
'Content-Type' => 'application/vnd.shoptet.v1.0' }
|
146
196
|
|
147
197
|
result = Shoptet::Request.get uri, headers
|
148
|
-
token_errors = handle_errors result, uri
|
198
|
+
token_errors = handle_errors result, uri, headers
|
149
199
|
|
150
200
|
if token_errors.any?
|
151
|
-
|
152
|
-
|
201
|
+
if retry_on_token_error
|
202
|
+
@on_token_error.call self
|
203
|
+
request uri, false
|
204
|
+
else
|
205
|
+
raise Error.new result
|
206
|
+
end
|
153
207
|
else
|
154
208
|
result
|
155
209
|
end
|
156
210
|
end
|
157
211
|
|
158
|
-
def handle_errors result, uri
|
212
|
+
def handle_errors result, uri, headers
|
159
213
|
error = result['error']
|
160
214
|
errors = result['errors'] || []
|
161
215
|
token_errors, non_token_errors = errors.partition { |err| ['invalid-token', 'expired-token'].include? err['errorCode'] }
|
@@ -163,29 +217,15 @@ class Shoptet
|
|
163
217
|
if error || non_token_errors.any?
|
164
218
|
if error == 'addon_suspended'
|
165
219
|
raise AddonSuspended
|
220
|
+
elsif error == 'addon_not_installed'
|
221
|
+
raise AddonNotInstalled
|
222
|
+
elsif errors.any? { |err| err["errorCode"] == 'invalid-token-no-rights' }
|
223
|
+
raise InvalidTokenNoRights
|
166
224
|
else
|
167
|
-
|
168
|
-
uri: uri,
|
169
|
-
headers: scrub_sensitive_headers(headers)
|
170
|
-
}
|
171
|
-
|
172
|
-
raise Error.new result, additional_data
|
225
|
+
raise Error.new result
|
173
226
|
end
|
174
227
|
end
|
175
228
|
|
176
229
|
token_errors
|
177
230
|
end
|
178
|
-
|
179
|
-
def scrub_sensitive_headers headers
|
180
|
-
scrubbed = {}
|
181
|
-
|
182
|
-
to_scrub = ['Shoptet-Access-Token', 'Authorization']
|
183
|
-
to_scrub.each do |header|
|
184
|
-
if headers[header]
|
185
|
-
scrubbed[header] = "#{headers[header][0..20]}..."
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
headers.merge scrubbed
|
190
|
-
end
|
191
231
|
end
|
data/lib/shoptet/request.rb
CHANGED
@@ -28,5 +28,16 @@ class Shoptet
|
|
28
28
|
rescue Net::OpenTimeout
|
29
29
|
retry if attempt < 4
|
30
30
|
end
|
31
|
+
|
32
|
+
def self.post uri, body
|
33
|
+
req = Net::HTTP::Post.new uri
|
34
|
+
req.set_form_data body
|
35
|
+
|
36
|
+
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
|
37
|
+
http.request req
|
38
|
+
end
|
39
|
+
|
40
|
+
JSON.parse res.body
|
41
|
+
end
|
31
42
|
end
|
32
43
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shoptet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Premysl Donat
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-11-
|
11
|
+
date: 2020-11-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: irb
|