iban_calculator 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: 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: