fidor_api 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.ruby-version +1 -1
  4. data/.travis.yml +5 -3
  5. data/CHANGELOG.md +114 -0
  6. data/Gemfile +3 -2
  7. data/README.md +12 -10
  8. data/lib/fidor_api/account.rb +7 -10
  9. data/lib/fidor_api/amount_attributes.rb +23 -20
  10. data/lib/fidor_api/approval_required.rb +9 -0
  11. data/lib/fidor_api/auth.rb +1 -1
  12. data/lib/fidor_api/beneficiary/ach.rb +39 -0
  13. data/lib/fidor_api/beneficiary/base.rb +118 -0
  14. data/lib/fidor_api/beneficiary/generic.rb +24 -0
  15. data/lib/fidor_api/beneficiary/p2p_account_number.rb +14 -0
  16. data/lib/fidor_api/beneficiary/p2p_phone.rb +14 -0
  17. data/lib/fidor_api/beneficiary/p2p_username.rb +14 -0
  18. data/lib/fidor_api/beneficiary/swift.rb +35 -0
  19. data/lib/fidor_api/beneficiary/unknown.rb +16 -0
  20. data/lib/fidor_api/beneficiary/utility.rb +35 -0
  21. data/lib/fidor_api/beneficiary.rb +27 -0
  22. data/lib/fidor_api/card.rb +31 -48
  23. data/lib/fidor_api/card_limit_attribute.rb +52 -0
  24. data/lib/fidor_api/card_limits.rb +6 -34
  25. data/lib/fidor_api/client.rb +8 -2
  26. data/lib/fidor_api/collection.rb +15 -6
  27. data/lib/fidor_api/confirmable_action.rb +45 -0
  28. data/lib/fidor_api/connectivity/connection.rb +113 -0
  29. data/lib/fidor_api/connectivity/endpoint.rb +82 -0
  30. data/lib/fidor_api/connectivity/resource.rb +76 -0
  31. data/lib/fidor_api/connectivity.rb +17 -0
  32. data/lib/fidor_api/constants.rb +3 -0
  33. data/lib/fidor_api/customer.rb +41 -23
  34. data/lib/fidor_api/customers/confirmations.rb +19 -0
  35. data/lib/fidor_api/errors.rb +14 -3
  36. data/lib/fidor_api/message.rb +17 -18
  37. data/lib/fidor_api/msisdn.rb +1 -1
  38. data/lib/fidor_api/password.rb +30 -0
  39. data/lib/fidor_api/preauth.rb +5 -12
  40. data/lib/fidor_api/session_token.rb +20 -0
  41. data/lib/fidor_api/transaction.rb +5 -12
  42. data/lib/fidor_api/transfer/ach.rb +46 -0
  43. data/lib/fidor_api/transfer/bank_internal.rb +37 -0
  44. data/lib/fidor_api/transfer/base.rb +36 -0
  45. data/lib/fidor_api/transfer/fps.rb +56 -0
  46. data/lib/fidor_api/transfer/generic.rb +134 -0
  47. data/lib/fidor_api/transfer/internal.rb +53 -0
  48. data/lib/fidor_api/transfer/p2p_account_number.rb +45 -0
  49. data/lib/fidor_api/transfer/p2p_phone.rb +45 -0
  50. data/lib/fidor_api/transfer/p2p_username.rb +45 -0
  51. data/lib/fidor_api/transfer/sepa.rb +56 -0
  52. data/lib/fidor_api/transfer/swift.rb +49 -0
  53. data/lib/fidor_api/transfer/utility.rb +50 -0
  54. data/lib/fidor_api/transfer.rb +13 -186
  55. data/lib/fidor_api/user.rb +12 -11
  56. data/lib/fidor_api/version.rb +1 -1
  57. data/lib/fidor_api.rb +39 -22
  58. metadata +37 -4
  59. data/lib/fidor_api/resource.rb +0 -84
@@ -1,8 +1,9 @@
1
1
  module FidorApi
2
-
3
- class Customer < Resource
2
+ class Customer < Connectivity::Resource
4
3
  extend ModelAttribute
5
4
 
5
+ self.endpoint = Connectivity::Endpoint.new('/customers', :collection)
6
+
6
7
  module Gender
7
8
  extend self
8
9
 
@@ -12,7 +13,7 @@ module FidorApi
12
13
 
13
14
  class Male < Base; end
14
15
  class Female < Base; end
15
- class Unknonw < Base; end
16
+ class Unknown < Base; end
16
17
 
17
18
  MAPPING = {
18
19
  Male => "m",
@@ -20,7 +21,7 @@ module FidorApi
20
21
  }
21
22
 
22
23
  def for_api_value(api_value)
23
- MAPPING.key(api_value) || Unknonw
24
+ MAPPING.key(api_value) || Unknown
24
25
  end
25
26
 
26
27
  def object_to_string(object)
@@ -64,13 +65,13 @@ module FidorApi
64
65
  attribute :own_interest, :boolean
65
66
  attribute :us_citizen, :boolean
66
67
  attribute :us_tax_payer, :boolean
68
+ attribute :preferred_language, :string
69
+ attribute :community_user_picture, :string
70
+ attribute :country_of_birth, :string
71
+ attribute :additional_first_name, :string
67
72
 
68
- def self.all(access_token, options = {})
69
- Collection.build(self, request(access_token: access_token, endpoint: "/customers", query_params: options).body)
70
- end
71
-
72
- def self.first(access_token)
73
- all(access_token, page: 1, per_page: 1).first
73
+ def self.first
74
+ all(page: 1, per_page: 1).first
74
75
  end
75
76
 
76
77
  def initialize(*args)
@@ -78,6 +79,20 @@ module FidorApi
78
79
  self.affiliate_uid = FidorApi.configuration.affiliate_uid
79
80
  end
80
81
 
82
+ def request_update(attributes)
83
+ self.endpoint = Connectivity::Endpoint.new('/customers', :collection, version: '2')
84
+ endpoint.for(self).put(action: 'request_update', payload: attributes.as_json)
85
+ true
86
+ rescue ValidationError => e
87
+ map_errors(e.fields)
88
+ false
89
+ end
90
+
91
+ def confirm_update(attributes)
92
+ self.endpoint = Connectivity::Endpoint.new('/customers', :collection, version: '2')
93
+ endpoint.for(self).put(action: 'confirm_update', payload: {token: attributes['token']})
94
+ end
95
+
81
96
  def gender
82
97
  Gender.for_api_value(@gender)
83
98
  end
@@ -94,29 +109,32 @@ module FidorApi
94
109
  attributes.tap { |a| a[:birthday] = a[:birthday].try(:to_date) }
95
110
  end
96
111
 
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
112
  private
106
113
 
107
- def self.resource
108
- "customers"
114
+ def remote_create
115
+ endpoint.for(self).post(payload: self.as_json, tokenless: true)
109
116
  end
110
117
 
111
118
  module ClientSupport
112
119
  def customers(options = {})
113
- Customer.all(token.access_token, options)
120
+ Customer.all(options)
114
121
  end
115
122
 
116
123
  def first_customer
117
- Customer.first(token.access_token)
124
+ Customer.first
125
+ end
126
+
127
+ def update_customer(id, attributes)
128
+ Customer.endpoint.for(id).put(payload: attributes)
129
+ end
130
+
131
+ def request_customer_update(id, attributes)
132
+ Customer.new(id: id).request_update(attributes)
133
+ end
134
+
135
+ def confirm_customer_update(id, attributes)
136
+ Customer.new(id: id).confirm_update(attributes)
118
137
  end
119
138
  end
120
139
  end
121
-
122
140
  end
@@ -0,0 +1,19 @@
1
+ module FidorApi
2
+ module Customers
3
+ class Confirmations < Connectivity::Resource
4
+ extend ModelAttribute
5
+
6
+ self.endpoint = Connectivity::Endpoint.new('/customers/confirmation', :collection)
7
+
8
+ def self.create(*attributes)
9
+ new(*attributes).save
10
+ end
11
+
12
+ private
13
+
14
+ def persisted?
15
+ false
16
+ end
17
+ end
18
+ end
19
+ end
@@ -6,12 +6,23 @@ module FidorApi
6
6
  InvalidRecordError = Class.new(Error)
7
7
  NoUpdatesAllowedError = Class.new(Error)
8
8
 
9
+ class ForbiddenError < Error
10
+ attr_accessor :code, :key
11
+
12
+ def initialize(message, code, key)
13
+ super(message)
14
+ self.code = code
15
+ self.key = key
16
+ end
17
+ end
18
+
9
19
  class ValidationError < Error
10
- attr_accessor :fields
20
+ attr_accessor :fields, :error_keys
11
21
 
12
- def initialize(message, fields)
22
+ def initialize(message, fields, error_keys)
13
23
  super(message)
14
- self.fields = fields
24
+ self.fields = fields
25
+ self.error_keys = error_keys
15
26
  end
16
27
  end
17
28
 
@@ -1,9 +1,10 @@
1
1
  module FidorApi
2
-
3
- class Message < Resource
2
+ class Message < Connectivity::Resource
4
3
  extend ModelAttribute
5
4
  extend AmountAttributes
6
5
 
6
+ self.endpoint = Connectivity::Endpoint.new('/messages', :collection)
7
+
7
8
  attribute :id, :integer
8
9
  attribute :subject, :string
9
10
  attribute :type, :string
@@ -17,17 +18,8 @@ module FidorApi
17
18
  attr_accessor :type, :filename, :content
18
19
  end
19
20
 
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
-
21
+ def attachment
22
+ response = endpoint.for(self).get(action: 'attachment')
31
23
  Attachment.new(
32
24
  type: response.headers["content-type"],
33
25
  filename: response.headers["content-disposition"][/filename="([^"]+)"/, 1],
@@ -35,19 +27,26 @@ module FidorApi
35
27
  )
36
28
  end
37
29
 
30
+ def content
31
+ endpoint.for(self).get(action: 'content').body
32
+ end
33
+
38
34
  module ClientSupport
39
35
  def messages(options = {})
40
- Message.all(token.access_token, options)
36
+ Message.all(options)
41
37
  end
42
38
 
43
39
  def message(id)
44
- Message.find(token.access_token, id)
40
+ Message.find(id)
45
41
  end
46
42
 
47
43
  def message_attachment(id)
48
- Message.attachment(token.access_token, id)
44
+ Message.new(id: id).attachment
45
+ end
46
+
47
+ def message_content(id)
48
+ Message.new(id: id).content
49
49
  end
50
50
  end
51
51
  end
52
-
53
- end
52
+ end
@@ -21,7 +21,7 @@ module FidorApi
21
21
  private
22
22
 
23
23
  def connection
24
- Faraday.new(url: FidorApi.configuration.oauth_url) do |config|
24
+ Faraday.new(url: FidorApi.configuration.oauth_url, ssl: { verify: FidorApi.configuration.verify_ssl }) do |config|
25
25
  config.use Faraday::Request::BasicAuthentication, FidorApi.configuration.htauth_user, FidorApi.configuration.htauth_password
26
26
  config.request :url_encoded
27
27
  config.response :logger if FidorApi.configuration.logging
@@ -0,0 +1,30 @@
1
+ module FidorApi
2
+ class Password < Connectivity::Resource
3
+ extend ModelAttribute
4
+
5
+ self.endpoint = Connectivity::Endpoint.new("/password_resets", :collection, version: "2", tokenless: true)
6
+
7
+ def self.request_new(email)
8
+ params = {email: email, type: "reset_token"}
9
+ response = endpoint.for(self).put(action: "new_token", payload: params)
10
+ response.body["success"]
11
+ end
12
+
13
+ def self.update(attributes)
14
+ response = endpoint.for(self).post(payload: attributes)
15
+ response.body["success"]
16
+ end
17
+
18
+ private
19
+
20
+ module ClientSupport
21
+ def request_new_password(email)
22
+ Password.request_new(email)
23
+ end
24
+
25
+ def update_password(attributes)
26
+ Password.update(attributes)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,9 +1,10 @@
1
1
  module FidorApi
2
-
3
- class Preauth < Resource
2
+ class Preauth < Connectivity::Resource
4
3
  extend ModelAttribute
5
4
  extend AmountAttributes
6
5
 
6
+ self.endpoint = Connectivity::Endpoint.new('/preauths', :collection)
7
+
7
8
  attribute :id, :integer
8
9
  attribute :account_id, :string
9
10
  attribute :preauth_type, :string
@@ -14,25 +15,17 @@ module FidorApi
14
15
  attribute :currency, :string
15
16
  amount_attribute :amount
16
17
 
17
- def self.all(access_token, options = {})
18
- Collection.build(self, request(access_token: access_token, endpoint: "/preauths", query_params: options).body)
19
- end
20
-
21
- def self.find(access_token, id)
22
- new(request(access_token: access_token, endpoint: "/preauths/#{id}").body)
23
- end
24
-
25
18
  def preauth_type_details
26
19
  @_preauth_type_details ||= PreauthDetails.build(@preauth_type, @preauth_type_details)
27
20
  end
28
21
 
29
22
  module ClientSupport
30
23
  def preauths(options = {})
31
- Preauth.all(token.access_token, options)
24
+ Preauth.all(options)
32
25
  end
33
26
 
34
27
  def preauth(id)
35
- Preauth.find(token.access_token, id)
28
+ Preauth.find(id)
36
29
  end
37
30
  end
38
31
  end
@@ -0,0 +1,20 @@
1
+ module FidorApi
2
+ class SessionToken < Connectivity::Resource
3
+ extend ModelAttribute
4
+ extend AmountAttributes
5
+
6
+ attribute :token, :string
7
+
8
+ self.endpoint = Connectivity::Endpoint.new('/session_tokens', :collection)
9
+
10
+ def self.create(access_token)
11
+ new endpoint.for(self).post(payload: {access_token: access_token}).body
12
+ end
13
+
14
+ module ClientSupport
15
+ def create_session_token
16
+ SessionToken.create(token.access_token)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,9 +1,10 @@
1
1
  module FidorApi
2
-
3
- class Transaction < Resource
2
+ class Transaction < Connectivity::Resource
4
3
  extend ModelAttribute
5
4
  extend AmountAttributes
6
5
 
6
+ self.endpoint = Connectivity::Endpoint.new('/transactions', :collection)
7
+
7
8
  attribute :id, :integer
8
9
  attribute :account_id, :string
9
10
  attribute :transaction_type, :string
@@ -18,25 +19,17 @@ module FidorApi
18
19
  attribute :updated_at, :time
19
20
  amount_attribute :amount
20
21
 
21
- def self.all(access_token, options = {})
22
- Collection.build(self, request(access_token: access_token, endpoint: "/transactions", query_params: options).body)
23
- end
24
-
25
- def self.find(access_token, id)
26
- new(request(access_token: access_token, endpoint: "/transactions/#{id}").body)
27
- end
28
-
29
22
  def transaction_type_details
30
23
  @_transaction_type_details ||= TransactionDetails.build(@transaction_type, @transaction_type_details)
31
24
  end
32
25
 
33
26
  module ClientSupport
34
27
  def transactions(options = {})
35
- Transaction.all(token.access_token, options)
28
+ Transaction.all(options)
36
29
  end
37
30
 
38
31
  def transaction(id)
39
- Transaction.find(token.access_token, id)
32
+ Transaction.find(id)
40
33
  end
41
34
  end
42
35
  end
@@ -0,0 +1,46 @@
1
+ module FidorApi
2
+ module Transfer
3
+ class ACH < Base
4
+ include Generic
5
+
6
+ attribute :account_number, :string
7
+ attribute :routing_code, :string
8
+
9
+ validates :contact_name, presence: true, unless: :beneficiary_reference_passed?
10
+ validates :account_number, presence: true, unless: :beneficiary_reference_passed?
11
+ validates :routing_code, presence: true, unless: :beneficiary_reference_passed?
12
+
13
+ def set_attributes(attrs = {})
14
+ set_beneficiary_attributes(attrs)
15
+ self.account_number = attrs.fetch("beneficiary", {}).fetch("routing_info", {})["account_number"]
16
+ self.routing_code = attrs.fetch("beneficiary", {}).fetch("routing_info", {})["routing_code"]
17
+ super(attrs.except("beneficiary"))
18
+ end
19
+
20
+ def as_json_routing_type
21
+ "ACH"
22
+ end
23
+
24
+ def as_json_routing_info
25
+ {
26
+ account_number: account_number,
27
+ routing_code: routing_code
28
+ }
29
+ end
30
+
31
+ module ClientSupport
32
+ def ach_transfers(options = {})
33
+ Transfer::ACH.all(options)
34
+ end
35
+
36
+ def ach_transfer(id)
37
+ Transfer::ACH.find(id)
38
+ end
39
+
40
+ def build_ach_transfer(attributes = {})
41
+ Transfer::ACH.new(attributes)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,37 @@
1
+ module FidorApi
2
+ module Transfer
3
+ class BankInternal < Base
4
+ include Generic
5
+ attribute :account_number, :string
6
+
7
+ validates :account_number, presence: true, unless: :beneficiary_reference_passed?
8
+
9
+ def set_attributes(attrs = {})
10
+ self.account_number = attrs.fetch("beneficiary", {}).fetch("routing_info", {})["account_number"]
11
+ super(attrs)
12
+ end
13
+
14
+ def as_json_routing_type
15
+ 'BANK_INTERNAL'
16
+ end
17
+
18
+ def as_json_routing_info
19
+ {
20
+ account_number: account_number
21
+ }
22
+ end
23
+
24
+ private
25
+
26
+ def remote_create
27
+ response = endpoint.for(self).post(payload: self.as_json)
28
+
29
+ if path = response.headers["X-Fidor-Confirmation-Path"]
30
+ self.confirmable_action = ConfirmableAction.new(id: path.split("/").last)
31
+ end
32
+
33
+ response
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,36 @@
1
+ module FidorApi
2
+ module Transfer
3
+ class Base < Connectivity::Resource
4
+ self.endpoint = Connectivity::Endpoint.new('/transfers', :collection)
5
+
6
+ attr_accessor :confirmable_action
7
+
8
+ def save
9
+ fail InvalidRecordError unless valid?
10
+ super
11
+ end
12
+
13
+ def needs_confirmation?
14
+ self.confirmable_action.present?
15
+ end
16
+
17
+ private
18
+
19
+ def remote_create
20
+ response = super
21
+ if path = response.headers["X-Fidor-Confirmation-Path"]
22
+ self.confirmable_action = ConfirmableAction.new(id: path.split("/").last)
23
+ end
24
+ response
25
+ end
26
+
27
+ def remote_update(*attributes)
28
+ response = super
29
+ if path = response.headers["X-Fidor-Confirmation-Path"]
30
+ self.confirmable_action = ConfirmableAction.new(id: path.split("/").last)
31
+ end
32
+ response
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,56 @@
1
+ module FidorApi
2
+ module Transfer
3
+ class FPS < Base
4
+ extend ModelAttribute
5
+ extend AmountAttributes
6
+
7
+ self.endpoint = Connectivity::Endpoint.new('/fps_transfers', :collection)
8
+
9
+ attribute :id, :integer
10
+ attribute :account_id, :string
11
+ attribute :user_id, :string
12
+ attribute :transaction_id, :string
13
+ attribute :remote_account, :string
14
+ attribute :remote_sort_code, :string
15
+ attribute :remote_name, :string
16
+ attribute :external_uid, :string
17
+ attribute :subject, :string
18
+ attribute :currency, :string
19
+ attribute :subject, :string
20
+ attribute :state, :string
21
+ attribute :created_at, :time
22
+ attribute :updated_at, :time
23
+ amount_attribute :amount
24
+
25
+ def self.required_attributes
26
+ [ :account_id, :external_uid, :remote_account, :remote_sort_code, :remote_name, :amount, :subject ]
27
+ end
28
+
29
+ def self.writeable_attributes
30
+ required_attributes
31
+ end
32
+
33
+ validates *required_attributes, presence: true
34
+
35
+ def as_json
36
+ attributes.slice *self.class.writeable_attributes
37
+ end
38
+
39
+ private
40
+
41
+ module ClientSupport
42
+ def fps_transfers(options = {})
43
+ Transfer::FPS.all(options)
44
+ end
45
+
46
+ def fps_transfer(id)
47
+ Transfer::FPS.find(id)
48
+ end
49
+
50
+ def build_fps_transfer(attributes = {})
51
+ Transfer::FPS.new(attributes)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,134 @@
1
+ module FidorApi
2
+ module Transfer
3
+ module Generic
4
+ ROUTING_INFO_ERROR_PREFIX = "beneficiary.routing_info.".freeze
5
+
6
+ def self.included(base)
7
+ base.extend ModelAttribute
8
+ base.extend AmountAttributes
9
+
10
+ base.validates *required_attributes, presence: true
11
+ base.validates :beneficiary_unique_name, presence: true, if: -> { create_beneficiary && !beneficiary_reference_passed? }
12
+
13
+ base.attribute :id, :string
14
+ base.attribute :account_id, :string
15
+ base.attribute :external_uid, :string
16
+ base.attribute :subject, :string
17
+ base.attribute :currency, :string
18
+ base.attribute :exchange_rate, :string
19
+ base.attribute :subject, :string
20
+ base.attribute :state, :string
21
+ base.amount_attribute :amount
22
+
23
+ base.attribute :beneficiary_unique_name, :string
24
+ base.attribute :contact_name, :string
25
+ base.attribute :contact_address_line_1, :string
26
+ base.attribute :contact_address_line_2, :string
27
+ base.attribute :contact_city, :string
28
+ base.attribute :contact_country, :string
29
+ base.attribute :bank_name, :string
30
+ base.attribute :bank_address_line_1, :string
31
+ base.attribute :bank_address_line_2, :string
32
+ base.attribute :bank_city, :string
33
+ base.attribute :bank_country, :string
34
+ base.attribute :create_beneficiary, :boolean
35
+
36
+ base.attribute :beneficiary_id, :string
37
+
38
+ base.attribute :created_at, :time
39
+ base.attribute :updated_at, :time
40
+ end
41
+
42
+ def self.required_attributes
43
+ [ :account_id, :external_uid, :amount, :subject, :currency ]
44
+ end
45
+
46
+ def as_json
47
+ transfer_json_params.merge(beneficiary_json_params)
48
+ end
49
+
50
+ private
51
+
52
+ def beneficiary_reference_passed?
53
+ beneficiary_id.present?
54
+ end
55
+
56
+ def transfer_json_params
57
+ {
58
+ account_id: account_id,
59
+ external_uid: external_uid,
60
+ amount: (amount * 100).to_i,
61
+ currency: currency,
62
+ subject: subject
63
+ }
64
+ end
65
+
66
+ def beneficiary_json_params
67
+ if beneficiary_reference_passed?
68
+ {
69
+ beneficiary_id: beneficiary_id
70
+ }
71
+ else
72
+ {
73
+ beneficiary: {
74
+ unique_name: beneficiary_unique_name.presence,
75
+ contact: {
76
+ name: contact_name,
77
+ address_line_1: contact_address_line_1,
78
+ address_line_2: contact_address_line_2,
79
+ city: contact_city,
80
+ country: contact_country
81
+ }.compact,
82
+ bank: {
83
+ name: bank_name,
84
+ address_line_1: bank_address_line_1,
85
+ address_line_2: bank_address_line_2,
86
+ city: bank_city,
87
+ country: bank_country
88
+ }.compact,
89
+ routing_type: as_json_routing_type,
90
+ routing_info: as_json_routing_info
91
+ },
92
+ create_beneficiary: create_beneficiary
93
+ }.compact
94
+ end
95
+ end
96
+
97
+ def set_beneficiary_attributes(attrs)
98
+ self.beneficiary_unique_name = attrs.fetch("beneficiary", {})["unique_name"]
99
+
100
+ self.contact_name = attrs.fetch("beneficiary", {}).fetch("contact", {})["name"]
101
+ self.contact_address_line_1 = attrs.fetch("beneficiary", {}).fetch("contact", {})["address_line_1"]
102
+ self.contact_address_line_2 = attrs.fetch("beneficiary", {}).fetch("contact", {})["address_line_2"]
103
+ self.contact_city = attrs.fetch("beneficiary", {}).fetch("contact", {})["city"]
104
+ self.contact_country = attrs.fetch("beneficiary", {}).fetch("contact", {})["country"]
105
+
106
+ self.bank_name = attrs.fetch("beneficiary", {}).fetch("bank", {})["name"]
107
+ self.bank_address_line_1 = attrs.fetch("beneficiary", {}).fetch("bank", {})["address_line_1"]
108
+ self.bank_address_line_2 = attrs.fetch("beneficiary", {}).fetch("bank", {})["address_line_2"]
109
+ self.bank_city = attrs.fetch("beneficiary", {}).fetch("bank", {})["city"]
110
+ self.bank_country = attrs.fetch("beneficiary", {}).fetch("bank", {})["country"]
111
+ end
112
+
113
+ def map_errors(fields)
114
+ fields.each do |hash|
115
+ field = hash["field"].to_sym
116
+ key = hash["key"].try :to_sym
117
+
118
+ if field == :base || respond_to?(field)
119
+ if key
120
+ errors.add(field, key, message: hash["message"])
121
+ else
122
+ errors.add(field, hash["message"])
123
+ end
124
+ elsif hash["field"] == "beneficiary.unique_name"
125
+ errors.add(:beneficiary_unique_name, hash["message"])
126
+ elsif hash["field"].start_with?(ROUTING_INFO_ERROR_PREFIX)
127
+ invalid_field = hash["field"][ROUTING_INFO_ERROR_PREFIX.size..-1]
128
+ errors.add(invalid_field, hash["key"].to_sym, message: hash["message"])
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end