fintecture 0.1.9 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|