fidor_api 0.0.1 → 0.0.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 35bab1256f83d253acc2cadc504cb76446365ae5
4
- data.tar.gz: 045a5090ae3dbbb4397795479782c5a3117a6795
3
+ metadata.gz: b18d0f77a280f02bee3ddf6b2bce5a3c4d598644
4
+ data.tar.gz: 820e2789982d1376be43f2b95be4c4e448c25902
5
5
  SHA512:
6
- metadata.gz: d8db1a19cf9c1f401f157d4549cbc6abb865e470b6067e12388d83f5afcabcad23b73aaaa7a327e1fc169b09ed779fb2b60ee687432826e0d65d9e66b1e22b5f
7
- data.tar.gz: 8a44e7020efbb525d8a07838cdf0a543fde15e6ffbbc883db9346c44c061176636479536fffdceeeb1be5f6ffecbb4ce6f6000c4c5e4817dcfd2c092eb0e6a6c
6
+ metadata.gz: a69f553f0953fb1967527fb58e50db7d4903fc39087ddfbc89d8d2f7cb3e0c8e50546b9a7c87f3d6b7f9da05b4ef5e1b4f7ec03cae0a68c69078570089224c39
7
+ data.tar.gz: 06e0802e771bcf251e7d8ef8e0f7f5e9be435740702c5fc7f74a5e1eae30ef584529a368cbac37d481e34872b744ba517ef90cec6dd4bc713846801314001688
data/.gitignore CHANGED
@@ -7,3 +7,4 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ .byebug_history
@@ -1 +1 @@
1
- 2.2.3
1
+ 2.3.1
@@ -1,6 +1,8 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.2.3
3
+ - "2.1.10"
4
+ - "2.2.5"
5
+ - "2.3.1"
4
6
  addons:
5
7
  code_climate:
6
- repo_token: 2ffd456a223e8c95dbd79a25a5ea3dca9899ece93fce3cfdfae3723a76f0028e
8
+ repo_token: 2ffd456a223e8c95dbd79a25a5ea3dca9899ece93fce3cfdfae3723a76f0028e
data/Gemfile CHANGED
@@ -1,6 +1,14 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in fidor_api.gemspec
4
3
  gemspec
5
4
 
6
- gem "codeclimate-test-reporter", group: :test, require: nil
5
+ group :development, :test do
6
+ gem "bundler", "~> 1.10"
7
+ gem "byebug", "~> 8.2"
8
+ gem "rake", "~> 10.0"
9
+ gem "rspec", "~> 3.3"
10
+ gem "shoulda-matchers", "~> 2.8"
11
+ gem "vcr", "~> 2.9"
12
+ gem "simplecov", "~> 0.10"
13
+ gem "codeclimate-test-reporter", group: :test, require: nil
14
+ end
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # FidorApi
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/fidor_api.svg)](https://badge.fury.io/rb/fidor_api)
3
4
  [![Build Status](https://travis-ci.org/klausmeyer/fidor_api.svg?branch=master)](https://travis-ci.org/klausmeyer/fidor_api)
4
5
  [![Test Coverage](https://codeclimate.com/github/klausmeyer/fidor_api/badges/coverage.svg)](https://codeclimate.com/github/klausmeyer/fidor_api/coverage)
5
6
  [![Code Climate](https://codeclimate.com/github/klausmeyer/fidor_api/badges/gpa.svg)](https://codeclimate.com/github/klausmeyer/fidor_api)
@@ -24,15 +25,48 @@ Or install it yourself as:
24
25
 
25
26
  ## Usage
26
27
 
27
- Examples:
28
+ ### 0. Configure
28
29
 
29
- 1. oAuth
30
+ ```ruby
31
+ FidorApi.configure do |config|
32
+ config.oauth_url = ENV["FIDOR_OAUTH_URL"]
33
+ config.api_url = ENV["FIDOR_API_URL"]
34
+ config.callback_url = ENV["FIDOR_API_CALLBACK"]
35
+ config.client_id = ENV["FIDOR_API_CLIENT_ID"]
36
+ config.client_secret = ENV["FIDOR_API_CLIENT_SECRET"]
37
+ config.htauth_user = ENV["FIDOR_API_HTAUTH_USER"]
38
+ config.htauth_password = ENV["FIDOR_API_HTAUTH_PASSWORD"]
39
+ config.affiliate_uid = ENV["FIDOR_API_AFFILIATE_UID"]
40
+ end
41
+ ```
42
+
43
+ ### 1. oAuth (Rails)
44
+
45
+ Redirect the user to the authorize URL:
30
46
 
31
47
  ```ruby
32
- todo
48
+ redirect_to FidorApi::Auth.authorize_url
49
+ ```
50
+
51
+ Use code passed to the callback URL and fetch the access token:
52
+
53
+ ```ruby
54
+ session[:api_token] = FidorApi::Auth.fetch_token(params[:code]).to_hash
55
+ ```
56
+
57
+ Renew token after it has expired:
58
+
59
+ ```ruby
60
+ def api_token
61
+ FidorApi::Token.new session[:api_token] if session[:api_token]
62
+ end
63
+
64
+ if api_token && !api_token.valid?
65
+ session[:api_token] = FidorApi::Auth.refresh_token(api_token).to_hash
66
+ end
33
67
  ```
34
68
 
35
- 2. Fetching data
69
+ ### 2. Fetching data
36
70
 
37
71
  ```ruby
38
72
  token = FidorApi::Token.new(access_token: "f859032a6ca0a4abb2be0583b8347937")
@@ -48,7 +82,7 @@ transaction = transactions.first
48
82
  # => FidorApi::Transaction
49
83
  ```
50
84
 
51
- 3. Creating transfers
85
+ ### 3. Creating transfers
52
86
 
53
87
  ```ruby
54
88
  token = FidorApi::Token.new(access_token: "f859032a6ca0a4abb2be0583b8347937")
@@ -18,15 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.require_paths = ["lib"]
19
19
 
20
20
  spec.add_dependency "faraday", "~> 0.8"
21
- spec.add_dependency "activesupport", "~> 4.2"
22
- spec.add_dependency "activemodel", "~> 4.2"
21
+ spec.add_dependency "activesupport", ">= 4.2", "< 5.1"
22
+ spec.add_dependency "activemodel", ">= 4.2", "< 5.1"
23
23
  spec.add_dependency "model_attribute", "~> 2.1"
24
-
25
- spec.add_development_dependency "bundler", "~> 1.10"
26
- spec.add_development_dependency "byebug", "~> 8.2"
27
- spec.add_development_dependency "rake", "~> 10.0"
28
- spec.add_development_dependency "rspec", "~> 3.3"
29
- spec.add_development_dependency "shoulda-matchers", "~> 2.8"
30
- spec.add_development_dependency "vcr", "~> 2.9"
31
- spec.add_development_dependency "simplecov", "~> 0.10"
32
24
  end
@@ -11,12 +11,14 @@ module FidorApi
11
11
  attr_accessor :configuration
12
12
 
13
13
  class Configuration
14
- attr_accessor :callback_url, :oauth_url, :api_url, :client_id, :client_secret, :logging
14
+ attr_accessor :callback_url, :oauth_url, :api_url, :client_id, :client_secret, :htauth_user, :htauth_password, :affiliate_uid, :os_type, :logging
15
15
  end
16
16
 
17
17
  def configure
18
- self.configuration = Configuration.new
19
- self.configuration.logging = true
18
+ self.configuration = Configuration.new.tap do |config|
19
+ config.logging = true
20
+ config.os_type = "iOS" # NOTE: As long as there is only iOS or Android we have to tell a fib ;)
21
+ end
20
22
  yield configuration
21
23
  end
22
24
  end
@@ -27,9 +29,14 @@ require "fidor_api/token"
27
29
  require "fidor_api/auth"
28
30
  require "fidor_api/resource"
29
31
  require "fidor_api/collection"
32
+ require "fidor_api/amount_attributes"
30
33
  require "fidor_api/user"
31
34
  require "fidor_api/account"
35
+ require "fidor_api/card"
36
+ require "fidor_api/card_limits"
32
37
  require "fidor_api/customer"
38
+ require "fidor_api/message"
39
+ require "fidor_api/msisdn"
33
40
  require "fidor_api/transaction_details"
34
41
  require "fidor_api/transaction"
35
42
  require "fidor_api/preauth_details"
@@ -2,26 +2,28 @@ module FidorApi
2
2
 
3
3
  class Account < Resource
4
4
  extend ModelAttribute
5
+ extend AmountAttributes
5
6
 
6
7
  attribute :id, :integer
7
8
  attribute :account_number, :string
8
9
  attribute :iban, :string
9
10
  attribute :bic, :string
10
- attribute :balance, :integer
11
- attribute :balance_available, :integer
12
- attribute :preauth_amount, :integer
13
- attribute :cash_flow_per_year, :integer
14
11
  attribute :is_debit_note_enabled, :boolean
15
12
  attribute :is_trusted, :boolean
16
13
  attribute :is_locked, :boolean
17
14
  attribute :currency, :string
18
- attribute :overdraft, :integer
19
15
  attribute :created_at, :time
20
16
  attribute :updated_at, :time
21
17
  attribute :customers, :string
22
18
 
19
+ amount_attribute :balance
20
+ amount_attribute :balance_available
21
+ amount_attribute :preauth_amount
22
+ amount_attribute :cash_flow_per_year
23
+ amount_attribute :overdraft
24
+
23
25
  def self.all(access_token, options = {})
24
- Collection.build(self, request(:get, access_token, "/accounts", options))
26
+ Collection.build(self, request(access_token: access_token, endpoint: "/accounts", query_params: options).body)
25
27
  end
26
28
 
27
29
  def self.first(access_token)
@@ -0,0 +1,27 @@
1
+ module AmountAttributes
2
+ def self.extended(base)
3
+ base.instance_variable_set('@amount_attributes', [])
4
+ end
5
+
6
+ def amount_attribute(name)
7
+ @amount_attributes << name
8
+
9
+ define_method name do
10
+ BigDecimal.new((instance_variable_get("@#{name}") / 100.00).to_s) if instance_variable_get("@#{name}").present?
11
+ end
12
+
13
+ define_method "#{name}=" do |value|
14
+ if value.instance_of?(BigDecimal)
15
+ instance_variable_set("@#{name}", (value * 100.00).to_i)
16
+ elsif value.instance_of?(Fixnum) || value.instance_of?(NilClass)
17
+ instance_variable_set("@#{name}", value)
18
+ else
19
+ raise ArgumentError, "Must be either Fixnum (1234) or BigDecimal (12.34)."
20
+ end
21
+ end
22
+ end
23
+
24
+ def attributes
25
+ super + @amount_attributes
26
+ end
27
+ end
@@ -31,7 +31,7 @@ module FidorApi
31
31
  Faraday.new(url: FidorApi.configuration.oauth_url) do |config|
32
32
  config.use Faraday::Request::BasicAuthentication, FidorApi.configuration.client_id, FidorApi.configuration.client_secret
33
33
  config.request :url_encoded
34
- config.response :logger if FidorApi.configuration.logging
34
+ config.response :logger if FidorApi.configuration.logging
35
35
  config.response :raise_error
36
36
  config.adapter Faraday.default_adapter
37
37
  end
@@ -0,0 +1,94 @@
1
+ module FidorApi
2
+
3
+ class Card < Resource
4
+ extend ModelAttribute
5
+ extend AmountAttributes
6
+
7
+ attribute :id, :integer
8
+ attribute :account_id, :string
9
+ attribute :inscription, :string
10
+ attribute :pin, :string
11
+ attribute :type, :string
12
+ attribute :design, :string
13
+ attribute :currency, :string
14
+ attribute :physical, :boolean
15
+ attribute :email_notification, :boolean
16
+ attribute :sms_notification, :boolean
17
+ attribute :payed, :boolean
18
+ attribute :state, :string
19
+ attribute :lock_reason, :string
20
+ attribute :disabled, :boolean
21
+ attribute :created_at, :time
22
+ attribute :updated_at, :time
23
+
24
+ amount_attribute :balance
25
+ amount_attribute :atm_limit
26
+ amount_attribute :transaction_single_limit
27
+ amount_attribute :transaction_volume_limit
28
+
29
+ def self.required_attributes
30
+ [ :account_id, :type, :design, :currency, :pin ]
31
+ end
32
+
33
+ validates *required_attributes, presence: true
34
+
35
+ def self.all(access_token, options = {})
36
+ Collection.build(self, request(access_token: access_token, endpoint: "/cards", query_params: options).body)
37
+ end
38
+
39
+ def self.find(access_token, id)
40
+ new(request(access_token: access_token, endpoint: "/cards/#{id}").body)
41
+ end
42
+
43
+ def self.lock(access_token, id)
44
+ request(method: :put, access_token: access_token, endpoint: "/cards/#{id}/lock")
45
+ true
46
+ end
47
+
48
+ def self.unlock(access_token, id)
49
+ request(method: :put, access_token: access_token, endpoint: "/cards/#{id}/unlock")
50
+ true
51
+ end
52
+
53
+ def save
54
+ if id.nil?
55
+ create
56
+ else
57
+ raise NoUpdatesAllowedError
58
+ end
59
+ end
60
+
61
+ def as_json
62
+ attributes.slice *self.class.required_attributes
63
+ end
64
+
65
+ private
66
+
67
+ def self.resource
68
+ "cards"
69
+ end
70
+
71
+ module ClientSupport
72
+ def cards(options = {})
73
+ Card.all(token.access_token, options)
74
+ end
75
+
76
+ def card(id)
77
+ Card.find(token.access_token, id)
78
+ end
79
+
80
+ def lock_card(id)
81
+ Card.lock(token.access_token, id)
82
+ end
83
+
84
+ def unlock_card(id)
85
+ Card.unlock(token.access_token, id)
86
+ end
87
+
88
+ def build_card(attributes = {})
89
+ Card.new(attributes.merge(client: self))
90
+ end
91
+ end
92
+ end
93
+
94
+ end
@@ -0,0 +1,42 @@
1
+ module FidorApi
2
+
3
+ class CardLimits < Resource
4
+ extend ModelAttribute
5
+ extend AmountAttributes
6
+
7
+ attribute :id, :integer
8
+ amount_attribute :atm_limit
9
+ amount_attribute :transaction_single_limit
10
+ amount_attribute :transaction_volume_limit
11
+
12
+ def self.find(access_token, id)
13
+ attributes = request(access_token: access_token, endpoint: "/cards/#{id}/limits").body
14
+ attributes.merge!(id: id)
15
+ new(attributes)
16
+ end
17
+
18
+ def self.change(access_token, id, limits = {})
19
+ attributes = limits.merge(id: id)
20
+
21
+ new(attributes).tap do |record|
22
+ record.set_attributes request(
23
+ method: :put,
24
+ access_token: access_token,
25
+ endpoint: "/cards/#{id}/limits",
26
+ body: record.as_json
27
+ ).body
28
+ end
29
+ end
30
+
31
+ module ClientSupport
32
+ def card_limits(id)
33
+ CardLimits.find(token.access_token, id)
34
+ end
35
+
36
+ def change_card_limits(id, limits)
37
+ CardLimits.change(token.access_token, id, limits)
38
+ end
39
+ end
40
+ end
41
+
42
+ end
@@ -6,11 +6,15 @@ module FidorApi
6
6
  attr_accessor :token
7
7
 
8
8
  include Account::ClientSupport
9
+ include Card::ClientSupport
10
+ include CardLimits::ClientSupport
9
11
  include Customer::ClientSupport
12
+ include Message::ClientSupport
10
13
  include Preauth::ClientSupport
11
14
  include Transaction::ClientSupport
12
15
  include Transfer::Internal::ClientSupport
13
16
  include Transfer::SEPA::ClientSupport
17
+ include Transfer::FPS::ClientSupport
14
18
  include User::ClientSupport
15
19
  end
16
20
 
@@ -2,25 +2,17 @@ module FidorApi
2
2
 
3
3
  class Collection
4
4
  include ActiveModel::Model
5
+ include Enumerable
5
6
 
6
7
  attr_accessor :records
7
8
  attr_accessor :total_pages, :current_page, :limit_value
8
9
 
9
- delegate :each, :first, to: :records
10
-
11
10
  def self.build(klass, response)
12
11
  new.tap do |object|
13
- # NOTE: We need this ugly hack since the sandbox is not wrapping records into data key.
14
- # Will hopefully go away in future.
15
- if response.is_a? Hash
16
- data = response["data"]
17
- collection = response["collection"]
18
- else
19
- data = response
20
- collection = collection_from_array response
21
- end
22
-
23
- object.records = data.map { |record| klass.new(record) }
12
+ data = response["data"]
13
+ collection = response["collection"]
14
+
15
+ object.records = data.map { |record| klass.new(record) }
24
16
 
25
17
  object.total_pages = collection["total_pages"]
26
18
  object.current_page = collection["current_page"]
@@ -28,8 +20,8 @@ module FidorApi
28
20
  end
29
21
  end
30
22
 
31
- def to_a
32
- records
23
+ def each(&block)
24
+ records.each(&block)
33
25
  end
34
26
 
35
27
  # --- kaminari stuff -- maybe move somewhere else
@@ -40,16 +32,6 @@ module FidorApi
40
32
  def next_page
41
33
  current_page + 1
42
34
  end
43
-
44
- private
45
-
46
- def self.collection_from_array(array)
47
- {
48
- "total_pages" => 1,
49
- "current_page" => 1,
50
- "per_page" => array.count
51
- }
52
- end
53
35
  end
54
36
 
55
37
  end
@@ -3,6 +3,31 @@ module FidorApi
3
3
  class Customer < Resource
4
4
  extend ModelAttribute
5
5
 
6
+ module Gender
7
+ extend self
8
+
9
+ class Base
10
+ include Singleton
11
+ end
12
+
13
+ class Male < Base; end
14
+ class Female < Base; end
15
+ class Unknonw < Base; end
16
+
17
+ MAPPING = {
18
+ Male => "m",
19
+ Female => "f"
20
+ }
21
+
22
+ def for_api_value(api_value)
23
+ MAPPING.key(api_value) || Unknonw
24
+ end
25
+
26
+ def object_to_string(object)
27
+ MAPPING[object]
28
+ end
29
+ end
30
+
6
31
  attribute :id, :integer
7
32
  attribute :email, :string
8
33
  attribute :first_name, :string
@@ -31,15 +56,58 @@ module FidorApi
31
56
  attribute :created_at, :time
32
57
  attribute :updated_at, :time
33
58
  attribute :creditor_identifier, :string
59
+ attribute :affiliate_uid, :string
60
+ attribute :verification_token, :string
61
+ attribute :password, :string
62
+ attribute :tos, :boolean
63
+ attribute :privacy_policy, :boolean
64
+ attribute :own_interest, :boolean
65
+ attribute :us_citizen, :boolean
66
+ attribute :us_tax_payer, :boolean
34
67
 
35
68
  def self.all(access_token, options = {})
36
- Collection.build(self, request(:get, access_token, "/customers", options))
69
+ Collection.build(self, request(access_token: access_token, endpoint: "/customers", query_params: options).body)
37
70
  end
38
71
 
39
72
  def self.first(access_token)
40
73
  all(access_token, page: 1, per_page: 1).first
41
74
  end
42
75
 
76
+ def initialize(*args)
77
+ super
78
+ self.affiliate_uid = FidorApi.configuration.affiliate_uid
79
+ end
80
+
81
+ def gender
82
+ Gender.for_api_value(@gender)
83
+ end
84
+
85
+ def gender=(value)
86
+ @gender = if value.class == Class && value.instance.is_a?(FidorApi::Customer::Gender::Base)
87
+ Gender.object_to_string(value)
88
+ else
89
+ value
90
+ end
91
+ end
92
+
93
+ def as_json(options = nil)
94
+ attributes.tap { |a| a[:birthday] = a[:birthday].try(:to_date) }
95
+ end
96
+
97
+ def save
98
+ if id.nil?
99
+ create(htauth: true, access_token: nil)
100
+ else
101
+ raise NoUpdatesAllowedError
102
+ end
103
+ end
104
+
105
+ private
106
+
107
+ def self.resource
108
+ "customers"
109
+ end
110
+
43
111
  module ClientSupport
44
112
  def customers(options = {})
45
113
  Customer.all(token.access_token, options)
@@ -4,5 +4,15 @@ module FidorApi
4
4
  ClientError = Class.new(Error)
5
5
  UnauthorizedTokenError = Class.new(Error)
6
6
  InvalidRecordError = Class.new(Error)
7
+ NoUpdatesAllowedError = Class.new(Error)
8
+
9
+ class ValidationError < Error
10
+ attr_accessor :fields
11
+
12
+ def initialize(message, fields)
13
+ super(message)
14
+ self.fields = fields
15
+ end
16
+ end
7
17
 
8
18
  end
@@ -0,0 +1,53 @@
1
+ module FidorApi
2
+
3
+ class Message < Resource
4
+ extend ModelAttribute
5
+ extend AmountAttributes
6
+
7
+ attribute :id, :integer
8
+ attribute :subject, :string
9
+ attribute :type, :string
10
+ attribute :opened_at, :time
11
+ attribute :created_at, :time
12
+ attribute :updated_at, :time
13
+ attribute :category, :string
14
+
15
+ class Attachment
16
+ include ActiveModel::Model
17
+ attr_accessor :type, :filename, :content
18
+ end
19
+
20
+ def self.all(access_token, options = {})
21
+ Collection.build(self, request(access_token: access_token, endpoint: "/messages", query_params: options).body)
22
+ end
23
+
24
+ def self.find(access_token, id)
25
+ new(request(access_token: access_token, endpoint: "/messages/#{id}").body)
26
+ end
27
+
28
+ def self.attachment(access_token, id)
29
+ response = request(access_token: access_token, endpoint: "/messages/#{id}/attachment")
30
+
31
+ Attachment.new(
32
+ type: response.headers["content-type"],
33
+ filename: response.headers["content-disposition"][/filename="([^"]+)"/, 1],
34
+ content: response.body,
35
+ )
36
+ end
37
+
38
+ module ClientSupport
39
+ def messages(options = {})
40
+ Message.all(token.access_token, options)
41
+ end
42
+
43
+ def message(id)
44
+ Message.find(token.access_token, id)
45
+ end
46
+
47
+ def message_attachment(id)
48
+ Message.attachment(token.access_token, id)
49
+ end
50
+ end
51
+ end
52
+
53
+ end
@@ -0,0 +1,45 @@
1
+ module FidorApi
2
+
3
+ module Msisdn
4
+ extend self
5
+
6
+ def check(msisdn)
7
+ post "/msisdn/check", {
8
+ msisdn: msisdn,
9
+ os_type: FidorApi.configuration.os_type,
10
+ affiliate_uid: FidorApi.configuration.affiliate_uid
11
+ }
12
+ end
13
+
14
+ def verify(msisdn, code)
15
+ post "/msisdn/verify", {
16
+ msisdn: msisdn,
17
+ code: code
18
+ }
19
+ end
20
+
21
+ private
22
+
23
+ def connection
24
+ Faraday.new(url: FidorApi.configuration.oauth_url) do |config|
25
+ config.use Faraday::Request::BasicAuthentication, FidorApi.configuration.htauth_user, FidorApi.configuration.htauth_password
26
+ config.request :url_encoded
27
+ config.response :logger if FidorApi.configuration.logging
28
+ config.response :raise_error
29
+ config.adapter Faraday.default_adapter
30
+ end
31
+ end
32
+
33
+ def post(endpoint, body)
34
+ response = connection.post endpoint do |request|
35
+ request.headers = {
36
+ "Accept" => "application/vnd.fidor.de; version=1,text/json",
37
+ "Content-Type" => "application/json"
38
+ }
39
+ request.body = body.to_json
40
+ end
41
+ response.body
42
+ end
43
+ end
44
+
45
+ end
@@ -2,23 +2,24 @@ module FidorApi
2
2
 
3
3
  class Preauth < Resource
4
4
  extend ModelAttribute
5
+ extend AmountAttributes
5
6
 
6
7
  attribute :id, :integer
7
8
  attribute :account_id, :string
8
9
  attribute :preauth_type, :string
9
10
  attribute :preauth_type_details, :json
10
- attribute :amount, :integer
11
11
  attribute :expires_at, :time
12
12
  attribute :created_at, :time
13
13
  attribute :updated_at, :time
14
14
  attribute :currency, :string
15
+ amount_attribute :amount
15
16
 
16
17
  def self.all(access_token, options = {})
17
- Collection.build(self, request(:get, access_token, "/preauths", options))
18
+ Collection.build(self, request(access_token: access_token, endpoint: "/preauths", query_params: options).body)
18
19
  end
19
20
 
20
21
  def self.find(access_token, id)
21
- new(request(:get, access_token, "/preauths/#{id}"))
22
+ new(request(access_token: access_token, endpoint: "/preauths/#{id}").body)
22
23
  end
23
24
 
24
25
  def preauth_type_details
@@ -44,7 +44,7 @@ module FidorApi
44
44
  attribute :remote_subject, :string
45
45
 
46
46
  def description
47
- remote_nick || remote_name || super
47
+ remote_name || remote_nick || super
48
48
  end
49
49
  end
50
50
 
@@ -5,41 +5,80 @@ module FidorApi
5
5
 
6
6
  attr_accessor :client
7
7
 
8
+ class Response
9
+ include ActiveModel::Model
10
+
11
+ attr_accessor :headers, :body
12
+
13
+ def body
14
+ if headers["content-type"] =~ /json/
15
+ JSON.parse(@body)
16
+ else
17
+ @body
18
+ end
19
+ end
20
+ end
21
+
8
22
  def initialize(attributes = {})
9
- self.client = client
10
23
  set_attributes(attributes)
11
24
  end
12
25
 
13
- def self.request(method, access_token, endpoint, query_params = {}, body = {})
14
- response = connection.public_send(method, endpoint) do |request|
26
+ def self.request(method: :get, access_token: nil, endpoint: nil, query_params: {}, body: {}, htauth: false)
27
+ response = connection(htauth: htauth).public_send(method, endpoint) do |request|
15
28
  request.params = query_params
16
- request.headers = {
17
- "Authorization" => "Bearer #{access_token}",
18
- "Accept" => "application/vnd.fidor.de; version=1,text/json",
19
- "Content-Type" => "application/json"
20
- }
29
+ request.headers = {}
30
+ request.headers["Authorization"] = "Bearer #{access_token}" if access_token
31
+ request.headers["Accept"] = "application/vnd.fidor.de; version=1,text/json"
32
+ request.headers["Content-Type"] = "application/json"
21
33
  request.body = body.to_json unless body.empty?
22
34
  end
23
- JSON.parse response.body
35
+ Response.new(headers: response.headers, body: response.body)
24
36
  rescue Faraday::Error::ClientError => e
25
- if e.response[:status] == 401 && e.response[:body] =~ /token_not_found|Unauthorized token|expired/
37
+ case e.response[:status]
38
+ when 401
26
39
  raise UnauthorizedTokenError
40
+ when 422
41
+ body = JSON.parse(e.response[:body])
42
+ raise ValidationError.new(body["message"], body["errors"])
27
43
  else
28
44
  raise ClientError
29
45
  end
30
46
  end
31
47
 
48
+ def self.model_name
49
+ ActiveModel::Name.new(self, nil, self.name.sub("FidorApi::", ""))
50
+ end
51
+
52
+ def persisted?
53
+ id.present?
54
+ end
55
+
32
56
  private
33
57
 
34
- def self.connection
58
+ def self.connection(htauth: false)
35
59
  Faraday.new(url: FidorApi.configuration.api_url) do |config|
36
- config.use Faraday::Request::BasicAuthentication, FidorApi.configuration.client_id, FidorApi.configuration.client_secret
60
+ config.use Faraday::Request::BasicAuthentication, FidorApi.configuration.htauth_user, FidorApi.configuration.htauth_password if htauth
37
61
  config.request :url_encoded
38
- config.response :logger if FidorApi.configuration.logging
62
+ config.response :logger if FidorApi.configuration.logging
39
63
  config.response :raise_error
40
64
  config.adapter Faraday.default_adapter
41
65
  end
42
66
  end
67
+
68
+ def create(options = {})
69
+ raise InvalidRecordError unless valid?
70
+ set_attributes self.class.request({ method: :post, access_token: client.try { |c| c.token.access_token }, endpoint: self.class.resource, body: as_json }.merge(options)).body
71
+ true
72
+ rescue ValidationError => e
73
+ map_errors(e.fields)
74
+ false
75
+ end
76
+
77
+ def map_errors(fields)
78
+ fields.each do |hash|
79
+ errors.add(hash["field"].to_sym, hash["message"]) if respond_to? hash["field"].to_sym
80
+ end
81
+ end
43
82
  end
44
83
 
45
84
  end
@@ -2,13 +2,13 @@ module FidorApi
2
2
 
3
3
  class Transaction < Resource
4
4
  extend ModelAttribute
5
+ extend AmountAttributes
5
6
 
6
7
  attribute :id, :integer
7
8
  attribute :account_id, :string
8
9
  attribute :transaction_type, :string
9
10
  attribute :transaction_type_details, :json
10
11
  attribute :subject, :string
11
- attribute :amount, :integer
12
12
  attribute :currency, :string
13
13
  attribute :booking_date, :time
14
14
  attribute :value_date, :time
@@ -16,13 +16,14 @@ module FidorApi
16
16
  attribute :return_transaction_id, :string
17
17
  attribute :created_at, :time
18
18
  attribute :updated_at, :time
19
+ amount_attribute :amount
19
20
 
20
21
  def self.all(access_token, options = {})
21
- Collection.build(self, request(:get, access_token, "/transactions", options))
22
+ Collection.build(self, request(access_token: access_token, endpoint: "/transactions", query_params: options).body)
22
23
  end
23
24
 
24
25
  def self.find(access_token, id)
25
- new(request(:get, access_token, "/transactions/#{id}"))
26
+ new(request(access_token: access_token, endpoint: "/transactions/#{id}").body)
26
27
  end
27
28
 
28
29
  def transaction_type_details
@@ -5,25 +5,26 @@ module FidorApi
5
5
  class Base < Resource
6
6
 
7
7
  def save
8
- raise InvalidRecordError unless valid?
9
-
10
- set_attributes self.class.request(:post, client.token.access_token, self.class.resource, {}, as_json)
11
-
12
- true
8
+ if id.nil?
9
+ create
10
+ else
11
+ raise NoUpdatesAllowedError
12
+ end
13
13
  end
14
14
 
15
15
  def self.all(access_token, options = {})
16
- Collection.build(self, request(:get, access_token, resource, options))
16
+ Collection.build(self, request(access_token: access_token, endpoint: resource, query_params: options).body)
17
17
  end
18
18
 
19
19
  def self.find(access_token, id)
20
- new(request(:get, access_token, "/#{resource}/#{id}"))
20
+ new(request(access_token: access_token, endpoint: "/#{resource}/#{id}").body)
21
21
  end
22
22
 
23
23
  end
24
24
 
25
25
  class Internal < Base
26
26
  extend ModelAttribute
27
+ extend AmountAttributes
27
28
 
28
29
  attribute :id, :integer
29
30
  attribute :account_id, :string
@@ -31,29 +32,33 @@ module FidorApi
31
32
  attribute :transaction_id, :string
32
33
  attribute :receiver, :string
33
34
  attribute :external_uid, :string
34
- attribute :amount, :integer
35
35
  attribute :currency, :string
36
36
  attribute :subject, :string
37
37
  attribute :state, :string
38
38
  attribute :created_at, :time
39
39
  attribute :updated_at, :time
40
+ amount_attribute :amount
40
41
 
41
42
  def self.required_attributes
42
43
  [ :account_id, :receiver, :external_uid, :amount, :subject ]
43
44
  end
44
45
 
46
+ def self.writeable_attributes
47
+ required_attributes
48
+ end
49
+
45
50
  validates *required_attributes, presence: true
46
51
 
52
+ def as_json
53
+ attributes.slice *self.class.writeable_attributes
54
+ end
55
+
47
56
  private
48
57
 
49
58
  def self.resource
50
59
  "internal_transfers"
51
60
  end
52
61
 
53
- def as_json
54
- attributes.slice *self.class.required_attributes
55
- end
56
-
57
62
  module ClientSupport
58
63
  def internal_transfers(options = {})
59
64
  Transfer::Internal.all(token.access_token, options)
@@ -71,6 +76,7 @@ module FidorApi
71
76
 
72
77
  class SEPA < Base
73
78
  extend ModelAttribute
79
+ extend AmountAttributes
74
80
 
75
81
  attribute :id, :integer
76
82
  attribute :account_id, :string
@@ -79,7 +85,6 @@ module FidorApi
79
85
  attribute :remote_iban, :string
80
86
  attribute :remote_bic, :string
81
87
  attribute :remote_name, :string
82
- attribute :amount, :integer
83
88
  attribute :external_uid, :string
84
89
  attribute :subject, :string
85
90
  attribute :currency, :string
@@ -87,23 +92,28 @@ module FidorApi
87
92
  attribute :state, :string
88
93
  attribute :created_at, :time
89
94
  attribute :updated_at, :time
95
+ amount_attribute :amount
90
96
 
91
97
  def self.required_attributes
92
- [ :account_id, :external_uid, :remote_iban, :remote_bic, :remote_name, :amount, :subject ]
98
+ [ :account_id, :external_uid, :remote_iban, :remote_name, :amount, :subject ]
99
+ end
100
+
101
+ def self.writeable_attributes
102
+ required_attributes + [:remote_bic]
93
103
  end
94
104
 
95
105
  validates *required_attributes, presence: true
96
106
 
107
+ def as_json
108
+ attributes.slice *self.class.writeable_attributes
109
+ end
110
+
97
111
  private
98
112
 
99
113
  def self.resource
100
114
  "sepa_credit_transfers"
101
115
  end
102
116
 
103
- def as_json
104
- attributes.slice *self.class.required_attributes
105
- end
106
-
107
117
  module ClientSupport
108
118
  def sepa_transfers(options = {})
109
119
  Transfer::SEPA.all(token.access_token, options)
@@ -119,6 +129,61 @@ module FidorApi
119
129
  end
120
130
  end
121
131
 
132
+ class FPS < Base
133
+ extend ModelAttribute
134
+ extend AmountAttributes
135
+
136
+ attribute :id, :integer
137
+ attribute :account_id, :string
138
+ attribute :user_id, :string
139
+ attribute :transaction_id, :string
140
+ attribute :remote_account, :string
141
+ attribute :remote_sort_code, :string
142
+ attribute :remote_name, :string
143
+ attribute :external_uid, :string
144
+ attribute :subject, :string
145
+ attribute :currency, :string
146
+ attribute :subject, :string
147
+ attribute :state, :string
148
+ attribute :created_at, :time
149
+ attribute :updated_at, :time
150
+ amount_attribute :amount
151
+
152
+ def self.required_attributes
153
+ [ :account_id, :external_uid, :remote_account, :remote_sort_code, :remote_name, :amount, :subject ]
154
+ end
155
+
156
+ def self.writeable_attributes
157
+ required_attributes
158
+ end
159
+
160
+ validates *required_attributes, presence: true
161
+
162
+ def as_json
163
+ attributes.slice *self.class.writeable_attributes
164
+ end
165
+
166
+ private
167
+
168
+ def self.resource
169
+ "fps_transfers"
170
+ end
171
+
172
+ module ClientSupport
173
+ def fps_transfers(options = {})
174
+ Transfer::FPS.all(token.access_token, options)
175
+ end
176
+
177
+ def fps_transfer(id)
178
+ Transfer::FPS.find(token.access_token, id)
179
+ end
180
+
181
+ def build_fps_transfer(attributes = {})
182
+ Transfer::FPS.new(attributes.merge(client: self))
183
+ end
184
+ end
185
+ end
186
+
122
187
  end
123
188
 
124
189
  end
@@ -10,7 +10,7 @@ module FidorApi
10
10
  attribute :updated_at, :time
11
11
 
12
12
  def self.current(access_token)
13
- new(request(:get, access_token, "/users/current"))
13
+ new(request(access_token: access_token, endpoint: "/users/current").body)
14
14
  end
15
15
 
16
16
  module ClientSupport
@@ -1,3 +1,3 @@
1
1
  module FidorApi
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fidor_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Klaus Meyer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-17 00:00:00.000000000 Z
11
+ date: 2016-05-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -28,30 +28,42 @@ dependencies:
28
28
  name: activesupport
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '4.2'
34
+ - - "<"
35
+ - !ruby/object:Gem::Version
36
+ version: '5.1'
34
37
  type: :runtime
35
38
  prerelease: false
36
39
  version_requirements: !ruby/object:Gem::Requirement
37
40
  requirements:
38
- - - "~>"
41
+ - - ">="
39
42
  - !ruby/object:Gem::Version
40
43
  version: '4.2'
44
+ - - "<"
45
+ - !ruby/object:Gem::Version
46
+ version: '5.1'
41
47
  - !ruby/object:Gem::Dependency
42
48
  name: activemodel
43
49
  requirement: !ruby/object:Gem::Requirement
44
50
  requirements:
45
- - - "~>"
51
+ - - ">="
46
52
  - !ruby/object:Gem::Version
47
53
  version: '4.2'
54
+ - - "<"
55
+ - !ruby/object:Gem::Version
56
+ version: '5.1'
48
57
  type: :runtime
49
58
  prerelease: false
50
59
  version_requirements: !ruby/object:Gem::Requirement
51
60
  requirements:
52
- - - "~>"
61
+ - - ">="
53
62
  - !ruby/object:Gem::Version
54
63
  version: '4.2'
64
+ - - "<"
65
+ - !ruby/object:Gem::Version
66
+ version: '5.1'
55
67
  - !ruby/object:Gem::Dependency
56
68
  name: model_attribute
57
69
  requirement: !ruby/object:Gem::Requirement
@@ -66,104 +78,6 @@ dependencies:
66
78
  - - "~>"
67
79
  - !ruby/object:Gem::Version
68
80
  version: '2.1'
69
- - !ruby/object:Gem::Dependency
70
- name: bundler
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '1.10'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '1.10'
83
- - !ruby/object:Gem::Dependency
84
- name: byebug
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: '8.2'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: '8.2'
97
- - !ruby/object:Gem::Dependency
98
- name: rake
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: '10.0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: '10.0'
111
- - !ruby/object:Gem::Dependency
112
- name: rspec
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - "~>"
116
- - !ruby/object:Gem::Version
117
- version: '3.3'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - "~>"
123
- - !ruby/object:Gem::Version
124
- version: '3.3'
125
- - !ruby/object:Gem::Dependency
126
- name: shoulda-matchers
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - "~>"
130
- - !ruby/object:Gem::Version
131
- version: '2.8'
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - "~>"
137
- - !ruby/object:Gem::Version
138
- version: '2.8'
139
- - !ruby/object:Gem::Dependency
140
- name: vcr
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - "~>"
144
- - !ruby/object:Gem::Version
145
- version: '2.9'
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - "~>"
151
- - !ruby/object:Gem::Version
152
- version: '2.9'
153
- - !ruby/object:Gem::Dependency
154
- name: simplecov
155
- requirement: !ruby/object:Gem::Requirement
156
- requirements:
157
- - - "~>"
158
- - !ruby/object:Gem::Version
159
- version: '0.10'
160
- type: :development
161
- prerelease: false
162
- version_requirements: !ruby/object:Gem::Requirement
163
- requirements:
164
- - - "~>"
165
- - !ruby/object:Gem::Version
166
- version: '0.10'
167
81
  description: Connect to the Fidor Bank API
168
82
  email:
169
83
  - spam@klaus-meyer.net
@@ -185,11 +99,16 @@ files:
185
99
  - fidor_api.gemspec
186
100
  - lib/fidor_api.rb
187
101
  - lib/fidor_api/account.rb
102
+ - lib/fidor_api/amount_attributes.rb
188
103
  - lib/fidor_api/auth.rb
104
+ - lib/fidor_api/card.rb
105
+ - lib/fidor_api/card_limits.rb
189
106
  - lib/fidor_api/client.rb
190
107
  - lib/fidor_api/collection.rb
191
108
  - lib/fidor_api/customer.rb
192
109
  - lib/fidor_api/errors.rb
110
+ - lib/fidor_api/message.rb
111
+ - lib/fidor_api/msisdn.rb
193
112
  - lib/fidor_api/preauth.rb
194
113
  - lib/fidor_api/preauth_details.rb
195
114
  - lib/fidor_api/resource.rb
@@ -219,7 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
219
138
  version: '0'
220
139
  requirements: []
221
140
  rubyforge_project:
222
- rubygems_version: 2.4.8
141
+ rubygems_version: 2.5.1
223
142
  signing_key:
224
143
  specification_version: 4
225
144
  summary: Simple ruby client for the Fidor Bank API