credit_card_validations 1.4.7 → 1.5.0

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: f8ea2ebb942c03630126dd73a4476458b633d0c7
4
- data.tar.gz: 66da4b0c371bbf689d98a1a117c0c96a5786e0e5
3
+ metadata.gz: 8cc121a408a642f75dfcfc595f63c58299895dfc
4
+ data.tar.gz: c30600f8e3925bce9cd79c1e30d0cb954696882f
5
5
  SHA512:
6
- metadata.gz: f6c5e3ce05891615ba785faca3a90528075261c309cf86e82e112267d000174d6e488e5b846d67c7fffe1b38daca47ff4307abdc6ec70a85079274a4f8dc3ec3
7
- data.tar.gz: d267bd198b0a6c4b2fbc7986bbf676c794d6f1d24f7ed6452e6aceadc69588ac579c523c462abbdedd78ab6617a8f24d8771ea88f3e1fdf9c1b6a18bb4d72af1
6
+ metadata.gz: 9b2c71d6eeef539a4adc6eb3aa3d971a5f0db812f2bf396de7e1d82be082243c657f43b5dcf4221b2d1e5e856dca2414160c567bedb5b651e8f63e15ff1d1f0e
7
+ data.tar.gz: d9979cffa4dec73c7f01b26c80ce654ede26fc4c4aa1458e932282867913d78d5685dbc74594096e8d7e67beca97849f4c068e99773bb2cb076388792d7f5c62
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Gem adds validator to check whether or not a given number actually falls within the ranges of possible numbers prior to performing such verification, and, as such, CreditCardValidations simply verifies that the credit card number provided is well-formed.
4
4
 
5
+ More info about card BIN numbers http://en.wikipedia.org/wiki/Bank_card_number
6
+
5
7
  [![Build Status](https://travis-ci.org/Fivell/credit_card_validations.png)](https://travis-ci.org/Fivell/credit_card_validations)
6
8
  [![Coverage Status](https://coveralls.io/repos/Fivell/credit_card_validations/badge.png)](https://coveralls.io/r/Fivell/credit_card_validations)
7
9
 
@@ -24,33 +26,55 @@ Or install it yourself as:
24
26
 
25
27
  The following issuing institutes are accepted:
26
28
 
27
- name | key
28
- -----------------------
29
- American Express | :amex
30
- China UnionPay | :unionpay
31
- Dankrot | :dankrot
32
- Diners Club | :diners
33
- Dinner Club US | :diners_us
34
- Discover | :discover
35
- JCB | :jcb
36
- Laser | :laser
37
- Maestro | :maestro
38
- MasterCard | :mastercard
39
- Solo | :solo
40
- Visa | :visa
29
+ name | key |
30
+ -------------------------------------------------------------------
31
+ American Express | :amex | http://en.wikipedia.org/wiki/American_Express
32
+ China UnionPay | :unionpay | http://en.wikipedia.org/wiki/China_UnionPay
33
+ Dankrot | :dankrot | http://en.wikipedia.org/wiki/Dankort
34
+ Diners Club | :diners | http://en.wikipedia.org/wiki/Diners_Club_International
35
+ Dinner Club US | :diners_us | http://en.wikipedia.org/wiki/Diners_Club_International#MasterCard_alliance
36
+ Discover | :discover | http://en.wikipedia.org/wiki/Discover_Card
37
+ JCB | :jcb | http://en.wikipedia.org/wiki/Japan_Credit_Bureau
38
+ Laser | :laser | http://en.wikipedia.org/wiki/Laser_%28debit_card%29
39
+ Maestro | :maestro | http://en.wikipedia.org/wiki/Maestro_%28debit_card%29
40
+ MasterCard | :mastercard | http://en.wikipedia.org/wiki/MasterCard
41
+ Rupay | :rupay | http://en.wikipedia.org/wiki/RuPay
42
+ Solo | :solo | http://en.wikipedia.org/wiki/Solo_(debit_card)
43
+ Switch | :switch | http://en.wikipedia.org/wiki/Switch_(debit_card)
44
+ Visa | :visa | http://en.wikipedia.org/wiki/Visa_Inc.
41
45
 
42
46
 
43
47
 
44
48
  Examples using string monkey patch
45
49
 
50
+ ```ruby
46
51
  require 'credit_card_validations/string'
47
52
  '5274 5763 9425 9961'.credit_card_brand
48
53
  '5274 5763 9425 9961'.valid_credit_card_brand?(:mastercard, :visa)
49
54
  '5274 5763 9425 9961'.valid_credit_card_brand?(:amex)
55
+ ```
56
+
57
+ ActiveModel support
58
+
59
+ only for certain brads
60
+
61
+ ```ruby
62
+ class CreditCardModel
63
+ attr_accessor :number
64
+ include ActiveModel::Validations
65
+ validates :number, credit_card_number: {brands: [:amex, :maestro]}
66
+ end
67
+ ```
68
+
69
+ for all known brands
50
70
 
71
+ ```ruby
72
+ validates :number, presence: true, credit_card_number: true
73
+ ```
51
74
 
52
75
  Examples using CreditCardValidations::Detector class
53
76
 
77
+ ```ruby
54
78
  number = "4111111111111111"
55
79
  detector = CreditCardValidations::Detector.new(number)
56
80
  detector.brand #:visa
@@ -58,38 +82,32 @@ Examples using CreditCardValidations::Detector class
58
82
  detector.valid?(:mastercard,:maestro) #false
59
83
  detector.valid?(:visa, :mastercard) #true
60
84
  detector.issuer_category #"Banking and financial"
85
+ ```
61
86
 
62
87
  Also You can add your own rules to detect other credit card brands/types
63
88
  passing name,length(integer/array of integers) and prefix(string/array of strings)
64
89
  Example
65
90
 
66
- CreditCardValidations::Detector.add_rule(:voyager, 15, '86')
91
+ ```ruby
92
+ CreditCardValidations.add_rule(:voyager, {length: 15, prefixes: '86'})
93
+ CreditCardValidations.add_rule(:en_route, {length: 15, prefixes: ['2014', '2149'], skip_luhn: true}) #skip luhn
94
+
67
95
  voyager_test_card_number = '869926275400212'
68
96
  CreditCardValidations::Detector.new(voyager_test_card_number).brand #:voyager
69
97
  CreditCardValidations::Detector.new(voyager_test_card_number).voyager? #true
70
-
71
-
98
+
99
+ en_route_test_card_number = '2014-0000-0000-001'
100
+ CreditCardValidations::Detector.new(en_route_test_card_number).brand #:en_route
101
+ CreditCardValidations::Detector.new(en_route_test_card_number).en_route? #true
102
+ ```
72
103
 
73
104
  Check luhn
74
105
 
106
+ ```ruby
75
107
  CreditCardValidations::Detector.new(@credit_card_number).valid_luhn?
76
-
77
-
78
- ActiveModel support
79
-
80
- only for certain brads
81
-
82
- class CreditCardModel
83
- attr_accessor :number
84
- include ActiveModel::Validations
85
- validates :number, credit_card_number: {brands: [:amex, :maestro]}
86
- end
87
-
88
- for all known brands
89
-
90
- validates :number, presence: true, credit_card_number: true
91
-
92
-
108
+ #or
109
+ CreditCardValidations::Luhn.valid?(@credit_card_number)
110
+ ```
93
111
 
94
112
 
95
113
  ## Contributing
@@ -4,7 +4,7 @@ module ActiveModel
4
4
 
5
5
  def validate_each(record, attribute, value)
6
6
  brands = options.fetch(:brands, :any)
7
- record.errors.add(attribute) unless credit_card_valid?(value, brands == :any ? [] : Array.wrap(brands) )
7
+ record.errors.add(attribute) unless credit_card_valid?(value, brands == :any ? [] : Array.wrap(brands))
8
8
  end
9
9
 
10
10
  def credit_card_valid?(number, brands = [])
@@ -11,16 +11,17 @@ module CreditCardValidations
11
11
  autoload :CardRules , 'credit_card_validations/card_rules'
12
12
  autoload :Detector , 'credit_card_validations/detector'
13
13
  autoload :Mmi, 'credit_card_validations/mmi'
14
+
15
+ def self.add_rule(name, options)
16
+ CreditCardValidations::Detector.add_rule(name, options.fetch(:length), options.fetch(:prefixes), options.fetch(:skip_luhn, false))
17
+ end
18
+
19
+ CardRules.rules.each do |name, rules|
20
+ rules.each do |rule_value|
21
+ add_rule(name, rule_value)
22
+ end
23
+ end
14
24
  end
15
25
 
16
26
 
17
- CreditCardValidations::CardRules.rules.each do |name, rules|
18
- rules.each do |rule_value|
19
- CreditCardValidations::Detector.add_rule(name,
20
- rule_value[:length],
21
- rule_value[:prefixes],
22
- rule_value[:skip_validation])
23
- end
24
-
25
- end
26
27
 
@@ -10,11 +10,11 @@ module CreditCardValidations
10
10
  mastercard: [
11
11
  {length: [16], prefixes: ['51', '52', '53', '54', '55']}
12
12
  ],
13
- ######## other brands ########
13
+
14
14
  amex: [
15
15
  {length: [15], prefixes: ['34', '37']}
16
16
  ],
17
-
17
+ ######## other brands ########
18
18
  diners: [
19
19
  {length: [14], prefixes: ['300', '301', '302', '303', '304', '305', '36', '38']},
20
20
  ],
@@ -43,12 +43,12 @@ module CreditCardValidations
43
43
  solo: [
44
44
  {length: [16, 18, 19], prefixes: ['6334', '6767']}
45
45
  ],
46
-
46
+
47
47
  switch: [
48
- {length: [16, 18, 19], prefixes: ['633110', '633312', '633304', '633303', '633301', '633300']}
49
-
48
+ {length: [16, 18, 19], prefixes: ['633110', '633312', '633304', '633303', '633301', '633300']}
49
+
50
50
  ],
51
-
51
+
52
52
  maestro: [
53
53
  {length: [12, 13, 14, 15, 16, 17, 18, 19], prefixes: ['5010', '5011', '5012', '5013', '5014', '5015', '5016', '5017', '5018',
54
54
  '502', '503', '504', '505', '506', '507', '508',
@@ -56,20 +56,21 @@ module CreditCardValidations
56
56
  '602', '603', '604', '605', '6060',
57
57
  '621', '627', '629',
58
58
  '677', '675', '674', '673', '672', '671', '670',
59
- '6760', '6761', '6762', '6763', '6764', '6765', '6766', '6768', '6769'
60
- ]}
59
+ '6760', '6761', '6762', '6763', '6764', '6765', '6766', '6768', '6769']}
61
60
  ],
62
-
61
+
63
62
  # Luhn validation are skipped for union pay cards because they have unknown generation algoritm
64
63
  unionpay: [
65
- {length: [16, 17, 18, 19], prefixes: ['622', '624', '625', '626', '628'], skip_validation: true}
64
+ {length: [16, 17, 18, 19], prefixes: ['622', '624', '625', '626', '628'], skip_luhn: true}
66
65
  ],
67
66
 
68
67
  dankrot: [
69
68
  {length: [16], prefixes: ['5019']}
69
+ ],
70
+
71
+ rupay: [
72
+ {length: [16], prefixes: ['6061', '6062', '6063', '6064', '6065', '6066', '6067', '6068', '6069', '607', '608'], skip_luhn: true}
70
73
  ]
71
-
72
-
73
74
 
74
75
  }
75
76
  end
@@ -9,26 +9,26 @@ module CreditCardValidations
9
9
  attr_reader :number
10
10
 
11
11
  def initialize(number)
12
- @number = number.to_s.tr('- ','')
12
+ @number = number.to_s.tr('- ', '')
13
13
  end
14
14
 
15
15
  # credit card number
16
16
  def valid?(*brands)
17
- !!valid_number?(*brands)
17
+ !!valid_number?(*brands)
18
18
  end
19
19
 
20
20
  #brand name
21
21
  def brand(*brands)
22
- valid_number?(*brands)
22
+ valid_number?(*brands)
23
23
  end
24
24
 
25
25
  def valid_number?(*brands)
26
26
  number_length = number.length
27
- brand_rules = brands.blank? ? self.rules : self.rules.slice(*brands.map{ |el| el.downcase })
27
+ brand_rules = brands.blank? ? self.rules : self.rules.slice(*brands.map { |el| el.downcase })
28
28
  unless brand_rules.blank?
29
29
  brand_rules.each do |brand_name, rules|
30
30
  rules.each do |rule|
31
- return brand_name if ( (rule[:skip_validation] || valid_luhn?) and rule[:length].include?(number_length) and number.match(rule[:regexp]))
31
+ return brand_name if ((rule[:skip_luhn] || valid_luhn?) and rule[:length].include?(number_length) and number.match(rule[:regexp]))
32
32
  end
33
33
  end
34
34
  end
@@ -44,21 +44,22 @@ module CreditCardValidations
44
44
 
45
45
  #create regexp by array of prefixes
46
46
  def compile_regexp(prefixes)
47
- Regexp.new("^((#{prefixes.join(")|(")}))")
47
+ Regexp.new("^((#{prefixes.join(")|(")}))")
48
48
  end
49
49
 
50
50
  #create rule for detecting brand
51
- def add_rule(brand, length, prefixes, skip_validation = false)
51
+ def add_rule(brand, length, prefixes, skip_luhn = false)
52
52
  prefixes = Array.wrap(prefixes)
53
53
  length = Array.wrap(length)
54
54
  rules[brand] = [] if rules[brand].blank?
55
- rules[brand] << {length: length, regexp: compile_regexp(prefixes), prefixes: prefixes, skip_validation: skip_validation}
55
+ rules[brand] << {length: length, regexp: compile_regexp(prefixes), prefixes: prefixes, skip_luhn: skip_luhn}
56
56
  #create methods like visa? mastercard? etc
57
57
  class_eval <<-BOOLEAN_RULE, __FILE__, __LINE__
58
58
  def #{brand}?
59
59
  valid?(:#{brand})
60
60
  end
61
61
  BOOLEAN_RULE
62
+ rules[brand]
62
63
  end
63
64
  end
64
65
 
@@ -14,23 +14,25 @@
14
14
  #For example, American Express, Diner's Club, Carte Blanche, and JCB are in the travel and entertainment category; VISA, MasterCard, and Discover are in the banking and financial category (Discover being in the Merchandising and banking/financial category); and Sun Oil and Exxon are in the petroleum category.
15
15
 
16
16
 
17
- module CreditCardValidations::Mmi
17
+ module CreditCardValidations
18
+ module Mmi
18
19
 
19
- ISSUER_CATEGORIES = {
20
- '0' =>'ISO/TC 68 nd other industry assignments',
21
- '1' => 'Airlines',
22
- '2' => 'Airlines and other industry assignments',
23
- '3' => 'Travel and entertainment and banking/financial',
24
- '4' => 'Banking and financial',
25
- '5' => 'Banking and financial',
26
- '6' => 'Merchandising and banking/financial',
27
- '7' => 'Petroleum and other industry assignments',
28
- '8' => 'Healthcare, telecommunications and other industry assignments',
29
- '9' => 'National assignment'
20
+ ISSUER_CATEGORIES = {
21
+ '0' => 'ISO/TC 68 nd other industry assignments',
22
+ '1' => 'Airlines',
23
+ '2' => 'Airlines and other industry assignments',
24
+ '3' => 'Travel and entertainment and banking/financial',
25
+ '4' => 'Banking and financial',
26
+ '5' => 'Banking and financial',
27
+ '6' => 'Merchandising and banking/financial',
28
+ '7' => 'Petroleum and other industry assignments',
29
+ '8' => 'Healthcare, telecommunications and other industry assignments',
30
+ '9' => 'National assignment'
30
31
 
31
- }
32
+ }
32
33
 
33
- def issuer_category
34
- ISSUER_CATEGORIES[@number.to_s[0]]
34
+ def issuer_category
35
+ ISSUER_CATEGORIES[@number.to_s[0]]
36
+ end
35
37
  end
36
38
  end
@@ -1,9 +1,12 @@
1
+ #
2
+ #
3
+ #
1
4
  class String
2
5
  def credit_card_brand
3
- CreditCardValidations::Detector.new(self).brand
4
- end
5
-
6
+ CreditCardValidations::Detector.new(self).brand
7
+ end
8
+
6
9
  def valid_credit_card_brand?(*brands)
7
- CreditCardValidations::Detector.new(self).valid?(*brands)
8
- end
10
+ CreditCardValidations::Detector.new(self).valid?(*brands)
11
+ end
9
12
  end
@@ -1,3 +1,3 @@
1
1
  module CreditCardValidations
2
- VERSION = "1.4.7"
2
+ VERSION = "1.5.0"
3
3
  end
@@ -1,6 +1,5 @@
1
1
  require_relative 'test_helper'
2
2
 
3
-
4
3
  class CreditCardValidationsTest < MiniTest::Test
5
4
 
6
5
  class CreditCardModel
@@ -18,20 +17,21 @@ class CreditCardValidationsTest < MiniTest::Test
18
17
  def initialize name
19
18
  super name
20
19
  @test_numbers = {
21
- visa: ['4012 8888 8888 1881','4111111111111111'],
22
- mastercard: ['5274 5763 9425 9961', '5555-5555-5555-4444'],
23
- diners: ['3020 4169 3226 43', '30569309025904'],
24
- amex: ['3782 8224 6310 005', '371449635398431'],
25
- discover: ['6011 1111 1111 1117','6011000990139424'],
26
- maestro: ['6759 6498 2643 8453'],
27
- jcb: ['3575 7591 5225 4876', '3566002020360505' ],
28
- solo: ['6767 6222 2222 2222 222'],
29
- unionpay: ['6264-1852-1292-2132-067', '6288997715452584', '6269 9920 5813 4322'],
30
- dankrot: ['5019717010103742'],
31
- switch: ['6331101999990016']
20
+ visa: ['4012 8888 8888 1881', '4111111111111111'],
21
+ mastercard: ['5274 5763 9425 9961', '5555-5555-5555-4444'],
22
+ diners: ['3020 4169 3226 43', '30569309025904'],
23
+ amex: ['3782 8224 6310 005', '371449635398431'],
24
+ discover: ['6011 1111 1111 1117', '6011000990139424'],
25
+ maestro: ['6759 6498 2643 8453'],
26
+ jcb: ['3575 7591 5225 4876', '3566002020360505'],
27
+ solo: ['6767 6222 2222 2222 222'],
28
+ unionpay: ['6264-1852-1292-2132-067', '6288997715452584', '6269 9920 5813 4322'],
29
+ dankrot: ['5019717010103742'],
30
+ switch: ['6331101999990016'],
31
+ rupay: ['6076-6000-0619-9992']
32
32
  }
33
33
  end
34
-
34
+
35
35
  def test_card_brand_detection
36
36
  @test_numbers.each do |key, value|
37
37
  value.each do |card_number|
@@ -40,21 +40,21 @@ class CreditCardValidationsTest < MiniTest::Test
40
40
  end
41
41
  end
42
42
  end
43
-
43
+
44
44
  def test_card_brand_is_nil_if_credit_card_invalid
45
45
  assert_nil detector('1111111111111111').brand
46
46
  end
47
-
47
+
48
48
  def test_card_brand_detection_with_restriction
49
49
  @test_numbers.slice(:visa, :mastercard).each do |key, value|
50
50
  assert_equal key, detector(value.first).brand(:visa, :mastercard)
51
51
  end
52
-
52
+
53
53
  @test_numbers.except(:visa, :mastercard).each do |key, value|
54
54
  assert_nil detector(value.first).brand(:visa, :mastercard)
55
55
  end
56
56
  end
57
-
57
+
58
58
  def test_card_valid_method
59
59
  @test_numbers.each do |key, value|
60
60
  value.each do |card_number|
@@ -90,14 +90,14 @@ class CreditCardValidationsTest < MiniTest::Test
90
90
  end
91
91
 
92
92
  def test_active_model_validator
93
- cc = CreditCardModel.new
94
- cc.number = @test_numbers[:maestro].first
95
- assert cc.valid?
93
+ cc = CreditCardModel.new
94
+ cc.number = @test_numbers[:maestro].first
95
+ assert cc.valid?
96
96
 
97
- cc = CreditCardModel.new
98
- cc.number = @test_numbers[:mastercard].first
99
- assert !cc.valid?
100
- assert cc.errors[:number].include?(cc.errors.generate_message(:number, :invalid))
97
+ cc = CreditCardModel.new
98
+ cc.number = @test_numbers[:mastercard].first
99
+ assert !cc.valid?
100
+ assert cc.errors[:number].include?(cc.errors.generate_message(:number, :invalid))
101
101
 
102
102
 
103
103
  cc = CreditCardModelAny.new
@@ -110,13 +110,13 @@ class CreditCardValidationsTest < MiniTest::Test
110
110
 
111
111
  def test_string_extension
112
112
  require 'credit_card_validations/string'
113
- assert_equal @test_numbers[:mastercard].first.credit_card_brand, :mastercard
114
- assert @test_numbers[:mastercard].first.valid_credit_card_brand?(:mastercard)
113
+ assert_equal @test_numbers[:mastercard].first.credit_card_brand, :mastercard
114
+ assert @test_numbers[:mastercard].first.valid_credit_card_brand?(:mastercard)
115
115
  assert !@test_numbers[:mastercard].first.valid_credit_card_brand?(:visa, :amex)
116
116
  end
117
117
 
118
118
 
119
- def test_skip_validation
119
+ def test_skip_luhn
120
120
  d = detector(@test_numbers[:unionpay].first)
121
121
 
122
122
  d.expects(:valid_luhn?).never
@@ -133,8 +133,8 @@ class CreditCardValidationsTest < MiniTest::Test
133
133
  end
134
134
 
135
135
  def test_mmi
136
- d = detector(@test_numbers[:visa])
137
- assert_equal d.issuer_category, CreditCardValidations::Mmi::ISSUER_CATEGORIES[@test_numbers[:visa][0]]
136
+ d = detector(@test_numbers[:visa])
137
+ assert_equal d.issuer_category, CreditCardValidations::Mmi::ISSUER_CATEGORIES[@test_numbers[:visa][0]]
138
138
  end
139
139
 
140
140
  protected
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: credit_card_validations
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.7
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Igor