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.
@@ -1,61 +1,262 @@
1
- require 'json'
2
- require 'faraday'
3
- require 'fintecture/api/endpoints/pis'
4
- require 'fintecture/api/base_url'
5
-
6
- module Fintecture
7
- class Pis
8
- class << self
9
-
10
- # Headers
11
- def prepare_payment(access_token, payload)
12
- url = prepare_payment_endpoint
13
-
14
- Fintecture::Faraday::Authentication::Connection.post(
15
- url: url,
16
- req_body: payload.to_json,
17
- custom_content_type: 'application/json',
18
- bearer: "Bearer #{access_token}",
19
- secure_headers: true
20
- )
21
- end
22
-
23
- # This needs headers
24
- def get_payments(access_token, session_id)
25
- url = payment_endpoint
26
-
27
- Fintecture::Faraday::Authentication::Connection.get(
28
- url: "#{url}/#{session_id}",
29
- custom_content_type: 'application/json',
30
- bearer: "Bearer #{access_token}",
31
- secure_headers: true
32
- )
33
- end
34
-
35
- def get_access_token
36
- response = Fintecture::Authentication.get_access_token
37
-
38
- JSON.parse response.body
39
- end
40
-
41
- private
42
-
43
- def prepare_payment_endpoint
44
- "#{api_base_url}/#{Fintecture::Api::Endpoints::Pis::PREPARE}"
45
- end
46
-
47
- def payment_endpoint
48
- "#{api_base_url}/#{Fintecture::Api::Endpoints::Pis::PAYMENTS}"
49
- end
50
-
51
- def base_url
52
- Fintecture::Api::BaseUrl::FINTECTURE_CONNECT_URL[Fintecture.environment.to_sym]
53
- end
54
-
55
- def api_base_url
56
- Fintecture::Api::BaseUrl::FINTECTURE_API_URL[Fintecture.environment.to_sym]
57
- end
58
-
59
- end
60
- end
1
+ require 'json'
2
+ require 'faraday'
3
+ require 'fintecture/api/endpoints/pis'
4
+ require 'fintecture/api/base_url'
5
+
6
+ module Fintecture
7
+ class Pis
8
+ class << self
9
+
10
+
11
+
12
+
13
+ # ------------ PUBLIC METHODS ------------
14
+ # Connect
15
+ def get_connect(access_token = nil, payment_attrs = nil)
16
+ # Build the request payload
17
+ payload = build_payload_connect(as_json payment_attrs)
18
+ # Do the _get_connect_request request
19
+ _get_connect_request access_token, payload, payment_attrs
20
+ end
21
+
22
+ # Request_to_pay
23
+ def request_to_pay(access_token = nil, payment_attrs = nil)
24
+ # Build the request payload
25
+ payload = build_payload_request_to_pay(as_json payment_attrs)
26
+ # Do the _request_to_pay_request request
27
+ _request_to_pay_request access_token, payload, payment_attrs
28
+ end
29
+
30
+ # Get_payments
31
+ def get_payments(access_token = nil, session_id = nil)
32
+ # Do the get_payments request
33
+ _get_payments_request access_token, session_id
34
+ end
35
+
36
+ # Get_access_token
37
+ def get_access_token
38
+ # Do the get_access_token request
39
+ response = Fintecture::Authentication.get_access_token
40
+ JSON.parse response.body
41
+ end
42
+
43
+
44
+
45
+
46
+ private
47
+ # ------------ REQUESTS ------------
48
+ # Connect
49
+ def _get_connect_request(access_token, payload, payment_attrs)
50
+
51
+ # Get the url request
52
+ url = connect_endpoint
53
+
54
+ # Build uri params
55
+ params = {}
56
+ params['state'] = payment_attrs['state']
57
+ params['redirect_uri'] = payment_attrs['redirect_uri'] if payment_attrs['redirect_uri']
58
+ query_string = "?#{params.map{|key, value| "#{key}=#{value}"}.join('&')}"
59
+
60
+ # Do connect request
61
+ Fintecture::Faraday::Authentication::Connection.post(
62
+ url: url + query_string,
63
+ req_body: payload.to_json,
64
+ custom_content_type: 'application/json',
65
+ bearer: "Bearer #{access_token}",
66
+ secure_headers: true
67
+ )
68
+ end
69
+
70
+ # Request_to_pay
71
+ def _request_to_pay_request(access_token, payload, payment_attrs)
72
+
73
+ # Get the url request
74
+ url = request_to_pay_endpoint
75
+
76
+ additional_headers = {}
77
+ additional_headers['x-language'] = payment_attrs[:x_language]
78
+
79
+ # Do connect request
80
+ Fintecture::Faraday::Authentication::Connection.post(
81
+ url: url,
82
+ req_body: payload.to_json,
83
+ custom_content_type: 'application/json',
84
+ bearer: "Bearer #{access_token}",
85
+ secure_headers: true,
86
+ additional_headers: additional_headers
87
+ )
88
+ end
89
+
90
+ # Get_payments
91
+ def _get_payments_request(access_token, session_id)
92
+ url = payment_endpoint
93
+
94
+ Fintecture::Faraday::Authentication::Connection.get(
95
+ url: "#{url}/#{session_id}",
96
+ custom_content_type: 'application/json',
97
+ bearer: "Bearer #{access_token}",
98
+ secure_headers: true
99
+ )
100
+ end
101
+
102
+
103
+
104
+
105
+ # ------------ BUILD PAYLOADS ------------
106
+ # Connect - Build the payload from payment_attrs
107
+ def build_payload_connect(payment_attrs = nil)
108
+ # Mandatory attributes
109
+ attributes = {
110
+ amount: payment_attrs['amount'].to_s,
111
+ currency: payment_attrs['currency'],
112
+ communication: payment_attrs['communication'],
113
+ end_to_end_id: payment_attrs['end_to_end_id'] || Fintecture::Utils::Crypto.generate_uuid_only_chars
114
+ }
115
+
116
+ # Optionals attributes
117
+ attributes['execution_date'] = payment_attrs['execution_date'] if payment_attrs['execution_date']
118
+ attributes['debited_account_id'] = payment_attrs['debited_account_id'] if payment_attrs['debited_account_id']
119
+ attributes['debited_account_type'] = payment_attrs['debited_account_type'] if payment_attrs['debited_account_type']
120
+ attributes['scheme'] = payment_attrs['scheme'] if payment_attrs['scheme']
121
+
122
+ # Mandatory attributes => beneficiary
123
+ if payment_attrs['beneficiary']
124
+ attributes['beneficiary'] = {
125
+ name: payment_attrs['beneficiary']['name'],
126
+ street: payment_attrs['beneficiary']['street'],
127
+ zip: payment_attrs['beneficiary']['zip'],
128
+ city: payment_attrs['beneficiary']['city'],
129
+ country: payment_attrs['beneficiary']['country'],
130
+ iban: payment_attrs['beneficiary']['iban'],
131
+ swift_bic: payment_attrs['beneficiary']['swift_bic']
132
+ }
133
+
134
+ # Optionals attributes => beneficiary
135
+ attributes['beneficiary']['number'] = payment_attrs['beneficiary']['number'] if payment_attrs['beneficiary']['number']
136
+ attributes['beneficiary']['complement'] = payment_attrs['beneficiary']['complement'] if payment_attrs['beneficiary']['complement']
137
+ attributes['beneficiary']['form'] = payment_attrs['beneficiary']['form'] if payment_attrs['beneficiary']['form']
138
+ attributes['beneficiary']['incorporation'] = payment_attrs['beneficiary']['incorporation'] if payment_attrs['beneficiary']['incorporation']
139
+ end
140
+
141
+ # Mandatory meta data
142
+ meta = {
143
+ psu_name: payment_attrs['customer_full_name'],
144
+ psu_email: payment_attrs['customer_email'],
145
+ psu_phone: payment_attrs['customer_phone']
146
+ }
147
+
148
+ # Optionals meta data
149
+ meta['psu_phone_prefix'] = payment_attrs['customer_phone_prefix'] if payment_attrs['customer_phone_prefix']
150
+ meta['psu_ip'] = payment_attrs['customer_ip'] if payment_attrs['customer_ip']
151
+
152
+ # Mandatory meta => psu_address
153
+ meta['psu_address'] = {
154
+ street: payment_attrs['customer_address']['street'],
155
+ city: payment_attrs['customer_address']['city'],
156
+ zip: payment_attrs['customer_address']['zip'],
157
+ country: payment_attrs['customer_address']['country']
158
+ }
159
+
160
+ # Optionals meta => psu_address
161
+ meta['psu_address']['number'] = payment_attrs['customer_address']['number'] if payment_attrs['customer_address']['number']
162
+ meta['psu_address']['complement'] = payment_attrs['customer_address']['complement'] if payment_attrs['customer_address']['complement']
163
+
164
+ # Return the payload
165
+ {
166
+ meta: meta,
167
+ data: {
168
+ type: 'PIS',
169
+ attributes: attributes,
170
+ }
171
+ }
172
+ end
173
+
174
+ # Request_to_pay - Build the payload from payment_attrs
175
+ def build_payload_request_to_pay(payment_attrs = nil)
176
+ # Mandatory attributes
177
+ attributes = {
178
+ amount: payment_attrs['amount'],
179
+ currency: payment_attrs['currency'],
180
+ communication: payment_attrs['communication']
181
+ }
182
+
183
+ # Mandatory meta data
184
+ meta = {
185
+ psu_name: payment_attrs['customer_full_name'],
186
+ psu_email: payment_attrs['customer_email'],
187
+ psu_phone: payment_attrs['customer_phone'],
188
+ psu_phone_prefix: payment_attrs['customer_phone_prefix']
189
+ }
190
+
191
+ # Optionals meta psu_address
192
+ if payment_attrs['customer_address']
193
+ meta['psu_address'] = {}
194
+ meta['psu_address']['street'] = payment_attrs['customer_address']['street'] if payment_attrs['customer_address']['street']
195
+ meta['psu_address']['number'] = payment_attrs['customer_address']['number'] if payment_attrs['customer_address']['number']
196
+ meta['psu_address']['city'] = payment_attrs['customer_address']['city'] if payment_attrs['customer_address']['city']
197
+ meta['psu_address']['zip'] = payment_attrs['customer_address']['zip'] if payment_attrs['customer_address']['zip']
198
+ meta['psu_address']['country'] = payment_attrs['customer_address']['country'] if payment_attrs['customer_address']['country']
199
+ end
200
+
201
+ # Optionals meta data
202
+ meta['expirary'] = payment_attrs['expirary'] if payment_attrs['expirary']
203
+ meta['cc'] = payment_attrs['cc'] if payment_attrs['cc']
204
+ meta['bcc'] = payment_attrs['bcc'] if payment_attrs['bcc']
205
+
206
+
207
+ # Return the payload
208
+ {
209
+ meta: meta,
210
+ data: {
211
+ type: 'REQUEST_TO_PAY',
212
+ attributes: attributes,
213
+ }
214
+ }
215
+ end
216
+
217
+
218
+
219
+
220
+ # ------------ API ENDPOINTS ------------
221
+ # Request_to_pay
222
+ def request_to_pay_endpoint
223
+ "#{api_base_url}/#{Fintecture::Api::Endpoints::Pis::REQUEST_TO_PAY}"
224
+ end
225
+
226
+ # Payment
227
+ def payment_endpoint
228
+ "#{api_base_url}/#{Fintecture::Api::Endpoints::Pis::PAYMENTS}"
229
+ end
230
+
231
+ # Connect
232
+ def connect_endpoint
233
+ "#{api_base_url}/#{Fintecture::Api::Endpoints::Pis::CONNECT}"
234
+ end
235
+
236
+
237
+
238
+
239
+ # ------------ BASE URL ------------
240
+ def base_url
241
+ Fintecture::Api::BaseUrl::FINTECTURE_CONNECT_URL[Fintecture.environment.to_sym]
242
+ end
243
+
244
+ def api_base_url
245
+ Fintecture::Api::BaseUrl::FINTECTURE_API_URL[Fintecture.environment.to_sym]
246
+ end
247
+
248
+
249
+
250
+ # ------------ TOOLS ------------
251
+ def as_json(element)
252
+ return JSON(element.to_json) if element.is_a? Hash
253
+
254
+ begin
255
+ element.as_json
256
+ rescue NoMethodError
257
+ raise Fintecture::ValidationException.new("invalid parameter format, the parameter should be a Hash or an Object Model instead a #{element.class.name}")
258
+ end
259
+ end
260
+ end
261
+ end
61
262
  end
@@ -1,14 +1,14 @@
1
-
2
-
3
-
4
- module Fintecture
5
- module Utils
6
- module Constants
7
-
8
- SIGNEDHEADERPARAMETERLIST = %w[(request-target) Date Digest X-Request-ID];
9
- PSU_TYPES = %w[retail corporate all]
10
- SCOPES = %w[pis ais]
11
-
12
- end
13
- end
1
+
2
+
3
+
4
+ module Fintecture
5
+ module Utils
6
+ module Constants
7
+
8
+ SIGNEDHEADERPARAMETERLIST = %w[(request-target) Date Digest X-Request-ID];
9
+ PSU_TYPES = %w[retail corporate all]
10
+ SCOPES = %w[pis ais]
11
+
12
+ end
13
+ end
14
14
  end
@@ -1,76 +1,78 @@
1
- require 'securerandom'
2
- require 'openssl'
3
- require 'base64'
4
- require 'json'
5
- require 'fintecture/exceptions'
6
- require 'fintecture/utils/constants'
7
- require 'uri'
8
-
9
- module Fintecture
10
- module Utils
11
- class Crypto
12
- class << self
13
-
14
- def generate_uuid
15
- SecureRandom.uuid
16
- end
17
-
18
- def generate_uuid_only_chars
19
- generate_uuid.gsub!('-','')
20
- end
21
-
22
- def sign_payload(payload)
23
- payload = payload.to_json.to_s if payload.is_a? Hash
24
-
25
- digest = OpenSSL::Digest::SHA256.new
26
- private_key = OpenSSL::PKey::RSA.new(Fintecture.private_key)
27
-
28
- begin
29
- signature = private_key.sign(digest, payload)
30
- Base64.strict_encode64(signature)
31
- rescue
32
- raise Fintecture::CryptoException.new('error during signature')
33
- end
34
- end
35
-
36
- def decrypt_private(digest)
37
- digest = URI.unescape digest
38
- encrypted_string = Base64.decode64(digest)
39
- private_key = OpenSSL::PKey::RSA.new(Fintecture.private_key)
40
-
41
- begin
42
- private_key.private_decrypt(encrypted_string, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)
43
- rescue OpenSSL::PKey::RSAError => e
44
- raise Fintecture::CryptoException.new("error while decrypt, #{e.message}")
45
- rescue
46
- raise Fintecture::CryptoException.new('error during decryption')
47
- end
48
- end
49
-
50
- def hash_base64(plain_text)
51
- digest = Digest::SHA256.digest plain_text
52
- Base64.strict_encode64(digest)
53
- end
54
-
55
- def create_signature_header(headers)
56
- signing = []
57
- header = []
58
-
59
- Fintecture::Utils::Constants::SIGNEDHEADERPARAMETERLIST.each do |param|
60
- next unless headers[param]
61
-
62
- param_low = param.downcase
63
- signing << "#{param_low}: #{headers[param]}"
64
- header << param_low
65
- end
66
-
67
- # Double quote in join needed. If not we will get two slashes \\n
68
- signature = sign_payload signing.join("\n")
69
-
70
- 'keyId="' + Fintecture.app_id + '",algorithm="rsa-sha256",headers="' + header.join(' ') + '",signature="' + signature + '"'
71
- end
72
-
73
- end
74
- end
75
- end
1
+ require 'securerandom'
2
+ require 'openssl'
3
+ require 'base64'
4
+ require 'json'
5
+ require 'fintecture/exceptions'
6
+ require 'fintecture/utils/constants'
7
+ require 'uri'
8
+
9
+ module Fintecture
10
+ module Utils
11
+ class Crypto
12
+ class << self
13
+
14
+ def generate_uuid
15
+ SecureRandom.uuid
16
+ end
17
+
18
+ def generate_uuid_only_chars
19
+ generate_uuid.gsub!('-','')
20
+ end
21
+
22
+ def sign_payload(payload)
23
+ payload = payload.to_json.to_s if payload.is_a? Hash
24
+ digest = OpenSSL::Digest::SHA256.new
25
+ private_key = OpenSSL::PKey::RSA.new(Fintecture.private_key)
26
+
27
+ begin
28
+ signature = private_key.sign(digest, payload)
29
+ Base64.strict_encode64(signature)
30
+ rescue
31
+ raise Fintecture::CryptoException.new('error during signature')
32
+ end
33
+ end
34
+
35
+ def decrypt_private(digest)
36
+ digest = URI.unescape digest
37
+ encrypted_string = Base64.decode64(digest)
38
+ private_key = OpenSSL::PKey::RSA.new(Fintecture.private_key)
39
+
40
+ begin
41
+ private_key.private_decrypt(encrypted_string, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)
42
+ rescue OpenSSL::PKey::RSAError => e
43
+ raise Fintecture::CryptoException.new("error while decrypt, #{e.message}")
44
+ rescue
45
+ raise Fintecture::CryptoException.new('error during decryption')
46
+ end
47
+ end
48
+
49
+ def hash_base64(plain_text)
50
+ digest = Digest::SHA256.digest plain_text
51
+ Base64.strict_encode64(digest)
52
+ end
53
+
54
+ def create_signature_header(headers)
55
+ signing = []
56
+ header = []
57
+
58
+
59
+
60
+ Fintecture::Utils::Constants::SIGNEDHEADERPARAMETERLIST.each do |param|
61
+ next unless headers[param]
62
+
63
+ param_low = param.downcase
64
+ signing << "#{param_low}: #{headers[param]}"
65
+ header << param_low
66
+ end
67
+
68
+
69
+ # Double quote in join needed. If not we will get two slashes \\n
70
+ signature = sign_payload signing.join("\n")
71
+ 'keyId="' + Fintecture.app_id + '",algorithm="rsa-sha256",headers="' + header.join(' ') + '",signature="' + signature + '"'
72
+
73
+ end
74
+
75
+ end
76
+ end
77
+ end
76
78
  end
@@ -1,15 +1,15 @@
1
- require 'time'
2
-
3
- module Fintecture
4
- module Utils
5
- class Date
6
- class << self
7
-
8
- def header_time
9
- Time.now.utc.strftime("%a, %d %b %Y %H:%M:%S GMT")
10
- end
11
-
12
- end
13
- end
14
- end
1
+ require 'time'
2
+
3
+ module Fintecture
4
+ module Utils
5
+ class Date
6
+ class << self
7
+
8
+ def header_time
9
+ Time.now.utc.strftime("%a, %d %b %Y %H:%M:%S GMT")
10
+ end
11
+
12
+ end
13
+ end
14
+ end
15
15
  end
@@ -1,26 +1,26 @@
1
- require 'fintecture/exceptions'
2
-
3
- module Fintecture
4
- module Utils
5
- class Validation
6
- class << self
7
-
8
- def raise_if_klass_mismatch(target, klass, param_name = nil)
9
- return if target.is_a? klass
10
-
11
- raise Fintecture::ValidationException.new("invalid #{param_name ? param_name : 'parameter'} format, the parameter should be a #{klass} instead a #{target.class.name}")
12
- end
13
-
14
- def raise_if_invalid_date_format(date)
15
- return unless date
16
- valid_format = date.match(/\d{4}-\d{2}-\d{2}/)
17
- valid_date = ::Date.strptime(date, '%Y-%m-%d') rescue false
18
- return if valid_format && valid_date
19
-
20
- raise Fintecture::ValidationException.new("invalidss #{date} date, the format should be YYYY-MM-DD")
21
- end
22
-
23
- end
24
- end
25
- end
1
+ require 'fintecture/exceptions'
2
+
3
+ module Fintecture
4
+ module Utils
5
+ class Validation
6
+ class << self
7
+
8
+ def raise_if_klass_mismatch(target, klass, param_name = nil)
9
+ return if target.is_a? klass
10
+
11
+ raise Fintecture::ValidationException.new("invalid #{param_name ? param_name : 'parameter'} format, the parameter should be a #{klass} instead a #{target.class.name}")
12
+ end
13
+
14
+ def raise_if_invalid_date_format(date)
15
+ return unless date
16
+ valid_format = date.match(/\d{4}-\d{2}-\d{2}/)
17
+ valid_date = ::Date.strptime(date, '%Y-%m-%d') rescue false
18
+ return if valid_format && valid_date
19
+
20
+ raise Fintecture::ValidationException.new("invalidss #{date} date, the format should be YYYY-MM-DD")
21
+ end
22
+
23
+ end
24
+ end
25
+ end
26
26
  end
@@ -1,3 +1,3 @@
1
- module Fintecture
2
- VERSION = '0.1.9'
3
- end
1
+ module Fintecture
2
+ VERSION = '0.2.1'
3
+ end