This is not meant to be an exhaustive list of all possible numbers, nor the only or best method to verify that they pass the "checksum" test, but here's what I came up with.
I wrote this mostly to link a Ruby version of the code to Wikipedia's article on Luhn checksum validation, since nearly every other language in use was listed, but Ruby was sadly missing.
#!/usr/bin/env ruby # # Copyright (c) 2008 Michael Graff. All rights reserved. # # Redistribution and use in source and binary forms, with or # without modification, are permitted provided that the following # conditions are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # 3. The name of Michael Graff may not be used to endorse or promote # products derived from this software without specific prior # written permission. # # THIS SOFTWARE IS PROVIDED BY Michael Graff ``AS IS'' AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Micahel Graff # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY # OF SUCH DAMAGE. # class Luhn public def self.check_luhn(s) s.gsub!(/[^0-9]/, "") ss = s.reverse.split(//) alternate = false total = 0 ss.each do |c| if alternate total += double_it(c.to_i) else total += c.to_i end alternate = !alternate end (total % 10) == 0 end private def self.double_it(i) i = i * 2 if i > 9 i = i % 10 + 1 end i end end if $0 == __FILE__ def test_valid(s) result = Luhn::check_luhn(s) if result puts "VALID: #{s}" else puts "INVALID: #{s} (should be valid)" end end test_valid('5105 1051 0510 5100') # Mastercard test_valid('5555 5555 5555 4444') # Mastercard test_valid('4222 2222 2222 2') # Visa test_valid('4111 1111 1111 1111') # Visa test_valid('4012 8888 8888 1881') # Visa test_valid('3782 8224 6310 005') # American Express test_valid('3714 4963 5398 431') # American Express test_valid('3787 3449 3671 000') # American Express Corporate test_valid('3782 8224 6310 005') # Amex test_valid('3400 0000 0000 009') # Amex test_valid('3700 0000 0000 002') # Amex test_valid('38520000023237') # Diners Club (14 digits) test_valid('30569309025904') # Diners Club (14 digits) test_valid('6011111111111117') # Discover (16 digits) test_valid('6011 0000 0000 0004') # Discover test_valid('6011 0000 0000 0012') # Discover test_valid('6011000990139424') # Discover (16 digits) test_valid('6011601160116611') # Discover (16 digits) test_valid('3530111333300000') # JCB (16 digits) test_valid('3566002020360505') # JCB (16 digits) test_valid('5431111111111111') # Mastercard (16 digits) end
No comments:
Post a Comment