figo 1.2.5 → 1.3.3

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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/config.yml +4 -0
  4. data/console_demo.rb +1 -1
  5. data/figo.gemspec +3 -3
  6. data/lib/account/api_call.rb +55 -0
  7. data/lib/account/model.rb +122 -0
  8. data/lib/account_balance/api_call.rb +18 -0
  9. data/lib/account_balance/model.rb +31 -0
  10. data/lib/authentification/api_call.rb +88 -0
  11. data/lib/bank/api_call.rb +49 -0
  12. data/lib/bank/model.rb +23 -0
  13. data/lib/base.rb +56 -0
  14. data/lib/cacert.pem +0 -0
  15. data/lib/figo.rb +54 -380
  16. data/lib/helpers/error.rb +20 -0
  17. data/lib/helpers/https.rb +52 -0
  18. data/lib/notification/api_call.rb +40 -0
  19. data/lib/notification/model.rb +27 -0
  20. data/lib/payment/api_call.rb +71 -0
  21. data/lib/payment/model.rb +75 -0
  22. data/lib/process/api_call.rb +17 -0
  23. data/lib/process/model.rb +34 -0
  24. data/lib/security/api_call.rb +59 -0
  25. data/lib/security/model.rb +83 -0
  26. data/lib/standing_order/api_call.rb +24 -0
  27. data/lib/standing_order/model.rb +75 -0
  28. data/lib/synchronization_status/api_call.rb +27 -0
  29. data/lib/synchronization_status/model.rb +23 -0
  30. data/lib/task/api_call.rb +37 -0
  31. data/lib/task/model.rb +43 -0
  32. data/lib/transaction/api_call.rb +57 -0
  33. data/lib/transaction/model.rb +75 -0
  34. data/lib/user/api_call.rb +46 -0
  35. data/lib/user/model.rb +55 -0
  36. data/test/config.yml +7 -0
  37. data/test/test_account_sync_and_setup.rb +67 -0
  38. data/test/test_accounts.rb +106 -0
  39. data/test/test_authentififcation.rb +68 -0
  40. data/test/test_business_processes.rb +43 -0
  41. data/test/test_figo.rb +5 -86
  42. data/test/test_notifications.rb +83 -0
  43. data/test/test_payments.rb +106 -0
  44. data/test/test_securities.rb +70 -0
  45. data/test/test_standing_orders.rb +49 -0
  46. data/test/test_transactions.rb +87 -0
  47. data/test/test_user_management.rb +91 -0
  48. metadata +64 -14
  49. data/lib/models.rb +0 -466
@@ -0,0 +1,20 @@
1
+ module Figo
2
+ # Base class for all errors transported via the figo Connect API.
3
+ class Error < RuntimeError
4
+ # Initialize error object.
5
+ #
6
+ # @param error [String] the error code
7
+ # @param error_description [String] the error description
8
+ def initialize(error, error_description)
9
+ @error = error
10
+ @error_description = error_description
11
+ end
12
+
13
+ # Convert error object to string.
14
+ #
15
+ # @return [String] the error description
16
+ def to_s
17
+ return @error_description
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,52 @@
1
+ require "net/http/persistent"
2
+ module Figo
3
+ # HTTPS class with certificate authentication and enhanced error handling.
4
+ class HTTPS < Net::HTTP::Persistent
5
+ # Overwrite `initialize` method from `Net::HTTP::Persistent`.
6
+ #
7
+ # Verify fingerprints of server SSL/TLS certificates.
8
+ def initialize(name = nil, proxy = nil, fingerprints)
9
+ super(name: name, proxy: proxy)
10
+
11
+ # Attribute ca_file must be set, otherwise verify_callback would never be called.
12
+ @ca_file = "lib/cacert.pem"
13
+ @verify_callback = proc do |preverify_ok, store_context|
14
+ if preverify_ok and store_context.error == 0
15
+ certificate = OpenSSL::X509::Certificate.new(store_context.chain[0])
16
+ fingerprint = Digest::SHA1.hexdigest(certificate.to_der).upcase.scan(/../).join(":")
17
+ fingerprints.include?(fingerprint)
18
+ else
19
+ false
20
+ end
21
+ end
22
+ end
23
+
24
+ # Overwrite `request` method from `Net::HTTP::Persistent`.
25
+ #
26
+ # Raise error when a REST API error is returned.
27
+ def request(uri, req = nil, &block)
28
+ response = super(uri, req, &block)
29
+
30
+ # Evaluate HTTP response.
31
+ case response
32
+ when Net::HTTPSuccess
33
+ return response
34
+ when Net::HTTPBadRequest
35
+ hash = JSON.parse(response.body)
36
+ raise Error.new(hash["error"], hash["error"]["description"])
37
+ when Net::HTTPUnauthorized
38
+ raise Error.new("unauthorized", "Missing, invalid or expired access token.")
39
+ when Net::HTTPForbidden
40
+ raise Error.new("forbidden", "Insufficient permission.")
41
+ when Net::HTTPNotFound
42
+ return nil
43
+ when Net::HTTPMethodNotAllowed
44
+ raise Error.new("method_not_allowed", "Unexpected request method.")
45
+ when Net::HTTPServiceUnavailable
46
+ raise Error.new("service_unavailable", "Exceeded rate limit.")
47
+ else
48
+ raise Error.new("internal_server_error", "We are very sorry, but something went wrong.")
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,40 @@
1
+ require_relative "model.rb"
2
+ module Figo
3
+ # Retrieve list of registered notifications.
4
+ #
5
+ # @return [Notification] an array of `Notification` objects, one for each registered notification
6
+ def notifications
7
+ query_api_object Notification, "/rest/notifications", nil, "GET", "notifications"
8
+ end
9
+
10
+ # Retrieve specific notification.
11
+ #
12
+ # @param notification_id [String] ID of the notification to be retrieved
13
+ # @return [Notification] `Notification` object for the respective notification
14
+ def get_notification(notification_id)
15
+ query_api_object Notification, "/rest/notifications/#{notification_id}"
16
+ end
17
+
18
+ # Register a new notification.
19
+ #
20
+ # @param notification [Notification] notification to be crated. It should not have a notification_id set.
21
+ # @return [Notification] newly created `Notification` object
22
+ def add_notification(notification)
23
+ query_api_object Notification, "/rest/notifications", notification.dump(), "POST"
24
+ end
25
+
26
+ # Modify notification.
27
+ #
28
+ # @param notification [Notification] modified notification object
29
+ # @return [Notification] modified notification returned by server
30
+ def modify_notification(notification)
31
+ query_api_object Notification, "/rest/notifications/#{notification.notification_id}", notification.dump(), "PUT"
32
+ end
33
+
34
+ # Unregister notification.
35
+ #
36
+ # @param notification [Notification, String] notification object which should be deleted or its ID
37
+ def remove_notification(notification)
38
+ query_api notification.is_a?(String) ? "/rest/notifications/#{notification}" : "/rest/notifications/#{notification.notification_id}", nil, "DELETE"
39
+ end
40
+ end
@@ -0,0 +1,27 @@
1
+ require_relative "../base.rb"
2
+ module Figo
3
+ # Object representing a configured notification, e.g. a webhook or email hook
4
+ class Notification < Base
5
+ @dump_attributes = [:observe_key, :notify_uri, :state]
6
+
7
+ def initialize(session, json)
8
+ super(session, json)
9
+ end
10
+
11
+ # Internal figo Connect notification ID from the notification registration response
12
+ # @return [String]
13
+ attr_accessor :notification_id
14
+
15
+ # One of the notification keys specified in the figo Connect API specification
16
+ # @return [String]
17
+ attr_accessor :observe_key
18
+
19
+ # Notification messages will be sent to this URL
20
+ # @return [String]
21
+ attr_accessor :notify_uri
22
+
23
+ # State similiar to sync and logon process. It will passed as POST payload for webhooks
24
+ # @return [String]
25
+ attr_accessor :state
26
+ end
27
+ end
@@ -0,0 +1,71 @@
1
+ require_relative "model.rb"
2
+ module Figo
3
+ # Retrieve list of all payments (on all accounts or one)
4
+ #
5
+ # @param account_id [String] ID of the account for whicht to list the payments
6
+ # @return [Payment] an array of `Payment` objects, one for each payment
7
+ def payments(account_id = nil)
8
+ query_api_object Payment, account_id.nil? ? "/rest/payments" : "/rest/accounts/#{account_id}/payments", nil, "GET", "payments"
9
+ end
10
+
11
+ # Retrieve specific payment.
12
+ #
13
+ # @param account_id [String] ID for the account on which the payment to be retrieved was created
14
+ # @param payment_id [String] ID of the notification to be retrieved
15
+ # @return [Payment] `Payment` object for the respective payment
16
+ def get_payment(account_id, payment_id)
17
+ query_api_object Payment, "/rest/accounts/#{account_id}/payments/#{payment_id}"
18
+ end
19
+
20
+ # Create new payment
21
+ #
22
+ # @param payment [Payment] payment object to be created. It should not have a payment_id set.
23
+ # @return [Payment] newly created `Payment` object
24
+ def add_payment(payment)
25
+ query_api_object Payment, "/rest/accounts/#{payment.account_id}/payments", payment.dump(), "POST"
26
+ end
27
+
28
+ # Modify payment
29
+ #
30
+ # @param payment [Payment] modified payment object
31
+ # @return [Payment] modified payment object
32
+ def modify_payment(payment)
33
+ query_api_object Payment, "/rest/accounts/#{payment.account_id}/payments/#{payment.payment_id}", payment.dump(), "PUT"
34
+ end
35
+
36
+ # Submit payment to bank server
37
+ #
38
+ # @param payment [Payment] payment to be submitted
39
+ # @param tan_scheme_id [String] TAN scheme ID of user-selected TAN scheme
40
+ # @param state [String] Any kind of string that will be forwarded in the callback response message
41
+ # @param redirect_uri [String] At the end of the submission process a response will be sent to this callback URL
42
+ # @return [String] The result parameter is the URL to be opened by the user.
43
+ def submit_payment (payment, tan_scheme_id, state, redirect_uri)
44
+ params = {tan_scheme_id: tan_scheme_id, state: state}
45
+ if(redirect_uri)
46
+ params["redirect_uri"] = redirect_uri;
47
+ end
48
+
49
+ res = query_api("/rest/accounts/" + payment.account_id + "/payments/" + payment.payment_id + "/submit", params, "POST")
50
+
51
+ if(res.task_token)
52
+ "https://" + Config.api_endpoint + "/task/start?id=" + result.task_token
53
+ callback(error);
54
+ else
55
+ res
56
+ end
57
+ end
58
+
59
+ # Remove payment
60
+ #
61
+ # @param payment [Payment, String] payment object which should be removed
62
+ def remove_payment(payment)
63
+ query_api "/rest/accounts/#{payment.account_id}/payments/#{payment.payment_id}", nil, "DELETE"
64
+ end
65
+
66
+ # Retreive payment proposals
67
+ #
68
+ def get_payment_proposals
69
+ query_api "/rest/address_book", nil, "GET"
70
+ end
71
+ end
@@ -0,0 +1,75 @@
1
+ require_relative "../base.rb"
2
+ module Figo
3
+ # Object representing a Payment
4
+ class Payment < Base
5
+ @dump_attributes = [:type, :name, :account_number, :bank_code, :amount, :currency, :purpose]
6
+
7
+ def initialize(session, json)
8
+ super(session, json)
9
+ end
10
+
11
+ # Internal figo Connect payment ID
12
+ # @return [String]
13
+ attr_accessor :payment_id
14
+
15
+ # Internal figo Connect account ID
16
+ # @return [String]
17
+ attr_accessor :account_id
18
+
19
+ # Payment type
20
+ # @return [String]
21
+ attr_accessor :type
22
+
23
+ # Name of creditor or debtor
24
+ # @return [String]
25
+ attr_accessor :name
26
+
27
+ # Account number of creditor or debtor
28
+ # @return [String]
29
+ attr_accessor :account_number
30
+
31
+ # Bank code of creditor or debtor
32
+ # @return [String]
33
+ attr_accessor :bank_code
34
+
35
+ # Bank name of creditor or debtor
36
+ # @return [String]
37
+ attr_accessor :bank_name
38
+
39
+ # Icon of creditor or debtor bank
40
+ # @return [String]
41
+ attr_accessor :bank_icon
42
+
43
+ # Icon of the creditor or debtor bank in other resolutions
44
+ # @return [Hash]
45
+ attr_accessor :bank_additional_icons
46
+
47
+ # Order amount
48
+ # @return [DecNum]
49
+ attr_accessor :amount
50
+
51
+ # Three-character currency code
52
+ # @return [String]
53
+ attr_accessor :currency
54
+
55
+ # Purpose text
56
+ # @return [String]
57
+ attr_accessor :purpose
58
+
59
+ # Timestamp of submission to the bank server
60
+ # @return [DateTime]
61
+ attr_accessor :submission_timestamp
62
+
63
+ # Internal creation timestamp on the figo Connect server
64
+ # @return [DateTime]
65
+ attr_accessor :creation_timestamp
66
+
67
+ # Internal modification timestamp on the figo Connect server
68
+ # @return [DateTime]
69
+ attr_accessor :modification_timestamp
70
+
71
+ # ID of the transaction corresponding to this payment. This field is only set if the payment has been matched to a transaction
72
+ # @return [String]
73
+ attr_accessor :transaction_id
74
+ end
75
+ end
@@ -0,0 +1,17 @@
1
+ require_relative "model.rb"
2
+ module Figo
3
+ # Begin process.
4
+ #
5
+ # @param process [Hash] - Process token object
6
+ def start_process(process)
7
+ query_api "/process/start?id=" + process.process_token, nil, "GET"
8
+ end
9
+
10
+ # Create a process.
11
+ #
12
+ # @param proc [Hash] - Process object
13
+ # @return [Hash] - The result parameter is a ProcessToken object of a newly created process.
14
+ def create_process(proc)
15
+ query_api_object ProcessToken, "/client/process", proc.dump(), "POST", nil
16
+ end
17
+ end
@@ -0,0 +1,34 @@
1
+ require_relative "../base.rb"
2
+ module Figo
3
+ ### Object representing a process token
4
+ class ProcessToken < Base
5
+ @dump_attributes = [:process_token];
6
+ def initialize(session, json)
7
+ super(session, json)
8
+ end
9
+
10
+ # Properties:
11
+ # @param process_token [Object] - Process ID
12
+ attr_accessor :process_token
13
+ end
14
+
15
+ ### Object representing a Bsiness Process
16
+ class Process < Base
17
+ @dump_attributes = [:email, :password, :redirect_uri, :state, :steps]
18
+ def initialize(session, json)
19
+ super(session, json)
20
+ end
21
+
22
+ # Properties:
23
+ # @param email [String] - The email of the existing user to use as context or the new user to create beforehand
24
+ attr_accessor :email
25
+ # @param password [String] - The password of the user existing or new user
26
+ attr_accessor :password
27
+ # @param redirect_uri [String] - The authorization code will be sent to this callback URL
28
+ attr_accessor :redirect_uri
29
+ # @param state [String] - Any kind of string that will be forwarded in the callback response message
30
+ attr_accessor :state
31
+ # @param steps [String] - A list of steps definitions
32
+ attr_accessor :steps
33
+ end
34
+ end
@@ -0,0 +1,59 @@
1
+ require_relative "model.rb"
2
+ require 'json'
3
+
4
+ module Figo
5
+ # Retrieve a security.
6
+ #
7
+ # @param account_id [String] - ID of the account the security belongs to
8
+ # @param security_id [String] - ID of the security to retrieve
9
+ # @return [Security] - A single security object.
10
+ def get_security(account_id, security_id)
11
+ query_api_object Security, "/rest/accounts/" + account_id + "/securities/" + security_id, nil, "GET", nil
12
+ end
13
+
14
+ # Retrieve securities of one or all accounts.
15
+ #
16
+ # @param options [Object] - further options (all are optional)
17
+ # @param options.account_id [String] - ID of the account for which to retrieve the securities
18
+ # @param options.accounts [Array] - filter the securities to be only from these accounts
19
+ # @param options.since [Date] - ISO date filtering the returned securities by their creation or last modification date
20
+ # @param options.since_type [String] - defines hot the `since` will be interpreted: `traded`, `created` or `modified`
21
+ # @param options.count [Number] - limit the number of returned transactions
22
+ # @param options.offset [Number] - offset into the implicit list of transactions
23
+ # @return [Security] - An array of `Security` objects.
24
+ def get_securities(options = nil)
25
+ options ||= {}
26
+ options["count"] ||= 1000
27
+ options["offset"] ||= 0
28
+ if(!options["account_id"])
29
+ query_api_object Security, "/rest/securities?" + URI.encode_www_form(options), nil, "GET", 'securities'
30
+ else
31
+ account_id = options["account_id"]
32
+ options.delete("account_id")
33
+ query_api_object Security, "/rest/accounts/" + account_id + "/securities?" + URI.encode_www_form(options), nil, "GET", "securities"
34
+ end
35
+ end
36
+
37
+ # Modify a security.
38
+ # @param account_id [String] - ID of the account the security belongs to
39
+ # @param security_id [String] - ID of the security to change
40
+ # @param visited [Boolean] - a bit showing whether the user has already seen this security or not
41
+
42
+ def modify_security (account_id, security_id, visited)
43
+ data = {:visited => visited}
44
+ query_api "/rest/accounts/" + account_id + "/securities/" + security_id, data, "PUT"
45
+ end
46
+
47
+ # Modify securities of one or all accounts.
48
+ # @param visited [Boolean] - a bit showing whether the user has already seen these securities or not
49
+ # @param account_id [String] - ID of the account securities belongs to (optional)
50
+
51
+ def modify_securities (visited, account_id = nil)
52
+ data = {visited: visited}
53
+ if (account_id)
54
+ query_api "/rest/accounts/" + account_id + "/securities", data, "PUT"
55
+ else
56
+ query_api "/rest/securities", data, "PUT"
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,83 @@
1
+ require_relative "../base.rb"
2
+ module Figo
3
+ # Object representing a Payment
4
+ class Security < Base
5
+ @dump_attributes = [:name, :isin, :wkn, :currency, :quantity, :amount, :amount_original_currency, :exchange_rate, :price, :price_currency, :purchase_price, :purchase_price_currency, :visited]
6
+
7
+ def initialize(session, json)
8
+ super(session, json)
9
+ end
10
+
11
+ # Name of creditor or debtor
12
+ # @return [String]
13
+ attr_accessor :name
14
+
15
+ # Order amount
16
+ # @return [DecNum]
17
+ attr_accessor :amount
18
+
19
+ # Three-character currency code
20
+ # @return [String]
21
+ attr_accessor :currency
22
+
23
+ # Internal figo Connect security ID
24
+ # @return [String]
25
+ attr_accessor :security_id
26
+
27
+ # Internal figo Connect account ID
28
+ # @return [String]
29
+ attr_accessor :account_id
30
+
31
+ # International Securities Identification Number
32
+ # @return [String]
33
+ attr_accessor :isin
34
+
35
+ # Wertpapierkennnummer (if available)
36
+ # @return [String]
37
+ attr_accessor :wkn
38
+
39
+ # Number of pieces or value
40
+ # @return [Number]
41
+ attr_accessor :quantity
42
+
43
+ # Monetary value in trading currency
44
+ # @return [Number]
45
+ attr_accessor :amount_original_currency
46
+
47
+ # Exchange rate between trading and account currency
48
+ # @return [Number]
49
+ attr_accessor :exchange_rate
50
+
51
+ # Current price
52
+ # @return [Number]
53
+ attr_accessor :price
54
+
55
+ # Currency of current price
56
+ # @return [String]
57
+ attr_accessor :price_currency
58
+
59
+ # Purchase price
60
+ # @return [Number]
61
+ attr_accessor :purchase_price
62
+
63
+ # Currency of purchase price
64
+ # @return [String]
65
+ attr_accessor :purchase_price_currency
66
+
67
+ # This flag indicates whether the security has already been marked as visited by the user
68
+ # @return [Boolean]
69
+ attr_accessor :visited
70
+
71
+ # Trading timestamp
72
+ # @return [Date]
73
+ attr_accessor :trade_timestamp
74
+
75
+ # Internal creation timestamp on the figo Connect server
76
+ # @return [Date]
77
+ attr_accessor :creation_timestamp
78
+
79
+ # Internal modification timestamp on the figo
80
+ # @return [Date]
81
+ attr_accessor :modification_timestamp
82
+ end
83
+ end