figo 1.2.5 → 1.3.3

Sign up to get free protection for your applications and to get access to all the features.
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