ibanity 1.9.1 → 1.10.0
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/CHANGELOG.md +6 -0
- data/ibanity.gemspec +1 -0
- data/lib/ibanity/api/flat_resource.rb +20 -0
- data/lib/ibanity/api/ponto_connect/payment_activation_request.rb +10 -0
- data/lib/ibanity/api/webhooks/key.rb +11 -0
- data/lib/ibanity/api/webhooks/ponto_connect.rb +24 -0
- data/lib/ibanity/api/webhooks/xs2a.rb +24 -0
- data/lib/ibanity/client.rb +4 -3
- data/lib/ibanity/error.rb +2 -0
- data/lib/ibanity/version.rb +1 -1
- data/lib/ibanity/webhook.rb +94 -0
- data/lib/ibanity.rb +17 -1
- metadata +22 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 55b04259d7e3e1f8cd8ee53b23d5b50fd4803d0a15822870b59b2e3bd78820a2
|
4
|
+
data.tar.gz: 79003b1d051b9e517ea786dab240b19dca82bfcbf8379784eacccdd15a7e8481
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f11e1268e728697e6f75cdc0eb7a79358d8359ee4eada54ddf7e452ef7147b9f0c548724047a5d99454ca785840ab5e72c0b16448b587789d27f3b6ced89a47e
|
7
|
+
data.tar.gz: 96132c499b4e33ed9681f6998d1f7923e260d715078777a503dfd13c98a4979fcf03854fa96f217d3527a0e248cec994710fdfe74b3816afc92302d91ab60316
|
data/CHANGELOG.md
CHANGED
data/ibanity.gemspec
CHANGED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Ibanity
|
2
|
+
class FlatResource < OpenStruct
|
3
|
+
def self.list_by_uri(uri:, key:)
|
4
|
+
raw_response = Ibanity.client.get(uri: uri)
|
5
|
+
items = raw_response[key].map { |raw_item| new(raw_item) }
|
6
|
+
Ibanity::Collection.new(
|
7
|
+
klass: self,
|
8
|
+
items: items,
|
9
|
+
links: nil,
|
10
|
+
paging: nil,
|
11
|
+
synchronized_at: nil,
|
12
|
+
latest_synchronization: nil
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(raw)
|
17
|
+
super(raw)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module Ibanity
|
2
|
+
module PontoConnect
|
3
|
+
class PaymentActivationRequest < Ibanity::BaseResource
|
4
|
+
def self.create(access_token:, **attributes)
|
5
|
+
uri = Ibanity.ponto_connect_api_schema["paymentActivationRequests"]
|
6
|
+
create_by_uri(uri: uri, resource_type: "paymentActivationRequest", attributes: attributes, customer_access_token: access_token)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Ibanity
|
2
|
+
module Webhooks
|
3
|
+
module PontoConnect
|
4
|
+
module Synchronization
|
5
|
+
class SucceededWithoutChange < Ibanity::BaseResource
|
6
|
+
end
|
7
|
+
|
8
|
+
class Failed < Ibanity::BaseResource
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module Account
|
13
|
+
class DetailsUpdated < Ibanity::BaseResource
|
14
|
+
end
|
15
|
+
|
16
|
+
class TransactionsCreated < Ibanity::BaseResource
|
17
|
+
end
|
18
|
+
|
19
|
+
class TransactionsUpdated < Ibanity::BaseResource
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Ibanity
|
2
|
+
module Webhooks
|
3
|
+
module Xs2a
|
4
|
+
module Synchronization
|
5
|
+
class SucceededWithoutChange < Ibanity::BaseResource
|
6
|
+
end
|
7
|
+
|
8
|
+
class Failed < Ibanity::BaseResource
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module Account
|
13
|
+
class DetailsUpdated < Ibanity::BaseResource
|
14
|
+
end
|
15
|
+
|
16
|
+
class TransactionsCreated < Ibanity::BaseResource
|
17
|
+
end
|
18
|
+
|
19
|
+
class TransactionsUpdated < Ibanity::BaseResource
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/ibanity/client.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Ibanity
|
2
2
|
class Client
|
3
3
|
|
4
|
-
attr_reader :base_uri, :signature_certificate, :signature_key, :isabel_connect_client_id, :isabel_connect_client_secret, :ponto_connect_client_id, :ponto_connect_client_secret
|
4
|
+
attr_reader :base_uri, :signature_certificate, :signature_key, :isabel_connect_client_id, :isabel_connect_client_secret, :ponto_connect_client_id, :ponto_connect_client_secret, :application_id
|
5
5
|
|
6
6
|
def initialize(
|
7
7
|
certificate:,
|
@@ -13,12 +13,12 @@ module Ibanity
|
|
13
13
|
signature_key_passphrase: nil,
|
14
14
|
api_scheme: "https",
|
15
15
|
api_host: "api.ibanity.com",
|
16
|
-
api_port: "443",
|
17
16
|
ssl_ca_file: nil,
|
18
17
|
isabel_connect_client_id: "valid_client_id",
|
19
18
|
isabel_connect_client_secret: "valid_client_secret",
|
20
19
|
ponto_connect_client_id: nil,
|
21
20
|
ponto_connect_client_secret: nil,
|
21
|
+
application_id: nil,
|
22
22
|
debug_http_requests: false)
|
23
23
|
@isabel_connect_client_id = isabel_connect_client_id
|
24
24
|
@isabel_connect_client_secret = isabel_connect_client_secret
|
@@ -32,8 +32,9 @@ module Ibanity
|
|
32
32
|
@signature_certificate_id = signature_certificate_id
|
33
33
|
@signature_key = OpenSSL::PKey::RSA.new(signature_key, signature_key_passphrase)
|
34
34
|
end
|
35
|
-
@base_uri = "#{api_scheme}://#{api_host}
|
35
|
+
@base_uri = "#{api_scheme}://#{api_host}"
|
36
36
|
@ssl_ca_file = ssl_ca_file
|
37
|
+
@application_id = application_id
|
37
38
|
end
|
38
39
|
|
39
40
|
def get(uri:, query_params: {}, customer_access_token: nil, headers: nil, json: true)
|
data/lib/ibanity/error.rb
CHANGED
@@ -22,6 +22,8 @@ module Ibanity
|
|
22
22
|
formatted_errors.join("\n")
|
23
23
|
elsif @errors.is_a?(Hash)
|
24
24
|
"* #{@errors["error"]}: #{@errors["error_description"]}\n * Error hint: #{@errors["error_hint"]}\n * ibanity_request_id: #{@ibanity_request_id}"
|
25
|
+
elsif @errors.is_a?(String)
|
26
|
+
@errors
|
25
27
|
else
|
26
28
|
super
|
27
29
|
end
|
data/lib/ibanity/version.rb
CHANGED
@@ -0,0 +1,94 @@
|
|
1
|
+
module Ibanity
|
2
|
+
module Webhook
|
3
|
+
DEFAULT_TOLERANCE = 30
|
4
|
+
SIGNING_ALGORITHM = "RS512"
|
5
|
+
|
6
|
+
# Initializes an Ibanity Webhooks event object from a JSON payload.
|
7
|
+
#
|
8
|
+
# This may raise JSON::ParserError if the payload is not valid JSON, or
|
9
|
+
# Ibanity::Error if the signature verification fails.
|
10
|
+
def self.construct_event!(payload, signature_header, tolerance: DEFAULT_TOLERANCE)
|
11
|
+
Signature.verify!(payload, signature_header, tolerance)
|
12
|
+
|
13
|
+
raw_item = JSON.parse(payload)
|
14
|
+
klass = raw_item["data"]["type"].split(".").map{|klass| klass.sub(/\S/, &:upcase)}.join("::")
|
15
|
+
Ibanity::Webhooks.const_get(klass).new(raw_item["data"])
|
16
|
+
end
|
17
|
+
|
18
|
+
module Signature
|
19
|
+
# Verifies the signature header for a given payload.
|
20
|
+
#
|
21
|
+
# Raises an Ibanity::Error in the following cases:
|
22
|
+
# - the header does not match the expected format
|
23
|
+
# - the digest does not match the payload
|
24
|
+
# - the issued at or expiration timestamp is not within the tolerance
|
25
|
+
# - the audience or issuer does not match the application config
|
26
|
+
#
|
27
|
+
# Returns true otherwise
|
28
|
+
def self.verify!(payload, signature_header, tolerance)
|
29
|
+
begin
|
30
|
+
key_details = JOSE::JWT.peek_protected(signature_header).to_hash
|
31
|
+
raise unless key_details["alg"] == SIGNING_ALGORITHM && key_details["kid"]
|
32
|
+
rescue
|
33
|
+
raise Ibanity::Error.new("Key details could not be parsed from the header", nil)
|
34
|
+
end
|
35
|
+
|
36
|
+
key = Ibanity.webhook_keys.find { |key| key.kid == key_details["kid"] }
|
37
|
+
|
38
|
+
if key.nil?
|
39
|
+
raise Ibanity::Error.new("The key id from the header didn't match an available signing key", nil)
|
40
|
+
end
|
41
|
+
signer = JOSE::JWK.from(key.to_h {|key, value| [key.to_s, value] })
|
42
|
+
verified, claims_string, _jws = JOSE::JWT.verify_strict(signer, [SIGNING_ALGORITHM], signature_header)
|
43
|
+
|
44
|
+
raise Ibanity::Error.new("The signature verification failed", nil) unless verified
|
45
|
+
|
46
|
+
jwt = JOSE::JWT.from(claims_string)
|
47
|
+
|
48
|
+
validate_digest!(jwt, payload)
|
49
|
+
validate_issued_at!(jwt, tolerance)
|
50
|
+
validate_expiration!(jwt, tolerance)
|
51
|
+
validate_issuer!(jwt)
|
52
|
+
validate_audience!(jwt)
|
53
|
+
|
54
|
+
true
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def self.validate_digest!(jwt, payload)
|
60
|
+
unless Digest::SHA512.base64digest(payload) == jwt.fields["digest"]
|
61
|
+
raise_invalid_signature_error!("digest")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.validate_issued_at!(jwt, tolerance)
|
66
|
+
unless jwt.fields["iat"] <= Time.now.to_i + tolerance
|
67
|
+
raise_invalid_signature_error!("iat")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.validate_expiration!(jwt, tolerance)
|
72
|
+
unless jwt.fields["exp"] >= Time.now.to_i - tolerance
|
73
|
+
raise_invalid_signature_error!("exp")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.validate_issuer!(jwt)
|
78
|
+
unless jwt.fields["iss"] == Ibanity.client.base_uri
|
79
|
+
raise_invalid_signature_error!("iss")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.validate_audience!(jwt)
|
84
|
+
unless jwt.fields["aud"] == Ibanity.client.application_id
|
85
|
+
raise_invalid_signature_error!("aud")
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.raise_invalid_signature_error!(field)
|
90
|
+
raise Ibanity::Error.new("The signature #{field} is invalid", nil)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/lib/ibanity.rb
CHANGED
@@ -4,6 +4,7 @@ require "uri"
|
|
4
4
|
require "rest_client"
|
5
5
|
require "json"
|
6
6
|
require "securerandom"
|
7
|
+
require "jose"
|
7
8
|
|
8
9
|
require_relative "ibanity/util"
|
9
10
|
require_relative "ibanity/error"
|
@@ -11,6 +12,8 @@ require_relative "ibanity/collection"
|
|
11
12
|
require_relative "ibanity/client"
|
12
13
|
require_relative "ibanity/http_signature"
|
13
14
|
require_relative "ibanity/api/base_resource"
|
15
|
+
require_relative "ibanity/api/flat_resource"
|
16
|
+
require_relative "ibanity/webhook"
|
14
17
|
require_relative "ibanity/api/xs2a/account"
|
15
18
|
require_relative "ibanity/api/xs2a/transaction"
|
16
19
|
require_relative "ibanity/api/xs2a/holding"
|
@@ -55,6 +58,10 @@ require_relative "ibanity/api/ponto_connect/sandbox/financial_institution_accoun
|
|
55
58
|
require_relative "ibanity/api/ponto_connect/sandbox/financial_institution_transaction"
|
56
59
|
require_relative "ibanity/api/ponto_connect/onboarding_details"
|
57
60
|
require_relative "ibanity/api/ponto_connect/reauthorization_request"
|
61
|
+
require_relative "ibanity/api/ponto_connect/payment_activation_request"
|
62
|
+
require_relative "ibanity/api/webhooks/key"
|
63
|
+
require_relative "ibanity/api/webhooks/xs2a"
|
64
|
+
require_relative "ibanity/api/webhooks/ponto_connect"
|
58
65
|
|
59
66
|
module Ibanity
|
60
67
|
class << self
|
@@ -69,6 +76,7 @@ module Ibanity
|
|
69
76
|
@isabel_connect_api_schema = nil
|
70
77
|
@consent_api_schema = nil
|
71
78
|
@ponto_connect_api_schema = nil
|
79
|
+
@webhooks_api_schema = nil
|
72
80
|
@sandbox_api_schema = nil
|
73
81
|
@configuration = nil
|
74
82
|
yield configuration
|
@@ -89,8 +97,8 @@ module Ibanity
|
|
89
97
|
:ponto_connect_client_secret,
|
90
98
|
:api_scheme,
|
91
99
|
:api_host,
|
92
|
-
:api_port,
|
93
100
|
:ssl_ca_file,
|
101
|
+
:application_id,
|
94
102
|
:debug_http_requests
|
95
103
|
).new
|
96
104
|
end
|
@@ -115,6 +123,14 @@ module Ibanity
|
|
115
123
|
@consent_api_schema ||= client.get(uri: "#{client.base_uri}/consent")["links"]
|
116
124
|
end
|
117
125
|
|
126
|
+
def webhooks_api_schema
|
127
|
+
@webhooks_api_schema ||= client.get(uri: "#{client.base_uri}/webhooks")["links"]
|
128
|
+
end
|
129
|
+
|
130
|
+
def webhook_keys
|
131
|
+
@webhook_keys ||= Ibanity::Webhooks::Key.list
|
132
|
+
end
|
133
|
+
|
118
134
|
def respond_to_missing?(method_name, include_private = false)
|
119
135
|
client.respond_to?(method_name, include_private)
|
120
136
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ibanity
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ibanity
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rest-client
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 1.8.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: jose
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.1.3
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.1.3
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rspec
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -60,6 +74,7 @@ files:
|
|
60
74
|
- lib/ibanity/api/base_resource.rb
|
61
75
|
- lib/ibanity/api/consent/consent.rb
|
62
76
|
- lib/ibanity/api/consent/processing_operation.rb
|
77
|
+
- lib/ibanity/api/flat_resource.rb
|
63
78
|
- lib/ibanity/api/isabel_connect/access_token.rb
|
64
79
|
- lib/ibanity/api/isabel_connect/account.rb
|
65
80
|
- lib/ibanity/api/isabel_connect/account_report.rb
|
@@ -76,6 +91,7 @@ files:
|
|
76
91
|
- lib/ibanity/api/ponto_connect/integration.rb
|
77
92
|
- lib/ibanity/api/ponto_connect/onboarding_details.rb
|
78
93
|
- lib/ibanity/api/ponto_connect/payment.rb
|
94
|
+
- lib/ibanity/api/ponto_connect/payment_activation_request.rb
|
79
95
|
- lib/ibanity/api/ponto_connect/reauthorization_request.rb
|
80
96
|
- lib/ibanity/api/ponto_connect/sandbox/financial_institution_account.rb
|
81
97
|
- lib/ibanity/api/ponto_connect/sandbox/financial_institution_transaction.rb
|
@@ -88,6 +104,9 @@ files:
|
|
88
104
|
- lib/ibanity/api/sandbox/financial_institution_holding.rb
|
89
105
|
- lib/ibanity/api/sandbox/financial_institution_transaction.rb
|
90
106
|
- lib/ibanity/api/sandbox/financial_institution_user.rb
|
107
|
+
- lib/ibanity/api/webhooks/key.rb
|
108
|
+
- lib/ibanity/api/webhooks/ponto_connect.rb
|
109
|
+
- lib/ibanity/api/webhooks/xs2a.rb
|
91
110
|
- lib/ibanity/api/xs2a/account.rb
|
92
111
|
- lib/ibanity/api/xs2a/account_information_access_request.rb
|
93
112
|
- lib/ibanity/api/xs2a/account_information_access_request_authorization.rb
|
@@ -108,6 +127,7 @@ files:
|
|
108
127
|
- lib/ibanity/http_signature.rb
|
109
128
|
- lib/ibanity/util.rb
|
110
129
|
- lib/ibanity/version.rb
|
130
|
+
- lib/ibanity/webhook.rb
|
111
131
|
- spec/lib/ibanity/base_resource_spec.rb
|
112
132
|
- spec/lib/ibanity/http_signature_spec.rb
|
113
133
|
- spec/lib/ibanity/util_spec.rb
|