bridge_bankin 0.1.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 +7 -0
- data/.github/workflows/main.yml +24 -0
- data/.gitignore +13 -0
- data/.rspec +3 -0
- data/.rubocop.yml +45 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +99 -0
- data/LICENSE.txt +21 -0
- data/README.md +43 -0
- data/Rakefile +12 -0
- data/bin/console +16 -0
- data/bin/setup +8 -0
- data/bridge_bankin.gemspec +49 -0
- data/lib/bridge_bankin.rb +19 -0
- data/lib/bridge_bankin/account.rb +25 -0
- data/lib/bridge_bankin/api/client.rb +113 -0
- data/lib/bridge_bankin/api/error.rb +36 -0
- data/lib/bridge_bankin/api/resource.rb +18 -0
- data/lib/bridge_bankin/authorization.rb +23 -0
- data/lib/bridge_bankin/bank.rb +21 -0
- data/lib/bridge_bankin/bridge_object.rb +105 -0
- data/lib/bridge_bankin/category.rb +21 -0
- data/lib/bridge_bankin/configuration.rb +27 -0
- data/lib/bridge_bankin/connect.rb +51 -0
- data/lib/bridge_bankin/insight.rb +16 -0
- data/lib/bridge_bankin/item.rb +48 -0
- data/lib/bridge_bankin/object_types.rb +18 -0
- data/lib/bridge_bankin/resources.rb +13 -0
- data/lib/bridge_bankin/stock.rb +26 -0
- data/lib/bridge_bankin/transaction.rb +53 -0
- data/lib/bridge_bankin/transfer.rb +53 -0
- data/lib/bridge_bankin/user.rb +60 -0
- data/lib/bridge_bankin/version.rb +5 -0
- metadata +220 -0
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BridgeBankin
|
4
|
+
module API
|
5
|
+
class Error < StandardError
|
6
|
+
def initialize(code, response_body = {})
|
7
|
+
@payload = response_body
|
8
|
+
@code = code
|
9
|
+
@type = payload[:type]
|
10
|
+
@documentation_url = payload[:documentation_url]
|
11
|
+
|
12
|
+
super(payload[:message])
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :payload, :code, :type, :documentation_url
|
16
|
+
end
|
17
|
+
|
18
|
+
class BadRequestError < Error; end
|
19
|
+
|
20
|
+
class UnauthorizedError < Error; end
|
21
|
+
|
22
|
+
class ForbiddenError < Error; end
|
23
|
+
|
24
|
+
class NotFoundError < Error; end
|
25
|
+
|
26
|
+
class ConflictError < Error; end
|
27
|
+
|
28
|
+
class UnsupportedMediaTypeError < Error; end
|
29
|
+
|
30
|
+
class UnprocessableEntityError < Error; end
|
31
|
+
|
32
|
+
class TooManyRequestsError < Error; end
|
33
|
+
|
34
|
+
class InternalServerError < Error; end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BridgeBankin
|
4
|
+
module API
|
5
|
+
module Resource
|
6
|
+
def protected_resource(access_token)
|
7
|
+
api_client.access_token = access_token
|
8
|
+
yield
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def api_client
|
14
|
+
@api_client ||= API::Client.new
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "time"
|
4
|
+
|
5
|
+
module BridgeBankin
|
6
|
+
class Authorization
|
7
|
+
attr_reader :access_token, :expires_at
|
8
|
+
|
9
|
+
def initialize(access_token, expires_at)
|
10
|
+
@access_token = access_token
|
11
|
+
@expires_at = Time.parse(expires_at)
|
12
|
+
end
|
13
|
+
|
14
|
+
class << self
|
15
|
+
include API::Resource
|
16
|
+
|
17
|
+
def generate_token(email:, password:)
|
18
|
+
response = api_client.post("/v2/authenticate", email: email, password: password)
|
19
|
+
new(response[:access_token], response[:expires_at])
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BridgeBankin
|
4
|
+
class Bank < BridgeObject
|
5
|
+
RESOURCE_TYPE = "bank"
|
6
|
+
|
7
|
+
class << self
|
8
|
+
include API::Resource
|
9
|
+
|
10
|
+
def list(**params)
|
11
|
+
data = api_client.get("/v2/banks", params)
|
12
|
+
convert_to_bridge_object(data)
|
13
|
+
end
|
14
|
+
|
15
|
+
def find(id:, **params)
|
16
|
+
data = api_client.get("/v2/banks/#{id}", params)
|
17
|
+
convert_to_bridge_object(data)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BridgeBankin
|
4
|
+
class BridgeObject
|
5
|
+
HIDDEN_ATTRIBUTES = %i[resource_type resource_uri].freeze
|
6
|
+
|
7
|
+
def initialize(**attrs)
|
8
|
+
define_instance_variables(attrs)
|
9
|
+
end
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def convert_to_bridge_object(**data)
|
13
|
+
if data[:resources]
|
14
|
+
data[:resources].map { |resource| convert_to_bridge_object(resource) }
|
15
|
+
elsif data.is_a?(Array)
|
16
|
+
data.map { |val| convert_to_bridge_object(val) }
|
17
|
+
else
|
18
|
+
object_from_resource_type(data)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def object_classes
|
25
|
+
@object_classes ||= ObjectTypes.resource_types_to_classes
|
26
|
+
end
|
27
|
+
|
28
|
+
def object_from_resource_type(data)
|
29
|
+
object_classes.fetch(data[:resource_type], BridgeObject).new(data)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_hash
|
34
|
+
instance_variables.each_with_object({}) do |var, hash|
|
35
|
+
hash[var.to_s.delete("@")] =
|
36
|
+
case instance_variable_get(var)
|
37
|
+
when BridgeObject
|
38
|
+
instance_variable_get(var).to_hash
|
39
|
+
when Array
|
40
|
+
instance_variable_get(var).map { |val| val.is_a?(BridgeObject) ? val.to_hash : val }
|
41
|
+
else
|
42
|
+
instance_variable_get(var)
|
43
|
+
end
|
44
|
+
end.transform_keys!(&:to_sym)
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_json(*_args)
|
48
|
+
to_hash.to_json
|
49
|
+
end
|
50
|
+
|
51
|
+
def ==(other)
|
52
|
+
other.is_a?(BridgeObject) && to_hash == other.to_hash
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def define_instance_variables(attrs)
|
58
|
+
attrs.each do |key, value|
|
59
|
+
next if HIDDEN_ATTRIBUTES.include?(key)
|
60
|
+
|
61
|
+
handle_values_types(key, value) do |parsed_value|
|
62
|
+
instance_variable_set("@#{key}".to_sym, parsed_value)
|
63
|
+
self.class.class_eval { attr_reader key }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def handle_values_types(key, value)
|
69
|
+
yield(
|
70
|
+
case value
|
71
|
+
when Array
|
72
|
+
handle_array_values(value)
|
73
|
+
when Hash
|
74
|
+
handle_hash_values(value)
|
75
|
+
when String
|
76
|
+
handle_time_values(key, value)
|
77
|
+
else
|
78
|
+
value
|
79
|
+
end
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
83
|
+
def handle_array_values(array)
|
84
|
+
array.map do |value|
|
85
|
+
next value unless value.is_a?(Hash)
|
86
|
+
|
87
|
+
handle_hash_values(value)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def handle_hash_values(hash)
|
92
|
+
self.class.convert_to_bridge_object(hash)
|
93
|
+
end
|
94
|
+
|
95
|
+
def handle_time_values(key, value)
|
96
|
+
if key == :date
|
97
|
+
Date.parse(value)
|
98
|
+
elsif key.to_s.match?(/_at$/)
|
99
|
+
Time.parse(value)
|
100
|
+
else
|
101
|
+
value
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BridgeBankin
|
4
|
+
class Category < BridgeObject
|
5
|
+
RESOURCE_TYPE = "category"
|
6
|
+
|
7
|
+
class << self
|
8
|
+
include API::Resource
|
9
|
+
|
10
|
+
def list(**params)
|
11
|
+
data = api_client.get("/v2/categories", params)
|
12
|
+
convert_to_bridge_object(data)
|
13
|
+
end
|
14
|
+
|
15
|
+
def find(id:, **params)
|
16
|
+
data = api_client.get("/v2/categories/#{id}", params)
|
17
|
+
convert_to_bridge_object(data)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BridgeBankin
|
4
|
+
def self.configuration
|
5
|
+
@configuration ||= Configuration.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.configuration=(config)
|
9
|
+
@configuration = config
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.configure
|
13
|
+
yield configuration
|
14
|
+
end
|
15
|
+
|
16
|
+
class Configuration
|
17
|
+
attr_reader :api_base_url, :api_version
|
18
|
+
attr_accessor :api_client_id, :api_client_secret
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
@api_base_url = "https://sync.bankin.com"
|
22
|
+
@api_version = "2019-02-18"
|
23
|
+
@api_client_id = "d16099aec29e445dbb31cf3966b3821e"
|
24
|
+
@api_client_secret = "HEb73vHEGB4Hunv5OMXFUDNIgNonYJ89YaHHRSyidVgCPbCtFWqtED5fZYObA0lm"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BridgeBankin
|
4
|
+
class Connect < BridgeObject
|
5
|
+
class << self
|
6
|
+
include API::Resource
|
7
|
+
|
8
|
+
def connect_item(access_token:, **params)
|
9
|
+
protected_resource(access_token) do
|
10
|
+
data = api_client.get("/v2/connect/items/add/url", params)
|
11
|
+
convert_to_bridge_object(data)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def connect_item_with_iban(access_token:, **params)
|
16
|
+
protected_resource(access_token) do
|
17
|
+
data = api_client.post("/v2/connect/items/add/url", params)
|
18
|
+
convert_to_bridge_object(data)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def edit_item(access_token:, **params)
|
23
|
+
protected_resource(access_token) do
|
24
|
+
data = api_client.get("/v2/connect/items/edit/url", params)
|
25
|
+
convert_to_bridge_object(data)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def item_sync(access_token:, **params)
|
30
|
+
protected_resource(access_token) do
|
31
|
+
data = api_client.get("/v2/connect/items/sync", params)
|
32
|
+
convert_to_bridge_object(data)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def validate_email(access_token:, **params)
|
37
|
+
protected_resource(access_token) do
|
38
|
+
data = api_client.get("/v2/connect/users/email/confirmation/url", params)
|
39
|
+
convert_to_bridge_object(data)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def validate_pro_items(access_token:, **params)
|
44
|
+
protected_resource(access_token) do
|
45
|
+
data = api_client.get("/v2/connect/items/pro/confirmation/url", params)
|
46
|
+
convert_to_bridge_object(data)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BridgeBankin
|
4
|
+
class Insight < BridgeObject
|
5
|
+
class << self
|
6
|
+
include API::Resource
|
7
|
+
|
8
|
+
def categories_insights(access_token:, **params)
|
9
|
+
protected_resource(access_token) do
|
10
|
+
data = api_client.get("/v2/insights/category", params)
|
11
|
+
convert_to_bridge_object(data)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BridgeBankin
|
4
|
+
class Item < BridgeObject
|
5
|
+
RESOURCE_TYPE = "item"
|
6
|
+
|
7
|
+
# TODO: Add support of item statuses
|
8
|
+
|
9
|
+
class << self
|
10
|
+
include API::Resource
|
11
|
+
|
12
|
+
def list(access_token:, **params)
|
13
|
+
protected_resource(access_token) do
|
14
|
+
data = api_client.get("/v2/items", params)
|
15
|
+
convert_to_bridge_object(data)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def find(id:, access_token:, **params)
|
20
|
+
protected_resource(access_token) do
|
21
|
+
data = api_client.get("/v2/items/#{id}", params)
|
22
|
+
convert_to_bridge_object(data)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def refresh(id:, access_token:, **params)
|
27
|
+
protected_resource(access_token) do
|
28
|
+
data = api_client.post("/v2/items/#{id}/refresh", params)
|
29
|
+
convert_to_bridge_object(data)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def refresh_status(id:, access_token:, **params)
|
34
|
+
protected_resource(access_token) do
|
35
|
+
data = api_client.get("/v2/items/#{id}/refresh/status", params)
|
36
|
+
convert_to_bridge_object(data)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def delete(id:, access_token:, **params)
|
41
|
+
protected_resource(access_token) do
|
42
|
+
data = api_client.delete("/v2/items/#{id}", params)
|
43
|
+
convert_to_bridge_object(data)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BridgeBankin
|
4
|
+
module ObjectTypes
|
5
|
+
def self.resource_types_to_classes
|
6
|
+
{
|
7
|
+
Account::RESOURCE_TYPE => Account,
|
8
|
+
Bank::RESOURCE_TYPE => Bank,
|
9
|
+
Category::RESOURCE_TYPE => Category,
|
10
|
+
Item::RESOURCE_TYPE => Item,
|
11
|
+
Stock::RESOURCE_TYPE => Stock,
|
12
|
+
Transaction::RESOURCE_TYPE => Transaction,
|
13
|
+
Transfer::RESOURCE_TYPE => Transfer,
|
14
|
+
User::RESOURCE_TYPE => User
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bridge_bankin/authorization"
|
4
|
+
require "bridge_bankin/account"
|
5
|
+
require "bridge_bankin/category"
|
6
|
+
require "bridge_bankin/stock"
|
7
|
+
require "bridge_bankin/bank"
|
8
|
+
require "bridge_bankin/user"
|
9
|
+
require "bridge_bankin/connect"
|
10
|
+
require "bridge_bankin/item"
|
11
|
+
require "bridge_bankin/transaction"
|
12
|
+
require "bridge_bankin/transfer"
|
13
|
+
require "bridge_bankin/insight"
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BridgeBankin
|
4
|
+
class Stock < BridgeObject
|
5
|
+
RESOURCE_TYPE = "stock"
|
6
|
+
|
7
|
+
class << self
|
8
|
+
include API::Resource
|
9
|
+
|
10
|
+
def list(**params)
|
11
|
+
data = api_client.get("/v2/stocks", params)
|
12
|
+
convert_to_bridge_object(data)
|
13
|
+
end
|
14
|
+
|
15
|
+
def list_updated(**params)
|
16
|
+
data = api_client.get("/v2/stocks/updated", params)
|
17
|
+
convert_to_bridge_object(data)
|
18
|
+
end
|
19
|
+
|
20
|
+
def find(id:, **params)
|
21
|
+
data = api_client.get("/v2/stocks/#{id}", params)
|
22
|
+
convert_to_bridge_object(data)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BridgeBankin
|
4
|
+
class Transaction < BridgeObject
|
5
|
+
RESOURCE_TYPE = "transaction"
|
6
|
+
|
7
|
+
class << self
|
8
|
+
include API::Resource
|
9
|
+
|
10
|
+
def list(access_token:, **params)
|
11
|
+
protected_resource(access_token) do
|
12
|
+
data = api_client.get("/v2/transactions", params)
|
13
|
+
convert_to_bridge_object(data)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def list_updated(access_token:, **params)
|
18
|
+
protected_resource(access_token) do
|
19
|
+
data = api_client.get("/v2/transactions/updated", params)
|
20
|
+
convert_to_bridge_object(data)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def find(id:, access_token:, **params)
|
25
|
+
protected_resource(access_token) do
|
26
|
+
data = api_client.get("/v2/transactions/#{id}", params)
|
27
|
+
convert_to_bridge_object(data)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def list_by_account(account_id:, access_token:, **params)
|
32
|
+
protected_resource(access_token) do
|
33
|
+
data = api_client.get("/v2/accounts/#{account_id}/transactions", params)
|
34
|
+
convert_to_bridge_object(data)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def list_updated_by_account(account_id:, access_token:, **params)
|
39
|
+
protected_resource(access_token) do
|
40
|
+
data = api_client.get("/v2/accounts/#{account_id}/transactions/updated", params)
|
41
|
+
convert_to_bridge_object(data)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def list_by_iban(access_token:, **params)
|
46
|
+
protected_resource(access_token) do
|
47
|
+
data = api_client.post("/v2/transactions/search", params)
|
48
|
+
convert_to_bridge_object(data)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|