Class: Cardia::CreditCard

Inherits:
Object show all
Includes:
Validateable
Defined in:
lib/cardia/credit_card.rb

Overview

Represents a credit card

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Validateable

#errors, #valid?

Constructor Details

#initialize(options = {}) ⇒ CreditCard

Creates a new Credit card instance Valid options are

  • :number

  • :month

  • :year

  • :first_name

  • :last_name

  • :verification_value

  • :type



19
20
21
22
23
# File 'lib/cardia/credit_card.rb', line 19

def initialize(options = {})
  options.each do |key, value|
    self.send("#{key}=", value)
  end
end

Instance Attribute Details

#first_nameObject

Returns the value of attribute first_name.



8
9
10
# File 'lib/cardia/credit_card.rb', line 8

def first_name
  @first_name
end

#last_nameObject

Returns the value of attribute last_name.



8
9
10
# File 'lib/cardia/credit_card.rb', line 8

def last_name
  @last_name
end

#monthObject

Returns the value of attribute month.



8
9
10
# File 'lib/cardia/credit_card.rb', line 8

def month
  @month
end

#numberObject

Returns the value of attribute number.



8
9
10
# File 'lib/cardia/credit_card.rb', line 8

def number
  @number
end

#typeObject

Returns the value of attribute type.



8
9
10
# File 'lib/cardia/credit_card.rb', line 8

def type
  @type
end

#verification_valueObject

Optional verification_value (CVV, CVV2 etc)



26
27
28
# File 'lib/cardia/credit_card.rb', line 26

def verification_value
  @verification_value
end

#yearObject

Returns the value of attribute year.



8
9
10
# File 'lib/cardia/credit_card.rb', line 8

def year
  @year
end

Class Method Details

.card_companiesObject

:nodoc:



152
153
154
# File 'lib/cardia/credit_card.rb', line 152

def self.card_companies #:nodoc:
  return card_companies_to_pattern.keys
end

.card_companies_to_patternObject

Get the regexps for different card companies

Known card types

*Card Type* Prefix Length mastercard 51-55 16 visa 4 13, 16 american_express 34, 37 15 diners_club 300-305, 36, 38 14 enroute 2014, 2149 15 discover 6011 16 jcb 3 16 jcb 2131, 1800 15 bankcard 5610, 56022 16 switch various 16,18,19 solo 63, 6767 16,18,19



137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/cardia/credit_card.rb', line 137

def self.card_companies_to_pattern #:nodoc:
  {
    'visa' =>  /^4\d{12}(\d{3})?$/,
    'master' =>  /^5[1-5]\d{14}$/,
    'discover' =>  /^6011\d{12}$/,
    'american_express' =>  /^3[47]\d{13}$/,
    'diners_club' =>  /^3(0[0-5]|[68]\d)\d{11}$/,
    'enroute' =>  /^2(014|149)\d{11}$/,
    'jcb' =>  /^(3\d{4}|2131|1800)\d{11}$/,
    'bankcard' =>  /^56(10\d\d|022[1-5])\d{10}$/,
    'switch' =>  [/^49(03(0[2-9]|3[5-9])|11(0[1-2]|7[4-9]|8[1-2])|36[0-9]{2})\d{10}(\d{2,3})?$/, /^564182\d{10}(\d{2,3})?$/, /^6(3(33[0-4][0-9])|759[0-9]{2})\d{10}(\d{2,3})?$/],
    'solo' =>  /^6(3(34[5-9][0-9])|767[0-9]{2})\d{10}(\d{2,3})?$/
  }
end

.invalid_card_for_testingObject

Returns an invalid credit card for testing purposes



52
53
54
55
56
# File 'lib/cardia/credit_card.rb', line 52

def self.invalid_card_for_testing
  result = self.valid_card_for_testing
  result.number = "45699713888448360"
  return result
end

.type?(number) ⇒ Boolean

Returns a string containing the type of card from the list of known information below.

Returns:

  • (Boolean)


157
158
159
160
161
# File 'lib/cardia/credit_card.rb', line 157

def self.type?(number) #:nodoc:
  card_companies_to_pattern.each do |company, patterns|
    return company if [patterns].flatten.any? { |pattern| number =~ pattern  }
  end
end

.valid_card_for_testingObject

Returns a valid credit card (visa) for testing purposes.



40
41
42
43
44
45
46
47
48
49
# File 'lib/cardia/credit_card.rb', line 40

def self.valid_card_for_testing
  result = self.new
  result.number               = "4569971388844836"
  result.verification_value   = "081"
  result.expiry_date          = Date.parse("2017-03-01")
  result.type                 = "visa"
  result.first_name           = "John"
  result.last_name            = "Doe"
  return result
end

.valid_number?(number) ⇒ Boolean

Returns true if it validates. Optionally, you can pass a card type as an argument and make sure it is of the correct type.

References

Returns:

  • (Boolean)


167
168
169
170
171
172
173
174
175
176
177
# File 'lib/cardia/credit_card.rb', line 167

def self.valid_number?(number)
  return false unless number.to_s.length >= 13

  sum = 0
  for i in 0..number.length
    weight = number[-1 * (i + 2), 1].to_i * (2 - (i % 2))
    sum += (weight < 10) ? weight : weight - 9
  end

  (number[-1,1].to_i == (10 - sum % 10) % 10)
end

Instance Method Details

#before_validateObject

:nodoc:



58
59
60
61
62
63
# File 'lib/cardia/credit_card.rb', line 58

def before_validate #:nodoc:
  self.type.downcase! if type.respond_to?(:downcase)
  self.month = month.to_i
  self.year = year.to_i
  self.number.to_s.gsub!(/[^\d]/, "")
end

#display_numberObject

Show the card number, with all but last 4 numbers replace with “x”. (xxxxxxxxxxxx-4338)



180
181
182
183
# File 'lib/cardia/credit_card.rb', line 180

def display_number
  return @number if @number.blank? || @number.length < 5
  "#{'x' * (@number.length - 4)}-#{@number[-4, 4]}"
end

#expired?Boolean

:nodoc:

Returns:

  • (Boolean)


95
96
97
# File 'lib/cardia/credit_card.rb', line 95

def expired? #:nodoc:
  Time.now > Time.parse("#{month}/28/#{year}") rescue true
end

#expiresObject

Expiry date in mmyy format



81
82
83
# File 'lib/cardia/credit_card.rb', line 81

def expires
  expiry_date.strftime("%m%y")
end

#expiry_dateObject

:nodoc:



91
92
93
# File 'lib/cardia/credit_card.rb', line 91

def expiry_date #:nodoc:
  Date.parse("#{year}-#{month}-01")
end

#expiry_date=(a_date) ⇒ Object

Sets the expiry date, takes a Date instance



86
87
88
89
# File 'lib/cardia/credit_card.rb', line 86

def expiry_date=(a_date)
  self.year = a_date.year
  self.month = a_date.month
end

#first_name?Boolean

:nodoc:

Returns:

  • (Boolean)


103
104
105
# File 'lib/cardia/credit_card.rb', line 103

def first_name? #:nodoc:
  @first_name != nil
end

#last_name?Boolean

:nodoc:

Returns:

  • (Boolean)


107
108
109
# File 'lib/cardia/credit_card.rb', line 107

def last_name? #:nodoc:
  @last_name != nil
end

#nameObject

:nodoc:



111
112
113
# File 'lib/cardia/credit_card.rb', line 111

def name #:nodoc:
  "#{@first_name} #{@last_name}"
end

#name?Boolean

:nodoc:

Returns:

  • (Boolean)


99
100
101
# File 'lib/cardia/credit_card.rb', line 99

def name? #:nodoc:
  @first_name != nil and @last_name != nil
end

#payment_typeObject



115
116
117
# File 'lib/cardia/credit_card.rb', line 115

def payment_type
  "1000"
end

#to_paramObject

:nodoc:



28
29
30
31
32
33
34
35
36
37
# File 'lib/cardia/credit_card.rb', line 28

def to_param #:nodoc:
return {
  :number => self.number,
  :month => self.month,
  :year => self.year,
  :type => self.type,
  :first_name => self.first_name,
  :last_name => self.last_name,
  :verification_value => self.verification_value}
end

#validateObject

:nodoc:



65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/cardia/credit_card.rb', line 65

def validate #:nodoc:
  @errors.add "year", "expired"                             if expired?
  #@errors.add "first_name", "cannot be empty"               unless @first_name
  #@errors.add "last_name", "cannot be empty"                unless @last_name
  @errors.add "month", "cannot be empty"                    unless (1..12).include?(month.to_i)
  @errors.add "year", "cannot be empty"                     unless (Time.now.year..Time.now.year+10).include?(year.to_i)

  # Bogus card is pretty much for testing purposes. Lets just skip these extra tests if its used
  return if type == 'bogus'

  @errors.add "number", "is not a vaild credit card number" unless CreditCard.valid_number?(number)
  @errors.add "type", "is invalid."                         unless CreditCard.card_companies.include?(type)
  @errors.add "type", "is not the correct card type"        unless CreditCard.type?(number) == type
end

#verification_value?Boolean

:nodoc:

Returns:

  • (Boolean)


119
120
121
# File 'lib/cardia/credit_card.rb', line 119

def verification_value? #:nodoc:
  @verification_value != nil
end