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.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -3
  3. data/lib/shoptet.rb +133 -64
  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: 8f8ef4e3ca1fad89c2736773c9ed8d85d579c0f065a87f77f78f19010f4626c6
4
- data.tar.gz: aad9e4adc1d9c73126f97638c90897cf067e3db8b129bcad13631f1a9b81eaad
3
+ metadata.gz: 419d01d58f819a79e524940a21eb8cca44fca53cc77257acd87f6a0e0f699bb6
4
+ data.tar.gz: 0366bbceb70df4b75ccef62ed9ac853b5fd1e5d56b81833ee5c1a87ee99f6208
5
5
  SHA512:
6
- metadata.gz: a4ad0b4003782abde395644bc8a981b72a69a43c84676bae4bbf4bef09fec1161d194cdd2e6e6df72bb711fe28c0ac4c1612619945542308428144e945b6ed77
7
- data.tar.gz: 9b085d8e2a808cb4ef80c7f27b89c6d9b801abfa715d9586c86df0f8138115592b7c0270a614d1b35482d8d596d7cc37e6d01d73f00ca73406fd817703cf9aff
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://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,15 +1,10 @@
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
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.5'
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(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
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
- #TODO: return ['data'] already
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
- request 'https://api.myshoptet.com/api/eshop'
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
- request 'https://api.myshoptet.com/api/eshop/design'
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 warehouses api_params = {}
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('data', 'order')
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.dig('data')
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
- additional_data = {
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
@@ -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.5
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-09 00:00:00.000000000 Z
11
+ date: 2020-11-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: irb