fintecture 0.1.9 → 0.2.1
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/.gitignore +19 -16
- data/.rspec +3 -3
- data/.travis.yml +7 -7
- data/CODE_OF_CONDUCT.md +74 -74
- data/Gemfile +5 -5
- data/Gemfile.lock +59 -40
- data/LICENSE.txt +674 -674
- data/README.md +238 -152
- data/Rakefile +6 -6
- data/bin/console +14 -14
- data/bin/setup +8 -8
- data/fintecture.gemspec +43 -43
- data/lib/fintecture/api/base_url.rb +28 -27
- data/lib/fintecture/api/endpoints/authentication.rb +12 -12
- data/lib/fintecture/api/endpoints/pis.rb +13 -12
- data/lib/fintecture/authentication.rb +75 -75
- data/lib/fintecture/connect.rb +37 -219
- data/lib/fintecture/exceptions.rb +32 -3
- data/lib/fintecture/faraday/authentication/connection.rb +120 -74
- data/lib/fintecture/pis.rb +261 -60
- data/lib/fintecture/utils/constants.rb +13 -13
- data/lib/fintecture/utils/crypto.rb +77 -75
- data/lib/fintecture/utils/date.rb +14 -14
- data/lib/fintecture/utils/validation.rb +25 -25
- data/lib/fintecture/version.rb +3 -3
- data/lib/fintecture.rb +81 -81
- metadata +6 -6
@@ -1,13 +1,14 @@
|
|
1
|
-
module Fintecture
|
2
|
-
module Api
|
3
|
-
module Endpoints
|
4
|
-
module Pis
|
5
|
-
PIS = 'pis/
|
6
|
-
PISPROVIDER = "#{PIS}/provider"
|
7
|
-
PISCUSTOMER = "#{PIS}/customer"
|
8
|
-
|
9
|
-
PAYMENTS = "#{PIS}/payments"
|
10
|
-
|
11
|
-
|
12
|
-
|
1
|
+
module Fintecture
|
2
|
+
module Api
|
3
|
+
module Endpoints
|
4
|
+
module Pis
|
5
|
+
PIS = 'pis/v2'
|
6
|
+
PISPROVIDER = "#{PIS}/provider"
|
7
|
+
PISCUSTOMER = "#{PIS}/customer"
|
8
|
+
REQUEST_TO_PAY = "#{PIS}/request-to-pay"
|
9
|
+
PAYMENTS = "#{PIS}/payments"
|
10
|
+
CONNECT = "#{PIS}/connect"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
13
14
|
end
|
@@ -1,76 +1,76 @@
|
|
1
|
-
require 'json'
|
2
|
-
require 'faraday'
|
3
|
-
|
4
|
-
module Fintecture
|
5
|
-
class Authentication
|
6
|
-
class << self
|
7
|
-
|
8
|
-
def authorize(redirect_uri, state = nil)
|
9
|
-
query_string = "?#{{
|
10
|
-
response_type: 'code',
|
11
|
-
app_id: Fintecture.app_id,
|
12
|
-
redirect_uri: redirect_uri,
|
13
|
-
state: state
|
14
|
-
}.map{|key, value| "#{key}=#{value}"}.join('&')}"
|
15
|
-
|
16
|
-
::Faraday.get "#{token_authorize_endpoint}#{query_string}"
|
17
|
-
end
|
18
|
-
|
19
|
-
def get_access_token(auth_code = nil)
|
20
|
-
body = access_token_data auth_code
|
21
|
-
|
22
|
-
Fintecture::Faraday::Authentication::Connection.post url: access_token_url, req_body: body
|
23
|
-
end
|
24
|
-
|
25
|
-
def refresh_token(refresh_token)
|
26
|
-
body = refresh_token_data refresh_token
|
27
|
-
|
28
|
-
Fintecture::Faraday::Authentication::Connection.post url: refresh_token_url, req_body: body
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
def base_url
|
34
|
-
Fintecture::Api::BaseUrl::FINTECTURE_OAUTH_URL[Fintecture.environment.to_sym]
|
35
|
-
end
|
36
|
-
|
37
|
-
def token_authorize_endpoint
|
38
|
-
"#{base_url}#{Fintecture::Api::Endpoints::Authentication::OAUTH_TOKEN_AUTHORIZE}"
|
39
|
-
end
|
40
|
-
|
41
|
-
def access_token_url
|
42
|
-
"#{base_url}#{Fintecture::Api::Endpoints::Authentication::OAUTH_ACCESS_TOKEN}"
|
43
|
-
end
|
44
|
-
|
45
|
-
def refresh_token_url
|
46
|
-
"#{base_url}#{Fintecture::Api::Endpoints::Authentication::OAUTH_REFRESH_TOKEN}"
|
47
|
-
end
|
48
|
-
|
49
|
-
def access_token_data(auth_code)
|
50
|
-
data = {
|
51
|
-
scope: 'PIS',
|
52
|
-
app_id: Fintecture.app_id,
|
53
|
-
grant_type: 'client_credentials'
|
54
|
-
}
|
55
|
-
|
56
|
-
if auth_code
|
57
|
-
data = {
|
58
|
-
scope: 'AIS',
|
59
|
-
code: auth_code,
|
60
|
-
grant_type: 'authorization_code'
|
61
|
-
}
|
62
|
-
end
|
63
|
-
|
64
|
-
data
|
65
|
-
end
|
66
|
-
|
67
|
-
def refresh_token_data(refresh_token)
|
68
|
-
{
|
69
|
-
grant_type: 'refresh_token',
|
70
|
-
refresh_token: refresh_token
|
71
|
-
}
|
72
|
-
end
|
73
|
-
|
74
|
-
end
|
75
|
-
end
|
1
|
+
require 'json'
|
2
|
+
require 'faraday'
|
3
|
+
|
4
|
+
module Fintecture
|
5
|
+
class Authentication
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def authorize(redirect_uri, state = nil)
|
9
|
+
query_string = "?#{{
|
10
|
+
response_type: 'code',
|
11
|
+
app_id: Fintecture.app_id,
|
12
|
+
redirect_uri: redirect_uri,
|
13
|
+
state: state
|
14
|
+
}.map{|key, value| "#{key}=#{value}"}.join('&')}"
|
15
|
+
|
16
|
+
::Faraday.get "#{token_authorize_endpoint}#{query_string}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_access_token(auth_code = nil)
|
20
|
+
body = access_token_data auth_code
|
21
|
+
|
22
|
+
Fintecture::Faraday::Authentication::Connection.post url: access_token_url, req_body: body
|
23
|
+
end
|
24
|
+
|
25
|
+
def refresh_token(refresh_token)
|
26
|
+
body = refresh_token_data refresh_token
|
27
|
+
|
28
|
+
Fintecture::Faraday::Authentication::Connection.post url: refresh_token_url, req_body: body
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def base_url
|
34
|
+
Fintecture::Api::BaseUrl::FINTECTURE_OAUTH_URL[Fintecture.environment.to_sym]
|
35
|
+
end
|
36
|
+
|
37
|
+
def token_authorize_endpoint
|
38
|
+
"#{base_url}#{Fintecture::Api::Endpoints::Authentication::OAUTH_TOKEN_AUTHORIZE}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def access_token_url
|
42
|
+
"#{base_url}#{Fintecture::Api::Endpoints::Authentication::OAUTH_ACCESS_TOKEN}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def refresh_token_url
|
46
|
+
"#{base_url}#{Fintecture::Api::Endpoints::Authentication::OAUTH_REFRESH_TOKEN}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def access_token_data(auth_code)
|
50
|
+
data = {
|
51
|
+
scope: 'PIS',
|
52
|
+
app_id: Fintecture.app_id,
|
53
|
+
grant_type: 'client_credentials'
|
54
|
+
}
|
55
|
+
|
56
|
+
if auth_code
|
57
|
+
data = {
|
58
|
+
scope: 'AIS',
|
59
|
+
code: auth_code,
|
60
|
+
grant_type: 'authorization_code'
|
61
|
+
}
|
62
|
+
end
|
63
|
+
|
64
|
+
data
|
65
|
+
end
|
66
|
+
|
67
|
+
def refresh_token_data(refresh_token)
|
68
|
+
{
|
69
|
+
grant_type: 'refresh_token',
|
70
|
+
refresh_token: refresh_token
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
76
|
end
|
data/lib/fintecture/connect.rb
CHANGED
@@ -1,220 +1,38 @@
|
|
1
|
-
require 'base64'
|
2
|
-
require 'json'
|
3
|
-
require 'faraday'
|
4
|
-
require 'fintecture/pis'
|
5
|
-
require 'fintecture/utils/validation'
|
6
|
-
require 'fintecture/exceptions'
|
7
|
-
require 'fintecture/utils/date'
|
8
|
-
require 'fintecture/utils/constants'
|
9
|
-
|
10
|
-
module Fintecture
|
11
|
-
class Connect
|
12
|
-
class << self
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
def verify_url_parameters(parameters = nil)
|
39
|
-
@post_payment_attrs = as_json parameters
|
40
|
-
|
41
|
-
validate_post_payment_integrity
|
42
|
-
|
43
|
-
decrypted = Fintecture::Utils::Crypto.decrypt_private @post_payment_attrs['s']
|
44
|
-
local_digest = build_local_digest @post_payment_attrs
|
45
|
-
|
46
|
-
decrypted == local_digest
|
47
|
-
end
|
48
|
-
|
49
|
-
private
|
50
|
-
|
51
|
-
def build_url(config)
|
52
|
-
"#{base_url}/#{@type}/#{@payment_attrs['psu_type']}/#{@payment_attrs['country']}?config=#{Base64.strict_encode64(config)}"
|
53
|
-
end
|
54
|
-
|
55
|
-
def validate_payment_integrity
|
56
|
-
Fintecture::Utils::Validation.raise_if_klass_mismatch @payment_attrs, Hash, 'payment_attrs'
|
57
|
-
|
58
|
-
raise Fintecture::ValidationException.new("access_token is a mandatory field") if @access_token.nil?
|
59
|
-
|
60
|
-
@payment_attrs['psu_type'] = 'retail' unless @payment_attrs['psu_type']
|
61
|
-
@payment_attrs['country'] = 'all' unless @payment_attrs['country']
|
62
|
-
|
63
|
-
error_msg = 'invalid payment payload parameter'
|
64
|
-
|
65
|
-
raise Fintecture::ValidationException.new("#{error_msg} type") unless Fintecture::Utils::Constants::SCOPES.include? @type
|
66
|
-
raise Fintecture::ValidationException.new("#{@payment_attrs['psu_type']} PSU type not allowed") unless Fintecture::Utils::Constants::PSU_TYPES.include? @payment_attrs['psu_type']
|
67
|
-
|
68
|
-
raise Fintecture::ValidationException.new('end_to_end_id must be an alphanumeric string') if(@payment_attrs['end_to_end_id'] && !@payment_attrs['end_to_end_id'].match(/^[0-9a-zA-Z]*$/))
|
69
|
-
Fintecture::Utils::Validation.raise_if_invalid_date_format(@payment_attrs['execution_date']) if(@payment_attrs['execution_date'])
|
70
|
-
|
71
|
-
%w[amount currency customer_full_name customer_email customer_ip redirect_uri].each do |param|
|
72
|
-
raise Fintecture::ValidationException.new("#{param} is a mandatory field") if @payment_attrs[param].nil?
|
73
|
-
end
|
74
|
-
|
75
|
-
# Check if string
|
76
|
-
%w[communication redirect_uri provider customer_phone].each do |param|
|
77
|
-
Fintecture::Utils::Validation.raise_if_klass_mismatch(@payment_attrs[param], String, param) if(@payment_attrs[param])
|
78
|
-
end
|
79
|
-
|
80
|
-
# Check customer_address structure
|
81
|
-
Fintecture::Utils::Validation.raise_if_klass_mismatch(@payment_attrs['customer_address'], Hash) if(@payment_attrs['customer_address'])
|
82
|
-
|
83
|
-
raise Fintecture::ValidationException.new('customer_address country must be a 2 letters string') if(@payment_attrs['customer_address'] && @payment_attrs['customer_address']['country'] && !@payment_attrs['customer_address']['country'].match(/^[a-zA-Z]{2}$/))
|
84
|
-
|
85
|
-
%w[street number complement zip city country].each do |param|
|
86
|
-
Fintecture::Utils::Validation.raise_if_klass_mismatch(@payment_attrs['customer_address'][param], String, param) if(@payment_attrs['customer_address'] && @payment_attrs['customer_address'][param])
|
87
|
-
end
|
88
|
-
|
89
|
-
# Check beneficiary structure
|
90
|
-
|
91
|
-
Fintecture::Utils::Validation.raise_if_klass_mismatch(@payment_attrs['beneficiary'], Hash) if(@payment_attrs['beneficiary'])
|
92
|
-
|
93
|
-
%w[name street city iban swift_bic].each do |param|
|
94
|
-
raise Fintecture::ValidationException.new("beneficiary #{param} is a mandatory field") if @payment_attrs['beneficiary'] && @payment_attrs['beneficiary'][param].nil?
|
95
|
-
end
|
96
|
-
|
97
|
-
raise Fintecture::ValidationException.new('beneficiary country must be a 2 letters string') if(@payment_attrs['beneficiary'] && @payment_attrs['beneficiary']['country'] && !@payment_attrs['beneficiary']['country'].match(/^[a-zA-Z]{2}$/))
|
98
|
-
|
99
|
-
%w[name street number complement zip city country iban swift_bic bank_name].each do |param|
|
100
|
-
Fintecture::Utils::Validation.raise_if_klass_mismatch(@payment_attrs['beneficiary'][param], String, param) if(@payment_attrs['beneficiary'] && @payment_attrs['beneficiary'][param])
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
def validate_post_payment_integrity
|
105
|
-
Fintecture::Utils::Validation.raise_if_klass_mismatch @post_payment_attrs, Hash, 'post_payment_attrs'
|
106
|
-
|
107
|
-
%w[s state status session_id customer_id provider].each do |param|
|
108
|
-
raise Fintecture::ValidationException.new("invalid post payment parameter #{param}") if @post_payment_attrs[param].nil?
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
def build_payload
|
113
|
-
attributes = {
|
114
|
-
amount: @payment_attrs['amount'],
|
115
|
-
currency: @payment_attrs['currency'],
|
116
|
-
communication: @payment_attrs['communication'],
|
117
|
-
end_to_end_id: @payment_attrs['end_to_end_id'],
|
118
|
-
execution_date: @payment_attrs['execution_date'],
|
119
|
-
provider: @payment_attrs['provider']
|
120
|
-
}
|
121
|
-
|
122
|
-
if @payment_attrs['beneficiary']
|
123
|
-
attributes['beneficiary'] = {
|
124
|
-
name: @payment_attrs['beneficiary']['name'],
|
125
|
-
street: @payment_attrs['beneficiary']['street'],
|
126
|
-
number: @payment_attrs['beneficiary']['number'],
|
127
|
-
complement: @payment_attrs['beneficiary']['complement'],
|
128
|
-
zip: @payment_attrs['beneficiary']['zip'],
|
129
|
-
city: @payment_attrs['beneficiary']['city'],
|
130
|
-
country: @payment_attrs['beneficiary']['country'],
|
131
|
-
iban: @payment_attrs['beneficiary']['iban'],
|
132
|
-
swift_bic: @payment_attrs['beneficiary']['swift_bic'],
|
133
|
-
bank_name: @payment_attrs['beneficiary']['bank_name']
|
134
|
-
}
|
135
|
-
end
|
136
|
-
|
137
|
-
meta = {
|
138
|
-
psu_name: @payment_attrs['customer_full_name'],
|
139
|
-
psu_email: @payment_attrs['customer_email'],
|
140
|
-
psu_ip: @payment_attrs['customer_ip'],
|
141
|
-
psu_phone: @payment_attrs['customer_phone'],
|
142
|
-
psu_address: @payment_attrs['customer_address']
|
143
|
-
}
|
144
|
-
|
145
|
-
data = {
|
146
|
-
type: 'PAYMENT',
|
147
|
-
attributes: attributes,
|
148
|
-
}
|
149
|
-
|
150
|
-
prepare_payment_response = Fintecture::Pis.prepare_payment( @access_token, {
|
151
|
-
data: data,
|
152
|
-
meta: meta
|
153
|
-
})
|
154
|
-
prepare_payment_response_body = JSON.parse(prepare_payment_response.body)
|
155
|
-
data_attributes = {amount: @payment_attrs['amount'], currency: @payment_attrs['currency']}
|
156
|
-
data_attributes[:execution_date] = @payment_attrs['execution_date'] if @payment_attrs['execution_date']
|
157
|
-
data_attributes[:beneficiary] = { name: @payment_attrs['beneficiary']['name'] } if @payment_attrs['beneficiary'] && @payment_attrs['beneficiary']['name']
|
158
|
-
{
|
159
|
-
meta: {session_id: prepare_payment_response_body['meta']['session_id']},
|
160
|
-
data: { attributes: data_attributes}
|
161
|
-
}
|
162
|
-
end
|
163
|
-
|
164
|
-
def build_signature(payload, date, x_request_id)
|
165
|
-
date_string = "x-date: #{date}"
|
166
|
-
digest_string = "digest: SHA-256=#{Fintecture::Utils::Crypto.hash_base64(payload.to_json)}"
|
167
|
-
x_request_id_string = "x-request-id: #{x_request_id}"
|
168
|
-
|
169
|
-
Fintecture::Utils::Crypto.sign_payload "#{digest_string}\n#{date_string}\n#{x_request_id_string}"
|
170
|
-
end
|
171
|
-
|
172
|
-
def build_config(payload)
|
173
|
-
header_time = Fintecture::Utils::Date.header_time
|
174
|
-
x_request_id = Fintecture::Utils::Crypto.generate_uuid
|
175
|
-
config = {
|
176
|
-
app_id: Fintecture.app_id,
|
177
|
-
access_token: @access_token,
|
178
|
-
date: header_time,
|
179
|
-
request_id: x_request_id,
|
180
|
-
signature_type: SIGNATURE_TYPE,
|
181
|
-
signature: build_signature(payload, header_time, x_request_id),
|
182
|
-
redirect_uri: @payment_attrs['redirect_uri'] || '',
|
183
|
-
origin_uri: @payment_attrs['origin_uri'] || '',
|
184
|
-
state: @payment_attrs['state'],
|
185
|
-
payload: payload
|
186
|
-
}
|
187
|
-
config[:provider] = @payment_attrs['provider'] if @payment_attrs['provider']
|
188
|
-
config
|
189
|
-
end
|
190
|
-
|
191
|
-
def build_local_digest(parameters)
|
192
|
-
test_string = {
|
193
|
-
app_id: Fintecture.app_id,
|
194
|
-
app_secret: Fintecture.app_secret,
|
195
|
-
session_id: parameters['session_id'],
|
196
|
-
status: parameters['status'],
|
197
|
-
customer_id: parameters['customer_id'],
|
198
|
-
provider: parameters['provider'],
|
199
|
-
state: parameters['state']
|
200
|
-
}.map{|key, value| "#{key}=#{value}"}.join('&')
|
201
|
-
|
202
|
-
Fintecture::Utils::Crypto.hash_base64 test_string
|
203
|
-
end
|
204
|
-
|
205
|
-
def base_url
|
206
|
-
Fintecture::Api::BaseUrl::FINTECTURE_CONNECT_URL[Fintecture.environment.to_sym]
|
207
|
-
end
|
208
|
-
|
209
|
-
def as_json(element)
|
210
|
-
return JSON(element.to_json) if element.is_a? Hash
|
211
|
-
|
212
|
-
begin
|
213
|
-
element.as_json
|
214
|
-
rescue NoMethodError
|
215
|
-
raise Fintecture::ValidationException.new("invalid parameter format, the parameter should be a Hash or an Object Model instead a #{element.class.name}")
|
216
|
-
end
|
217
|
-
end
|
218
|
-
end
|
219
|
-
end
|
1
|
+
require 'base64'
|
2
|
+
require 'json'
|
3
|
+
require 'faraday'
|
4
|
+
require 'fintecture/pis'
|
5
|
+
require 'fintecture/utils/validation'
|
6
|
+
require 'fintecture/exceptions'
|
7
|
+
require 'fintecture/utils/date'
|
8
|
+
require 'fintecture/utils/constants'
|
9
|
+
|
10
|
+
module Fintecture
|
11
|
+
class Connect
|
12
|
+
class << self
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
# Build the base of url
|
17
|
+
def api_base_url
|
18
|
+
Fintecture::Api::BaseUrl::FINTECTURE_API_URL[Fintecture.environment.to_sym]
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
def as_json(element)
|
28
|
+
return JSON(element.to_json) if element.is_a? Hash
|
29
|
+
|
30
|
+
begin
|
31
|
+
element.as_json
|
32
|
+
rescue NoMethodError
|
33
|
+
raise Fintecture::ValidationException.new("invalid parameter format, the parameter should be a Hash or an Object Model instead a #{element.class.name}")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
220
38
|
end
|
@@ -1,4 +1,33 @@
|
|
1
|
-
module Fintecture
|
2
|
-
class ValidationException < Exception; end
|
3
|
-
class CryptoException < Exception; end
|
1
|
+
module Fintecture
|
2
|
+
class ValidationException < Exception; end
|
3
|
+
class CryptoException < Exception; end
|
4
|
+
class ApiException
|
5
|
+
class << self
|
6
|
+
|
7
|
+
def error(res)
|
8
|
+
body = JSON.parse res.body
|
9
|
+
|
10
|
+
code = body['code']
|
11
|
+
log_id = body['log_id']
|
12
|
+
errors = body['errors']
|
13
|
+
|
14
|
+
raise Exception.new(_construct_message(res.status, code, log_id, errors))
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
private
|
19
|
+
def _construct_message(status, code, log_id, errors_array)
|
20
|
+
error_string = "\nFintecture server errors : "
|
21
|
+
error_string += "\n status: #{status} "
|
22
|
+
error_string += "\n code: #{code}"
|
23
|
+
error_string += "\n id : #{log_id}"
|
24
|
+
errors_array.each do |error|
|
25
|
+
formated_error = error.map {|key,value| " #{key}: #{value}"}.join("\n")
|
26
|
+
error_string += "\n\n#{formated_error}"
|
27
|
+
end
|
28
|
+
error_string += "\n\n"
|
29
|
+
error_string
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
4
33
|
end
|
@@ -1,74 +1,120 @@
|
|
1
|
-
require 'base64'
|
2
|
-
require 'faraday'
|
3
|
-
require 'uri'
|
4
|
-
require 'fintecture/utils/crypto'
|
5
|
-
require 'fintecture/utils/date'
|
6
|
-
|
7
|
-
module Fintecture
|
8
|
-
module Faraday
|
9
|
-
module Authentication
|
10
|
-
class Connection
|
11
|
-
class << self
|
12
|
-
|
13
|
-
def connection(url)
|
14
|
-
::Faraday.new(url: url) do |faraday|
|
15
|
-
faraday.request :url_encoded
|
16
|
-
faraday.adapter ::Faraday.default_adapter
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def post(url:, req_body: nil, custom_content_type: nil, bearer: nil, secure_headers: false)
|
21
|
-
conn = connection(url)
|
22
|
-
|
23
|
-
conn.post do |req|
|
24
|
-
req.
|
25
|
-
req.
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
1
|
+
require 'base64'
|
2
|
+
require 'faraday'
|
3
|
+
require 'uri'
|
4
|
+
require 'fintecture/utils/crypto'
|
5
|
+
require 'fintecture/utils/date'
|
6
|
+
|
7
|
+
module Fintecture
|
8
|
+
module Faraday
|
9
|
+
module Authentication
|
10
|
+
class Connection
|
11
|
+
class << self
|
12
|
+
|
13
|
+
def connection(url)
|
14
|
+
::Faraday.new(url: url) do |faraday|
|
15
|
+
faraday.request :url_encoded
|
16
|
+
faraday.adapter ::Faraday.default_adapter
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def post(url:, req_body: nil, custom_content_type: nil, bearer: nil, secure_headers: false, additional_headers: nil)
|
21
|
+
conn = connection(url)
|
22
|
+
|
23
|
+
res = conn.post do |req|
|
24
|
+
req.options.params_encoder = Faraday::DisabledEncoder
|
25
|
+
req.headers = req_headers(custom_content_type, bearer, secure_headers, additional_headers, method: 'post', body: req_body, url: url)
|
26
|
+
req.body = req_body
|
27
|
+
end
|
28
|
+
|
29
|
+
!res.success? ? Fintecture::ApiException.error(res) : res
|
30
|
+
end
|
31
|
+
|
32
|
+
def get(url:, req_body: nil, custom_content_type: nil, bearer: nil, secure_headers: false, additional_headers: nil)
|
33
|
+
conn = connection(url)
|
34
|
+
|
35
|
+
res = conn.get do |req|
|
36
|
+
req.options.params_encoder = Faraday::DisabledEncoder
|
37
|
+
req.headers = req_headers(custom_content_type, bearer, secure_headers, additional_headers, method: 'get', url: url)
|
38
|
+
req.body = req_body
|
39
|
+
end
|
40
|
+
|
41
|
+
!res.success? ? Fintecture::ApiException.error(res) : res
|
42
|
+
end
|
43
|
+
|
44
|
+
def req_headers(custom_content_type, bearer, secure_headers, additional_headers, method: '', body: {}, url:)
|
45
|
+
|
46
|
+
client_token = Base64.strict_encode64("#{Fintecture.app_id}:#{Fintecture.app_secret}")
|
47
|
+
|
48
|
+
{
|
49
|
+
'Accept' => 'application/json',
|
50
|
+
'User-Agent' => "Fintecture Ruby SDK v #{Fintecture::VERSION}",
|
51
|
+
'Authorization' => bearer ? bearer : "Basic #{client_token}",
|
52
|
+
'Content-Type' => custom_content_type ? custom_content_type : 'application/x-www-form-urlencoded',
|
53
|
+
}.merge(secure_headers ? req_secure_headers(additional_headers, body: body, url: url, method: method) : {})
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
def req_secure_headers(additional_headers, body: {}, url: '', method: '')
|
58
|
+
raise Fintecture::ValidationException.new('additional_headers must be an object') if additional_headers != nil && !additional_headers.is_a?(Hash)
|
59
|
+
|
60
|
+
payload = ( body.class.name == 'String' ? body : body.to_s )
|
61
|
+
path_name = URI(url).path
|
62
|
+
search_params = URI(url).query
|
63
|
+
|
64
|
+
|
65
|
+
request_target = search_params ? "#{method.downcase} #{path_name}?#{search_params}" : "#{method.downcase} #{path_name}"
|
66
|
+
date = Fintecture::Utils::Date.header_time.to_s
|
67
|
+
digest = load_digest(payload)
|
68
|
+
x_request_id = Fintecture::Utils::Crypto.generate_uuid
|
69
|
+
|
70
|
+
|
71
|
+
headers = {
|
72
|
+
'Date' => date,
|
73
|
+
'X-Request-ID' => x_request_id
|
74
|
+
}.merge(payload ? digest : {})
|
75
|
+
|
76
|
+
# Add additional_headers if exists
|
77
|
+
headers = headers.merge(additional_headers) if additional_headers != nil
|
78
|
+
|
79
|
+
|
80
|
+
headers['Signature'] = Fintecture::Utils::Crypto.create_signature_header({'(request-target)' => request_target}.merge(headers))
|
81
|
+
headers
|
82
|
+
end
|
83
|
+
|
84
|
+
def load_digest(payload)
|
85
|
+
{'Digest' => "SHA-256=#{Fintecture::Utils::Crypto.hash_base64(payload)}"}
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
module DisabledEncoder
|
94
|
+
class << self
|
95
|
+
extend Forwardable
|
96
|
+
def_delegators :'Faraday::Utils', :escape, :unescape
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
def self.encode(params)
|
101
|
+
return nil if params.nil?
|
102
|
+
|
103
|
+
query_string = "#{params.map{|key, value| "#{key}=#{value}"}.join('&')}"
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
class << self
|
110
|
+
attr_accessor :sort_params
|
111
|
+
end
|
112
|
+
|
113
|
+
# Useful default for OAuth and caching.
|
114
|
+
@sort_params = true
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
|