iban_calculator 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: 19c90f0379c87c7251c554191b6ee1ca82f7e7c5
4
- data.tar.gz: 1906317a98ebfa25ec45d4bdff1a0c3d01448ab0
3
+ metadata.gz: 3967a9c57971d2941311ac3669ab2b440f1e4aed
4
+ data.tar.gz: e639752002e485025b6255f9592a62b9900ee763
5
5
  SHA512:
6
- metadata.gz: 2210281de1e0c117cf9881d0f0adea74b8f37271a48032dc5a735a9068fdc3e49e69a990ec8bf650f893eb25c865373582a4c5d5746050f4d99f261ee4b0372a
7
- data.tar.gz: 4d69c1cef82b442417c2a2096a408eb394f5d1ad8673cdef9c047a245625b8a2e2271e8a2d36200ea583460a15809d0cc8e6db7ef753c4f09b7692f9b2028035
6
+ metadata.gz: 57c403612b7adb97f2240c89411186d186c35c30f7c027580b06be44fd42b19ee394a2dbbb8157556f5e31986a6be9f8018c8a14b90941698316290fe4df931f
7
+ data.tar.gz: 6ab47c60821c888040d2989a2c22817cf23a22dd4a6731a9cfbe9440961b95f8baec156824b374e5607751ab3f438ae20f49b394bb0b4d6e73fef3aa9fe392c7
@@ -0,0 +1,9 @@
1
+ 0.0.2
2
+ -----
3
+
4
+ * Add support for validating IBANs and fetching related data such as legacy data
5
+
6
+ 0.0.1
7
+ -----
8
+
9
+ * Initial release with support for calculating IBANs based on legacy data
data/README.md CHANGED
@@ -34,6 +34,10 @@ Whenever you need to convert European legacy account data to new SEPA IBAN forma
34
34
 
35
35
  Example data can be found at: http://www.iban-bic.com/sample_accounts.html
36
36
 
37
+ You can also validate a given IBAN and fetch additional data about it:
38
+
39
+ IbanCalculator.validate_iban 'AL90208110080000001039531801'
40
+
37
41
 
38
42
  ## Contributing
39
43
 
@@ -2,21 +2,34 @@ require 'iban_calculator/version'
2
2
  require 'active_support/configurable'
3
3
  require 'active_support/core_ext/hash'
4
4
  require 'logger'
5
+
6
+ require 'iban_calculator/bank'
7
+ require 'iban_calculator/bic_candidate'
5
8
  require 'iban_calculator/iban_bic'
9
+ require 'iban_calculator/iban_validator_response'
6
10
  require 'iban_calculator/invalid_data'
7
11
 
8
12
  module IbanCalculator
13
+ # Extensions
9
14
  include ActiveSupport::Configurable
10
15
 
16
+ # Configuration
11
17
  config_accessor(:url) { 'https://ssl.ibanrechner.de/soap/?wsdl' }
12
18
  config_accessor(:user) { '' }
13
19
  config_accessor(:password) { '' }
14
20
  config_accessor(:logger) { Logger.new(STDOUT) }
15
21
 
22
+ # Errors
16
23
  ServiceError = Class.new(StandardError)
17
24
 
18
25
  def self.calculate_iban(attributes = {})
19
26
  client = IbanBic.new(config.user, config.password, config.url, config.logger)
20
27
  client.calculate_iban(attributes)
21
28
  end
29
+
30
+ def self.validate_iban(iban)
31
+ client = Savon.client(wsdl: config.url, logger: config.logger)
32
+ response = client.call(:validate_iban, message: { iban: iban, user: config.user, password: config.password })
33
+ IbanValidatorResponse.new(response.body[:validate_iban_response][:return])
34
+ end
22
35
  end
@@ -0,0 +1,27 @@
1
+ module IbanCalculator
2
+ class Bank
3
+ attr_accessor :code, :name, :country, :address, :url, :branch, :branch_code
4
+
5
+ def initialize(attributes = {})
6
+ self.code = attributes[:code]
7
+ self.name = attributes[:name]
8
+ self.country = attributes[:country]
9
+ self.address = attributes[:address]
10
+ self.url = attributes[:url]
11
+ self.branch = attributes[:branch]
12
+ self.branch_code = attributes[:branch_code]
13
+ end
14
+
15
+ def as_json(opts = {})
16
+ {
17
+ code: code,
18
+ name: name,
19
+ country: country,
20
+ address: address,
21
+ url: url,
22
+ branch: branch,
23
+ branch_code: branch_code,
24
+ }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,37 @@
1
+ module IbanCalculator
2
+ class BicCandidate
3
+ attr_accessor :bic, :city, :sample_url, :www_count, :zip
4
+
5
+ def self.build_list(raw_response)
6
+ Array.wrap(raw_response[:item]).map { |candidate| new(candidate) }
7
+ end
8
+
9
+ def initialize(raw_attributes = {})
10
+ self.bic = raw_attributes[:bic]
11
+ self.zip = string_or_default(raw_attributes[:zip])
12
+ self.city = string_or_default(raw_attributes[:city])
13
+ self.sample_url = string_or_default(raw_attributes[:sampleurl])
14
+ self.www_count = raw_attributes[:wwwcount].to_i
15
+ end
16
+
17
+ def source
18
+ www_count > 0 ? :www : :directory
19
+ end
20
+
21
+ def as_json(opts = {})
22
+ {
23
+ bic: bic,
24
+ zip: zip,
25
+ city: city,
26
+ sample_url: sample_url,
27
+ www_count: www_count,
28
+ }
29
+ end
30
+
31
+ private
32
+
33
+ def string_or_default(input, default = '')
34
+ input.kind_of?(String) ? input : default
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,75 @@
1
+ module IbanCalculator
2
+ class IbanValidatorResponse
3
+ CHECKS = {
4
+ length: :length_check,
5
+ account_number: :account_check,
6
+ bank_code: :bank_code_check,
7
+ iban_checksum: :iban_checksum_check,
8
+ }
9
+
10
+ attr_accessor :raw_response
11
+
12
+ def initialize(raw_response)
13
+ self.raw_response = raw_response
14
+ end
15
+
16
+ def valid?
17
+ return_code < 128
18
+ end
19
+
20
+ def return_code
21
+ @return_code ||= raw_response[:return_code].to_i
22
+ end
23
+
24
+ def bic_candidates
25
+ @bic_candidates ||= BicCandidate.build_list(raw_response[:bic_candidates])
26
+ end
27
+
28
+ def bank
29
+ @bank ||= begin Bank.new({
30
+ code: string_or_default(raw_response[:bank_code]),
31
+ name: string_or_default(raw_response[:bank]),
32
+ country: string_or_default(raw_response[:country]),
33
+ address: string_or_default(raw_response[:bank_address]).strip,
34
+ url: string_or_default(raw_response[:bank_url]),
35
+ branch: string_or_default(raw_response[:branch]),
36
+ branch_code: string_or_default(raw_response[:branch_code]),
37
+ })
38
+ end
39
+ end
40
+
41
+ def account_number
42
+ @account_number ||= raw_response[:account_number]
43
+ end
44
+
45
+ def checks
46
+ CHECKS.each_with_object({}) do |(app_key, api_key), result|
47
+ result[app_key] = string_or_default(raw_response[api_key], 'not_checked')
48
+ end
49
+ end
50
+
51
+ def updated_at
52
+ @data_created_at ||= Date.parse(raw_response[:data_age])
53
+ end
54
+
55
+ def errors
56
+ @errors ||= InvalidData.new('', return_code).errors
57
+ end
58
+
59
+ def as_json(opts = {})
60
+ {
61
+ account_number: account_number,
62
+ bank: bank.as_json(opts),
63
+ bic_candidates: bic_candidates.map { |c| c.as_json(opts) },
64
+ updated_at: updated_at,
65
+ checks: checks,
66
+ }
67
+ end
68
+
69
+ private
70
+
71
+ def string_or_default(input, default = '')
72
+ input.kind_of?(String) ? input : default
73
+ end
74
+ end
75
+ end
@@ -1,3 +1,3 @@
1
1
  module IbanCalculator
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -0,0 +1,105 @@
1
+ RSpec.describe IbanCalculator::BicCandidate do
2
+
3
+ subject { described_class.new(single_candidate[:item]) }
4
+
5
+ describe '.build_list' do
6
+ it 'returns an array if one item is added' do
7
+ expect(described_class.build_list(single_candidate).size).to eq(1)
8
+ end
9
+
10
+ it 'returns an array of multiple items' do
11
+ expect(described_class.build_list(multiple_candidates).size).to eq(2)
12
+ end
13
+
14
+ it 'returns BicCandiate objects' do
15
+ expect(described_class.build_list(single_candidate).first).to be_kind_of(described_class)
16
+ end
17
+ end
18
+
19
+ describe '.new' do
20
+ it 'assigns its bic' do
21
+ expect(subject.bic).to eq('BOFIIE2D')
22
+ end
23
+
24
+ it 'assigns its city' do
25
+ expect(subject.city).to eq('city')
26
+ end
27
+
28
+ it 'assigns its zip' do
29
+ expect(subject.zip).to eq('zip')
30
+ end
31
+
32
+ it 'assigns its www_count' do
33
+ expect(subject.www_count).to eq(0)
34
+ end
35
+
36
+ it 'assigns its sample_url' do
37
+ expect(subject.sample_url).to eq('sample_url')
38
+ end
39
+ end
40
+
41
+ describe '#source' do
42
+ it 'returns directory if document has no www count' do
43
+ subject.www_count = 0
44
+ expect(subject.source).to eq(:directory)
45
+ end
46
+
47
+ it 'returns www if document has www count' do
48
+ subject.www_count = 1
49
+ expect(subject.source).to eq(:www)
50
+ end
51
+ end
52
+
53
+ describe '#as_json' do
54
+ it 'takes a hash as argument to be compatible with rails' do
55
+ expect{ subject.as_json({}) }.to_not raise_error
56
+ end
57
+
58
+ it 'returns all attributes' do
59
+ expect(subject.as_json).to eq({
60
+ bic: 'BOFIIE2D',
61
+ zip: 'zip',
62
+ city: 'city',
63
+ sample_url: 'sample_url',
64
+ www_count: 0
65
+ })
66
+ end
67
+ end
68
+
69
+ def single_candidate
70
+ {
71
+ :item => {
72
+ :bic => 'BOFIIE2D',
73
+ :zip => 'zip',
74
+ :city => 'city',
75
+ :wwwcount => '0',
76
+ :sampleurl => 'sample_url',
77
+ :'@xsi:type' => 'tns:BICStruct'
78
+ },
79
+ :'@xsi:type' => 'SOAP-ENC:Array',
80
+ :'@soap_enc:array_type' => 'tns:BICStruct[1]'
81
+ }
82
+ end
83
+
84
+ def multiple_candidates
85
+ {
86
+ :item => [{
87
+ :bic => 'BOFIIE2D',
88
+ :zip => 'zip',
89
+ :city => 'city',
90
+ :wwwcount => '0',
91
+ :sampleurl => 'sample_url',
92
+ :'@xsi:type' => 'tns:BICStruct'
93
+ }, {
94
+ :bic => 'BOFIIE2D',
95
+ :zip => 'zip',
96
+ :city => 'city',
97
+ :wwwcount => '0',
98
+ :sampleurl => 'sample_url',
99
+ :'@xsi:type' => 'tns:BICStruct'
100
+ }],
101
+ :'@xsi:type' => 'SOAP-ENC:Array',
102
+ :'@soap_enc:array_type' => 'tns:BICStruct[1]'
103
+ }
104
+ end
105
+ end
@@ -0,0 +1,208 @@
1
+ RSpec.describe IbanCalculator::IbanValidatorResponse do
2
+
3
+ let(:valid) { described_class.new(valid_response) }
4
+ let(:invalid) { described_class.new(invalid_response) }
5
+
6
+ describe '#valid?' do
7
+ it 'returns true if response is valid' do
8
+ expect(valid.valid?).to eq(true)
9
+ end
10
+
11
+ it 'returns false if response is not valid' do
12
+ expect(invalid.valid?).to eq(false)
13
+ end
14
+ end
15
+
16
+ describe '#return_code' do
17
+ it 'returns its code' do
18
+ expect(valid.return_code).to eq(0)
19
+ end
20
+ end
21
+
22
+ describe '#bic_candidates' do
23
+ it 'returns an array' do
24
+ expect(valid.bic_candidates).to be_instance_of(Array)
25
+ end
26
+ end
27
+
28
+ describe '#bank' do
29
+ it 'returns a bank hash' do
30
+ expect(valid.bank).to be_instance_of(IbanCalculator::Bank)
31
+ end
32
+
33
+ it 'returns bank name' do
34
+ expect(valid.bank.name).to eq('Bank of Ireland')
35
+ end
36
+
37
+ it 'returns bank address' do
38
+ expect(valid.bank.address).to eq('Dublin 2')
39
+ end
40
+
41
+ it 'returns bank code' do
42
+ expect(valid.bank.code).to eq('90-00-17')
43
+ end
44
+
45
+ it 'returns bank country' do
46
+ expect(valid.bank.country).to eq('IE')
47
+ end
48
+
49
+ it 'returns bank url' do
50
+ expect(valid.bank.url).to eq('')
51
+ end
52
+
53
+ it 'returns bank branch' do
54
+ expect(valid.bank.branch).to eq('')
55
+ end
56
+
57
+ it 'returns bank branch_code' do
58
+ expect(valid.bank.branch_code).to eq('')
59
+ end
60
+ end
61
+
62
+ describe '#account_number' do
63
+ it 'returns its account number' do
64
+ expect(valid.account_number).to eq('10027952')
65
+ end
66
+ end
67
+
68
+ describe '#checks' do
69
+ context 'valid response' do
70
+ it 'returns a hash of checks and their results' do
71
+ expect(valid.checks).to eq({
72
+ length: 'passed',
73
+ bank_code: 'passed',
74
+ account_number: 'passed',
75
+ iban_checksum: 'passed',
76
+ })
77
+ end
78
+ end
79
+
80
+ context 'invalid response' do
81
+ it 'returns a hash of checks and their results' do
82
+ expect(invalid.checks).to eq({
83
+ length: 'failed',
84
+ bank_code: 'not_checked',
85
+ account_number: 'not_checked',
86
+ iban_checksum: 'not_checked',
87
+ })
88
+ end
89
+ end
90
+ end
91
+
92
+ describe '#updated_at' do
93
+ it 'returns a proper date object' do
94
+ expect(valid.updated_at).to eq(Date.new(2014, 07, 06))
95
+ end
96
+ end
97
+
98
+ describe '#errors' do
99
+ context 'valid response' do
100
+ it 'returns an empty array' do
101
+ expect(valid.errors).to eq({})
102
+ end
103
+ end
104
+
105
+ context 'invalid response' do
106
+ it 'returns an empty array' do
107
+ expect(invalid.errors).to eq({ account_number: [:invalid_length] })
108
+ end
109
+ end
110
+ end
111
+
112
+ describe '#as_json' do
113
+ it 'returns an hash with all attributes' do
114
+ expect(valid.as_json).to eq({
115
+ account_number: '10027952',
116
+ bank: { code: '90-00-17', name: 'Bank of Ireland', country: 'IE', address: 'Dublin 2', url: '', branch: '', branch_code: '' },
117
+ bic_candidates: [{ bic: 'BOFIIE2D', zip: '', city: '', sample_url: '', www_count: 0 }],
118
+ checks: { length: 'passed', account_number: 'passed', bank_code: 'passed', iban_checksum: 'passed' },
119
+ updated_at: Date.new(2014, 7, 6)
120
+ })
121
+ end
122
+ end
123
+
124
+ def valid_response
125
+ {
126
+ :iban=>"IE92BOFI90001710027952",
127
+ :result=>"passed",
128
+ :return_code=>"0",
129
+ :checks=>{
130
+ :item=>["length", "bank_code", "account_number", "iban_checksum"],
131
+ :"@xsi:type"=>"SOAP-ENC:Array",
132
+ :"@soap_enc:array_type"=>"xsd:string[4]"},
133
+ :bic_candidates=>{
134
+ :item=>{
135
+ :bic=>"BOFIIE2D",
136
+ :zip=>{:"@xsi:type"=>"xsd:string"},
137
+ :city=>{:"@xsi:type"=>"xsd:string"},
138
+ :wwwcount=>"0",
139
+ :sampleurl=>{:"@xsi:type"=>"xsd:string"},
140
+ :"@xsi:type"=>"tns:BICStruct"},
141
+ :"@xsi:type"=>"SOAP-ENC:Array",
142
+ :"@soap_enc:array_type"=>"tns:BICStruct[1]"},
143
+ :country=>"IE",
144
+ :bank_code=>"90-00-17",
145
+ :bank=>"Bank of Ireland",
146
+ :bank_address=>"Dublin 2 ",
147
+ :bank_url=>{:"@xsi:type"=>"xsd:string"},
148
+ :branch=>{:"@xsi:type"=>"xsd:string"},
149
+ :branch_code=>{:"@xsi:type"=>"xsd:string"},
150
+ :in_scl_directory=>"no",
151
+ :sct=>{:"@xsi:type"=>"xsd:string"},
152
+ :sdd=>{:"@xsi:type"=>"xsd:string"},
153
+ :b2b=>{:"@xsi:type"=>"xsd:string"},
154
+ :account_number=>"10027952",
155
+ :account_validation_method=>{:"@xsi:type"=>"xsd:string"},
156
+ :account_validation=>{:"@xsi:type"=>"xsd:string"},
157
+ :length_check=>"passed",
158
+ :account_check=>"passed",
159
+ :bank_code_check=>"passed",
160
+ :iban_checksum_check=>"passed",
161
+ :data_age=>"20140706",
162
+ :iba_nformat=>"IEkk AAAA BBBB BBCC CCCC CC",
163
+ :formatcomment=>"The first 4 alphanumeric characters are the start of the SWIFT code. Then a 6 digit long routing code and an 8 digit account code follow, both numeric.",
164
+ :balance=>"1",
165
+ :"@xsi:type"=>"tns:IBANValResStruct"
166
+ }
167
+ end
168
+
169
+ def invalid_response
170
+ {
171
+ :iban => "IE92BOFI900017100",
172
+ :result => "failed",
173
+ :return_code => "512",
174
+ :checks => {
175
+ :item => "length",
176
+ :"@xsi:type" => "SOAP-ENC:Array",
177
+ :"@soap_enc:array_type" => "xsd:string[1]"
178
+ },
179
+ :bic_candidates => {
180
+ :"@xsi:type" => "SOAP-ENC:Array",
181
+ :"@soap_enc:array_type" => "tns:BICStruct[0]"
182
+ },
183
+ :country => "IE",
184
+ :bank_code => {:"@xsi:type" => "xsd:string"},
185
+ :bank => {:"@xsi:type" => "xsd:string"},
186
+ :bank_address => {:"@xsi:type" => "xsd:string"},
187
+ :bank_url => {:"@xsi:type" => "xsd:string"},
188
+ :branch => {:"@xsi:type" => "xsd:string"},
189
+ :branch_code => {:"@xsi:type" => "xsd:string"},
190
+ :in_scl_directory => "no",
191
+ :sct => {:"@xsi:type" => "xsd:string"},
192
+ :sdd => {:"@xsi:type" => "xsd:string"},
193
+ :b2b => {:"@xsi:type" => "xsd:string"},
194
+ :account_number => {:"@xsi:type" => "xsd:string"},
195
+ :account_validation_method => {:"@xsi:type" => "xsd:string"},
196
+ :account_validation => {:"@xsi:type" => "xsd:string"},
197
+ :length_check => "failed",
198
+ :account_check => {:"@xsi:type" => "xsd:string"},
199
+ :bank_code_check => {:"@xsi:type" => "xsd:string"},
200
+ :iban_checksum_check => {:"@xsi:type" => "xsd:string"},
201
+ :data_age => {:"@xsi:type" => "xsd:string"},
202
+ :iba_nformat => "IEkk AAAA BBBB BBCC CCCC CC",
203
+ :formatcomment => "The first 4 alphanumeric characters are the start of the SWIFT code. Then a 6 digit long routing code and an 8 digit account code follow, both numeric.",
204
+ :balance => "0",
205
+ :"@xsi:type" => "tns:IBANValResStruct"
206
+ }
207
+ end
208
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iban_calculator
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
  - Maximilian Schulz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-04 00:00:00.000000000 Z
11
+ date: 2014-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -89,17 +89,23 @@ extra_rdoc_files: []
89
89
  files:
90
90
  - ".gitignore"
91
91
  - ".rspec"
92
+ - CHANGELOG.md
92
93
  - Gemfile
93
94
  - LICENSE.txt
94
95
  - README.md
95
96
  - Rakefile
96
97
  - iban_calculator.gemspec
97
98
  - lib/iban_calculator.rb
99
+ - lib/iban_calculator/bank.rb
100
+ - lib/iban_calculator/bic_candidate.rb
98
101
  - lib/iban_calculator/iban_bic.rb
102
+ - lib/iban_calculator/iban_validator_response.rb
99
103
  - lib/iban_calculator/invalid_data.rb
100
104
  - lib/iban_calculator/version.rb
105
+ - spec/bic_candidate_spec.rb
101
106
  - spec/iban_bic_spec.rb
102
107
  - spec/iban_calculator_spec.rb
108
+ - spec/iban_validator_response_spec.rb
103
109
  - spec/invalid_data_spec.rb
104
110
  - spec/spec_helper.rb
105
111
  homepage: https://github.com/railslove/iban_calculator
@@ -127,8 +133,10 @@ signing_key:
127
133
  specification_version: 4
128
134
  summary: Calculate IBAN and BIC for countries of Single European Payments Area (SEPA).
129
135
  test_files:
136
+ - spec/bic_candidate_spec.rb
130
137
  - spec/iban_bic_spec.rb
131
138
  - spec/iban_calculator_spec.rb
139
+ - spec/iban_validator_response_spec.rb
132
140
  - spec/invalid_data_spec.rb
133
141
  - spec/spec_helper.rb
134
142
  has_rdoc: