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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d33b8e8414b4a922aa26cc3cd8cbb5d6d7bdff30
4
- data.tar.gz: e091d3ae3a764120fb5e2e2a0d9f6098a4e4f85b
3
+ metadata.gz: 522d66983f2ecf3c65e75386ef0749f3bbcb2919
4
+ data.tar.gz: 1db05284c5e87715a096355f07d61704312d194d
5
5
  SHA512:
6
- metadata.gz: 5c9dc3f1706a858ae802ce40d76dbcdb9d3f3e5b6e6dcf5337c09379fc3f5279283ed75d4a33164fbc437552e494c7f045609545ac1eba3cb8b33fc65c97c1a6
7
- data.tar.gz: 837a9922915b002ce70de7c2c2813970a51b03992289d721340ea8b22befee10ea21214dd9db1f0d928af016d7d77f6701db4c395d1ffa44a5ef1086510013d4
6
+ metadata.gz: 73d0b043a1b5eb4337bc51a0e8f5c740da13954fe1063135b65791f2b8b2532d2d2f5314c339c81a6455dda7ef89d01a9dd8fe5b413ebcfe4d8e81153a56ca4c
7
+ data.tar.gz: 7cd01b360f8cfad374e8558fa5ddfb9ea41a939b73fb6d36f8cc10b9ff59dbb717d2b2b2f206074271107aea54e76274bedccd60ce216598e4ef3b11fa46dfd2
data/Gemfile CHANGED
@@ -4,3 +4,4 @@ gemspec
4
4
 
5
5
  gem "rake"
6
6
  gem "minitest"
7
+ gem "net-http-persistent", ">= 3.0.0"
@@ -0,0 +1,4 @@
1
+ API_ENDPOINT: api.figo.me
2
+ FINGER_PRINTS:
3
+ - "38:AE:4A:32:6F:16:EA:15:81:33:8B:B0:D8:E4:A6:35:E7:27:F1:07"
4
+ - "DB:E2:E9:15:8F:C9:90:30:84:FE:36:CA:A6:11:38:D8:5A:20:5D:93"
@@ -10,5 +10,5 @@ end
10
10
 
11
11
  # Print out the list of all transaction originators/recipients of a specific account.
12
12
  session.get_account("A1.1").transactions.each do |transaction|
13
- puts transaction.name
13
+ puts transaction.name
14
14
  end
@@ -1,8 +1,8 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "figo"
3
- s.version = "1.2.5"
4
- s.authors = ["Stefan Richter"]
5
- s.email = ["stefan.richter@figo.me"]
3
+ s.version = "1.3.3"
4
+ s.authors = ["Denys Zaliskyi"]
5
+ s.email = ["dz@figo.me"]
6
6
  s.homepage = "https://github.com/figo-connect/ruby-figo"
7
7
  s.license = "MIT"
8
8
  s.summary = %q{API wrapper for figo Connect.}
@@ -0,0 +1,55 @@
1
+ require_relative "model.rb"
2
+ module Figo
3
+ # Retrieve all accounts
4
+ #
5
+ # @return [Array] an array of `Account` objects, one for each account the user has granted the app access
6
+ def accounts
7
+ query_api_object Account, "/rest/accounts", nil, "GET", "accounts"
8
+ end
9
+
10
+ # Retrieve specific account.
11
+ #
12
+ # @param account_id [String] ID of the account to be retrieved.
13
+ # @return [Account] account object
14
+ def get_account(account_id)
15
+ query_api_object Account, "/rest/accounts/#{account_id}"
16
+ end
17
+
18
+ # Modify specific account
19
+ #
20
+ # @param account [Account] modified account to be saved
21
+ # @return [Account] modified account returned by the server
22
+ def modify_account(account)
23
+ query_api_object Account, "/rest/accounts/#{account.account_id}", account.dump(), "PUT"
24
+ end
25
+
26
+ # Remove specific account
27
+ #
28
+ # @param account [Account, String] the account to be removed or its ID
29
+ def remove_account(account)
30
+ query_api account.is_a?(String) ? "/rest/accounts/#{account}" : "/rest/accounts/#{account.account_id}", nil, "DELETE"
31
+ end
32
+
33
+ # Set bank account sort order
34
+ #
35
+ # @param accounts [Array] List of JSON objects with the field account_id set to the internal figo Connect account ID (the accounts will be sorted in the list order)
36
+ def account_sort_order (accounts)
37
+ query_api "/rest/accounts", accounts, "PUT"
38
+ end
39
+
40
+ # Add new bank account_sort_order
41
+ #
42
+ # @param country_code [String] Two-letter country code
43
+ # @param credentials [Array] List of login credential strings
44
+ # @param bank_code [String] Bank code (will be overriden if IBAN is present)
45
+ # @param iban [String] IBAN
46
+ # @param save_pon [Boolean] This flag indicates whether the user has chosen to save the PIN on the figo Connect server
47
+ def add_account(country, credentials, bank_code, iban, save_pin)
48
+ data = {"country" => country, "credentials" => credentials}
49
+ data["iban"] = iban if (iban)
50
+ data["bank_code"] = bank_code if(bank_code)
51
+ data["save_pin"] = !!save_pin == save_pin ? save_pin : false
52
+
53
+ query_api_object TaskToken, "/rest/accounts", data, "POST"
54
+ end
55
+ end
@@ -0,0 +1,122 @@
1
+ require_relative "../base.rb"
2
+ module Figo
3
+ # Object representing one bank account of the User
4
+ class Account < Base
5
+ @dump_attributes = [:name, :owner, :auto_sync]
6
+
7
+ def initialize(session, json)
8
+ super(session, json)
9
+ end
10
+
11
+ # Internal figo Connect account ID
12
+ # @return [String]
13
+ attr_accessor :account_id
14
+
15
+ # Internal figo Connect bank ID
16
+ # @return [String]
17
+ attr_accessor :bank_id
18
+
19
+ # Account name
20
+ # @return [String]
21
+ attr_accessor :name
22
+
23
+ # Account owner
24
+ # @return [String]
25
+ attr_accessor :owner
26
+
27
+ # This flag indicates whether the account will be automatically synchronized
28
+ # @return [Boolean]
29
+ attr_accessor :auto_sync
30
+
31
+ # Account number
32
+ # @return [String]
33
+ attr_accessor :account_number
34
+
35
+ # Bank code
36
+ # @return [String]
37
+ attr_accessor :bank_code
38
+
39
+ # Bank name
40
+ # @return [String]
41
+ attr_accessor :bank_name
42
+
43
+ # Three-character currency code
44
+ # @return [String]
45
+ attr_accessor :currency
46
+
47
+ # IBAN
48
+ # @return [String]
49
+ attr_accessor :iban
50
+
51
+ # BIC
52
+ # @return [String]
53
+ attr_accessor :bic
54
+
55
+ # Account type
56
+ # @return [String]
57
+ attr_accessor :type
58
+
59
+ # Account icon URL
60
+ # @return [String]
61
+ attr_accessor :icon
62
+
63
+ # Account icon URLs for other resolutions
64
+ # @return [Hash]
65
+ attr_accessor :additional_icons
66
+
67
+ # This flag indicates whether the balance of this account is added to the total balance of accounts
68
+ # @return [Boolean]
69
+ attr_accessor :in_total_balance
70
+
71
+ # Synchronization status object
72
+ # @return [SynchronizationStatus]
73
+ attr_accessor :status
74
+
75
+ # AccountBalance object
76
+ # @return [AccountBalance]
77
+ attr_accessor :balance
78
+
79
+ # Request list of transactions of this account
80
+ #
81
+ # @param since [String, Date] this parameter can either be a transaction ID or a date
82
+ # @param count [Integer] limit the number of returned transactions
83
+ # @param offset [Integer] which offset into the result set should be used to determin the first transaction to return (useful in combination with count)
84
+ # @param include_pending [Boolean] this flag indicates whether pending transactions should be included
85
+ # in the response; pending transactions are always included as a complete set, regardless of
86
+ # the `since` parameter
87
+ # @return [Array] an array of `Transaction` objects, one for each transaction of this account
88
+ def transactions(since = nil, count = 1000, offset = 0, include_pending = false)
89
+ @session.transactions @account_id, since, count, offset, include_pending
90
+ end
91
+
92
+ # Request specific transaction.
93
+ #
94
+ # @param transaction_id [String] ID of the transaction to be retrieved
95
+ # @return [Transaction] transaction object
96
+ def get_transaction(transaction_id)
97
+ @session.get_transaction @acount_id, transaction_id
98
+ end
99
+
100
+ # Retrieve list of payments on this account
101
+ #
102
+ # @return [Payment] an array of `Payment` objects, one for each payment
103
+ def payments
104
+ @session.payments @account_id
105
+ end
106
+
107
+ # Retrieve specific payment on this account
108
+ #
109
+ # @param payment_id [String] ID of the notification to be retrieved
110
+ # @return [Payment] `Payment` object for the respective payment
111
+ def get_payment(payment_id)
112
+ @session.get_payment @account_id, payment_id
113
+ end
114
+
115
+ # Retrieve bank of this account
116
+ #
117
+ # @return [Bank] `Bank` object for the respective bank
118
+ def bank
119
+ @session.get_bank @bank_id
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,18 @@
1
+ require_relative "model.rb"
2
+ module Figo
3
+ # Retrieve balance of an account.
4
+ #
5
+ # @return [AccountBalance] account balance object
6
+ def get_account_balance(account_id)
7
+ query_api_object AccountBalance, "/rest/accounts/#{account_id}/balance"
8
+ end
9
+
10
+ # Modify balance or account limits
11
+ #
12
+ # @param account_id [String] ID of the account which balance should be modified
13
+ # @param account_balance [AccountBalance] modified AccountBalance to be saved
14
+ # @return [AccountBalance] modified AccountBalance returned by server
15
+ def modify_account_balance(account_id, account_balance)
16
+ query_api_object AccountBalance, "/rest/accounts/#{account_id}/balance", account_balance.dump(), "PUT"
17
+ end
18
+ end
@@ -0,0 +1,31 @@
1
+ require_relative "../base.rb"
2
+ module Figo
3
+ # Object representing the balance of a certain bank account of the User
4
+ class AccountBalance < Base
5
+ @dump_attributes = [:credit_line, :monthly_spending_limit]
6
+
7
+ def initialize(session, json)
8
+ super(session, json)
9
+ end
10
+
11
+ # Account balance or `nil` if the balance is not yet known
12
+ # @return [DecNum]
13
+ attr_accessor :balance
14
+
15
+ # Bank server timestamp of balance or `nil` if the balance is not yet known
16
+ # @return [Date]
17
+ attr_accessor :balance_date
18
+
19
+ # Credit line.
20
+ # @return [DecNum]
21
+ attr_accessor :credit_line
22
+
23
+ # User-defined spending limit
24
+ # @return [DecNum]
25
+ attr_accessor :monthly_spending_limit
26
+
27
+ # Synchronization status object
28
+ # @return [SynchronizationStatus]
29
+ attr_accessor :status
30
+ end
31
+ end
@@ -0,0 +1,88 @@
1
+ module Figo
2
+ # Get the URL a user should open in the web browser to start the login process.
3
+ #
4
+ # When the process is completed, the user is redirected to the URL provided to
5
+ # the constructor and passes on an authentication code. This code can be converted
6
+ # into an access token for data access.
7
+ #
8
+ # @param state [String] this string will be passed on through the complete login
9
+ # process and to the redirect target at the end. It should be used to
10
+ # validated the authenticity of the call to the redirect URL
11
+ # @param scope [String] optional scope of data access to ask the user for,
12
+ # e.g. `accounts=ro`
13
+ # @return [String] the URL to be opened by the user.
14
+ def login_url(state, scope = nil)
15
+ data = { "response_type" => "code", "client_id" => @client_id, "state" => state }
16
+ data["redirect_uri"] = @redirect_uri unless @redirect_uri.nil?
17
+ data["scope"] = scope unless scope.nil?
18
+ return "https://#{$api_endpoint}/auth/code?" + URI.encode_www_form(data)
19
+ end
20
+
21
+
22
+ # Exchange authorization code or refresh token for access token.
23
+ #
24
+ # @param authorization_code_or_refresh_token [String] either the authorization
25
+ # code received as part of the call to the redirect URL at the end of the
26
+ # logon process, or a refresh token
27
+ # @param scope [String] optional scope of data access to ask the user for,
28
+ # e.g. `accounts=ro`
29
+ # @return [Hash] object with the keys `access_token`, `refresh_token` and `expires`, as documented in the figo Connect API specification.
30
+ def obtain_access_token(authorization_code_or_refresh_token, scope = nil)
31
+ # Authorization codes always start with "O" and refresh tokens always start with "R".
32
+ if authorization_code_or_refresh_token[0] == "O"
33
+ data = { "grant_type" => "authorization_code", "code" => authorization_code_or_refresh_token }
34
+ data["redirect_uri"] = @redirect_uri unless @redirect_uri.nil?
35
+ elsif authorization_code_or_refresh_token[0] == "R"
36
+ data = { "grant_type" => "refresh_token", "refresh_token" => authorization_code_or_refresh_token }
37
+ data["scope"] = scope unless scope.nil?
38
+ end
39
+ query_api "/auth/token", data
40
+ end
41
+
42
+ # Revoke refresh token or access token.
43
+ #
44
+ # @note this action has immediate effect, i.e. you will not be able use that token anymore after this call.
45
+ #
46
+ # @param refresh_token_or_access_token [String] access or refresh token to be revoked
47
+ # @return [nil]
48
+ def revoke_token(refresh_token_or_access_token)
49
+ data = { "token" => refresh_token_or_access_token }
50
+ query_api "/auth/revoke", data
51
+ end
52
+
53
+ # Create a new figo Account
54
+ #
55
+ # @param name [String] First and last name
56
+ # @param email [String] Email address; It must obey the figo username & password policy
57
+ # @param password [String] New figo Account password; It must obey the figo username & password policy
58
+ # @param language [String] Two-letter code of preferred language
59
+ # @param send_newsletter [Boolean] This flag indicates whether the user has agreed to be contacted by email -- Not accepted by backend at the moment
60
+ # @return [Hash] object with the key `recovery_password` as documented in the figo Connect API specification
61
+ def create_user(name, email, password, language='de', send_newsletter=true)
62
+ data = { 'name' => name, 'email' => email, 'password' => password, 'language' => language, 'affiliate_client_id' => @client_id} #'send_newsletter' => send_newsletter,
63
+ query_api "/auth/user", data
64
+ end
65
+
66
+ # Re-send verification email
67
+ #
68
+ def resend_verification()
69
+ query_api "/rest/user/resend_verification", nil, "POST"
70
+ end
71
+
72
+ # Return a Token dictionary which tokens are used for further API calls.
73
+ #
74
+ # @param username [String] figo username
75
+ # @param password [String] figo password
76
+ # @return The result parameter is an object with the keys `access_token`, `token_type`, `expires_in`, `refresh_token` and `scope` as documented in the figo Connect API specification.
77
+ def credential_login(username, password, device_name = nil, device_type = nil, device_udid = nil, scope = nil)
78
+ options = { grant_type: "password", username: username, password: password }
79
+
80
+ options[:device_name] = device_name if (device_name)
81
+ options[:device_type] = device_type if (device_type)
82
+ options[:device_udid] = device_udid if (device_udid)
83
+ options[:scope] = scope if (scope)
84
+
85
+ query_api "/auth/token", options
86
+ end
87
+
88
+ end
@@ -0,0 +1,49 @@
1
+ require_relative "model.rb"
2
+ module Figo
3
+ # Retrieve specific bank
4
+ #
5
+ # @return [Bank] bank object
6
+ def get_bank(bank_id)
7
+ query_api_object Bank, "/rest/banks/#{bank_id}"
8
+ end
9
+
10
+ # Modify bank
11
+ #
12
+ # @param bank [Bank] modified bank object
13
+ # @return [Bank] modified bank object returned by server
14
+ def modify_bank(bank)
15
+ query_api_object Bank, "/rest/banks/#{bank.bank_id}", bank.dump(), "PUT"
16
+ end
17
+
18
+ # Remove stored PIN from bank
19
+ #
20
+ # @param bank [Bank, String] the bank whose stored PIN should be removed or its ID
21
+ # @return [nil]
22
+ def remove_bank_pin(bank)
23
+ query_api bank.is_a?(String) ? "/rest/banks/#{bank}/remove_pin" : "/rest/banks/#{bank.bank_id}/remove_pin", nil, "POST"
24
+ end
25
+
26
+ # Get bank information from standard bank code
27
+ #
28
+ # @param country_code [String]
29
+ # @param bank_code [String] bank sort code (Bankleitzahl)
30
+ # @return [Hash] JSON response
31
+ def find_bank(bank_code, country_code = "DE")
32
+ query_api "/rest/catalog/banks/#{country_code}/#{bank_code}"
33
+ end
34
+
35
+ # Get supported services
36
+ #
37
+ # @param country_code [String] the country code the service comes from
38
+ # @param service [String] filter the type of service to request (optional): `banks`, `services` or everything (default)
39
+ def get_supported_payment_services(country_code="DE", service)
40
+ case service
41
+ when "banks"
42
+ query_api("/rest/catalog/banks/" + country_code, nil)
43
+ when "service"
44
+ query_api("/rest/catalog/services/" + country_code, nil)
45
+ else
46
+ query_api("/rest/catalog/" + country_code, nil)
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,23 @@
1
+ require_relative "../base.rb"
2
+ module Figo
3
+ # Object representing a bank, i.e. an connection to a bank
4
+ class Bank < Base
5
+ @dump_attributes = [:sepa_creditor_id]
6
+
7
+ def initialize(session, json)
8
+ super(session, json)
9
+ end
10
+
11
+ # Internal figo Connect bank ID
12
+ # @return [String]
13
+ attr_accessor :bank_id
14
+
15
+ # SEPA direct debit creditor ID
16
+ # @return [String]
17
+ attr_accessor :sepa_creditor_id
18
+
19
+ # This flag indicates whether the user has chosen to save the PIN on the figo Connect server
20
+ # @return [Boolean]
21
+ attr_accessor :save_pin
22
+ end
23
+ end
@@ -0,0 +1,56 @@
1
+ require "date"
2
+ require "flt"
3
+
4
+ module Figo
5
+ # Set decimal precision to two digits.
6
+ Flt::DecNum.context.precision = 2
7
+
8
+ # Abstract base class for model objects.
9
+ class Base
10
+ # Attributes to be dumped (called by modify and create)
11
+ @dump_attributes = []
12
+ def self.dump_attributes
13
+ @dump_attributes
14
+ end
15
+
16
+ # Instantiate model object from hash.
17
+ #
18
+ # @param session [Session] figo `Session` object
19
+ # @param hash [Hash] use keys of this hash for model object creation
20
+ def initialize(session, hash)
21
+ @session = session
22
+
23
+ hash.each do |key, value|
24
+ key = key.to_s if key.is_a? Symbol
25
+ next unless respond_to? "#{key}="
26
+ next if value.nil?
27
+
28
+ if key == "status" and value.is_a? Hash
29
+ value = SynchronizationStatus.new(session, value)
30
+ elsif key == "balance" and value.is_a? Hash
31
+ value = AccountBalance.new(session, value)
32
+ elsif key == "amount" or key == "balance" or key == "credit_line" or key == "monthly_spending_limit"
33
+ value = Flt::DecNum(value.to_s)
34
+ elsif key.end_with?("_date")
35
+ value = DateTime.iso8601(value)
36
+ elsif key.end_with?("_timestamp")
37
+ value = DateTime.iso8601(value)
38
+ end
39
+ send("#{key}=", value)
40
+ end
41
+ end
42
+
43
+ # Dump committable attributes to a hash
44
+ def dump
45
+ result = {}
46
+ self.class.dump_attributes.each do |attribute|
47
+ value = send attribute
48
+ next if value.nil?
49
+ value = value.to_f if value.is_a? Flt::DecNum
50
+
51
+ result[attribute] = value
52
+ end
53
+ return result
54
+ end
55
+ end
56
+ end