fidor_api 0.0.1 → 0.0.2

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