shoptet 0.0.3 → 0.0.8

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.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -3
  3. data/lib/shoptet.rb +127 -62
  4. data/lib/shoptet/request.rb +20 -0
  5. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 682cc8f11ec548207514c501fb63e2c18ea8f9cb3a7ff4eb6db35b458b75b022
4
- data.tar.gz: ec70519cd497dd8a49e9c72ee1940ec084fa0a2203889de3292febb658885c1a
3
+ metadata.gz: 020dcc94bd92d287243ac40e3bf854a9f0e5f4c32670fe221aa7af1a6b785e39
4
+ data.tar.gz: 5d3701df86ba602c16e626b7f703b01c733ef6878a3cfa862217c17cad19890e
5
5
  SHA512:
6
- metadata.gz: 2ce582d9fdbac257cffd92e2b9cb60ac718141af95a2a744ad27605c35c883bbd82f9838deb9b1fde57802a37740f49309ac034b541b19ad2557e41b09ca0bbc
7
- data.tar.gz: 0bc005b177781df29dd9c7b0471d317ed108529b717455bd70a88bbb3ccbdc8b303bbd1ff21e9c2e7cb834a969876de547eecd86d17cddf32a80cfa473fe297a
6
+ metadata.gz: b060e7a30c1cd96da7f7978231f40648b6a738154a33b0c6b5d8be538edd7e0f2dbfaa29490a16e979337244e9bd432b69e2a0cb3cc604a36d4354ba6c20e3a1
7
+ data.tar.gz: '0599e14ba6550168b2b02b31a8b25cb1452d244e27acb358d7a858473033c6992e0dec4a4cf28cf04d46d6c83c82ee4e06d54a0d00e7a2dc1e4afdda06827cb1'
data/README.md CHANGED
@@ -1,8 +1,6 @@
1
1
  # Shoptet
2
2
 
3
- This is Ruby API wrapper for [Shoptet API](https://developers.shoptet.com/) which provides access to e-shop data for addon developers.
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
 
@@ -1,24 +1,72 @@
1
+ require 'delegate'
1
2
  require_relative 'shoptet/request'
2
3
 
3
4
  class Shoptet
4
- class Error < StandardError
5
- #TODO: check that this works
6
- attr_reader :additional_data
5
+ include Shoptet::UrlHelpers
7
6
 
8
- def initialize message, additional_data = {}
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
10
+ class InvalidTokenNoRights < StandardError; end
15
11
 
16
12
  DEFAULT_ON_TOKEN_ERROR = -> (api) do
17
13
  api.api_token = api.new_api_token
18
14
  end
19
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
+
20
68
  def self.version
21
- '0.0.3'
69
+ '0.0.8'
22
70
  end
23
71
 
24
72
  def self.ar_on_token_error(model)
@@ -38,20 +86,71 @@ class Shoptet
38
86
  end
39
87
  end
40
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
+
41
119
  attr_accessor :api_token
42
120
 
43
- def initialize(oauth_url, oauth_token, api_token = nil, on_token_error = nil)
121
+ def initialize oauth_url:, oauth_token:, shop_url:, client_id:, api_token: nil, on_token_error: nil
44
122
  @oauth_url = oauth_url
45
123
  @oauth_token = oauth_token
124
+ @shop_url = shop_url
125
+ @client_id = client_id
46
126
  @api_token = api_token
47
127
  @on_token_error = on_token_error || DEFAULT_ON_TOKEN_ERROR
48
128
  end
49
129
 
130
+ def authorize_url redirect_url, state
131
+ query = {
132
+ client_id: @client_id,
133
+ state: state,
134
+ scope: 'basic_eshop',
135
+ response_type: 'code',
136
+ redirect_uri: redirect_url
137
+ }.to_query
138
+
139
+ URI("#{@shop_url}action/OAuthServer/authorize?#{query}").to_s
140
+ end
141
+
50
142
  def shop_info api_params = {}
51
- request 'https://api.myshoptet.com/api/eshop'
143
+ result = request 'https://api.myshoptet.com/api/eshop'
144
+ result['data']
145
+ end
146
+
147
+ def design_info api_params = {}
148
+ result = request 'https://api.myshoptet.com/api/eshop/design'
149
+
150
+ result['data']
52
151
  end
53
152
 
54
- def warehouses api_params = {}
153
+ def stocks api_params = {}
55
154
  enumerize 'https://api.myshoptet.com/api/stocks', api_params
56
155
  end
57
156
 
@@ -64,6 +163,11 @@ class Shoptet
64
163
  enumerize uri, api_params
65
164
  end
66
165
 
166
+ def stocks_movements warehouse_id, api_params = {}
167
+ uri = "https://api.myshoptet.com/api/stocks/#{warehouse_id}/movements"
168
+ enumerize uri, api_params
169
+ end
170
+
67
171
  def product_categories api_params = {}
68
172
  enumerize 'https://api.myshoptet.com/api/categories', api_params
69
173
  end
@@ -94,13 +198,13 @@ class Shoptet
94
198
  def order code, api_params = {}
95
199
  uri = "https://api.myshoptet.com/api/orders/#{code}"
96
200
  result = request assemble_uri(uri, api_params)
97
- result.dig('data', 'order').merge(detail_url: uri)
201
+ result.dig 'data', 'order'
98
202
  end
99
203
 
100
204
  def product guid, api_params = {}
101
205
  uri = "https://api.myshoptet.com/api/products/#{guid}"
102
206
  result = request assemble_uri(uri, api_params)
103
- result.dig('data')
207
+ result['data']
104
208
  end
105
209
 
106
210
  def new_api_token
@@ -112,35 +216,6 @@ class Shoptet
112
216
  result.fetch 'access_token'
113
217
  end
114
218
 
115
- private
116
-
117
- def assemble_uri base, params = {}
118
- u = URI(base)
119
- u.query = URI.encode_www_form(params) if params.any?
120
-
121
- u.to_s
122
- end
123
-
124
- def enumerize base_uri, filters = {}, data_key = nil
125
- data_key ||= URI(base_uri).path.split('/').last
126
- uri = assemble_uri base_uri, filters
127
- size_proc = -> () { request(uri)['data']['paginator']['totalCount'] }
128
-
129
- Enumerator.new(size_proc) do |y|
130
- first_page = request uri
131
- total_pages = first_page.dig('data', 'paginator', 'pageCount') || 0
132
- other_pages = 2..total_pages
133
-
134
- first_page.dig('data', data_key).each { y.yield _1.merge(page_url: uri) }
135
-
136
- other_pages.each do |page|
137
- uri = assemble_uri base_uri, filters.merge(page: page)
138
- result = request uri
139
- result.dig('data', data_key).each { y.yield _1.merge(page_url: uri) }
140
- end
141
- end
142
- end
143
-
144
219
  def request uri, retry_on_token_error = true
145
220
  headers = { 'Shoptet-Access-Token' => @api_token,
146
221
  'Content-Type' => 'application/vnd.shoptet.v1.0' }
@@ -160,6 +235,12 @@ class Shoptet
160
235
  end
161
236
  end
162
237
 
238
+ private
239
+
240
+ def enumerize base_url, filters = {}, data_key = nil
241
+ ApiEnumerator.new base_url, filters, data_key, self
242
+ end
243
+
163
244
  def handle_errors result, uri, headers
164
245
  error = result['error']
165
246
  errors = result['errors'] || []
@@ -170,29 +251,13 @@ class Shoptet
170
251
  raise AddonSuspended
171
252
  elsif error == 'addon_not_installed'
172
253
  raise AddonNotInstalled
254
+ elsif errors.any? { |err| err["errorCode"] == 'invalid-token-no-rights' }
255
+ raise InvalidTokenNoRights
173
256
  else
174
- additional_data = {
175
- uri: uri,
176
- headers: scrub_sensitive_headers(headers)
177
- }
178
-
179
- raise Error.new result, additional_data
257
+ raise Error.new result
180
258
  end
181
259
  end
182
260
 
183
261
  token_errors
184
262
  end
185
-
186
- def scrub_sensitive_headers headers
187
- scrubbed = {}
188
-
189
- to_scrub = ['Shoptet-Access-Token', 'Authorization']
190
- to_scrub.each do |header|
191
- if headers[header]
192
- scrubbed[header] = "#{headers[header][0..20]}..."
193
- end
194
- end
195
-
196
- headers.merge scrubbed
197
- end
198
263
  end
@@ -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.3
4
+ version: 0.0.8
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-08 00:00:00.000000000 Z
11
+ date: 2020-11-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: irb