forked from PawelDecowski/jquery-creditcardvalidator
/
jquery.creditCardValidator.coffee
135 lines (113 loc) · 3.34 KB
/
jquery.creditCardValidator.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
###
jQuery Credit Card Validator
Copyright 2012 Pawel Decowski
This work is licensed under the Creative Commons Attribution-ShareAlike 3.0
Unported License. To view a copy of this license, visit:
http://creativecommons.org/licenses/by-sa/3.0/
or send a letter to:
Creative Commons, 444 Castro Street, Suite 900,
Mountain View, California, 94041, USA.
###
$ = jQuery
$.fn.validateCreditCard = (callback) ->
card_types = [
{
name: 'amex'
pattern: /^3[47]/
valid_length: [ 15 ]
}
{
name: 'diners_club_carte_blanche'
pattern: /^30[0-5]/
valid_length: [ 14 ]
}
{
name: 'diners_club_international'
pattern: /^36/
valid_length: [ 14 ]
}
{
name: 'diners_club_us_and_ca'
pattern: /^5[45]/
valid_length: [ 16 ]
}
{
name: 'jcb'
pattern: /^35(2[89]|[3-8][0-9])/
valid_length: [ 16 ]
}
{
name: 'laser'
pattern: /^(6304|630[69]|6771)/
valid_length: [ 16..19 ]
}
{
name: 'visa_electron'
pattern: /^(4026|417500|4508|4844|491(3|7))/
valid_length: [ 16 ]
}
{
name: 'visa'
pattern: /^4/
valid_length: [ 13, 16 ]
}
{
name: 'mastercard'
pattern: /^5[1-5]/
valid_length: [ 16 ]
}
{
name: 'maestro'
pattern: /^(5018|5020|5038|6304|6759|676[1-3])/
valid_length: [ 12..19 ]
}
{
name: 'discover'
pattern: /^(6011|622(12[6-9]|1[3-9][0-9]|[2-8][0-9]{2}|9[0-1][0-9]|92[0-5]|64[4-9])|65)/
valid_length: [ 16 ]
}
]
get_card_type = (number) ->
for card_type in card_types
if number.match card_type.pattern
return card_type
null
is_valid_luhn = (number) ->
sum = 0
for digit, n in number.split('').reverse().join('')
digit = +digit # the + casts the string to int
if n % 2
digit *= 2
if digit < 10 then sum += digit else sum += digit - 9
else
sum += digit
sum % 10 == 0
is_valid_length = (number, card_type) ->
number.length in card_type.valid_length
validate_number = (number) ->
card_type = get_card_type number
luhn_valid = false
length_valid = false
if card_type?
luhn_valid = is_valid_luhn number
length_valid = is_valid_length number, card_type
callback
card_type: card_type
luhn_valid: luhn_valid
length_valid: length_valid
validate = ->
number = normalize $(this).val()
validate_number number
normalize = (number) ->
number.replace /[ -]/g, ''
this.bind('input', ->
$(this).unbind('keyup') # if input event is fired (so is supported) then unbind keyup
validate.call this
)
# bind keyup in case input event isn't supported
this.bind('keyup', ->
validate.call this
)
# run validation straight away in case the card number is prefilled
validate.call this
this