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