Checking a Credit Card Checksum

Problem

You want to know whether a credit card number was entered correctly.

Solution

The last digit of every credit card is a checksum digit. You can compare the other digits against the checksum to catch mistakes someone might make when typing their credit card number.

Lucas Carlson's CreditCard library, available as the creditcard gem, contains Ruby implementations of the checksum algorithms. It adds methods to the String and Integer classes to check the internal consistency of a credit card number:

	require 'rubygems' 
	require 'creditcard'

	'5276 4400 6542 1319'.creditcard? # => true
	'5276440065421313'.creditcard? # => false
	1276440065421319.creditcard? # => false

CreditCard can also determine which brand of credit card a certain number is for:

	5276440065421313.creditcard_type # => "mastercard"

 

Discussion

The CreditCard library uses a well-known algorithm for finding the checksum digit of a credit card. If you can't or don't want to install the creditcard gem, you can just implement the algorithm yourself:

	module CreditCard
	 def creditcard?
	 numbers = self.to_s.gsub(/[^d]+/, '').split(//)

	 checksum = 0
	 0.upto numbers.length do |i|
	 weight = numbers[-1*(i+2)].to_i * (2 - (i%2))

	 checksum += weight % 9
	 end

	 return numbers[-1].to_i == 10 - checksum % 10
	 end
	end

	class String
	 include CreditCard
	end

	class Integer
	 include CreditCard
	end

	'5276 4400 6542 1319'.creditcard? # => true

How does it work? First, it converts the object to an array of numbers:

	numbers = '5276 4400 6542 1319'.gsub(/[^d]+/, '').split(//)
	# => ["5", "2", "7", "6", "4", "4", "0", "0",
	# => "6", "5", "4", "2", "1", "3", "1", "9"]

It then calculates a weight for each number based on its position, and adds that weight to a running checksum:

	checksum = 0
	0.upto numbers.length do |i|
	 weight = numbers[-1*(i+2)].to_i * (2 - (i%2))
	 checksum += weight % 9
	end
	checksum # => 51

If the last number of the card is equal to 10 minus the last digit of the checksum, the number is self-consistent:

	numbers[-1].to_i == 10 - checksum % 10 # => true

A self-consistent credit card number is just a number with a certain mathematical property. It can catch typos, but there's no guarantee that a real credit card exists with that number. To check that, you need to use a payment gateway like Authorize.net, and a gateway library like Payment::AuthorizeNet.

See Also

  • Recipe 16.8, "Charging a Credit Card"


Strings

Numbers

Date and Time

Arrays

Hashes

Files and Directories

Code Blocks and Iteration

Objects and Classes8

Modules and Namespaces

Reflection and Metaprogramming

XML and HTML

Graphics and Other File Formats

Databases and Persistence

Internet Services

Web Development Ruby on Rails

Web Services and Distributed Programming

Testing, Debugging, Optimizing, and Documenting

Packaging and Distributing Software

Automating Tasks with Rake

Multitasking and Multithreading

User Interface

Extending Ruby with Other Languages

System Administration



Ruby Cookbook
Ruby Cookbook (Cookbooks (OReilly))
ISBN: 0596523696
EAN: 2147483647
Year: N/A
Pages: 399

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net