ibanity 1.7.0 → 1.11.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/.github/workflows/gem-push.yml +1 -1
- data/CHANGELOG.md +28 -1
- data/ibanity.gemspec +1 -0
- data/lib/ibanity/api/base_resource.rb +50 -22
- data/lib/ibanity/api/flat_resource.rb +20 -0
- data/lib/ibanity/api/isabel_connect/access_token.rb +1 -0
- data/lib/ibanity/api/isabel_connect/bulk_payment_initiation_request.rb +4 -2
- data/lib/ibanity/api/isabel_connect/refresh_token.rb +3 -1
- data/lib/ibanity/api/isabel_connect/token.rb +39 -0
- data/lib/ibanity/api/ponto_connect/bulk_payment.rb +20 -0
- data/lib/ibanity/api/ponto_connect/payment_activation_request.rb +10 -0
- data/lib/ibanity/api/ponto_connect/reauthorization_request.rb +10 -0
- data/lib/ibanity/api/ponto_connect/sandbox/financial_institution_transaction.rb +8 -0
- data/lib/ibanity/api/sandbox/financial_institution_transaction.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/api/xs2a/transaction.rb +10 -5
- data/lib/ibanity/client.rb +83 -9
- data/lib/ibanity/error.rb +2 -0
- data/lib/ibanity/http_signature.rb +28 -5
- data/lib/ibanity/version.rb +1 -1
- data/lib/ibanity/webhook.rb +94 -0
- data/lib/ibanity.rb +24 -3
- data/spec/lib/ibanity/base_resource_spec.rb +42 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/support/fixture.rb +8 -0
- data/spec/support/fixtures/json/relationships/data_with_type.json +21 -0
- data/spec/support/fixtures/json/relationships/data_without_type.json +20 -0
- data/spec/support/fixtures/json/relationships/meta_with_type.json +20 -0
- data/spec/support/fixtures/json/relationships/no_links_related.json +15 -0
- metadata +38 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f0b9e9d3d5bd37f738613c1e77292d6cee3fcbf5016d3d5200d7f4715d673735
|
4
|
+
data.tar.gz: a757cd1e70e6588174e56de7584d10f04b1b2023c6cf9e0c02e5377c8b6a226b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6c9b41e71c94eac22e8416d5689bb1c02c6cee7c1ba73a0fad1da4d6154a3bd18e7ae16baf154b3e5d881a72e18d77e991580f3dd3486ceb5a5fa157b1b652cd
|
7
|
+
data.tar.gz: 6fbd44ba0f4d06bb8e890728311bdf8f28e00008688f6d9005e9da6c55377e98644f1e0d8890543a69de7884a83ed6cfabe1e97f01cf381067ad84a801878bd6
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,31 @@
|
|
1
1
|
# Changelog
|
2
|
+
|
3
|
+
## 1.11
|
4
|
+
|
5
|
+
* Allow to tweak RestClient's timeout.
|
6
|
+
|
7
|
+
## 1.10
|
8
|
+
|
9
|
+
* [Ponto Connect] Add support for payment activation requests.
|
10
|
+
|
11
|
+
* [Webhooks] Add support for webhook signature validation, keys endpoint, and events.
|
12
|
+
|
13
|
+
## 1.9
|
14
|
+
|
15
|
+
* [Ponto Connect] Add account reauthorization requests
|
16
|
+
|
17
|
+
* [Isabel Connect] Deprecate `Ibanity::IsabelConnect::AccessToken` and `Ibanity::IsabelConnect::RefreshToken`, please use `Ibanity::IsabelConnect::Token` instead
|
18
|
+
|
19
|
+
## 1.8
|
20
|
+
|
21
|
+
* [XS2A] Update sandbox transactions
|
22
|
+
|
23
|
+
* [XS2A] Add support to list updated transaction using `synchronization_id`
|
24
|
+
|
25
|
+
* [Ponto Connect] Add support to BulkPayments
|
26
|
+
|
27
|
+
* [Isabel Connect] Add `hideDetails` and `isShared` parameters to `BulkPaymentInititationRequest.create`
|
28
|
+
|
2
29
|
## 1.7
|
3
30
|
### Enhancements
|
4
31
|
|
@@ -29,7 +56,7 @@
|
|
29
56
|
|
30
57
|
### Enhancements
|
31
58
|
|
32
|
-
* Default signature algorithm is now ["hs2019"](https://tools.ietf.org/html/draft-cavage-http-signatures-12#appendix-E.2)
|
59
|
+
* Default signature algorithm is now ["hs2019"](https://tools.ietf.org/html/draft-cavage-http-signatures-12#appendix-E.2)
|
33
60
|
* Add support for periodic and bulk payments
|
34
61
|
* Add snake-case transformation for deeply nested data structures
|
35
62
|
|
data/ibanity.gemspec
CHANGED
@@ -86,6 +86,8 @@ module Ibanity
|
|
86
86
|
private
|
87
87
|
|
88
88
|
def prepare_attributes(raw)
|
89
|
+
raise "Unexpected raw type, expected hash, got #{raw}" unless raw.is_a?(Hash)
|
90
|
+
|
89
91
|
base = {
|
90
92
|
"id" => raw["id"],
|
91
93
|
}
|
@@ -97,23 +99,47 @@ module Ibanity
|
|
97
99
|
|
98
100
|
def setup_relationships(relationships, customer_access_token = nil)
|
99
101
|
relationships.each do |key, relationship|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
102
|
+
url = relationship.dig("links", "related")
|
103
|
+
id = relationship.dig("data", "id")
|
104
|
+
|
105
|
+
if url
|
106
|
+
setup_relationship(customer_access_token, key, relationship, url)
|
107
|
+
elsif id
|
108
|
+
self[Ibanity::Util.underscore("#{key}_id")] = id
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def setup_relationship(customer_access_token, key, relationship, url)
|
114
|
+
if relationship["data"]
|
115
|
+
resource = relationship.dig("data", "type") || key
|
116
|
+
klass = relationship_klass(resource)
|
117
|
+
method_name = Ibanity::Util.underscore(key)
|
118
|
+
define_singleton_method(method_name) do |headers: nil|
|
119
|
+
klass.find_by_uri(uri: url, headers: headers, customer_access_token: customer_access_token)
|
120
|
+
end
|
121
|
+
self[Ibanity::Util.underscore("#{key}_id")] = relationship.dig("data", "id")
|
122
|
+
elsif relationship["meta"]
|
123
|
+
resource = relationship.dig("meta", "type")
|
124
|
+
klass = relationship_klass(resource)
|
125
|
+
method_name = Ibanity::Util.underscore(key)
|
126
|
+
define_singleton_method(method_name) do |headers: nil|
|
127
|
+
klass.find_by_uri(uri: url, headers: headers, customer_access_token: customer_access_token)
|
128
|
+
end
|
129
|
+
elsif relationship.dig("links", "meta", "type")
|
130
|
+
resource = relationship.dig("links", "meta", "type")
|
131
|
+
klass = relationship_klass(resource)
|
132
|
+
method_name = Ibanity::Util.underscore(key)
|
133
|
+
define_singleton_method(method_name) do |headers: nil, **query_params|
|
134
|
+
klass.list_by_uri(uri: url, headers: headers, query_params: query_params, customer_access_token: customer_access_token)
|
135
|
+
end
|
136
|
+
else
|
137
|
+
resource = key
|
138
|
+
singular_resource = resource[0..-2]
|
139
|
+
klass = relationship_klass(singular_resource)
|
140
|
+
method_name = Ibanity::Util.underscore(resource)
|
141
|
+
define_singleton_method(method_name) do |headers: nil, **query_params|
|
142
|
+
klass.list_by_uri(uri: url, headers: headers, query_params: query_params, customer_access_token: customer_access_token)
|
117
143
|
end
|
118
144
|
end
|
119
145
|
end
|
@@ -126,11 +152,13 @@ module Ibanity
|
|
126
152
|
|
127
153
|
def relationship_klass(name)
|
128
154
|
camelized_name = Ibanity::Util.camelize(name)
|
129
|
-
enclosing_module =
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
155
|
+
enclosing_module =
|
156
|
+
if camelized_name == "FinancialInstitution"
|
157
|
+
Ibanity::Xs2a
|
158
|
+
else
|
159
|
+
Object.const_get(self.class.to_s.split("::")[0...-1].join("::"))
|
160
|
+
end
|
161
|
+
|
134
162
|
enclosing_module.const_get(camelized_name)
|
135
163
|
end
|
136
164
|
end
|
@@ -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
|
@@ -2,6 +2,7 @@ module Ibanity
|
|
2
2
|
module IsabelConnect
|
3
3
|
class AccessToken < Ibanity::OAuthResource
|
4
4
|
def self.create(refresh_token:, idempotency_key: nil)
|
5
|
+
warn "WARNING: Ibanity::IsabelConnect::AccessToken.create is deprecated, please use Ibanity::IsabelConnect::Token.create instead"
|
5
6
|
uri = Ibanity.isabel_connect_api_schema["oAuth2"]["accessTokens"]
|
6
7
|
arguments = [
|
7
8
|
["grant_type", "refresh_token"],
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Ibanity
|
2
2
|
module IsabelConnect
|
3
3
|
class BulkPaymentInitiationRequest < Ibanity::BaseResource
|
4
|
-
def self.create(access_token:, raw_content:, filename:, idempotency_key: nil)
|
4
|
+
def self.create(access_token:, raw_content:, filename:, idempotency_key: nil, is_shared: true, hide_details: false)
|
5
5
|
uri = Ibanity.isabel_connect_api_schema["bulkPaymentInitiationRequests"].sub("{bulkPaymentInitiationRequestId}", "")
|
6
6
|
create_file_by_uri(
|
7
7
|
uri: uri,
|
@@ -11,7 +11,9 @@ module Ibanity
|
|
11
11
|
idempotency_key: idempotency_key,
|
12
12
|
headers: {
|
13
13
|
content_type: :xml,
|
14
|
-
"Content-Disposition": "inline; filename=#{filename}"
|
14
|
+
"Content-Disposition": "inline; filename=#{filename}",
|
15
|
+
"Is-Shared": is_shared,
|
16
|
+
"Hide-Details": hide_details
|
15
17
|
}
|
16
18
|
)
|
17
19
|
end
|
@@ -2,6 +2,7 @@ module Ibanity
|
|
2
2
|
module IsabelConnect
|
3
3
|
class RefreshToken < Ibanity::OAuthResource
|
4
4
|
def self.create(authorization_code:, redirect_uri:, idempotency_key: nil)
|
5
|
+
warn "WARNING: Ibanity::IsabelConnect::RefreshToken.create is deprecated, please use Ibanity::IsabelConnect::Token.create instead"
|
5
6
|
uri = Ibanity.isabel_connect_api_schema["oAuth2"]["refreshTokens"]["create"]
|
6
7
|
arguments = [
|
7
8
|
["grant_type", "authorization_code"],
|
@@ -13,8 +14,9 @@ module Ibanity
|
|
13
14
|
payload = URI.encode_www_form(arguments)
|
14
15
|
create_by_uri(uri: uri, payload: payload, idempotency_key: idempotency_key)
|
15
16
|
end
|
16
|
-
|
17
|
+
|
17
18
|
def self.delete(token:)
|
19
|
+
warn "WARNING: Ibanity::IsabelConnect::RefreshToken.delete is deprecated, please use Ibanity::IsabelConnect::Token.delete instead"
|
18
20
|
uri = Ibanity.isabel_connect_api_schema["oAuth2"]["refreshTokens"]["revoke"]
|
19
21
|
arguments = [
|
20
22
|
["token", token],
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Ibanity
|
2
|
+
module IsabelConnect
|
3
|
+
class Token < Ibanity::OAuthResource
|
4
|
+
def self.create(refresh_token: nil, authorization_code: nil, redirect_uri: nil, idempotency_key: nil)
|
5
|
+
uri = Ibanity.isabel_connect_api_schema["oAuth2"]["token"]
|
6
|
+
arguments =
|
7
|
+
if refresh_token
|
8
|
+
[
|
9
|
+
["grant_type", "refresh_token"],
|
10
|
+
["refresh_token", refresh_token],
|
11
|
+
["client_id", Ibanity.client.isabel_connect_client_id],
|
12
|
+
["client_secret", Ibanity.client.isabel_connect_client_secret]
|
13
|
+
]
|
14
|
+
elsif authorization_code
|
15
|
+
[
|
16
|
+
["grant_type", "authorization_code"],
|
17
|
+
["code", authorization_code],
|
18
|
+
["client_id", Ibanity.client.isabel_connect_client_id],
|
19
|
+
["client_secret", Ibanity.client.isabel_connect_client_secret],
|
20
|
+
["redirect_uri", redirect_uri]
|
21
|
+
]
|
22
|
+
end
|
23
|
+
payload = URI.encode_www_form(arguments)
|
24
|
+
create_by_uri(uri: uri, payload: payload, idempotency_key: idempotency_key)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.delete(token:)
|
28
|
+
uri = Ibanity.isabel_connect_api_schema["oAuth2"]["revoke"]
|
29
|
+
arguments = [
|
30
|
+
["token", token],
|
31
|
+
["client_id", Ibanity.client.isabel_connect_client_id],
|
32
|
+
["client_secret", Ibanity.client.isabel_connect_client_secret]
|
33
|
+
]
|
34
|
+
payload = URI.encode_www_form(arguments)
|
35
|
+
create_by_uri(uri: uri, payload: payload)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Ibanity
|
2
|
+
module PontoConnect
|
3
|
+
class BulkPayment < Ibanity::BaseResource
|
4
|
+
def self.find(access_token:, account_id:, id:)
|
5
|
+
uri = Ibanity.ponto_connect_api_schema["account"]["bulkPayments"].sub("{accountId}", account_id).sub("{bulkPaymentId}", id)
|
6
|
+
find_by_uri(uri: uri, customer_access_token: access_token)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.create(account_id:, access_token: nil, **attributes)
|
10
|
+
uri = Ibanity.ponto_connect_api_schema["account"]["bulkPayments"].gsub("{accountId}", account_id).gsub("{bulkPaymentId}", "")
|
11
|
+
create_by_uri(uri: uri, resource_type: "bulkPayment", attributes: attributes, customer_access_token: access_token)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.delete(id:, account_id:, access_token:)
|
15
|
+
uri = Ibanity.ponto_connect_api_schema["account"]["bulkPayments"].gsub("{accountId}", account_id).gsub("{bulkPaymentId}", id)
|
16
|
+
destroy_by_uri(uri: uri, customer_access_token: access_token)
|
17
|
+
end
|
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,10 @@
|
|
1
|
+
module Ibanity
|
2
|
+
module PontoConnect
|
3
|
+
class ReauthorizationRequest < Ibanity::BaseResource
|
4
|
+
def self.create(account_id:, access_token:, **attributes)
|
5
|
+
uri = Ibanity.ponto_connect_api_schema["account"]["reauthorizationRequests"].gsub("{accountId}", account_id)
|
6
|
+
create_by_uri(uri: uri, resource_type: "reauthorizationRequest", attributes: attributes, customer_access_token: access_token)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -25,6 +25,14 @@ module Ibanity
|
|
25
25
|
.sub("{financialInstitutionTransactionId}", "")
|
26
26
|
create_by_uri(uri: uri, resource_type: "financialInstitutionTransaction", attributes: attributes, customer_access_token: access_token)
|
27
27
|
end
|
28
|
+
|
29
|
+
def self.update(access_token:, id:, financial_institution_id:, financial_institution_account_id:, **attributes)
|
30
|
+
uri = Ibanity.ponto_connect_api_schema["sandbox"]["financialInstitution"]["financialInstitutionAccount"]["financialInstitutionTransactions"]
|
31
|
+
.sub("{financialInstitutionId}", financial_institution_id)
|
32
|
+
.sub("{financialInstitutionAccountId}", financial_institution_account_id)
|
33
|
+
.sub("{financialInstitutionTransactionId}", id)
|
34
|
+
update_by_uri(uri: uri, resource_type: "financialInstitutionTransaction", attributes: attributes, customer_access_token: access_token)
|
35
|
+
end
|
28
36
|
end
|
29
37
|
end
|
30
38
|
end
|
@@ -31,6 +31,16 @@ module Ibanity
|
|
31
31
|
find_by_uri(uri: uri)
|
32
32
|
end
|
33
33
|
|
34
|
+
def self.update(id:, financial_institution_user_id:, financial_institution_id:, financial_institution_account_id:, idempotency_key: nil, **attributes)
|
35
|
+
path = Ibanity.sandbox_api_schema["financialInstitution"]["financialInstitutionAccount"]["financialInstitutionTransactions"]
|
36
|
+
.gsub("{financialInstitutionId}", financial_institution_id)
|
37
|
+
.gsub("{financialInstitutionUserId}", financial_institution_user_id)
|
38
|
+
.gsub("{financialInstitutionAccountId}", financial_institution_account_id)
|
39
|
+
.gsub("{financialInstitutionTransactionId}", id)
|
40
|
+
uri = Ibanity.client.build_uri(path)
|
41
|
+
update_by_uri(uri: uri, resource_type: "financialInstitutionTransaction", attributes: attributes, idempotency_key: idempotency_key)
|
42
|
+
end
|
43
|
+
|
34
44
|
def self.delete(id:, financial_institution_user_id:, financial_institution_id:, financial_institution_account_id:)
|
35
45
|
path = Ibanity.sandbox_api_schema["financialInstitution"]["financialInstitutionAccount"]["financialInstitutionTransactions"]
|
36
46
|
.gsub("{financialInstitutionId}", financial_institution_id)
|
@@ -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
|
@@ -1,11 +1,16 @@
|
|
1
1
|
module Ibanity
|
2
2
|
module Xs2a
|
3
3
|
class Transaction < Ibanity::BaseResource
|
4
|
-
def self.list(financial_institution_id
|
5
|
-
uri =
|
6
|
-
.
|
7
|
-
.sub("{
|
8
|
-
|
4
|
+
def self.list(financial_institution_id: nil, account_id: nil, synchronization_id: nil, customer_access_token:, headers: nil, **query_params)
|
5
|
+
uri = if synchronization_id
|
6
|
+
Ibanity.xs2a_api_schema["customer"]["synchronization"]["updatedTransactions"]
|
7
|
+
.sub("{synchronizationId}", synchronization_id)
|
8
|
+
else
|
9
|
+
Ibanity.xs2a_api_schema["customer"]["financialInstitution"]["transactions"]
|
10
|
+
.sub("{financialInstitutionId}", financial_institution_id)
|
11
|
+
.sub("{accountId}", account_id)
|
12
|
+
.sub("{transactionId}", "")
|
13
|
+
end
|
9
14
|
list_by_uri(uri: uri, query_params: query_params, customer_access_token: customer_access_token, headers: headers)
|
10
15
|
end
|
11
16
|
|
data/lib/ibanity/client.rb
CHANGED
@@ -1,22 +1,43 @@
|
|
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
|
-
def initialize(
|
6
|
+
def initialize(
|
7
|
+
certificate:,
|
8
|
+
key:,
|
9
|
+
key_passphrase:,
|
10
|
+
signature_certificate: nil,
|
11
|
+
signature_certificate_id: nil,
|
12
|
+
signature_key: nil,
|
13
|
+
signature_key_passphrase: nil,
|
14
|
+
api_scheme: "https",
|
15
|
+
api_host: "api.ibanity.com",
|
16
|
+
ssl_ca_file: nil,
|
17
|
+
isabel_connect_client_id: "valid_client_id",
|
18
|
+
isabel_connect_client_secret: "valid_client_secret",
|
19
|
+
ponto_connect_client_id: nil,
|
20
|
+
ponto_connect_client_secret: nil,
|
21
|
+
application_id: nil,
|
22
|
+
debug_http_requests: false,
|
23
|
+
timeout: 60
|
24
|
+
)
|
7
25
|
@isabel_connect_client_id = isabel_connect_client_id
|
8
26
|
@isabel_connect_client_secret = isabel_connect_client_secret
|
9
27
|
@ponto_connect_client_id = ponto_connect_client_id
|
10
28
|
@ponto_connect_client_secret = ponto_connect_client_secret
|
11
29
|
@certificate = OpenSSL::X509::Certificate.new(certificate)
|
12
30
|
@key = OpenSSL::PKey::RSA.new(key, key_passphrase)
|
31
|
+
@http_debug = debug_http_requests
|
13
32
|
if signature_certificate
|
14
33
|
@signature_certificate = OpenSSL::X509::Certificate.new(signature_certificate)
|
15
34
|
@signature_certificate_id = signature_certificate_id
|
16
35
|
@signature_key = OpenSSL::PKey::RSA.new(signature_key, signature_key_passphrase)
|
17
36
|
end
|
18
|
-
@base_uri = "#{api_scheme}://#{api_host}
|
37
|
+
@base_uri = "#{api_scheme}://#{api_host}"
|
19
38
|
@ssl_ca_file = ssl_ca_file
|
39
|
+
@application_id = application_id
|
40
|
+
@timeout = timeout
|
20
41
|
end
|
21
42
|
|
22
43
|
def get(uri:, query_params: {}, customer_access_token: nil, headers: nil, json: true)
|
@@ -25,12 +46,12 @@ module Ibanity
|
|
25
46
|
end
|
26
47
|
|
27
48
|
def post(uri:, payload:, query_params: {}, customer_access_token: nil, idempotency_key: nil, json: true, headers: nil)
|
28
|
-
headers = build_headers(customer_access_token: customer_access_token, idempotency_key: idempotency_key, extra_headers: headers, json: json)
|
49
|
+
headers = build_headers(customer_access_token: customer_access_token, idempotency_key: idempotency_key, extra_headers: headers, json: json, payload: payload)
|
29
50
|
execute(method: :post, uri: uri, headers: headers, query_params: query_params, payload: payload, json: json)
|
30
51
|
end
|
31
52
|
|
32
53
|
def patch(uri:, payload:, query_params: {}, customer_access_token: nil, idempotency_key: nil, json: true)
|
33
|
-
headers = build_headers(customer_access_token: customer_access_token, idempotency_key: idempotency_key, json: json)
|
54
|
+
headers = build_headers(customer_access_token: customer_access_token, idempotency_key: idempotency_key, json: json, payload: payload)
|
34
55
|
execute(method: :patch, uri: uri, headers: headers, query_params: query_params, payload: payload, json: json)
|
35
56
|
end
|
36
57
|
|
@@ -46,6 +67,15 @@ module Ibanity
|
|
46
67
|
private
|
47
68
|
|
48
69
|
def execute(method:, uri:, headers:, query_params: {}, payload: nil, json:)
|
70
|
+
case payload
|
71
|
+
when NilClass
|
72
|
+
payload = ''
|
73
|
+
when Hash
|
74
|
+
payload = json ? payload.to_json : payload
|
75
|
+
when Pathname
|
76
|
+
payload = File.open(payload, 'rb')
|
77
|
+
end
|
78
|
+
|
49
79
|
if @signature_certificate
|
50
80
|
signature = Ibanity::HttpSignature.new(
|
51
81
|
certificate: @signature_certificate,
|
@@ -55,23 +85,31 @@ module Ibanity
|
|
55
85
|
uri: uri,
|
56
86
|
query_params: query_params,
|
57
87
|
headers: headers,
|
58
|
-
payload: payload
|
88
|
+
payload: payload
|
59
89
|
)
|
60
90
|
headers.merge!(signature.signature_headers)
|
61
91
|
end
|
92
|
+
|
62
93
|
query = {
|
63
94
|
method: method,
|
64
95
|
url: uri,
|
65
96
|
headers: headers.merge(params: query_params),
|
66
|
-
payload: payload
|
97
|
+
payload: payload,
|
67
98
|
ssl_client_cert: @certificate,
|
68
99
|
ssl_client_key: @key,
|
69
|
-
ssl_ca_file: @ssl_ca_file
|
100
|
+
ssl_ca_file: @ssl_ca_file,
|
101
|
+
timeout: @timeout
|
70
102
|
}
|
103
|
+
|
104
|
+
log("HTTP Request", query) if @http_debug
|
105
|
+
|
71
106
|
raw_response = RestClient::Request.execute(query) do |response, request, result, &block|
|
107
|
+
log("HTTP response", { status: response.code, headers: response.headers, body: response.body }) if @http_debug
|
108
|
+
|
72
109
|
if response.code >= 400
|
73
110
|
ibanity_request_id = response.headers[:ibanity_request_id]
|
74
111
|
body = JSON.parse(response.body)
|
112
|
+
|
75
113
|
raise Ibanity::Error.new(body["errors"] || body, ibanity_request_id), "Ibanity request failed."
|
76
114
|
else
|
77
115
|
response.return!(&block)
|
@@ -80,12 +118,15 @@ module Ibanity
|
|
80
118
|
JSON.parse(raw_response)
|
81
119
|
rescue JSON::ParserError => e
|
82
120
|
return raw_response.body
|
121
|
+
ensure
|
122
|
+
payload.close if payload.is_a?(File)
|
83
123
|
end
|
84
124
|
|
85
|
-
def build_headers(customer_access_token: nil, idempotency_key: nil, extra_headers: nil, json:)
|
125
|
+
def build_headers(customer_access_token: nil, idempotency_key: nil, extra_headers: nil, json:, payload: nil)
|
86
126
|
headers = {
|
87
127
|
accept: :json,
|
88
128
|
}
|
129
|
+
headers["Transfer-Encoding"] = "chunked" if payload.is_a?(Pathname)
|
89
130
|
headers[:content_type] = :json if json
|
90
131
|
headers["Authorization"] = "Bearer #{customer_access_token}" unless customer_access_token.nil?
|
91
132
|
headers["Ibanity-Idempotency-Key"] = idempotency_key unless idempotency_key.nil?
|
@@ -95,5 +136,38 @@ module Ibanity
|
|
95
136
|
headers.merge(extra_headers)
|
96
137
|
end
|
97
138
|
end
|
139
|
+
|
140
|
+
def log(tag, info)
|
141
|
+
unless info.is_a?(Hash)
|
142
|
+
puts "[DEBUG] #{tag}: #{info}"
|
143
|
+
return
|
144
|
+
end
|
145
|
+
|
146
|
+
info = JSON.parse(info.to_json)
|
147
|
+
|
148
|
+
if info.dig("headers", "Authorization")
|
149
|
+
info["headers"]["Authorization"] = "[filtered]"
|
150
|
+
end
|
151
|
+
info.delete("proxy")
|
152
|
+
info.delete("ssl_client_cert")
|
153
|
+
info.delete("ssl_client_key")
|
154
|
+
if info.dig("payload").is_a?(Hash) && info.dig("payload", "client_secret")
|
155
|
+
info["payload"]["client_secret"] = "[filtered]"
|
156
|
+
end
|
157
|
+
|
158
|
+
if info["body"]&.is_a?(String)
|
159
|
+
begin
|
160
|
+
info["body"] = JSON.parse(info["body"])
|
161
|
+
rescue => exception
|
162
|
+
info["body"] = Base64.strict_encode64(info["body"])
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
begin
|
167
|
+
puts "[DEBUG] #{tag}: #{info.to_json}"
|
168
|
+
rescue => e
|
169
|
+
puts "[DEBUG] #{tag}: #{info}"
|
170
|
+
end
|
171
|
+
end
|
98
172
|
end
|
99
173
|
end
|
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
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require "base64"
|
2
|
+
require "pathname"
|
2
3
|
|
3
4
|
module Ibanity
|
4
5
|
class HttpSignature
|
@@ -29,16 +30,38 @@ module Ibanity
|
|
29
30
|
}
|
30
31
|
end
|
31
32
|
|
32
|
-
private
|
33
|
-
|
34
33
|
def payload_digest
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
@payload_digest ||= compute_digest
|
35
|
+
end
|
36
|
+
|
37
|
+
def compute_digest
|
38
|
+
case @payload
|
39
|
+
when NilClass
|
40
|
+
digest = compute_digest_string("")
|
41
|
+
when String
|
42
|
+
digest = compute_digest_string(@payload)
|
43
|
+
when File
|
44
|
+
digest = compute_digest_file(@payload)
|
45
|
+
end
|
38
46
|
base64 = Base64.urlsafe_encode64(digest.digest)
|
39
47
|
"SHA-512=#{base64}"
|
40
48
|
end
|
41
49
|
|
50
|
+
def compute_digest_string(str)
|
51
|
+
digest = OpenSSL::Digest::SHA512.new
|
52
|
+
digest.update(str)
|
53
|
+
end
|
54
|
+
|
55
|
+
def compute_digest_file(pathname)
|
56
|
+
digest = OpenSSL::Digest::SHA512.new
|
57
|
+
File.open(pathname, 'rb') do |f|
|
58
|
+
while buffer = f.read(256_000)
|
59
|
+
digest << buffer
|
60
|
+
end
|
61
|
+
end
|
62
|
+
digest
|
63
|
+
end
|
64
|
+
|
42
65
|
def headers_to_sign
|
43
66
|
result = ["(request-target)", "host", "digest", "(created)"]
|
44
67
|
result << "authorization" unless @headers["Authorization"].nil?
|
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"
|
@@ -33,6 +36,7 @@ require_relative "ibanity/api/isabel_connect/intraday_transaction"
|
|
33
36
|
require_relative "ibanity/api/isabel_connect/account_report"
|
34
37
|
require_relative "ibanity/api/isabel_connect/access_token"
|
35
38
|
require_relative "ibanity/api/isabel_connect/refresh_token"
|
39
|
+
require_relative "ibanity/api/isabel_connect/token"
|
36
40
|
require_relative "ibanity/api/isabel_connect/bulk_payment_initiation_request"
|
37
41
|
require_relative "ibanity/api/sandbox/financial_institution_account"
|
38
42
|
require_relative "ibanity/api/sandbox/financial_institution_transaction"
|
@@ -46,18 +50,24 @@ require_relative "ibanity/api/ponto_connect/synchronization"
|
|
46
50
|
require_relative "ibanity/api/consent/consent"
|
47
51
|
require_relative "ibanity/api/consent/processing_operation"
|
48
52
|
require_relative "ibanity/api/ponto_connect/payment"
|
53
|
+
require_relative "ibanity/api/ponto_connect/bulk_payment"
|
49
54
|
require_relative "ibanity/api/ponto_connect/user_info"
|
50
55
|
require_relative "ibanity/api/ponto_connect/usage"
|
51
56
|
require_relative "ibanity/api/ponto_connect/integration"
|
52
57
|
require_relative "ibanity/api/ponto_connect/sandbox/financial_institution_account"
|
53
58
|
require_relative "ibanity/api/ponto_connect/sandbox/financial_institution_transaction"
|
54
59
|
require_relative "ibanity/api/ponto_connect/onboarding_details"
|
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"
|
55
65
|
|
56
66
|
module Ibanity
|
57
67
|
class << self
|
58
68
|
def client
|
59
69
|
options = configuration.to_h.delete_if { |_, v| v.nil? }
|
60
|
-
@client ||= Ibanity::Client.new(options)
|
70
|
+
@client ||= Ibanity::Client.new(**options)
|
61
71
|
end
|
62
72
|
|
63
73
|
def configure
|
@@ -66,6 +76,7 @@ module Ibanity
|
|
66
76
|
@isabel_connect_api_schema = nil
|
67
77
|
@consent_api_schema = nil
|
68
78
|
@ponto_connect_api_schema = nil
|
79
|
+
@webhooks_api_schema = nil
|
69
80
|
@sandbox_api_schema = nil
|
70
81
|
@configuration = nil
|
71
82
|
yield configuration
|
@@ -86,8 +97,10 @@ module Ibanity
|
|
86
97
|
:ponto_connect_client_secret,
|
87
98
|
:api_scheme,
|
88
99
|
:api_host,
|
89
|
-
:
|
90
|
-
:
|
100
|
+
:ssl_ca_file,
|
101
|
+
:application_id,
|
102
|
+
:debug_http_requests,
|
103
|
+
:timeout
|
91
104
|
).new
|
92
105
|
end
|
93
106
|
|
@@ -111,6 +124,14 @@ module Ibanity
|
|
111
124
|
@consent_api_schema ||= client.get(uri: "#{client.base_uri}/consent")["links"]
|
112
125
|
end
|
113
126
|
|
127
|
+
def webhooks_api_schema
|
128
|
+
@webhooks_api_schema ||= client.get(uri: "#{client.base_uri}/webhooks")["links"]
|
129
|
+
end
|
130
|
+
|
131
|
+
def webhook_keys
|
132
|
+
@webhook_keys ||= Ibanity::Webhooks::Key.list
|
133
|
+
end
|
134
|
+
|
114
135
|
def respond_to_missing?(method_name, include_private = false)
|
115
136
|
client.respond_to?(method_name, include_private)
|
116
137
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require "ibanity"
|
2
|
+
|
3
|
+
class Ibanity::Xs2a::Car < Ibanity::BaseResource; end
|
4
|
+
class Ibanity::Xs2a::Manufacturer < Ibanity::BaseResource; end
|
5
|
+
|
6
|
+
RSpec.describe Ibanity::BaseResource do
|
7
|
+
describe "#relationship_klass" do
|
8
|
+
context "when 'data' attribute is present" do
|
9
|
+
it "retrieves the resource name from the 'type' attribute if it is present" do
|
10
|
+
car = Ibanity::Xs2a::Car.new(Fixture.load_json("relationships/data_with_type.json"))
|
11
|
+
|
12
|
+
expect(car).to respond_to(:maker)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "falls back to the element name otherwise" do
|
16
|
+
car = Ibanity::Xs2a::Car.new(Fixture.load_json("relationships/data_without_type.json"))
|
17
|
+
|
18
|
+
expect(car).to respond_to(:manufacturer)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "when the 'links' attribute is present" do
|
23
|
+
it "retrieves the resource name from the 'type' attribute within the 'links' attribute" do
|
24
|
+
car = Ibanity::Xs2a::Car.new(Fixture.load_json("relationships/meta_with_type.json"))
|
25
|
+
|
26
|
+
expect(car).to respond_to(:manufacturer)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "when there's no 'links/related' element" do
|
31
|
+
let(:car) { Ibanity::Xs2a::Car.new(Fixture.load_json("relationships/no_links_related.json")) }
|
32
|
+
|
33
|
+
it "sets up a '<relationship_key>_id' property when there is a 'data/id' element" do
|
34
|
+
expect(car.manufacturer_id).to eq("6680437c")
|
35
|
+
end
|
36
|
+
|
37
|
+
it "discards the relationship" do
|
38
|
+
expect(car).not_to respond_to(:manufacturer)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -12,10 +12,16 @@
|
|
12
12
|
# the additional setup, and require it from the spec files that actually need
|
13
13
|
# it.
|
14
14
|
#
|
15
|
+
|
16
|
+
Pathname.glob(Pathname.pwd().join("spec", "support", "**/*.rb")).each do |f|
|
17
|
+
require f
|
18
|
+
end
|
19
|
+
|
15
20
|
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
16
21
|
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
17
22
|
|
18
23
|
RSpec.configure do |config|
|
24
|
+
config.include(Fixture)
|
19
25
|
# rspec-expectations config goes here. You can use an alternate
|
20
26
|
# assertion/expectation library such as wrong or the stdlib/minitest
|
21
27
|
# assertions if you prefer.
|
@@ -0,0 +1,21 @@
|
|
1
|
+
{
|
2
|
+
"attributes": {
|
3
|
+
"color": "blue"
|
4
|
+
},
|
5
|
+
"id": "62ebd4687e",
|
6
|
+
"links": {
|
7
|
+
"self": "https://www.cardb.com/models/62ebd4687e"
|
8
|
+
},
|
9
|
+
"relationships": {
|
10
|
+
"maker": {
|
11
|
+
"data": {
|
12
|
+
"id": "c4ebf0f7",
|
13
|
+
"type": "manufacturer"
|
14
|
+
},
|
15
|
+
"links": {
|
16
|
+
"related": "https://www.cardb.com/manufacturers/c4ebf0f7"
|
17
|
+
}
|
18
|
+
}
|
19
|
+
},
|
20
|
+
"type": "car"
|
21
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
{
|
2
|
+
"attributes": {
|
3
|
+
"color": "blue"
|
4
|
+
},
|
5
|
+
"id": "62ebd4687e",
|
6
|
+
"links": {
|
7
|
+
"self": "https://www.cardb.com/models/62ebd4687e"
|
8
|
+
},
|
9
|
+
"relationships": {
|
10
|
+
"manufacturer": {
|
11
|
+
"data": {
|
12
|
+
"id": "c4ebf0f7"
|
13
|
+
},
|
14
|
+
"links": {
|
15
|
+
"related": "https://www.cardb.com/manufacturers/c4ebf0f7"
|
16
|
+
}
|
17
|
+
}
|
18
|
+
},
|
19
|
+
"type": "car"
|
20
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
{
|
2
|
+
"attributes": {
|
3
|
+
"color": "blue"
|
4
|
+
},
|
5
|
+
"id": "62ebd4687e",
|
6
|
+
"links": {
|
7
|
+
"self": "https://www.cardb.com/models/62ebd4687e"
|
8
|
+
},
|
9
|
+
"relationships": {
|
10
|
+
"manufacturer": {
|
11
|
+
"links": {
|
12
|
+
"related": "https://www.cardb.com/manufacturers/c4ebf0f7"
|
13
|
+
},
|
14
|
+
"meta": {
|
15
|
+
"type": "manufacturer"
|
16
|
+
}
|
17
|
+
}
|
18
|
+
},
|
19
|
+
"type": "car"
|
20
|
+
}
|
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.11.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-20 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
|
@@ -67,13 +82,17 @@ files:
|
|
67
82
|
- lib/ibanity/api/isabel_connect/bulk_payment_initiation_request.rb
|
68
83
|
- lib/ibanity/api/isabel_connect/intraday_transaction.rb
|
69
84
|
- lib/ibanity/api/isabel_connect/refresh_token.rb
|
85
|
+
- lib/ibanity/api/isabel_connect/token.rb
|
70
86
|
- lib/ibanity/api/isabel_connect/transaction.rb
|
71
87
|
- lib/ibanity/api/o_auth_resource.rb
|
72
88
|
- lib/ibanity/api/ponto_connect/account.rb
|
89
|
+
- lib/ibanity/api/ponto_connect/bulk_payment.rb
|
73
90
|
- lib/ibanity/api/ponto_connect/financial_institution.rb
|
74
91
|
- lib/ibanity/api/ponto_connect/integration.rb
|
75
92
|
- lib/ibanity/api/ponto_connect/onboarding_details.rb
|
76
93
|
- lib/ibanity/api/ponto_connect/payment.rb
|
94
|
+
- lib/ibanity/api/ponto_connect/payment_activation_request.rb
|
95
|
+
- lib/ibanity/api/ponto_connect/reauthorization_request.rb
|
77
96
|
- lib/ibanity/api/ponto_connect/sandbox/financial_institution_account.rb
|
78
97
|
- lib/ibanity/api/ponto_connect/sandbox/financial_institution_transaction.rb
|
79
98
|
- lib/ibanity/api/ponto_connect/synchronization.rb
|
@@ -85,6 +104,9 @@ files:
|
|
85
104
|
- lib/ibanity/api/sandbox/financial_institution_holding.rb
|
86
105
|
- lib/ibanity/api/sandbox/financial_institution_transaction.rb
|
87
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
|
88
110
|
- lib/ibanity/api/xs2a/account.rb
|
89
111
|
- lib/ibanity/api/xs2a/account_information_access_request.rb
|
90
112
|
- lib/ibanity/api/xs2a/account_information_access_request_authorization.rb
|
@@ -105,10 +127,17 @@ files:
|
|
105
127
|
- lib/ibanity/http_signature.rb
|
106
128
|
- lib/ibanity/util.rb
|
107
129
|
- lib/ibanity/version.rb
|
130
|
+
- lib/ibanity/webhook.rb
|
131
|
+
- spec/lib/ibanity/base_resource_spec.rb
|
108
132
|
- spec/lib/ibanity/http_signature_spec.rb
|
109
133
|
- spec/lib/ibanity/util_spec.rb
|
110
134
|
- spec/spec_helper.rb
|
111
135
|
- spec/support/crypto_helper.rb
|
136
|
+
- spec/support/fixture.rb
|
137
|
+
- spec/support/fixtures/json/relationships/data_with_type.json
|
138
|
+
- spec/support/fixtures/json/relationships/data_without_type.json
|
139
|
+
- spec/support/fixtures/json/relationships/meta_with_type.json
|
140
|
+
- spec/support/fixtures/json/relationships/no_links_related.json
|
112
141
|
- spec/support/fixtures/signature/test-certificate.pem
|
113
142
|
- spec/support/fixtures/signature/test-private_key.pem
|
114
143
|
- spec/support/fixtures/signature/test-public_key.pem
|
@@ -131,15 +160,21 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
131
160
|
- !ruby/object:Gem::Version
|
132
161
|
version: '0'
|
133
162
|
requirements: []
|
134
|
-
rubygems_version: 3.0.3
|
163
|
+
rubygems_version: 3.0.3.1
|
135
164
|
signing_key:
|
136
165
|
specification_version: 4
|
137
166
|
summary: Ibanity Ruby Client
|
138
167
|
test_files:
|
168
|
+
- spec/lib/ibanity/base_resource_spec.rb
|
139
169
|
- spec/lib/ibanity/http_signature_spec.rb
|
140
170
|
- spec/lib/ibanity/util_spec.rb
|
141
171
|
- spec/spec_helper.rb
|
142
172
|
- spec/support/crypto_helper.rb
|
173
|
+
- spec/support/fixture.rb
|
174
|
+
- spec/support/fixtures/json/relationships/data_with_type.json
|
175
|
+
- spec/support/fixtures/json/relationships/data_without_type.json
|
176
|
+
- spec/support/fixtures/json/relationships/meta_with_type.json
|
177
|
+
- spec/support/fixtures/json/relationships/no_links_related.json
|
143
178
|
- spec/support/fixtures/signature/test-certificate.pem
|
144
179
|
- spec/support/fixtures/signature/test-private_key.pem
|
145
180
|
- spec/support/fixtures/signature/test-public_key.pem
|