credit_card_validation 0.0.1
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.
- data/.gitignore +4 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/Guardfile +5 -0
- data/README.mdown +42 -0
- data/Rakefile +10 -0
- data/credit_card_validation.gemspec +29 -0
- data/lib/active_model/validations/credit_card_validator.rb +27 -0
- data/lib/credit_card_validation.rb +82 -0
- data/lib/credit_card_validation/version.rb +3 -0
- data/spec/active_record_validator_spec.rb +76 -0
- data/spec/credit_card_validation_spec.rb +72 -0
- data/spec/spec_helper.rb +20 -0
- metadata +180 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use ruby-1.9.2-p290@credit_card_validation --create
|
data/Gemfile
ADDED
data/Guardfile
ADDED
data/README.mdown
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# Credit Card Validation
|
2
|
+
|
3
|
+
This gem adds the capability of validating credit cards to ActiveRecord and ActiveModel (Rails 3+) and Ruby 1.9.2+.
|
4
|
+
|
5
|
+
### Installation
|
6
|
+
# add this to your Gemfile
|
7
|
+
gem "credit_card_validation"
|
8
|
+
|
9
|
+
# and run
|
10
|
+
bundle
|
11
|
+
|
12
|
+
### Usage
|
13
|
+
|
14
|
+
#### With ActiveRecord
|
15
|
+
class Order < ActiveRecord::Base
|
16
|
+
# standard validation
|
17
|
+
validates :card_number, credit_card: true
|
18
|
+
|
19
|
+
# with legacy syntax
|
20
|
+
validates_credit_card :card_number
|
21
|
+
end
|
22
|
+
|
23
|
+
#### With ActiveModel
|
24
|
+
class Order
|
25
|
+
include ActiveModel::Validations
|
26
|
+
|
27
|
+
attr_accessor :card_number
|
28
|
+
|
29
|
+
validates :card_number, credit_card: true
|
30
|
+
end
|
31
|
+
|
32
|
+
#### I18n
|
33
|
+
|
34
|
+
The default error message `is not a valid credit card`.
|
35
|
+
You can pass the `message: "my custom error"` option to your validation to define your own, custom message.
|
36
|
+
|
37
|
+
## Authors
|
38
|
+
|
39
|
+
**Rahul Trikha** (<http://twitter.com/rahult>)
|
40
|
+
|
41
|
+
## License
|
42
|
+
Copyright 2013 by Rahul Trikha (<http://www.rahultrikha.com>) and is released under the MIT license.
|
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "credit_card_validation/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "credit_card_validation"
|
7
|
+
s.version = CreditCardValidation::VERSION
|
8
|
+
s.authors = ["Rahul Trikha"]
|
9
|
+
s.email = ["rahul.trikha@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/rahult/credit_card_validation"
|
11
|
+
s.summary = %q{Offline Credit Card Validator written for Rails 3+ using ruby >= 1.9.2}
|
12
|
+
s.description = %q{A credit card validation library to check offline validity of any AMEX, Discover, MasterCard, Visa cards using length and Luhn algorithm.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "credit_card_validation"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
s.add_dependency "activerecord", ">= 3.0.0"
|
23
|
+
s.add_development_dependency "sqlite3"
|
24
|
+
s.add_development_dependency "rake"
|
25
|
+
s.add_development_dependency "turn"
|
26
|
+
s.add_development_dependency "growl"
|
27
|
+
s.add_development_dependency "minitest"
|
28
|
+
s.add_development_dependency "guard-minitest"
|
29
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'active_model'
|
2
|
+
|
3
|
+
module ActiveModel
|
4
|
+
|
5
|
+
module Validations
|
6
|
+
|
7
|
+
class CreditCardValidator < ActiveModel::EachValidator
|
8
|
+
|
9
|
+
def validate_each(record, attribute, value)
|
10
|
+
unless CreditCardValidation::Validator.new(value).valid?
|
11
|
+
record.errors[attribute] << (options[:message] || "is not a valid credit card")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
|
19
|
+
def validates_credit_card(*attributes)
|
20
|
+
validates_with CreditCardValidator, _merge_attributes(*attributes)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require "active_model/validations/credit_card_validator"
|
2
|
+
require "credit_card_validation/version"
|
3
|
+
|
4
|
+
module CreditCardValidation
|
5
|
+
|
6
|
+
class Validator
|
7
|
+
attr_accessor :card
|
8
|
+
|
9
|
+
def initialize(card=nil)
|
10
|
+
sanitize(card)
|
11
|
+
end
|
12
|
+
|
13
|
+
def sanitize(card)
|
14
|
+
self.card = card.gsub(/\s/,'') unless card.nil?
|
15
|
+
end
|
16
|
+
|
17
|
+
def type
|
18
|
+
case sanitize(card)
|
19
|
+
when /^(34|37)\d{13}$/
|
20
|
+
'AMEX'
|
21
|
+
when /^6011\d{12}$/
|
22
|
+
'Discover'
|
23
|
+
when /^5[1-5]\d{14}$/
|
24
|
+
'MasterCard'
|
25
|
+
when /^4(\d{12}|\d{15})$/
|
26
|
+
'VISA'
|
27
|
+
else 'Unknown'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def meet_luhn_verification
|
32
|
+
total = sanitize(card).reverse.split(//).inject([0,0]) do |accum,number|
|
33
|
+
number = number.to_i
|
34
|
+
accum[0] += (accum[1] % 2 == 0 ? number : rotate(number * 2))
|
35
|
+
accum[1] += 1
|
36
|
+
accum
|
37
|
+
end
|
38
|
+
|
39
|
+
total[0] % 10 == 0
|
40
|
+
end
|
41
|
+
|
42
|
+
def rotate(number)
|
43
|
+
if number > 9
|
44
|
+
number = number % 10 + 1
|
45
|
+
end
|
46
|
+
number
|
47
|
+
end
|
48
|
+
|
49
|
+
def valid?
|
50
|
+
(type != "Unkown") && meet_luhn_verification
|
51
|
+
end
|
52
|
+
|
53
|
+
def validity
|
54
|
+
valid? ? "valid" : "invalid"
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_s
|
58
|
+
"#{type}: #{card}".ljust(28) + " (#{validity})"
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
if __FILE__==$0
|
66
|
+
cards = "4111111111111111
|
67
|
+
4111111111111
|
68
|
+
4012888888881881
|
69
|
+
378282246310005
|
70
|
+
6011111111111117
|
71
|
+
5105105105105100
|
72
|
+
5105 1051 0510 5106
|
73
|
+
9111111111111111"
|
74
|
+
|
75
|
+
validator = CreditCardValidation::Validator.new
|
76
|
+
|
77
|
+
cards.lines.each do |line|
|
78
|
+
validator.card = line.chomp.strip
|
79
|
+
validator.valid?
|
80
|
+
puts validator
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class CreditCard < ActiveRecord::Base
|
4
|
+
validates :card_number, presence: true, credit_card: true
|
5
|
+
end
|
6
|
+
|
7
|
+
describe ActiveModel::Validations::CreditCardValidator do
|
8
|
+
before do
|
9
|
+
@credit_card = CreditCardValidation::Validator.new
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "when asked about validity of a AMEX card" do
|
13
|
+
it "should respond true for a valid card" do
|
14
|
+
@credit_card.card = "378282246310005"
|
15
|
+
@credit_card.must_be :valid?
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should respond false for a invalid card" do
|
19
|
+
@credit_card.card = "37828224631000"
|
20
|
+
@credit_card.wont_be :valid?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "when asked about validity of a Discover card" do
|
25
|
+
it "should respond true for a valid card" do
|
26
|
+
@credit_card.card = "6011111111111117"
|
27
|
+
@credit_card.must_be :valid?
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should respond false for a invalid card" do
|
31
|
+
@credit_card.card = "601111111111111"
|
32
|
+
@credit_card.wont_be :valid?
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "when asked about validity of a MasterCard card" do
|
37
|
+
it "should respond true for a valid card" do
|
38
|
+
@credit_card.card = "5105105105105100"
|
39
|
+
@credit_card.must_be :valid?
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should respond false for a invalid card" do
|
43
|
+
@credit_card.card = "5105105105105106"
|
44
|
+
@credit_card.wont_be :valid?
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should respond false for a invalid card" do
|
48
|
+
@credit_card.card = "510510510510510"
|
49
|
+
@credit_card.wont_be :valid?
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "when asked about validity of a VISA card" do
|
54
|
+
it "should respond true for a valid card" do
|
55
|
+
@credit_card.card = "4111111111111111"
|
56
|
+
@credit_card.must_be :valid?
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should respond true for a valid card" do
|
60
|
+
@credit_card.card = "4012888888881881"
|
61
|
+
@credit_card.must_be :valid?
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should respond false for a invalid card" do
|
65
|
+
@credit_card.card = "4111111111111"
|
66
|
+
@credit_card.wont_be :valid?
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "when asked about validity of a Unkown card" do
|
71
|
+
it "should respond false for a invalid card" do
|
72
|
+
@credit_card.card = "9111111111111111"
|
73
|
+
@credit_card.wont_be :valid?
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CreditCardValidation do
|
4
|
+
before do
|
5
|
+
@validator = CreditCardValidation::Validator.new
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "when asked about validity of a AMEX card" do
|
9
|
+
it "should respond true for a valid card" do
|
10
|
+
@validator.card = "378282246310005"
|
11
|
+
@validator.must_be :valid?
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should respond false for a invalid card" do
|
15
|
+
@validator.card = "37828224631000"
|
16
|
+
@validator.wont_be :valid?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "when asked about validity of a Discover card" do
|
21
|
+
it "should respond true for a valid card" do
|
22
|
+
@validator.card = "6011111111111117"
|
23
|
+
@validator.must_be :valid?
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should respond false for a invalid card" do
|
27
|
+
@validator.card = "601111111111111"
|
28
|
+
@validator.wont_be :valid?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "when asked about validity of a MasterCard card" do
|
33
|
+
it "should respond true for a valid card" do
|
34
|
+
@validator.card = "5105105105105100"
|
35
|
+
@validator.must_be :valid?
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should respond false for a invalid card" do
|
39
|
+
@validator.card = "5105105105105106"
|
40
|
+
@validator.wont_be :valid?
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should respond false for a invalid card" do
|
44
|
+
@validator.card = "510510510510510"
|
45
|
+
@validator.wont_be :valid?
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "when asked about validity of a VISA card" do
|
50
|
+
it "should respond true for a valid card" do
|
51
|
+
@validator.card = "4111111111111111"
|
52
|
+
@validator.must_be :valid?
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should respond true for a valid card" do
|
56
|
+
@validator.card = "4012888888881881"
|
57
|
+
@validator.must_be :valid?
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should respond false for a invalid card" do
|
61
|
+
@validator.card = "4111111111111"
|
62
|
+
@validator.wont_be :valid?
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "when asked about validity of a Unkown card" do
|
67
|
+
it "should respond false for a invalid card" do
|
68
|
+
@validator.card = "9111111111111111"
|
69
|
+
@validator.wont_be :valid?
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'turn/autorun'
|
2
|
+
require 'minitest/spec'
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'credit_card_validation'
|
5
|
+
require 'active_record'
|
6
|
+
|
7
|
+
ActiveRecord::Base.establish_connection(
|
8
|
+
:adapter => 'sqlite3',
|
9
|
+
:database => ':memory:'
|
10
|
+
)
|
11
|
+
|
12
|
+
ActiveRecord::Schema.define do
|
13
|
+
|
14
|
+
self.verbose = false
|
15
|
+
|
16
|
+
create_table :credit_cards, :force => true do |t|
|
17
|
+
t.string :card_number
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: credit_card_validation
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Rahul Trikha
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-21 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activerecord
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.0.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 3.0.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: sqlite3
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rake
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: turn
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: growl
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: minitest
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: guard-minitest
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
description: A credit card validation library to check offline validity of any AMEX,
|
127
|
+
Discover, MasterCard, Visa cards using length and Luhn algorithm.
|
128
|
+
email:
|
129
|
+
- rahul.trikha@gmail.com
|
130
|
+
executables: []
|
131
|
+
extensions: []
|
132
|
+
extra_rdoc_files: []
|
133
|
+
files:
|
134
|
+
- .gitignore
|
135
|
+
- .rvmrc
|
136
|
+
- Gemfile
|
137
|
+
- Guardfile
|
138
|
+
- README.mdown
|
139
|
+
- Rakefile
|
140
|
+
- credit_card_validation.gemspec
|
141
|
+
- lib/active_model/validations/credit_card_validator.rb
|
142
|
+
- lib/credit_card_validation.rb
|
143
|
+
- lib/credit_card_validation/version.rb
|
144
|
+
- spec/active_record_validator_spec.rb
|
145
|
+
- spec/credit_card_validation_spec.rb
|
146
|
+
- spec/spec_helper.rb
|
147
|
+
homepage: https://github.com/rahult/credit_card_validation
|
148
|
+
licenses: []
|
149
|
+
post_install_message:
|
150
|
+
rdoc_options: []
|
151
|
+
require_paths:
|
152
|
+
- lib
|
153
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
154
|
+
none: false
|
155
|
+
requirements:
|
156
|
+
- - ! '>='
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0'
|
159
|
+
segments:
|
160
|
+
- 0
|
161
|
+
hash: 2747215233205340247
|
162
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
163
|
+
none: false
|
164
|
+
requirements:
|
165
|
+
- - ! '>='
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0'
|
168
|
+
segments:
|
169
|
+
- 0
|
170
|
+
hash: 2747215233205340247
|
171
|
+
requirements: []
|
172
|
+
rubyforge_project: credit_card_validation
|
173
|
+
rubygems_version: 1.8.24
|
174
|
+
signing_key:
|
175
|
+
specification_version: 3
|
176
|
+
summary: Offline Credit Card Validator written for Rails 3+ using ruby >= 1.9.2
|
177
|
+
test_files:
|
178
|
+
- spec/active_record_validator_spec.rb
|
179
|
+
- spec/credit_card_validation_spec.rb
|
180
|
+
- spec/spec_helper.rb
|