lib/forgery/forgery/credit_card.rb
# Generates random credit card numbers.
class Forgery::CreditCard < Forgery
CARDS = Forgery::Extend([
{:type => 'Visa', :length => 16, :prefixes => %w"4539 4556 4916 4532 4929 40240071 4485 4716 4"},
{:type => 'MasterCard', :length => 16, :prefixes => %w"51 52 53 54 55"},
{:type => 'American Express', :length => 15, :prefixes => %w"34 37"},
{:type => 'Discover', :length => 16, :prefixes => ["6011"]}
])
# Gets a random credit card type
#
# Forgery(:credit_card).type
# # => "Visa"
def self.type
CARDS.random[:type]
end
# Gets a random credit card number
#
# Forgery(:credit_card).number
# # => "4539750423451972"
#
# Forgery(:credit_card).number(:type => 'Visa', :length => 13)
# # => "4556180133982"
#
# Supported Options
# [:type]
# The credit card type. Defaults to a random selection.
# [:length]
# The length of the credit card number. Defaults to the length for the selected card type.
# [:prefixes]
# The allowed prefixes for the card number. Defaults to prefixes for the selected card type.
def self.number(options={})
# find a card by type specified, or select a card randomly
card = if options[:type]
CARDS.find { |ccard| ccard[:type] == options[:type] }.clone
else
CARDS.random.clone
end
# merge the remaining options
card.merge!(options)
# start the number with a prefix for this card
number = Forgery::Extend(card[:prefixes]).random
# fill in the rest of the number with random digits, leave one space for the check digit
number << Forgery::Extend("#" * (card[:length] - number.length - 1)).to_numbers
# add the check digit
number += check_digit(number)
end
private
def self.check_digit(number)
# for explanation, please see: http://www.darkcoding.net/credit-card/luhn-formula/
sum = 0
digits = number.reverse.chars.to_a.collect { |digit| digit.to_i }
digits.each_with_index do |digit, index|
if index.even?
sum += if digit * 2 > 9
digit * 2 - 9
else
digit * 2
end
else
sum += digit
end
end
(((sum / 10 + 1) * 10 - sum) % 10).to_s
end
end