ibandit 0.11.25 → 0.11.26
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +16 -0
- data/data/structures.yml +11 -0
- data/lib/ibandit/constants.rb +2 -1
- data/lib/ibandit/iban.rb +19 -0
- data/lib/ibandit/local_details_cleaner.rb +14 -1
- data/lib/ibandit/version.rb +1 -1
- data/spec/ibandit/iban_spec.rb +132 -0
- data/spec/ibandit/local_details_cleaner_spec.rb +20 -0
- data/spec/ibandit/pseudo_iban_assembler_spec.rb +36 -0
- data/spec/ibandit/pseudo_iban_splitter_spec.rb +24 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 73a5ffec9e66a0ebf5dccf613bedb5e0da311444
|
4
|
+
data.tar.gz: a6d3de9434b4b87e3df2b9a6a4e6c841331b949c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce3d098232431f5d49b2c533afe6eac7ca260cabfcda9add4ff4cc2b3b0a3bb1bae8d98e3a0bfda1416d5ea0c96533bb9b31b38ab4f5cc06800a49e93d7f19f0
|
7
|
+
data.tar.gz: 6612b734b2bad0b49af6d2460b4536a26bea154ed81011c654c02202c68bc3d34db4b290dc1731831c0b77480202dc7f32c88bb86f507894a3bc3d23f9b4ddae
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -57,6 +57,7 @@ For example:
|
|
57
57
|
| Spain | :white_check_mark: | :white_check_mark: | |
|
58
58
|
| Sweden | :white_check_mark: | | :white_check_mark: |
|
59
59
|
| United Kingdom | :white_check_mark: | :white_check_mark: | |
|
60
|
+
| USA | | | :white_check_mark: |
|
60
61
|
|
61
62
|
## Usage
|
62
63
|
|
@@ -561,6 +562,21 @@ iban.country_code # => "NZ"
|
|
561
562
|
iban.bank_code # => "01"
|
562
563
|
iban.branch_code # => "0004"
|
563
564
|
iban.account_number # => "3333333044"
|
565
|
+
|
566
|
+
# USA
|
567
|
+
iban = Ibandit::IBAN.new(
|
568
|
+
country_code: 'US',
|
569
|
+
bank_code: '965498456', # 9-digit routing number
|
570
|
+
account_number: '0123456789' # 1 to 17 digits
|
571
|
+
)
|
572
|
+
iban.pseudo_iban # => "USZZ965498456_______0123456789"
|
573
|
+
iban.iban # => nil
|
574
|
+
|
575
|
+
iban = Ibandit::IBAN.new('USZZ965498456_______0123456789')
|
576
|
+
iban.country_code # => "US"
|
577
|
+
iban.bank_code # => "965498456"
|
578
|
+
iban.account_number # => "_______0123456789"
|
579
|
+
iban.iban # => nil
|
564
580
|
```
|
565
581
|
|
566
582
|
## Other libraries
|
data/data/structures.yml
CHANGED
@@ -897,3 +897,14 @@ CA:
|
|
897
897
|
:pseudo_iban_bank_code_length: 4
|
898
898
|
:pseudo_iban_branch_code_length: 5
|
899
899
|
:pseudo_iban_account_number_length: 12
|
900
|
+
US:
|
901
|
+
:bank_code_length: 9
|
902
|
+
:branch_code_length: 0
|
903
|
+
:account_number_length: 17
|
904
|
+
:bank_code_format: "\\d{9}"
|
905
|
+
# TODO: update account number format based on inputs from user research
|
906
|
+
:account_number_format: ".{1,17}"
|
907
|
+
:national_id_length: 9
|
908
|
+
:pseudo_iban_bank_code_length: 9
|
909
|
+
:pseudo_iban_branch_code_length: 0
|
910
|
+
:pseudo_iban_account_number_length: 17
|
data/lib/ibandit/constants.rb
CHANGED
@@ -4,7 +4,7 @@ module Ibandit
|
|
4
4
|
HR HU IE IS IT LT LU LV MC MT NL NO PL
|
5
5
|
PT RO SE SI SK SM].freeze
|
6
6
|
|
7
|
-
PSEUDO_IBAN_COUNTRY_CODES = %w[AU SE NZ CA].freeze
|
7
|
+
PSEUDO_IBAN_COUNTRY_CODES = %w[AU SE NZ CA US].freeze
|
8
8
|
DECONSTRUCTABLE_IBAN_COUNTRY_CODES =
|
9
9
|
CONSTRUCTABLE_IBAN_COUNTRY_CODES - PSEUDO_IBAN_COUNTRY_CODES
|
10
10
|
|
@@ -15,6 +15,7 @@ module Ibandit
|
|
15
15
|
"AU" => "_", # Using _ because AU account numbers are alphanumeric
|
16
16
|
"NZ" => "_",
|
17
17
|
"CA" => "_",
|
18
|
+
"US" => "_",
|
18
19
|
}.freeze
|
19
20
|
|
20
21
|
SUPPORTED_COUNTRY_CODES = (
|
data/lib/ibandit/iban.rb
CHANGED
@@ -284,6 +284,7 @@ module Ibandit
|
|
284
284
|
when "AU" then valid_australian_details?
|
285
285
|
when "NZ" then valid_nz_details?
|
286
286
|
when "CA" then valid_ca_details?
|
287
|
+
when "US" then bank_code_passes_checksum_test?
|
287
288
|
else true
|
288
289
|
end
|
289
290
|
end
|
@@ -383,6 +384,24 @@ module Ibandit
|
|
383
384
|
valid_modulus_check_branch_code?
|
384
385
|
end
|
385
386
|
|
387
|
+
# rubocop:disable Metrics/AbcSize
|
388
|
+
def bank_code_passes_checksum_test?
|
389
|
+
return false if swift_bank_code.length != 9
|
390
|
+
|
391
|
+
code_digits = swift_bank_code.chars.map(&:to_i)
|
392
|
+
mod =
|
393
|
+
(
|
394
|
+
3 * (code_digits[0] + code_digits[3] + code_digits[6]) +
|
395
|
+
7 * (code_digits[1] + code_digits[4] + code_digits[7]) +
|
396
|
+
1 * (code_digits[2] + code_digits[5] + code_digits[8])
|
397
|
+
) % 10
|
398
|
+
|
399
|
+
@errors[:bank_code] = Ibandit.translate(:is_invalid) unless mod.zero?
|
400
|
+
|
401
|
+
mod.zero?
|
402
|
+
end
|
403
|
+
# rubocop:enable Metrics/AbcSize
|
404
|
+
|
386
405
|
###################
|
387
406
|
# Private methods #
|
388
407
|
###################
|
@@ -32,7 +32,8 @@ module Ibandit
|
|
32
32
|
|
33
33
|
def self.required_fields(country_code)
|
34
34
|
case country_code
|
35
|
-
when "AT", "CY", "DE", "FI", "LT", "LU",
|
35
|
+
when "AT", "CY", "DE", "FI", "LT", "LU",
|
36
|
+
"LV", "NL", "RO", "SI", "SK", "US"
|
36
37
|
%i[bank_code account_number]
|
37
38
|
when "BE", "CZ", "DK", "EE", "ES", "HR",
|
38
39
|
"HU", "IS", "NO", "PL", "SE", "NZ"
|
@@ -99,6 +100,18 @@ module Ibandit
|
|
99
100
|
}
|
100
101
|
end
|
101
102
|
|
103
|
+
def self.clean_us_details(local_details)
|
104
|
+
return {} unless local_details[:bank_code].length == 9
|
105
|
+
|
106
|
+
account_number = local_details[:account_number].delete(" ")
|
107
|
+
return {} unless (1..17).cover?(account_number.length)
|
108
|
+
|
109
|
+
{
|
110
|
+
bank_code: local_details[:bank_code],
|
111
|
+
account_number: account_number.rjust(17, "_"),
|
112
|
+
}
|
113
|
+
end
|
114
|
+
|
102
115
|
def self.clean_bg_details(local_details)
|
103
116
|
# Bulgarian national bank details were replaced with IBANs in 2006.
|
104
117
|
local_details
|
data/lib/ibandit/version.rb
CHANGED
data/spec/ibandit/iban_spec.rb
CHANGED
@@ -601,6 +601,138 @@ describe Ibandit::IBAN do
|
|
601
601
|
to eq(account_number: "is the wrong length (should be 10 characters)")
|
602
602
|
end
|
603
603
|
end
|
604
|
+
|
605
|
+
context "when the IBAN was created with local details for US" do
|
606
|
+
let(:arg) do
|
607
|
+
{
|
608
|
+
country_code: "US",
|
609
|
+
bank_code: bank_code,
|
610
|
+
account_number: account_number,
|
611
|
+
}
|
612
|
+
end
|
613
|
+
|
614
|
+
context "and a 9 digit bank code" do
|
615
|
+
let(:bank_code) { "965498456" }
|
616
|
+
let(:account_number) { "01234567890123456" }
|
617
|
+
|
618
|
+
its(:country_code) { is_expected.to eq("US") }
|
619
|
+
its(:bank_code) { is_expected.to eq(bank_code) }
|
620
|
+
its(:account_number) { is_expected.to eq(account_number) }
|
621
|
+
its(:swift_bank_code) { is_expected.to eq(bank_code) }
|
622
|
+
its(:swift_branch_code) { is_expected.to eq(nil) }
|
623
|
+
its(:swift_account_number) { is_expected.to eq(account_number) }
|
624
|
+
its(:swift_national_id) { is_expected.to eq(bank_code) }
|
625
|
+
its(:pseudo_iban) do
|
626
|
+
is_expected.to eq("USZZ96549845601234567890123456")
|
627
|
+
end
|
628
|
+
|
629
|
+
its(:iban) { is_expected.to be_nil }
|
630
|
+
its(:valid?) { is_expected.to eq(true) }
|
631
|
+
its(:to_s) { is_expected.to eq("") }
|
632
|
+
end
|
633
|
+
|
634
|
+
context "and a 7 digit bank code" do
|
635
|
+
let(:bank_code) { "0123456" }
|
636
|
+
let(:account_number) { "01234567890123456" }
|
637
|
+
|
638
|
+
its(:country_code) { is_expected.to eq("US") }
|
639
|
+
its(:bank_code) { is_expected.to eq(bank_code) }
|
640
|
+
its(:account_number) { is_expected.to eq(account_number) }
|
641
|
+
its(:swift_bank_code) { is_expected.to eq(bank_code) }
|
642
|
+
its(:swift_branch_code) { is_expected.to eq(nil) }
|
643
|
+
its(:swift_account_number) { is_expected.to eq(account_number) }
|
644
|
+
its(:swift_national_id) { is_expected.to eq(bank_code) }
|
645
|
+
its(:pseudo_iban) do
|
646
|
+
is_expected.to eq("USZZ__012345601234567890123456")
|
647
|
+
end
|
648
|
+
|
649
|
+
its(:iban) { is_expected.to be_nil }
|
650
|
+
its(:valid?) { is_expected.to eq(false) }
|
651
|
+
its(:to_s) { is_expected.to eq("") }
|
652
|
+
end
|
653
|
+
|
654
|
+
context "and bank code that doesn't pass checksum test" do
|
655
|
+
let(:bank_code) { "900000000" }
|
656
|
+
let(:account_number) { "01234567890123456" }
|
657
|
+
|
658
|
+
its(:iban) { is_expected.to be_nil }
|
659
|
+
|
660
|
+
it "returns an error on bank_code attribute" do
|
661
|
+
expect(subject.valid?).to eq(false)
|
662
|
+
expect(subject.errors).to eq(bank_code: "is invalid")
|
663
|
+
end
|
664
|
+
end
|
665
|
+
|
666
|
+
context "and a 7 digit account number" do
|
667
|
+
let(:account_number) { "0123456" }
|
668
|
+
let(:bank_code) { "965498456" }
|
669
|
+
|
670
|
+
its(:country_code) { is_expected.to eq("US") }
|
671
|
+
its(:bank_code) { is_expected.to eq(bank_code) }
|
672
|
+
its(:account_number) { is_expected.to eq("__________0123456") }
|
673
|
+
its(:swift_bank_code) { is_expected.to eq(bank_code) }
|
674
|
+
its(:swift_branch_code) { is_expected.to eq(nil) }
|
675
|
+
its(:swift_account_number) { is_expected.to eq("__________0123456") }
|
676
|
+
its(:swift_national_id) { is_expected.to eq(bank_code) }
|
677
|
+
its(:pseudo_iban) do
|
678
|
+
is_expected.to eq("USZZ965498456__________0123456")
|
679
|
+
end
|
680
|
+
|
681
|
+
its(:iban) { is_expected.to be_nil }
|
682
|
+
its(:valid?) { is_expected.to eq(true) }
|
683
|
+
its(:to_s) { is_expected.to eq("") }
|
684
|
+
end
|
685
|
+
|
686
|
+
context "and a 17 digit account number" do
|
687
|
+
let(:account_number) { "01234567890123456" }
|
688
|
+
let(:bank_code) { "965498456" }
|
689
|
+
|
690
|
+
its(:country_code) { is_expected.to eq("US") }
|
691
|
+
its(:bank_code) { is_expected.to eq(bank_code) }
|
692
|
+
its(:account_number) { is_expected.to eq("01234567890123456") }
|
693
|
+
its(:swift_bank_code) { is_expected.to eq(bank_code) }
|
694
|
+
its(:swift_branch_code) { is_expected.to eq(nil) }
|
695
|
+
its(:swift_account_number) { is_expected.to eq(account_number) }
|
696
|
+
its(:swift_national_id) { is_expected.to eq(bank_code) }
|
697
|
+
its(:pseudo_iban) do
|
698
|
+
is_expected.to eq("USZZ96549845601234567890123456")
|
699
|
+
end
|
700
|
+
|
701
|
+
its(:iban) { is_expected.to be_nil }
|
702
|
+
its(:valid?) { is_expected.to be true }
|
703
|
+
its(:to_s) { is_expected.to eq("") }
|
704
|
+
end
|
705
|
+
end
|
706
|
+
|
707
|
+
context "when the IBAN was created from a US pseudo-IBAN" do
|
708
|
+
let(:arg) { "USZZ96549845601234567890123456" }
|
709
|
+
|
710
|
+
its(:country_code) { is_expected.to eq("US") }
|
711
|
+
its(:bank_code) { is_expected.to eq("965498456") }
|
712
|
+
its(:branch_code) { is_expected.to be_nil }
|
713
|
+
its(:account_number) { is_expected.to eq("01234567890123456") }
|
714
|
+
its(:swift_bank_code) { is_expected.to eq("965498456") }
|
715
|
+
its(:swift_branch_code) { is_expected.to eq(nil) }
|
716
|
+
its(:swift_account_number) { is_expected.to eq("01234567890123456") }
|
717
|
+
its(:swift_national_id) { is_expected.to eq("965498456") }
|
718
|
+
its(:pseudo_iban) do
|
719
|
+
is_expected.to eq("USZZ96549845601234567890123456")
|
720
|
+
end
|
721
|
+
|
722
|
+
its(:iban) { is_expected.to be_nil }
|
723
|
+
its(:valid?) { is_expected.to be true }
|
724
|
+
its(:to_s) { is_expected.to eq("") }
|
725
|
+
end
|
726
|
+
|
727
|
+
context "when the input is an invalid US pseudo-IBAN" do
|
728
|
+
let(:arg) { "USZZ__012345601234567890123456" }
|
729
|
+
|
730
|
+
it "is invalid and has the correct errors" do
|
731
|
+
expect(subject.valid?).to eq(false)
|
732
|
+
expect(subject.errors).
|
733
|
+
to eq(bank_code: "is the wrong length (should be 9 characters)")
|
734
|
+
end
|
735
|
+
end
|
604
736
|
end
|
605
737
|
|
606
738
|
describe "#to_s" do
|
@@ -1158,4 +1158,24 @@ describe Ibandit::LocalDetailsCleaner do
|
|
1158
1158
|
it { is_expected.to eq(local_details_with_swift) }
|
1159
1159
|
end
|
1160
1160
|
end
|
1161
|
+
|
1162
|
+
context "US" do
|
1163
|
+
context "when the account number has space characters" do
|
1164
|
+
let(:country_code) { "US" }
|
1165
|
+
let(:bank_code) { "012345678" }
|
1166
|
+
let(:account_number) { "0123-45678 1234567" }
|
1167
|
+
|
1168
|
+
its([:bank_code]) { is_expected.to eq(bank_code) }
|
1169
|
+
its([:account_number]) { is_expected.to eq("0123-456781234567") }
|
1170
|
+
end
|
1171
|
+
|
1172
|
+
context "when the account number is shorter than the maximum length" do
|
1173
|
+
let(:country_code) { "US" }
|
1174
|
+
let(:bank_code) { "012345678" }
|
1175
|
+
let(:account_number) { "0123456789" }
|
1176
|
+
|
1177
|
+
its([:bank_code]) { is_expected.to eq(bank_code) }
|
1178
|
+
its([:account_number]) { is_expected.to eq("_______0123456789") }
|
1179
|
+
end
|
1180
|
+
end
|
1161
1181
|
end
|
@@ -189,6 +189,42 @@ describe Ibandit::PseudoIBANAssembler do
|
|
189
189
|
end
|
190
190
|
end
|
191
191
|
|
192
|
+
context "for US" do
|
193
|
+
context "with valid parameters" do
|
194
|
+
let(:local_details) do
|
195
|
+
{
|
196
|
+
country_code: "US",
|
197
|
+
bank_code: "012345678",
|
198
|
+
account_number: "01234567890123456",
|
199
|
+
}
|
200
|
+
end
|
201
|
+
|
202
|
+
it { is_expected.to eq("USZZ01234567801234567890123456") }
|
203
|
+
end
|
204
|
+
|
205
|
+
context "without a bank_code" do
|
206
|
+
let(:local_details) do
|
207
|
+
{
|
208
|
+
country_code: "US",
|
209
|
+
account_number: "01234567890123456",
|
210
|
+
}
|
211
|
+
end
|
212
|
+
|
213
|
+
it { is_expected.to be_nil }
|
214
|
+
end
|
215
|
+
|
216
|
+
context "without an account number" do
|
217
|
+
let(:local_details) do
|
218
|
+
{
|
219
|
+
country_code: "US",
|
220
|
+
bank_code: "012345678",
|
221
|
+
}
|
222
|
+
end
|
223
|
+
|
224
|
+
it { is_expected.to be_nil }
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
192
228
|
context "for a country that does not have pseudo-IBANs" do
|
193
229
|
let(:local_details) do
|
194
230
|
{
|
@@ -95,5 +95,29 @@ describe Ibandit::PseudoIBANSplitter do
|
|
95
95
|
its([:branch_code]) { is_expected.to eq("00063") }
|
96
96
|
its([:account_number]) { is_expected.to eq("012345678900") }
|
97
97
|
end
|
98
|
+
|
99
|
+
context "for a US pseudo-IBAN without padding" do
|
100
|
+
let(:pseudo_iban) { "USZZ0123456780123456" }
|
101
|
+
|
102
|
+
its([:country_code]) { is_expected.to eq("US") }
|
103
|
+
its([:bank_code]) { is_expected.to eq("012345678") }
|
104
|
+
its([:account_number]) { is_expected.to eq("0123456") }
|
105
|
+
end
|
106
|
+
|
107
|
+
context "for a US pseudo-IBAN with padding" do
|
108
|
+
let(:pseudo_iban) { "USZZ012345678__________0123456" }
|
109
|
+
|
110
|
+
its([:country_code]) { is_expected.to eq("US") }
|
111
|
+
its([:bank_code]) { is_expected.to eq("012345678") }
|
112
|
+
its([:account_number]) { is_expected.to eq("0123456") }
|
113
|
+
end
|
114
|
+
|
115
|
+
context "for a US pseudo-IBAN with a 17-digit account number" do
|
116
|
+
let(:pseudo_iban) { "USZZ01234567801234567890123456" }
|
117
|
+
|
118
|
+
its([:country_code]) { is_expected.to eq("US") }
|
119
|
+
its([:bank_code]) { is_expected.to eq("012345678") }
|
120
|
+
its([:account_number]) { is_expected.to eq("01234567890123456") }
|
121
|
+
end
|
98
122
|
end
|
99
123
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ibandit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.11.
|
4
|
+
version: 0.11.26
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GoCardless
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-01-
|
11
|
+
date: 2019-01-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -210,7 +210,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
210
210
|
version: '0'
|
211
211
|
requirements: []
|
212
212
|
rubyforge_project:
|
213
|
-
rubygems_version: 2.
|
213
|
+
rubygems_version: 2.5.2.3
|
214
214
|
signing_key:
|
215
215
|
specification_version: 4
|
216
216
|
summary: Convert national banking details into IBANs, and vice-versa.
|