square.rb 3.3.0.20191217
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 +7 -0
- data/LICENSE +10 -0
- data/README.md +285 -0
- data/lib/square/api/apple_pay_api.rb +50 -0
- data/lib/square/api/base_api.rb +43 -0
- data/lib/square/api/cash_drawers_api.rb +150 -0
- data/lib/square/api/catalog_api.rb +545 -0
- data/lib/square/api/checkout_api.rb +49 -0
- data/lib/square/api/customers_api.rb +327 -0
- data/lib/square/api/employees_api.rb +86 -0
- data/lib/square/api/inventory_api.rb +295 -0
- data/lib/square/api/labor_api.rb +553 -0
- data/lib/square/api/locations_api.rb +146 -0
- data/lib/square/api/merchants_api.rb +82 -0
- data/lib/square/api/mobile_authorization_api.rb +52 -0
- data/lib/square/api/o_auth_api.rb +163 -0
- data/lib/square/api/orders_api.rb +266 -0
- data/lib/square/api/payments_api.rb +277 -0
- data/lib/square/api/refunds_api.rb +144 -0
- data/lib/square/api/reporting_api.rb +138 -0
- data/lib/square/api/transactions_api.rb +377 -0
- data/lib/square/api/v1_employees_api.rb +715 -0
- data/lib/square/api/v1_items_api.rb +2046 -0
- data/lib/square/api/v1_locations_api.rb +83 -0
- data/lib/square/api/v1_transactions_api.rb +568 -0
- data/lib/square/api_helper.rb +276 -0
- data/lib/square/client.rb +156 -0
- data/lib/square/configuration.rb +93 -0
- data/lib/square/exceptions/api_exception.rb +15 -0
- data/lib/square/http/api_response.rb +45 -0
- data/lib/square/http/auth/o_auth2.rb +12 -0
- data/lib/square/http/faraday_client.rb +59 -0
- data/lib/square/http/http_call_back.rb +19 -0
- data/lib/square/http/http_client.rb +99 -0
- data/lib/square/http/http_method_enum.rb +8 -0
- data/lib/square/http/http_request.rb +45 -0
- data/lib/square/http/http_response.rb +24 -0
- data/lib/square.rb +49 -0
- data/spec/user_journey_spec.rb +145 -0
- data/test/api/api_test_base.rb +24 -0
- data/test/api/test_catalog_api.rb +59 -0
- data/test/api/test_customers_api.rb +45 -0
- data/test/api/test_employees_api.rb +36 -0
- data/test/api/test_labor_api.rb +74 -0
- data/test/api/test_locations_api.rb +35 -0
- data/test/api/test_merchants_api.rb +40 -0
- data/test/api/test_payments_api.rb +42 -0
- data/test/api/test_refunds_api.rb +41 -0
- data/test/http_response_catcher.rb +19 -0
- data/test/test_helper.rb +94 -0
- metadata +190 -0
@@ -0,0 +1,276 @@
|
|
1
|
+
module Square
|
2
|
+
# API utility class
|
3
|
+
class APIHelper
|
4
|
+
# Serializes an array parameter (creates key value pairs).
|
5
|
+
# @param [String] The name of the parameter.
|
6
|
+
# @param [Array] The value of the parameter.
|
7
|
+
# @param [String] The format of the serialization.
|
8
|
+
def self.serialize_array(key, array, formatting: 'indexed')
|
9
|
+
tuples = []
|
10
|
+
|
11
|
+
if formatting == 'unindexed'
|
12
|
+
tuples += array.map { |element| ["#{key}[]", element] }
|
13
|
+
elsif formatting == 'indexed'
|
14
|
+
tuples += array.map.with_index do |element, index|
|
15
|
+
["#{key}[#{index}]", element]
|
16
|
+
end
|
17
|
+
elsif formatting == 'plain'
|
18
|
+
tuples += array.map { |element| [key, element] }
|
19
|
+
else
|
20
|
+
raise ArgumentError, 'Invalid format provided.'
|
21
|
+
end
|
22
|
+
tuples
|
23
|
+
end
|
24
|
+
|
25
|
+
# Replaces template parameters in the given url.
|
26
|
+
# @param [String] The query string builder to replace the template
|
27
|
+
# parameters.
|
28
|
+
# @param [Hash] The parameters to replace in the url.
|
29
|
+
def self.append_url_with_template_parameters(query_builder, parameters)
|
30
|
+
# perform parameter validation
|
31
|
+
unless query_builder.instance_of? String
|
32
|
+
raise ArgumentError, 'Given value for parameter \"query_builder\" is
|
33
|
+
invalid.'
|
34
|
+
end
|
35
|
+
|
36
|
+
# Return if there are no parameters to replace.
|
37
|
+
return query_builder if parameters.nil?
|
38
|
+
|
39
|
+
# Iterate and append parameters.
|
40
|
+
parameters.each do |key, value|
|
41
|
+
replace_value = ''
|
42
|
+
|
43
|
+
if value.nil?
|
44
|
+
replace_value = ''
|
45
|
+
elsif value.instance_of? Array
|
46
|
+
value.map! { |element| CGI.escape(element.to_s) }
|
47
|
+
replace_value = value.join('/')
|
48
|
+
else
|
49
|
+
replace_value = CGI.escape(value.to_s)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Find the template parameter and replace it with its value.
|
53
|
+
query_builder = query_builder.gsub('{' + key.to_s + '}', replace_value)
|
54
|
+
end
|
55
|
+
query_builder
|
56
|
+
end
|
57
|
+
|
58
|
+
# Appends the given set of parameters to the given query string.
|
59
|
+
# @param [String] The query string builder to add the query parameters to.
|
60
|
+
# @param [Hash] The parameters to append.
|
61
|
+
# @param [String] The format of array parameter serialization.
|
62
|
+
def self.append_url_with_query_parameters(query_builder, parameters,
|
63
|
+
array_serialization: 'indexed')
|
64
|
+
# Perform parameter validation.
|
65
|
+
unless query_builder.instance_of? String
|
66
|
+
raise ArgumentError, 'Given value for parameter \"query_builder\"
|
67
|
+
is invalid.'
|
68
|
+
end
|
69
|
+
|
70
|
+
# Return if there are no parameters to replace.
|
71
|
+
return query_builder if parameters.nil?
|
72
|
+
|
73
|
+
parameters.each do |key, value|
|
74
|
+
seperator = query_builder.include?('?') ? '&' : '?'
|
75
|
+
unless value.nil?
|
76
|
+
if value.instance_of? Array
|
77
|
+
value.compact!
|
78
|
+
query_builder += if array_serialization == 'csv'
|
79
|
+
"#{seperator}#{key}=#{value.map do |element|
|
80
|
+
CGI.escape(element.to_s)
|
81
|
+
end.join(',')}"
|
82
|
+
elsif array_serialization == 'psv'
|
83
|
+
"#{seperator}#{key}=#{value.map do |element|
|
84
|
+
CGI.escape(element.to_s)
|
85
|
+
end.join('|')}"
|
86
|
+
elsif array_serialization == 'tsv'
|
87
|
+
"#{seperator}#{key}=#{value.map do |element|
|
88
|
+
CGI.escape(element.to_s)
|
89
|
+
end.join("\t")}"
|
90
|
+
else
|
91
|
+
"#{seperator}#{APIHelper.serialize_array(
|
92
|
+
key, value, formatting: array_serialization
|
93
|
+
).map { |k, v| "#{k}=#{CGI.escape(v.to_s)}" }
|
94
|
+
.join('&')}"
|
95
|
+
end
|
96
|
+
else
|
97
|
+
query_builder += "#{seperator}#{key}=#{CGI.escape(value.to_s)}"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
query_builder
|
102
|
+
end
|
103
|
+
|
104
|
+
# Validates and processes the given Url.
|
105
|
+
# @param [String] The given Url to process.
|
106
|
+
# @return [String] Pre-processed Url as string.
|
107
|
+
def self.clean_url(url)
|
108
|
+
# Perform parameter validation.
|
109
|
+
raise ArgumentError, 'Invalid Url.' unless url.instance_of? String
|
110
|
+
|
111
|
+
# Ensure that the urls are absolute.
|
112
|
+
matches = url.match(%r{^(https?:\/\/[^\/]+)})
|
113
|
+
raise ArgumentError, 'Invalid Url format.' if matches.nil?
|
114
|
+
|
115
|
+
# Get the http protocol match.
|
116
|
+
protocol = matches[1]
|
117
|
+
|
118
|
+
# Check if parameters exist.
|
119
|
+
index = url.index('?')
|
120
|
+
|
121
|
+
# Remove redundant forward slashes.
|
122
|
+
query = url[protocol.length...(!index.nil? ? index : url.length)]
|
123
|
+
query.gsub!(%r{\/\/+}, '/')
|
124
|
+
|
125
|
+
# Get the parameters.
|
126
|
+
parameters = !index.nil? ? url[url.index('?')...url.length] : ''
|
127
|
+
|
128
|
+
# Return processed url.
|
129
|
+
protocol + query + parameters
|
130
|
+
end
|
131
|
+
|
132
|
+
# Parses JSON string.
|
133
|
+
# @param [String] A JSON string.
|
134
|
+
def self.json_deserialize(json)
|
135
|
+
return JSON.parse(json, symbolize_names: true)
|
136
|
+
rescue StandardError
|
137
|
+
raise TypeError, 'Server responded with invalid JSON.'
|
138
|
+
end
|
139
|
+
|
140
|
+
# Removes elements with empty values from a hash.
|
141
|
+
# @param [Hash] The hash to clean.
|
142
|
+
def self.clean_hash(hash)
|
143
|
+
hash.delete_if { |_key, value| value.to_s.strip.empty? }
|
144
|
+
end
|
145
|
+
|
146
|
+
# Form encodes a hash of parameters.
|
147
|
+
# @param [Hash] The hash of parameters to encode.
|
148
|
+
# @return [Hash] A hash with the same parameters form encoded.
|
149
|
+
def self.form_encode_parameters(form_parameters,
|
150
|
+
array_serialization: 'indexed')
|
151
|
+
encoded = {}
|
152
|
+
form_parameters.each do |key, value|
|
153
|
+
encoded.merge!(APIHelper.form_encode(value, key, formatting:
|
154
|
+
array_serialization))
|
155
|
+
end
|
156
|
+
encoded
|
157
|
+
end
|
158
|
+
|
159
|
+
def self.custom_merge(a, b)
|
160
|
+
x = {}
|
161
|
+
a.each do |key, value_a|
|
162
|
+
b.each do |k, value_b|
|
163
|
+
next unless key == k
|
164
|
+
x[k] = []
|
165
|
+
if value_a.instance_of? Array
|
166
|
+
value_a.each do |v|
|
167
|
+
x[k].push(v)
|
168
|
+
end
|
169
|
+
else
|
170
|
+
x[k].push(value_a)
|
171
|
+
end
|
172
|
+
if value_b.instance_of? Array
|
173
|
+
value_b.each do |v|
|
174
|
+
x[k].push(v)
|
175
|
+
end
|
176
|
+
else
|
177
|
+
x[k].push(value_b)
|
178
|
+
end
|
179
|
+
a.delete(k)
|
180
|
+
b.delete(k)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
x.merge!(a)
|
184
|
+
x.merge!(b)
|
185
|
+
x
|
186
|
+
end
|
187
|
+
|
188
|
+
# Form encodes an object.
|
189
|
+
# @param [Dynamic] An object to form encode.
|
190
|
+
# @param [String] The name of the object.
|
191
|
+
# @return [Hash] A form encoded representation of the object in the form
|
192
|
+
# of a hash.
|
193
|
+
def self.form_encode(obj, instance_name, formatting: 'indexed')
|
194
|
+
retval = {}
|
195
|
+
|
196
|
+
serializable_types = [String, Numeric, TrueClass,
|
197
|
+
FalseClass, Date, DateTime]
|
198
|
+
|
199
|
+
# Create a form encoded hash for this object.
|
200
|
+
if obj.nil?
|
201
|
+
nil
|
202
|
+
elsif obj.instance_of? Array
|
203
|
+
if formatting == 'indexed'
|
204
|
+
obj.each_with_index do |value, index|
|
205
|
+
retval.merge!(APIHelper.form_encode(value, instance_name + '[' +
|
206
|
+
index.to_s + ']'))
|
207
|
+
end
|
208
|
+
elsif serializable_types.map { |x| obj[0].is_a? x }.any?
|
209
|
+
obj.each do |value|
|
210
|
+
abc = if formatting == 'unindexed'
|
211
|
+
APIHelper.form_encode(value, instance_name + '[]',
|
212
|
+
formatting: formatting)
|
213
|
+
else
|
214
|
+
APIHelper.form_encode(value, instance_name,
|
215
|
+
formatting: formatting)
|
216
|
+
end
|
217
|
+
retval = APIHelper.custom_merge(retval, abc)
|
218
|
+
end
|
219
|
+
else
|
220
|
+
obj.each_with_index do |value, index|
|
221
|
+
retval.merge!(APIHelper.form_encode(value, instance_name + '[' +
|
222
|
+
index.to_s + ']', formatting: formatting))
|
223
|
+
end
|
224
|
+
end
|
225
|
+
elsif obj.instance_of? Hash
|
226
|
+
obj.each do |key, value|
|
227
|
+
retval.merge!(APIHelper.form_encode(value, instance_name + '[' +
|
228
|
+
key.to_s + ']', formatting: formatting))
|
229
|
+
end
|
230
|
+
elsif obj.instance_of? File
|
231
|
+
retval[instance_name] = UploadIO.new(
|
232
|
+
obj, 'application/octet-stream', File.basename(obj.path)
|
233
|
+
)
|
234
|
+
else
|
235
|
+
retval[instance_name] = obj
|
236
|
+
end
|
237
|
+
retval
|
238
|
+
end
|
239
|
+
|
240
|
+
# Retrieves a field from a Hash/Array based on an Array of keys/indexes
|
241
|
+
# @param [Hash, Array] The hash to extract data from
|
242
|
+
# @param [Array<String, Integer>] The keys/indexes to use
|
243
|
+
# @return [Object] The extracted value
|
244
|
+
def self.map_response(obj, keys)
|
245
|
+
val = obj
|
246
|
+
begin
|
247
|
+
keys.each do |key|
|
248
|
+
val = if val.is_a? Array
|
249
|
+
if key.to_i.to_s == key
|
250
|
+
val[key.to_i]
|
251
|
+
else
|
252
|
+
val = nil
|
253
|
+
end
|
254
|
+
else
|
255
|
+
val.fetch(key.to_sym)
|
256
|
+
end
|
257
|
+
end
|
258
|
+
rescue NoMethodError, TypeError, IndexError
|
259
|
+
val = nil
|
260
|
+
end
|
261
|
+
val
|
262
|
+
end
|
263
|
+
|
264
|
+
# Safely converts a string into an rfc3339 DateTime object
|
265
|
+
# @param [String] The datetime string
|
266
|
+
# @return [DateTime] A DateTime object of rfc3339 format
|
267
|
+
def self.rfc3339(date_time)
|
268
|
+
# missing timezone information
|
269
|
+
if date_time.end_with?('Z') || date_time.index('+')
|
270
|
+
DateTime.rfc3339(date_time)
|
271
|
+
else
|
272
|
+
DateTime.rfc3339(date_time + 'Z')
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
module Square
|
2
|
+
# square client class.
|
3
|
+
class Client
|
4
|
+
attr_reader :config
|
5
|
+
|
6
|
+
def sdk_version
|
7
|
+
'3.3.0.20191217'
|
8
|
+
end
|
9
|
+
|
10
|
+
def square_version
|
11
|
+
'2019-12-17'
|
12
|
+
end
|
13
|
+
|
14
|
+
# Access to mobile_authorization controller.
|
15
|
+
# @return [MobileAuthorizationApi] Returns the controller instance.
|
16
|
+
def mobile_authorization
|
17
|
+
@mobile_authorization ||= MobileAuthorizationApi.new config
|
18
|
+
end
|
19
|
+
|
20
|
+
# Access to o_auth controller.
|
21
|
+
# @return [OAuthApi] Returns the controller instance.
|
22
|
+
def o_auth
|
23
|
+
@o_auth ||= OAuthApi.new config
|
24
|
+
end
|
25
|
+
|
26
|
+
# Access to v1_locations controller.
|
27
|
+
# @return [V1LocationsApi] Returns the controller instance.
|
28
|
+
def v1_locations
|
29
|
+
@v1_locations ||= V1LocationsApi.new config
|
30
|
+
end
|
31
|
+
|
32
|
+
# Access to v1_employees controller.
|
33
|
+
# @return [V1EmployeesApi] Returns the controller instance.
|
34
|
+
def v1_employees
|
35
|
+
@v1_employees ||= V1EmployeesApi.new config
|
36
|
+
end
|
37
|
+
|
38
|
+
# Access to v1_transactions controller.
|
39
|
+
# @return [V1TransactionsApi] Returns the controller instance.
|
40
|
+
def v1_transactions
|
41
|
+
@v1_transactions ||= V1TransactionsApi.new config
|
42
|
+
end
|
43
|
+
|
44
|
+
# Access to v1_items controller.
|
45
|
+
# @return [V1ItemsApi] Returns the controller instance.
|
46
|
+
def v1_items
|
47
|
+
@v1_items ||= V1ItemsApi.new config
|
48
|
+
end
|
49
|
+
|
50
|
+
# Access to apple_pay controller.
|
51
|
+
# @return [ApplePayApi] Returns the controller instance.
|
52
|
+
def apple_pay
|
53
|
+
@apple_pay ||= ApplePayApi.new config
|
54
|
+
end
|
55
|
+
|
56
|
+
# Access to cash_drawers controller.
|
57
|
+
# @return [CashDrawersApi] Returns the controller instance.
|
58
|
+
def cash_drawers
|
59
|
+
@cash_drawers ||= CashDrawersApi.new config
|
60
|
+
end
|
61
|
+
|
62
|
+
# Access to catalog controller.
|
63
|
+
# @return [CatalogApi] Returns the controller instance.
|
64
|
+
def catalog
|
65
|
+
@catalog ||= CatalogApi.new config
|
66
|
+
end
|
67
|
+
|
68
|
+
# Access to customers controller.
|
69
|
+
# @return [CustomersApi] Returns the controller instance.
|
70
|
+
def customers
|
71
|
+
@customers ||= CustomersApi.new config
|
72
|
+
end
|
73
|
+
|
74
|
+
# Access to employees controller.
|
75
|
+
# @return [EmployeesApi] Returns the controller instance.
|
76
|
+
def employees
|
77
|
+
@employees ||= EmployeesApi.new config
|
78
|
+
end
|
79
|
+
|
80
|
+
# Access to inventory controller.
|
81
|
+
# @return [InventoryApi] Returns the controller instance.
|
82
|
+
def inventory
|
83
|
+
@inventory ||= InventoryApi.new config
|
84
|
+
end
|
85
|
+
|
86
|
+
# Access to labor controller.
|
87
|
+
# @return [LaborApi] Returns the controller instance.
|
88
|
+
def labor
|
89
|
+
@labor ||= LaborApi.new config
|
90
|
+
end
|
91
|
+
|
92
|
+
# Access to locations controller.
|
93
|
+
# @return [LocationsApi] Returns the controller instance.
|
94
|
+
def locations
|
95
|
+
@locations ||= LocationsApi.new config
|
96
|
+
end
|
97
|
+
|
98
|
+
# Access to reporting controller.
|
99
|
+
# @return [ReportingApi] Returns the controller instance.
|
100
|
+
def reporting
|
101
|
+
@reporting ||= ReportingApi.new config
|
102
|
+
end
|
103
|
+
|
104
|
+
# Access to checkout controller.
|
105
|
+
# @return [CheckoutApi] Returns the controller instance.
|
106
|
+
def checkout
|
107
|
+
@checkout ||= CheckoutApi.new config
|
108
|
+
end
|
109
|
+
|
110
|
+
# Access to orders controller.
|
111
|
+
# @return [OrdersApi] Returns the controller instance.
|
112
|
+
def orders
|
113
|
+
@orders ||= OrdersApi.new config
|
114
|
+
end
|
115
|
+
|
116
|
+
# Access to transactions controller.
|
117
|
+
# @return [TransactionsApi] Returns the controller instance.
|
118
|
+
def transactions
|
119
|
+
@transactions ||= TransactionsApi.new config
|
120
|
+
end
|
121
|
+
|
122
|
+
# Access to merchants controller.
|
123
|
+
# @return [MerchantsApi] Returns the controller instance.
|
124
|
+
def merchants
|
125
|
+
@merchants ||= MerchantsApi.new config
|
126
|
+
end
|
127
|
+
|
128
|
+
# Access to payments controller.
|
129
|
+
# @return [PaymentsApi] Returns the controller instance.
|
130
|
+
def payments
|
131
|
+
@payments ||= PaymentsApi.new config
|
132
|
+
end
|
133
|
+
|
134
|
+
# Access to refunds controller.
|
135
|
+
# @return [RefundsApi] Returns the controller instance.
|
136
|
+
def refunds
|
137
|
+
@refunds ||= RefundsApi.new config
|
138
|
+
end
|
139
|
+
|
140
|
+
def initialize(timeout: 60, max_retries: 0, retry_interval: 1,
|
141
|
+
backoff_factor: 1, environment: 'production',
|
142
|
+
access_token: 'TODO: Replace', additional_headers: {},
|
143
|
+
config: nil)
|
144
|
+
@config = if config.nil?
|
145
|
+
Configuration.new(timeout: timeout, max_retries: max_retries,
|
146
|
+
retry_interval: retry_interval,
|
147
|
+
backoff_factor: backoff_factor,
|
148
|
+
environment: environment,
|
149
|
+
access_token: access_token,
|
150
|
+
additional_headers: additional_headers)
|
151
|
+
else
|
152
|
+
config
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module Square
|
2
|
+
# All configuration including auth info and base URI for the API access
|
3
|
+
# are configured in this class.
|
4
|
+
class Configuration
|
5
|
+
# The attribute readers for properties.
|
6
|
+
attr_reader :http_client
|
7
|
+
attr_reader :timeout
|
8
|
+
attr_reader :max_retries
|
9
|
+
attr_reader :retry_interval
|
10
|
+
attr_reader :backoff_factor
|
11
|
+
attr_reader :environment
|
12
|
+
attr_reader :access_token
|
13
|
+
|
14
|
+
def additional_headers
|
15
|
+
@additional_headers.clone
|
16
|
+
end
|
17
|
+
|
18
|
+
class << self
|
19
|
+
attr_reader :environments
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(timeout: 60, max_retries: 0, retry_interval: 1,
|
23
|
+
backoff_factor: 1, environment: 'production',
|
24
|
+
access_token: 'TODO: Replace', additional_headers: {})
|
25
|
+
# The value to use for connection timeout
|
26
|
+
@timeout = timeout
|
27
|
+
|
28
|
+
# The number of times to retry an endpoint call if it fails
|
29
|
+
@max_retries = max_retries
|
30
|
+
|
31
|
+
# Pause in seconds between retries
|
32
|
+
@retry_interval = retry_interval
|
33
|
+
|
34
|
+
# The amount to multiply each successive retry's interval amount
|
35
|
+
# by in order to provide backoff
|
36
|
+
@backoff_factor = backoff_factor
|
37
|
+
|
38
|
+
# Current API environment
|
39
|
+
@environment = environment
|
40
|
+
|
41
|
+
# OAuth 2.0 Access Token
|
42
|
+
@access_token = access_token
|
43
|
+
|
44
|
+
# Additional headers to add to each API request
|
45
|
+
@additional_headers = additional_headers.clone
|
46
|
+
|
47
|
+
# The Http Client to use for making requests.
|
48
|
+
@http_client = create_http_client
|
49
|
+
end
|
50
|
+
|
51
|
+
def clone_with(timeout: nil, max_retries: nil, retry_interval: nil,
|
52
|
+
backoff_factor: nil, environment: nil, access_token: nil,
|
53
|
+
additional_headers: nil)
|
54
|
+
timeout ||= self.timeout
|
55
|
+
max_retries ||= self.max_retries
|
56
|
+
retry_interval ||= self.retry_interval
|
57
|
+
backoff_factor ||= self.backoff_factor
|
58
|
+
environment ||= self.environment
|
59
|
+
access_token ||= self.access_token
|
60
|
+
additional_headers ||= self.additional_headers
|
61
|
+
|
62
|
+
Configuration.new(timeout: timeout, max_retries: max_retries,
|
63
|
+
retry_interval: retry_interval,
|
64
|
+
backoff_factor: backoff_factor,
|
65
|
+
environment: environment, access_token: access_token,
|
66
|
+
additional_headers: additional_headers)
|
67
|
+
end
|
68
|
+
|
69
|
+
def create_http_client
|
70
|
+
FaradayClient.new(timeout: timeout, max_retries: max_retries,
|
71
|
+
retry_interval: retry_interval,
|
72
|
+
backoff_factor: backoff_factor)
|
73
|
+
end
|
74
|
+
|
75
|
+
# All the environments the SDK can run in.
|
76
|
+
@environments = {
|
77
|
+
'production' => {
|
78
|
+
'default' => 'https://connect.squareup.com'
|
79
|
+
},
|
80
|
+
'sandbox' => {
|
81
|
+
'default' => 'https://connect.squareupsandbox.com'
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
# Generates the appropriate base URI for the environment and the server.
|
86
|
+
# @param [Configuration::Server] The server enum for which the base URI is
|
87
|
+
# required.
|
88
|
+
# @return [String] The base URI.
|
89
|
+
def get_base_uri(server = 'default')
|
90
|
+
self.class.environments[environment][server].clone
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Square
|
2
|
+
# Class for exceptions when there is a network error, status code error, etc.
|
3
|
+
class APIException < StandardError
|
4
|
+
attr_reader :response, :response_code
|
5
|
+
|
6
|
+
# The constructor.
|
7
|
+
# @param [String] The reason for raising an exception.
|
8
|
+
# @param [HttpResponse] The HttpReponse of the API call.
|
9
|
+
def initialize(reason, response)
|
10
|
+
super(reason)
|
11
|
+
@response = response
|
12
|
+
@response_code = response.status_code
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Square
|
2
|
+
# Http response received.
|
3
|
+
class ApiResponse
|
4
|
+
attr_reader(:status_code, :reason_phrase, :headers, :raw_body, :request,
|
5
|
+
:data, :errors, :body, :cursor)
|
6
|
+
|
7
|
+
# The constructor
|
8
|
+
# @param [HttpResponse] The original, raw response from the api.
|
9
|
+
# @param [Object] The data field specified for the response.
|
10
|
+
# @param [Array<String>] Any errors returned by the server.
|
11
|
+
def initialize(http_response,
|
12
|
+
data: nil,
|
13
|
+
errors: nil)
|
14
|
+
@status_code = http_response.status_code
|
15
|
+
@reason_phrase = http_response.reason_phrase
|
16
|
+
@headers = http_response.headers
|
17
|
+
@raw_body = http_response.raw_body
|
18
|
+
@request = http_response.request
|
19
|
+
@errors = errors
|
20
|
+
|
21
|
+
if data.is_a? Hash
|
22
|
+
if data.keys.any?
|
23
|
+
@body = Struct.new(*data.keys) do
|
24
|
+
define_method(:to_s) { http_response.raw_body }
|
25
|
+
end.new(*data.values)
|
26
|
+
|
27
|
+
@cursor = data.fetch(:cursor, nil)
|
28
|
+
data.reject! { |k| k == :cursor || k == :errors }
|
29
|
+
@data = Struct.new(*data.keys).new(*data.values) if data.keys.any?
|
30
|
+
end
|
31
|
+
else
|
32
|
+
@data = data
|
33
|
+
@body = data
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def success?
|
38
|
+
status_code >= 200 && status_code < 300
|
39
|
+
end
|
40
|
+
|
41
|
+
def error?
|
42
|
+
status_code >= 400 && status_code < 600
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Square
|
2
|
+
# Utility class for OAuth 2 authorization and token management.
|
3
|
+
class OAuth2
|
4
|
+
# Add OAuth2 authentication to the http request.
|
5
|
+
# @param [HttpRequest] The HttpRequest object to which authentication will
|
6
|
+
# be added.
|
7
|
+
def self.apply(config, http_request)
|
8
|
+
token = config.access_token
|
9
|
+
http_request.headers['Authorization'] = "Bearer #{token}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'faraday/http_cache'
|
2
|
+
require 'faraday_middleware'
|
3
|
+
|
4
|
+
module Square
|
5
|
+
# An implementation of HttpClient.
|
6
|
+
class FaradayClient < HttpClient
|
7
|
+
# The constructor.
|
8
|
+
def initialize(timeout:, max_retries:, retry_interval:,
|
9
|
+
backoff_factor:, cache: false, verify: true)
|
10
|
+
@connection = Faraday.new do |faraday|
|
11
|
+
faraday.use Faraday::HttpCache, serializer: Marshal if cache
|
12
|
+
faraday.use FaradayMiddleware::FollowRedirects
|
13
|
+
faraday.request :multipart
|
14
|
+
faraday.request :url_encoded
|
15
|
+
faraday.ssl[:ca_file] = Certifi.where
|
16
|
+
faraday.ssl[:verify] = verify
|
17
|
+
faraday.request :retry, max: max_retries, interval: retry_interval,
|
18
|
+
backoff_factor: backoff_factor
|
19
|
+
faraday.adapter Faraday.default_adapter
|
20
|
+
faraday.options[:params_encoder] = Faraday::FlatParamsEncoder
|
21
|
+
faraday.options[:timeout] = timeout if timeout > 0
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Method overridden from HttpClient.
|
26
|
+
def execute_as_string(http_request)
|
27
|
+
response = @connection.send(
|
28
|
+
http_request.http_method.downcase,
|
29
|
+
http_request.query_url
|
30
|
+
) do |request|
|
31
|
+
request.headers = http_request.headers
|
32
|
+
unless http_request.parameters.empty?
|
33
|
+
request.body = http_request.parameters
|
34
|
+
end
|
35
|
+
end
|
36
|
+
convert_response(response, http_request)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Method overridden from HttpClient.
|
40
|
+
def execute_as_binary(http_request)
|
41
|
+
response = @connection.send(
|
42
|
+
http_request.http_method.downcase,
|
43
|
+
http_request.query_url
|
44
|
+
) do |request|
|
45
|
+
request.headers = http_request.headers
|
46
|
+
unless http_request.parameters.empty?
|
47
|
+
request.body = http_request.parameters
|
48
|
+
end
|
49
|
+
end
|
50
|
+
convert_response(response, http_request)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Method overridden from HttpClient.
|
54
|
+
def convert_response(response, http_request)
|
55
|
+
HttpResponse.new(response.status, response.reason_phrase,
|
56
|
+
response.headers, response.body, http_request)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Square
|
2
|
+
# HttpCallBack allows defining callables for pre and post API calls.
|
3
|
+
class HttpCallBack
|
4
|
+
# A controller will call this method before making an HTTP Request.
|
5
|
+
# @param [HttpRequest] The HttpRequest object which the HttpClient
|
6
|
+
# will execute.
|
7
|
+
def on_before_request(_http_request)
|
8
|
+
raise NotImplementedError, 'This method needs
|
9
|
+
to be implemented in a child class.'
|
10
|
+
end
|
11
|
+
|
12
|
+
# A controller will call this method after making an HTTP Request.
|
13
|
+
# @param [HttpResponse] The HttpReponse of the API call.
|
14
|
+
def on_after_response(_http_response)
|
15
|
+
raise NotImplementedError, 'This method needs
|
16
|
+
to be implemented in a child class.'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|