shoptet 0.0.19 → 0.0.24
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/Gemfile.lock +1 -1
- data/lib/shoptet.rb +51 -102
- data/lib/shoptet/api_enumerator.rb +44 -0
- data/lib/shoptet/request.rb +14 -26
- data/shoptet.gemspec +2 -0
- metadata +17 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c47eb6556f7edaf410be790e1e34d50a688f4e7e985b7c3ba13f1025534cbce6
|
|
4
|
+
data.tar.gz: 327dcd29816c88ba5c3657c5d4a9ca7d73fa5befc940226b669572f46666a562
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 91cd6589e4a09aab0480f55807ae6e8ab8c256af0018753087f77f195cc8e06fb007774106586942ec90485f90804e02a48fe99857cf41ecb05ac1afe41b5bd8
|
|
7
|
+
data.tar.gz: f364707ed6c8c1a3c2381837f41e1b783a2d8902768d48bfd3762e50b4cd109b7ea6530898a38e2cf6c6984c543c8c4a12dd653d2a09679fcdd57831c84c43db
|
data/Gemfile.lock
CHANGED
data/lib/shoptet.rb
CHANGED
|
@@ -1,78 +1,25 @@
|
|
|
1
1
|
require 'delegate'
|
|
2
2
|
require_relative 'shoptet/request'
|
|
3
|
+
require_relative 'shoptet/api_enumerator'
|
|
3
4
|
|
|
4
5
|
class Shoptet
|
|
5
|
-
include Shoptet::UrlHelpers
|
|
6
|
-
|
|
7
6
|
class Error < StandardError; end
|
|
8
7
|
class AddonSuspended < StandardError; end
|
|
9
8
|
class AddonNotInstalled < StandardError; end
|
|
10
9
|
class InvalidTokenNoRights < StandardError; end
|
|
11
|
-
class
|
|
10
|
+
class EmptyResponse < StandardError; end
|
|
12
11
|
class MaxPageReached < StandardError; end
|
|
13
12
|
|
|
14
13
|
EXPIRED_TOKEN_CODE = 'expired-token'
|
|
15
14
|
INVALID_TOKEN_CODE = 'invalid-token'
|
|
16
15
|
ADDON_NOT_INSTALLED = 'Addon installation is not approved.'
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
ON_TOKEN_ERROR = -> (api) do
|
|
19
18
|
api.api_token = api.new_api_token
|
|
20
19
|
end
|
|
21
20
|
|
|
22
|
-
class ApiEnumerator < SimpleDelegator
|
|
23
|
-
def initialize base_url, filters, data_key, api
|
|
24
|
-
@base_url = base_url
|
|
25
|
-
@filters = filters
|
|
26
|
-
@data_key = data_key || URI(base_url).path.split('/').last
|
|
27
|
-
@api = api
|
|
28
|
-
|
|
29
|
-
@enum = Enumerator.new do |y|
|
|
30
|
-
first_page.dig('data', @data_key).each { y.yield _1 }
|
|
31
|
-
|
|
32
|
-
if total_pages > 1
|
|
33
|
-
other_pages = 2..(total_pages - 1)
|
|
34
|
-
other_pages.each do |page|
|
|
35
|
-
uri = @api.assemble_uri base_url, filters.merge(page: page)
|
|
36
|
-
result = @api.request uri
|
|
37
|
-
result.dig('data', @data_key).each { y.yield _1 }
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
last_page.dig('data', @data_key).each { y.yield _1 }
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
super @enum
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def first_page
|
|
48
|
-
@first_page ||=
|
|
49
|
-
begin
|
|
50
|
-
uri = @api.assemble_uri @base_url, @filters
|
|
51
|
-
@api.request uri
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def total_pages
|
|
56
|
-
first_page.dig('data', 'paginator', 'pageCount') || 0
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def last_page
|
|
60
|
-
return first_page if total_pages < 2
|
|
61
|
-
|
|
62
|
-
@last_page ||=
|
|
63
|
-
begin
|
|
64
|
-
uri = @api.assemble_uri @base_url, @filters.merge(page: total_pages)
|
|
65
|
-
@api.request uri
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def size
|
|
70
|
-
first_page['data']['paginator']['totalCount']
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
21
|
def self.version
|
|
75
|
-
'0.0.
|
|
22
|
+
'0.0.24'
|
|
76
23
|
end
|
|
77
24
|
|
|
78
25
|
def self.ar_on_token_error(model)
|
|
@@ -102,7 +49,7 @@ class Shoptet
|
|
|
102
49
|
'scope' => 'api'
|
|
103
50
|
}
|
|
104
51
|
|
|
105
|
-
Shoptet::Request.post
|
|
52
|
+
Shoptet::Request.post(url, data)
|
|
106
53
|
end
|
|
107
54
|
|
|
108
55
|
def self.login_token url, code, client_id, client_secret, redirect_url
|
|
@@ -115,11 +62,11 @@ class Shoptet
|
|
|
115
62
|
scope: 'basic_eshop'
|
|
116
63
|
}
|
|
117
64
|
|
|
118
|
-
Shoptet::Request.post
|
|
65
|
+
Shoptet::Request.post(url, data)
|
|
119
66
|
end
|
|
120
67
|
|
|
121
68
|
def self.basic_eshop url, access_token
|
|
122
|
-
Shoptet::Request.get
|
|
69
|
+
Shoptet::Request.get(url, { 'Authorization' => "Bearer #{access_token}" })
|
|
123
70
|
end
|
|
124
71
|
|
|
125
72
|
attr_accessor :api_token
|
|
@@ -130,11 +77,11 @@ class Shoptet
|
|
|
130
77
|
@shop_url = shop_url
|
|
131
78
|
@client_id = client_id
|
|
132
79
|
@api_token = api_token
|
|
133
|
-
@on_token_error = on_token_error ||
|
|
80
|
+
@on_token_error = on_token_error || ON_TOKEN_ERROR
|
|
134
81
|
end
|
|
135
82
|
|
|
136
83
|
def endpoints api_params = {}
|
|
137
|
-
enumerize
|
|
84
|
+
enumerize('https://api.myshoptet.com/api/system/endpoints', api_params)
|
|
138
85
|
end
|
|
139
86
|
|
|
140
87
|
def endpoint_approved? endpoint
|
|
@@ -143,6 +90,10 @@ class Shoptet
|
|
|
143
90
|
@approved_endpoints.any? { _1['endpoint'] == endpoint }
|
|
144
91
|
end
|
|
145
92
|
|
|
93
|
+
def endpoints_approved? *endpoints_to_check
|
|
94
|
+
endpoints_to_check.all? { endpoint_approved? _1 }
|
|
95
|
+
end
|
|
96
|
+
|
|
146
97
|
def authorize_url redirect_url, state
|
|
147
98
|
query = {
|
|
148
99
|
client_id: @client_id,
|
|
@@ -152,101 +103,101 @@ class Shoptet
|
|
|
152
103
|
redirect_uri: redirect_url
|
|
153
104
|
}.to_query
|
|
154
105
|
|
|
155
|
-
URI("#{@shop_url}action/OAuthServer/authorize?#{query}")
|
|
106
|
+
URI("#{@shop_url}action/OAuthServer/authorize?#{query}")
|
|
156
107
|
end
|
|
157
108
|
|
|
158
109
|
def shop_info api_params = {}
|
|
159
|
-
|
|
160
|
-
result = request url
|
|
110
|
+
result = request('https://api.myshoptet.com/api/eshop', api_params)
|
|
161
111
|
result['data']
|
|
162
112
|
end
|
|
163
113
|
|
|
164
114
|
def design_info api_params = {}
|
|
165
|
-
|
|
166
|
-
result = request url
|
|
115
|
+
result = request('https://api.myshoptet.com/api/eshop/design', api_params)
|
|
167
116
|
|
|
168
117
|
result['data']
|
|
169
118
|
end
|
|
170
119
|
|
|
171
120
|
def stocks api_params = {}
|
|
172
|
-
enumerize
|
|
121
|
+
enumerize('https://api.myshoptet.com/api/stocks', api_params)
|
|
173
122
|
end
|
|
174
123
|
|
|
175
124
|
def products api_params = {}
|
|
176
|
-
enumerize
|
|
125
|
+
enumerize("https://api.myshoptet.com/api/products", api_params)
|
|
177
126
|
end
|
|
178
127
|
|
|
179
128
|
def supplies warehouse_id, api_params = {}
|
|
180
|
-
|
|
181
|
-
enumerize uri, api_params
|
|
129
|
+
enumerize("https://api.myshoptet.com/api/stocks/#{warehouse_id}/supplies", api_params)
|
|
182
130
|
end
|
|
183
131
|
|
|
184
132
|
def stocks_movements warehouse_id, api_params = {}
|
|
185
|
-
|
|
186
|
-
enumerize uri, api_params
|
|
133
|
+
enumerize("https://api.myshoptet.com/api/stocks/#{warehouse_id}/movements", api_params)
|
|
187
134
|
end
|
|
188
135
|
|
|
189
136
|
def product_categories api_params = {}
|
|
190
|
-
enumerize
|
|
137
|
+
enumerize('https://api.myshoptet.com/api/categories', api_params)
|
|
191
138
|
end
|
|
192
139
|
|
|
193
140
|
def products_changes api_params = {}
|
|
194
|
-
|
|
195
|
-
enumerize uri, api_params
|
|
141
|
+
enumerize('https://api.myshoptet.com/api/products/changes', api_params)
|
|
196
142
|
end
|
|
197
143
|
|
|
198
144
|
def price_lists api_params = {}
|
|
199
|
-
enumerize
|
|
145
|
+
enumerize('https://api.myshoptet.com/api/pricelists', api_params)
|
|
200
146
|
end
|
|
201
147
|
|
|
202
148
|
def prices price_list_id, api_params = {}
|
|
203
|
-
|
|
204
|
-
enumerize uri, api_params, 'pricelist'
|
|
149
|
+
enumerize("https://api.myshoptet.com/api/pricelists/#{price_list_id}", api_params, 'pricelist')
|
|
205
150
|
end
|
|
206
151
|
|
|
207
152
|
def orders api_params = {}
|
|
208
|
-
enumerize
|
|
153
|
+
enumerize('https://api.myshoptet.com/api/orders', api_params)
|
|
209
154
|
end
|
|
210
155
|
|
|
211
|
-
def orders_changes
|
|
212
|
-
|
|
213
|
-
enumerize
|
|
156
|
+
def orders_changes from:
|
|
157
|
+
api_params = { from: from.iso8601 }
|
|
158
|
+
enumerize('https://api.myshoptet.com/api/orders/changes', api_params)
|
|
214
159
|
end
|
|
215
160
|
|
|
216
161
|
def order code, api_params = {}
|
|
217
|
-
|
|
218
|
-
result
|
|
219
|
-
result.dig 'data', 'order'
|
|
162
|
+
result = request("https://api.myshoptet.com/api/orders/#{code}", api_params)
|
|
163
|
+
result.dig('data', 'order')
|
|
220
164
|
end
|
|
221
165
|
|
|
222
166
|
def product guid, api_params = {}
|
|
223
|
-
|
|
224
|
-
result
|
|
167
|
+
result = request("https://api.myshoptet.com/api/products/#{guid}", api_params)
|
|
168
|
+
result['data']
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def product_by_code code, api_params = {}
|
|
172
|
+
result = request("https://api.myshoptet.com/api/products/code/#{code}", api_params)
|
|
225
173
|
result['data']
|
|
226
174
|
end
|
|
227
175
|
|
|
228
176
|
def new_api_token
|
|
229
177
|
headers = { 'Authorization' => "Bearer #{@oauth_token}" }
|
|
230
178
|
|
|
231
|
-
result = Shoptet::Request.get
|
|
232
|
-
handle_errors
|
|
179
|
+
result = Shoptet::Request.get(URI(@oauth_url), headers)
|
|
180
|
+
handle_errors(result)
|
|
233
181
|
|
|
234
|
-
result.fetch
|
|
182
|
+
result.fetch('access_token')
|
|
235
183
|
end
|
|
236
184
|
|
|
237
|
-
def request
|
|
185
|
+
def request url, api_params = {}, retry_on_token_error = true
|
|
186
|
+
url = URI(url)
|
|
187
|
+
url.query = URI.encode_www_form(api_params) if api_params.any?
|
|
188
|
+
|
|
238
189
|
headers = { 'Shoptet-Access-Token' => @api_token,
|
|
239
190
|
'Content-Type' => 'application/vnd.shoptet.v1.0' }
|
|
240
191
|
|
|
241
|
-
result = Shoptet::Request.get
|
|
242
|
-
token_errors = handle_errors
|
|
192
|
+
result = Shoptet::Request.get(url, headers)
|
|
193
|
+
token_errors = handle_errors(result)
|
|
243
194
|
|
|
244
195
|
if token_errors.any?
|
|
245
196
|
if retry_on_token_error
|
|
246
|
-
@on_token_error.call
|
|
247
|
-
request
|
|
197
|
+
@on_token_error.call(self)
|
|
198
|
+
request(url, api_params, false)
|
|
248
199
|
else
|
|
249
|
-
raise Error.new
|
|
200
|
+
raise Error.new(result)
|
|
250
201
|
end
|
|
251
202
|
else
|
|
252
203
|
result
|
|
@@ -254,9 +205,7 @@ class Shoptet
|
|
|
254
205
|
end
|
|
255
206
|
|
|
256
207
|
def suspended?
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
false if data
|
|
208
|
+
false if shop_info
|
|
260
209
|
rescue Shoptet::AddonSuspended
|
|
261
210
|
true
|
|
262
211
|
end
|
|
@@ -264,10 +213,10 @@ class Shoptet
|
|
|
264
213
|
private
|
|
265
214
|
|
|
266
215
|
def enumerize base_url, filters = {}, data_key = nil
|
|
267
|
-
ApiEnumerator.new
|
|
216
|
+
ApiEnumerator.new(base_url, filters, data_key, self)
|
|
268
217
|
end
|
|
269
218
|
|
|
270
|
-
def handle_errors result
|
|
219
|
+
def handle_errors result
|
|
271
220
|
error = result['error']
|
|
272
221
|
errors = result['errors'] || []
|
|
273
222
|
token_errors, non_token_errors = errors.partition do |err|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
class Shoptet
|
|
2
|
+
class ApiEnumerator < SimpleDelegator
|
|
3
|
+
def initialize base_url, filters, data_key, api
|
|
4
|
+
@base_url = base_url
|
|
5
|
+
@filters = filters
|
|
6
|
+
@data_key = data_key || URI(base_url).path.split('/').last
|
|
7
|
+
@api = api
|
|
8
|
+
|
|
9
|
+
@enum = Enumerator.new do |y|
|
|
10
|
+
first_page.dig('data', @data_key).each { y.yield _1 }
|
|
11
|
+
|
|
12
|
+
if total_pages > 1
|
|
13
|
+
other_pages = 2..(total_pages - 1)
|
|
14
|
+
other_pages.each do |page|
|
|
15
|
+
result = @api.request(base_url, filters.merge(page: page))
|
|
16
|
+
result.dig('data', @data_key).each { y.yield _1 }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
last_page.dig('data', @data_key).each { y.yield _1 }
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
super @enum
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def first_page
|
|
27
|
+
@first_page ||= @api.request(@base_url, @filters)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def last_page
|
|
31
|
+
return first_page if total_pages < 2
|
|
32
|
+
|
|
33
|
+
@last_page ||= @api.request(@base_url, @filters.merge(page: total_pages))
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def total_pages
|
|
37
|
+
first_page.dig('data', 'paginator', 'pageCount') || 0
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def size
|
|
41
|
+
first_page.dig('data', 'paginator', 'totalCount')
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
data/lib/shoptet/request.rb
CHANGED
|
@@ -1,53 +1,41 @@
|
|
|
1
1
|
require 'net/http'
|
|
2
|
-
|
|
3
|
-
#TODO: keep_alive_timeout ?
|
|
2
|
+
require 'oj'
|
|
4
3
|
|
|
5
4
|
class Shoptet
|
|
6
|
-
module UrlHelpers
|
|
7
|
-
def assemble_uri base, params = {}
|
|
8
|
-
u = URI(base)
|
|
9
|
-
u.query = URI.encode_www_form(params) if params.any?
|
|
10
|
-
|
|
11
|
-
u.to_s
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
5
|
class Request
|
|
16
|
-
def self.get
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
http = Net::HTTP.new parsed_uri.host, parsed_uri.port
|
|
6
|
+
def self.get url, headers
|
|
7
|
+
http = Net::HTTP.new(url.host, url.port)
|
|
20
8
|
http.use_ssl = true
|
|
21
9
|
http.open_timeout = 60
|
|
22
10
|
http.read_timeout = 60
|
|
23
11
|
http.write_timeout = 60
|
|
24
12
|
http.ssl_timeout = 60
|
|
25
13
|
|
|
26
|
-
request = Net::HTTP::Get.new
|
|
14
|
+
request = Net::HTTP::Get.new(url)
|
|
27
15
|
headers.each do |key, value|
|
|
28
16
|
request[key] = value
|
|
29
17
|
end
|
|
30
18
|
|
|
31
|
-
response = http.request
|
|
32
|
-
parsed_body =
|
|
19
|
+
response = http.request(request)
|
|
20
|
+
parsed_body = Oj.load(response.body, mode: :compat)
|
|
33
21
|
|
|
34
22
|
unless parsed_body
|
|
35
|
-
message = "Status code: #{response.code}, url: #{
|
|
36
|
-
fail Shoptet::
|
|
23
|
+
message = "Status code: #{response.code}, url: #{url}"
|
|
24
|
+
fail Shoptet::EmptyResponse.new(message)
|
|
37
25
|
end
|
|
38
26
|
|
|
39
27
|
parsed_body
|
|
40
28
|
end
|
|
41
29
|
|
|
42
|
-
def self.post
|
|
43
|
-
|
|
44
|
-
|
|
30
|
+
def self.post url, body
|
|
31
|
+
request = Net::HTTP::Post.new(url)
|
|
32
|
+
request.set_form_data(body)
|
|
45
33
|
|
|
46
|
-
|
|
47
|
-
http.request
|
|
34
|
+
response = Net::HTTP.start(url.host, url.port, use_ssl: true) do |http|
|
|
35
|
+
http.request(request)
|
|
48
36
|
end
|
|
49
37
|
|
|
50
|
-
|
|
38
|
+
Oj.load(response.body, mode: :compat)
|
|
51
39
|
end
|
|
52
40
|
end
|
|
53
41
|
end
|
data/shoptet.gemspec
CHANGED
metadata
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
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.24
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Premysl Donat
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-01-25 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: oj
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
13
27
|
- !ruby/object:Gem::Dependency
|
|
14
28
|
name: irb
|
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -40,6 +54,7 @@ files:
|
|
|
40
54
|
- bin/console
|
|
41
55
|
- bin/setup
|
|
42
56
|
- lib/shoptet.rb
|
|
57
|
+
- lib/shoptet/api_enumerator.rb
|
|
43
58
|
- lib/shoptet/request.rb
|
|
44
59
|
- shoptet.gemspec
|
|
45
60
|
homepage: https://github.com/Masa331/shoptet
|