credit_card_validations 1.4.7 → 1.5.0

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