# 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.

• Recipe 16.8, "Charging a Credit Card"

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