shoptet 0.0.5 → 0.0.10
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 +133 -64
- data/lib/shoptet/request.rb +20 -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: 419d01d58f819a79e524940a21eb8cca44fca53cc77257acd87f6a0e0f699bb6
|
4
|
+
data.tar.gz: 0366bbceb70df4b75ccef62ed9ac853b5fd1e5d56b81833ee5c1a87ee99f6208
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ced7cedf10bf236c1fe434ef729707cfb152fb747f02391d037ec2adff66f5aed43c41081e1b59b43e6b8d47fe52924d1323b0c554c340e49fad2cceebd5030
|
7
|
+
data.tar.gz: 887f3afe91e7b8bcbefe3bdac69bf6ce4c81a3525f27967969893aad172d5d4248e77585ec59a3c4f5ca6b8a79e7a1a16a45e605561f94a3e0b2e8e1aef8a41b
|
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,15 +1,10 @@
|
|
1
|
+
require 'delegate'
|
1
2
|
require_relative 'shoptet/request'
|
2
3
|
|
3
4
|
class Shoptet
|
4
|
-
|
5
|
-
#TODO: check that this works
|
6
|
-
attr_reader :additional_data
|
5
|
+
include Shoptet::UrlHelpers
|
7
6
|
|
8
|
-
|
9
|
-
super(message)
|
10
|
-
@additional_data = additional_data
|
11
|
-
end
|
12
|
-
end
|
7
|
+
class Error < StandardError; end
|
13
8
|
class AddonSuspended < StandardError; end
|
14
9
|
class AddonNotInstalled < StandardError; end
|
15
10
|
class InvalidTokenNoRights < StandardError; end
|
@@ -18,8 +13,60 @@ class Shoptet
|
|
18
13
|
api.api_token = api.new_api_token
|
19
14
|
end
|
20
15
|
|
16
|
+
class ApiEnumerator < SimpleDelegator
|
17
|
+
def initialize base_url, filters, data_key, api
|
18
|
+
@base_url = base_url
|
19
|
+
@filters = filters
|
20
|
+
@data_key = data_key || URI(base_url).path.split('/').last
|
21
|
+
@api = api
|
22
|
+
|
23
|
+
@enum = Enumerator.new do |y|
|
24
|
+
first_page.dig('data', @data_key).each { y.yield _1 }
|
25
|
+
|
26
|
+
if total_pages > 1
|
27
|
+
other_pages = 2..(total_pages - 1)
|
28
|
+
other_pages.each do |page|
|
29
|
+
uri = @api.assemble_uri base_url, filters.merge(page: page)
|
30
|
+
result = @api.request uri
|
31
|
+
result.dig('data', @data_key).each { y.yield _1 }
|
32
|
+
end
|
33
|
+
|
34
|
+
last_page.dig('data', @data_key).each { y.yield _1 }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
super @enum
|
39
|
+
end
|
40
|
+
|
41
|
+
def first_page
|
42
|
+
@first_page ||=
|
43
|
+
begin
|
44
|
+
uri = @api.assemble_uri @base_url, @filters
|
45
|
+
@api.request uri
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def total_pages
|
50
|
+
first_page.dig('data', 'paginator', 'pageCount') || 0
|
51
|
+
end
|
52
|
+
|
53
|
+
def last_page
|
54
|
+
return first_page if total_pages < 2
|
55
|
+
|
56
|
+
@last_page ||=
|
57
|
+
begin
|
58
|
+
uri = @api.assemble_uri @base_url, @filters.merge(page: total_pages)
|
59
|
+
@api.request uri
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def size
|
64
|
+
first_page['data']['paginator']['totalCount']
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
21
68
|
def self.version
|
22
|
-
'0.0.
|
69
|
+
'0.0.10'
|
23
70
|
end
|
24
71
|
|
25
72
|
def self.ar_on_token_error(model)
|
@@ -39,25 +86,83 @@ class Shoptet
|
|
39
86
|
end
|
40
87
|
end
|
41
88
|
|
89
|
+
def self.install url, redirect_url, client_id, client_secret, code
|
90
|
+
data = {
|
91
|
+
'redirect_uri' => redirect_url,
|
92
|
+
'client_id' => client_id,
|
93
|
+
'client_secret' => client_secret,
|
94
|
+
'code' => code,
|
95
|
+
'grant_type' => 'authorization_code',
|
96
|
+
'scope' => 'api'
|
97
|
+
}
|
98
|
+
|
99
|
+
Shoptet::Request.post url, data
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.login_token url, code, client_id, client_secret, redirect_url
|
103
|
+
data = {
|
104
|
+
code: code,
|
105
|
+
grant_type: 'authorization_code',
|
106
|
+
client_id: client_id,
|
107
|
+
client_secret: client_secret,
|
108
|
+
redirect_uri: redirect_url,
|
109
|
+
scope: 'basic_eshop'
|
110
|
+
}
|
111
|
+
|
112
|
+
Shoptet::Request.post url, data
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.basic_eshop url, access_token
|
116
|
+
Shoptet::Request.get url, { 'Authorization' => "Bearer #{access_token}" }
|
117
|
+
end
|
118
|
+
|
42
119
|
attr_accessor :api_token
|
43
120
|
|
44
|
-
def initialize
|
121
|
+
def initialize oauth_url:, oauth_token:, shop_url:, client_id:, api_token: nil, on_token_error: nil
|
45
122
|
@oauth_url = oauth_url
|
46
123
|
@oauth_token = oauth_token
|
124
|
+
@shop_url = shop_url
|
125
|
+
@client_id = client_id
|
47
126
|
@api_token = api_token
|
48
127
|
@on_token_error = on_token_error || DEFAULT_ON_TOKEN_ERROR
|
49
128
|
end
|
50
129
|
|
51
|
-
|
130
|
+
def endpoints api_params = {}
|
131
|
+
enumerize 'https://api.myshoptet.com/api/system/endpoints', api_params
|
132
|
+
end
|
133
|
+
|
134
|
+
def endpoint_approved? endpoint
|
135
|
+
@approved_endpoints ||= endpoints
|
136
|
+
|
137
|
+
@approved_endpoints.any? { _1['endpoint'] == endpoint }
|
138
|
+
end
|
139
|
+
|
140
|
+
def authorize_url redirect_url, state
|
141
|
+
query = {
|
142
|
+
client_id: @client_id,
|
143
|
+
state: state,
|
144
|
+
scope: 'basic_eshop',
|
145
|
+
response_type: 'code',
|
146
|
+
redirect_uri: redirect_url
|
147
|
+
}.to_query
|
148
|
+
|
149
|
+
URI("#{@shop_url}action/OAuthServer/authorize?#{query}").to_s
|
150
|
+
end
|
151
|
+
|
52
152
|
def shop_info api_params = {}
|
53
|
-
|
153
|
+
url = assemble_uri 'https://api.myshoptet.com/api/eshop', api_params
|
154
|
+
result = request url
|
155
|
+
result['data']
|
54
156
|
end
|
55
157
|
|
56
158
|
def design_info api_params = {}
|
57
|
-
|
159
|
+
url = assemble_uri 'https://api.myshoptet.com/api/eshop/design', api_params
|
160
|
+
result = request url
|
161
|
+
|
162
|
+
result['data']
|
58
163
|
end
|
59
164
|
|
60
|
-
def
|
165
|
+
def stocks api_params = {}
|
61
166
|
enumerize 'https://api.myshoptet.com/api/stocks', api_params
|
62
167
|
end
|
63
168
|
|
@@ -70,6 +175,11 @@ class Shoptet
|
|
70
175
|
enumerize uri, api_params
|
71
176
|
end
|
72
177
|
|
178
|
+
def stocks_movements warehouse_id, api_params = {}
|
179
|
+
uri = "https://api.myshoptet.com/api/stocks/#{warehouse_id}/movements"
|
180
|
+
enumerize uri, api_params
|
181
|
+
end
|
182
|
+
|
73
183
|
def product_categories api_params = {}
|
74
184
|
enumerize 'https://api.myshoptet.com/api/categories', api_params
|
75
185
|
end
|
@@ -100,13 +210,13 @@ class Shoptet
|
|
100
210
|
def order code, api_params = {}
|
101
211
|
uri = "https://api.myshoptet.com/api/orders/#{code}"
|
102
212
|
result = request assemble_uri(uri, api_params)
|
103
|
-
result.dig
|
213
|
+
result.dig 'data', 'order'
|
104
214
|
end
|
105
215
|
|
106
216
|
def product guid, api_params = {}
|
107
217
|
uri = "https://api.myshoptet.com/api/products/#{guid}"
|
108
218
|
result = request assemble_uri(uri, api_params)
|
109
|
-
result
|
219
|
+
result['data']
|
110
220
|
end
|
111
221
|
|
112
222
|
def new_api_token
|
@@ -118,35 +228,6 @@ class Shoptet
|
|
118
228
|
result.fetch 'access_token'
|
119
229
|
end
|
120
230
|
|
121
|
-
private
|
122
|
-
|
123
|
-
def assemble_uri base, params = {}
|
124
|
-
u = URI(base)
|
125
|
-
u.query = URI.encode_www_form(params) if params.any?
|
126
|
-
|
127
|
-
u.to_s
|
128
|
-
end
|
129
|
-
|
130
|
-
def enumerize base_uri, filters = {}, data_key = nil
|
131
|
-
data_key ||= URI(base_uri).path.split('/').last
|
132
|
-
uri = assemble_uri base_uri, filters
|
133
|
-
size_proc = -> () { request(uri)['data']['paginator']['totalCount'] }
|
134
|
-
|
135
|
-
Enumerator.new(size_proc) do |y|
|
136
|
-
first_page = request uri
|
137
|
-
total_pages = first_page.dig('data', 'paginator', 'pageCount') || 0
|
138
|
-
other_pages = 2..total_pages
|
139
|
-
|
140
|
-
first_page.dig('data', data_key).each { y.yield _1 }
|
141
|
-
|
142
|
-
other_pages.each do |page|
|
143
|
-
uri = assemble_uri base_uri, filters.merge(page: page)
|
144
|
-
result = request uri
|
145
|
-
result.dig('data', data_key).each { y.yield _1 }
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
231
|
def request uri, retry_on_token_error = true
|
151
232
|
headers = { 'Shoptet-Access-Token' => @api_token,
|
152
233
|
'Content-Type' => 'application/vnd.shoptet.v1.0' }
|
@@ -166,6 +247,12 @@ class Shoptet
|
|
166
247
|
end
|
167
248
|
end
|
168
249
|
|
250
|
+
private
|
251
|
+
|
252
|
+
def enumerize base_url, filters = {}, data_key = nil
|
253
|
+
ApiEnumerator.new base_url, filters, data_key, self
|
254
|
+
end
|
255
|
+
|
169
256
|
def handle_errors result, uri, headers
|
170
257
|
error = result['error']
|
171
258
|
errors = result['errors'] || []
|
@@ -179,28 +266,10 @@ class Shoptet
|
|
179
266
|
elsif errors.any? { |err| err["errorCode"] == 'invalid-token-no-rights' }
|
180
267
|
raise InvalidTokenNoRights
|
181
268
|
else
|
182
|
-
|
183
|
-
uri: uri,
|
184
|
-
headers: scrub_sensitive_headers(headers)
|
185
|
-
}
|
186
|
-
|
187
|
-
raise Error.new result, additional_data
|
269
|
+
raise Error.new result
|
188
270
|
end
|
189
271
|
end
|
190
272
|
|
191
273
|
token_errors
|
192
274
|
end
|
193
|
-
|
194
|
-
def scrub_sensitive_headers headers
|
195
|
-
scrubbed = {}
|
196
|
-
|
197
|
-
to_scrub = ['Shoptet-Access-Token', 'Authorization']
|
198
|
-
to_scrub.each do |header|
|
199
|
-
if headers[header]
|
200
|
-
scrubbed[header] = "#{headers[header][0..20]}..."
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
headers.merge scrubbed
|
205
|
-
end
|
206
275
|
end
|
data/lib/shoptet/request.rb
CHANGED
@@ -3,6 +3,15 @@ require 'net/http'
|
|
3
3
|
#TODO: keep_alive_timeout ?
|
4
4
|
|
5
5
|
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
|
+
|
6
15
|
class Request
|
7
16
|
def self.get uri, headers
|
8
17
|
attempt ||= 0
|
@@ -28,5 +37,16 @@ class Shoptet
|
|
28
37
|
rescue Net::OpenTimeout
|
29
38
|
retry if attempt < 4
|
30
39
|
end
|
40
|
+
|
41
|
+
def self.post uri, body
|
42
|
+
req = Net::HTTP::Post.new uri
|
43
|
+
req.set_form_data body
|
44
|
+
|
45
|
+
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
|
46
|
+
http.request req
|
47
|
+
end
|
48
|
+
|
49
|
+
JSON.parse res.body
|
50
|
+
end
|
31
51
|
end
|
32
52
|
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.10
|
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-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: irb
|