Business-CreditCard-0.36/0000755000175000017500000000000012730050701013706 5ustar ivanivanBusiness-CreditCard-0.36/META.yml0000644000175000017500000000100312730050701015151 0ustar ivanivan--- abstract: unknown author: - unknown build_requires: ExtUtils::MakeMaker: '0' configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 1 generated_by: 'ExtUtils::MakeMaker version 7.0401, CPAN::Meta::Converter version 2.150005' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Business-CreditCard no_index: directory: - t - inc requires: Test::More: '0' version: '0.36' x_serialization_backend: 'CPAN::Meta::YAML version 0.012' Business-CreditCard-0.36/MANIFEST0000644000175000017500000000031512730050701015036 0ustar ivanivanChanges CreditCard.pm MANIFEST Makefile.PL README BINS META.yml t/test.t t/agreements.t t/validation.t t/validate_card.t META.json Module JSON meta-data (added by MakeMaker) Business-CreditCard-0.36/BINS0000644000175000017500000001477612643267571014425 0ustar ivanivanfrom http://perl.about.com/compute/perl/library/nosearch/P073000.htm verified by http://www.beachnet.com/~hstiles/cardtype.html Card Type Prefix Length MasterCard 51-55 16 VISA 4 13, 16 American Express (AMEX) 34, 37 15 Diners Club/Carte Blanche 300-305, 36, 38 14 enRoute 2014, 2149 15 Discover 6011 16 JCB 3 16 JCB 2131, 1800 15 -- from Neale Banks According to a booklet I have from Westpac (an Aussie bank), a card number starting with 5610 or 56022[1-5] is a BankCard BankCards have exactly 16 digits. -- from "Becker, Max" It's mostly used in the UK and is either called "Switch" or "Solo". Card Type Prefix Length Switch various 16,18,19 Solo 63, 6767 16,18,19 switch 4903 0[2-9] 3[5-9] 4911 0[1-2] 7[4-9] 8[1-2] 4936 -- from http://en.wikipedia.org/wiki/Credit_card_number#Prefixes As of November 8, 2004, MasterCard and Diner's club formed an alliance. Cards issued in Canada and the USA start with 55 and are treated as MasterCards worldwide. International cards use the 36 prefix and are treated as mastercards in Canada and the US, but are treated as Diner's Club cards elsewhere. Diner's club international's website makes no reference to old 38 prefix numbers, and they can be presumed reissued under the 55 or 36 BIN prefix. Effective October 1, 2006, the Discover Network will activate new Issuer Identification Numbers (IINs) to support a variety of card types and products. Additionally, Discover and China Union Pay (CUP) have established a strategic alliance and reciprocity agreement. As a result, IIN ranges from CUP will be enabled to facilitate the acceptance of CUP credit Cards on the Discover Network by October 1, 2006. CUP credit cards will be enabled on Discover Network with a 16-digit Card Number only. The updated IIN table is shown below. Minimum IIN Maximum IIN Product 650000 650099 Consumer Debit 650100 650199 Commercial Debit 650200 650399 Stored Value 650400 650599 Stored Value 650600 650799 Consumer Credit 650800 650999 Commercial Credit 651000 659999 Reserved for Future Use China Union Pay 62212600 62292599 Credit Please ensure that your POS terminals, websites and any pertinent internal systems can accept these new IINs. -- from http://en.wikipedia.org/wiki/Laser_(debit_card)#Technical Laser cards are prefixed with either "6304", "6706", "6771" or "6709", and may be between 16 and 19 characters in length. -- from https://www.discovernetworkvar.com/pdf_docs/9-2_VAR_ALERT_Sep_2009.pdf Be sure to update your POS systems now with the following expanded Issuer Identification Number ("IIN") Ranges. The IIN Range table listed below includes Diners Club International ("DCI") and other Issuers and Card programs that operate on Discover Network. These ranges are required for Card transaction routing and detailed in Release 9.2 of the Discover® Network Acquirer Operating Regulations and Technical Specifications: Start End Issuing Network 30000000 30599999 DCI 30950000 30959999 DCI 35280000 358999991 JCB 36000000 369999992 DCI 38000000 39999999 DCI 60110000 60110999 Discover Network 60112000 60114999 Discover Network 60117400 60117499 Discover Network 60117700 60117999 Discover Network 60118600 60119999 Discover Network 62212600 62292599 CUP 62400000 62699999 CUP 62820000 62889999 CUP 64400000 65999999 Discover Network 1 This IIN range (35280000 to 35899999) shall be enabled only by Merchant Processors in connection with Merchant relationships, POS Devices or otherw of the United States of America and the District of Columbia, Puerto Rico, th Northern Mariana Islands and Guam, subject to certain exceptions in Acquir applicable. 2 The PAN length for this IIN Range (36000000 to 36999999) is 14 digits. -- from SBH Israel / Nir Alfandari: Local Isracard: 8(-9?) digits From http://www.wysiwyg.co.il/Anatomy-of-CreditCard-Number-formats.asp#IsraCard-algorithm 8-9 digits, non-LUHN validation From Erik Levinse: i think it's like luhn, except instead of 212121... you put +987654321 under the number you're validating, multiply each, and do mod 11 on +the sum, instead of mod 10. -------------------- From Jason Terry: list of the IIN values that were given to us by Discover. We manually tested a number from each end of the range to make sure B:CC worked. 30000000-30599999 DCI 30950000-30959999 DCI 35280000-35899999 JCB * us only 36000000-36999999 DCI * 14 digits 38000000-39999999 DCI 60110000-60110999 DN 60112000-60114999 DN 60117400-60117499 DN 60117700-60117999 DN 60118600-60119999 DN 62212600-62292599 CUP 62400000-62699999 CUP 62820000-62889999 CUP 64400000-65999999 DN --- DCI = diner's, now discover everywhere JCB = treat JCB as discover inside the US DN = Discover Network CUP = China Union Pay, treat as Discover outside China Business-CreditCard-0.36/META.json0000644000175000017500000000160212730050701015326 0ustar ivanivan{ "abstract" : "unknown", "author" : [ "unknown" ], "dynamic_config" : 1, "generated_by" : "ExtUtils::MakeMaker version 7.0401, CPAN::Meta::Converter version 2.150005", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "Business-CreditCard", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "Test::More" : "0" } } }, "release_status" : "stable", "version" : "0.36", "x_serialization_backend" : "JSON::PP version 2.27300" } Business-CreditCard-0.36/Makefile.PL0000644000175000017500000000053311772171262015674 0ustar ivanivanuse ExtUtils::MakeMaker; # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. WriteMakefile( 'NAME' => 'Business::CreditCard', 'VERSION_FROM' => 'CreditCard.pm', # finds $VERSION 'LICENSE' => 'perl', 'PREREQ_PM' => { 'Test::More' => 0, } ); Business-CreditCard-0.36/t/0000755000175000017500000000000012730050701014151 5ustar ivanivanBusiness-CreditCard-0.36/t/agreements.t0000644000175000017500000000573612654405203016511 0ustar ivanivanuse Test::More tests => 5; use Business::CreditCard; #w ok ( test_card_id_us() ); ok ( test_card_id_ca() ); ok ( test_card_id_mx() ); ok ( test_card_id_cn() ); ok ( test_card_id_base() ); sub test_card_id_us { local($Business::CreditCard::Country) = 'US'; my %cards = ( '3528000000000007' => 'Discover card', '3589000000000003' => 'Discover card', # '30000000000004' => 'Discover card', # '30500000000003' => 'Discover card', # '30950000000000' => 'Discover card', #'6200000000000005' => 'Discover card', #is 620 a valid CUP now? '6220000000000008' => 'Discover card', ); test_cards(\%cards); } sub test_cards { my $cards = shift; while( my ($k, $v)=each(%$cards) ){ if(cardtype($k) ne $v){ warn "Card $k - should be $v for $Business::CreditCard::Country ". " but cardtype returns ". cardtype($k). "\n"; return; } } return 1; } sub test_card_id_ca { local($Business::CreditCard::Country) = 'CA'; # my %cards = ( # '3528000000000007' => 'Discover card', # '3589000000000003' => 'Discover card', ## '30000000000004' => 'Discover card', ## '30500000000003' => 'Discover card', ## '30950000000000' => 'Discover card', # #'6200000000000005' => 'Discover card', #is 620 a valid CUP now? # '6220000000000008' => 'Discover card', # ); my %cards = ( '3528000000000007' => 'JCB', '3589000000000003' => 'JCB', # '30000000000004' => 'Discover card', # '30500000000003' => 'Discover card', # '30950000000000' => 'Discover card', #'6200000000000005' => 'Discover card', #is 620 a valid CUP now? '6220000000000008' => 'China Union Pay', ); test_cards(\%cards); } #"all other countries" sub test_card_id_mx { local($Business::CreditCard::Country) = 'MX'; my %cards = ( '3528000000000007' => 'JCB', '3589000000000003' => 'JCB', # '30000000000004' => 'Discover card', # '30500000000003' => 'Discover card', # '30950000000000' => 'Discover card', #'6200000000000005' => 'Discover card', #is 620 a valid CUP now? '6220000000000008' => 'Discover card', ); test_cards(\%cards); } sub test_card_id_cn { local($Business::CreditCard::Country) = 'CN'; my %cards = ( '3528000000000007' => 'JCB', '3589000000000003' => 'JCB', # '30000000000004' => 'Discover card', # '30500000000003' => 'Discover card', # '30950000000000' => 'Discover card', #'6200000000000005' => 'Discover card', #is 620 a valid CUP now? '6220000000000008' => 'China Union Pay', ); test_cards(\%cards); } sub test_card_id_base { local($Business::CreditCard::Country) = ''; my %cards = ( '3528000000000007' => 'JCB', '3589000000000003' => 'JCB', # '30000000000004' => 'Discover card', # '30500000000003' => 'Discover card', # '30950000000000' => 'Discover card', #'6200000000000005' => 'Discover card', #is 620 a valid CUP now? #XXX this is technically an issue ("base" for CUP is still CUP) ##'6220000000000008' => 'China Union Pay', #but module will say "Discover card" ); test_cards(\%cards); } Business-CreditCard-0.36/t/test.t0000644000175000017500000000443512730043665015336 0ustar ivanivan use Test::More tests => 1; use Business::CreditCard; ok( test_card_identification() ); sub test_card_identification { # # For the curious the table of test number aren't real credit card # in fact they won't validate but they do obey the rule for the # cardtype table to identify the card type. # my %test_table=( '5212345678901234' => 'MasterCard', '5512345678901234' => 'MasterCard', '2512345678901234' => 'MasterCard', '4123456789012' => 'VISA card', '4929492492497' => 'VISA card', '4512345678901234' => 'VISA card', '341234567890123' => 'American Express card', '371234567890123' => 'American Express card', #'36123456789012' => "Diner's Club/Carte Blanche", #'36123456789012' => 'MasterCard', '36123456789012' => 'Discover card', '201412345678901' => 'enRoute', '214912345678901' => 'enRoute', '6011123456789012' => 'Discover card', '3123456789012345' => 'JCB', '213112345678901' => 'JCB', '180012345678901' => 'JCB', '1800123456789012' => 'Unknown', '312345678901234' => 'Unknown', '4111xxxxxxxxxxxx' => 'VISA card', '6599xxxxxxxxxxxx' => 'Discover card', '6222xxxxxxxxxxxx' => 'Discover card', #China Union Pay '6304980000000000004' => 'Laser', '6499xxxxxxxxxxxx' => 'Discover card', '5610xxxxxxxxxxxx' => 'BankCard', '6250xxxxxxxxxxxx' => 'Discover card', #China Union Pay '6280xxxxxxxxxxxx' => 'Discover card', #China Union Pay '12345678' => 'Isracard', '123456780' => 'Isracard', '60xx xxxx xxxx xxxx' => 'Discover card', #discover w/2 digits ); while( my ($k, $v)=each(%test_table) ){ if(cardtype($k) ne $v){ warn "Card $k - should be $v but cardtype returns ". cardtype($k). "\n"; return; } } return 1; } Business-CreditCard-0.36/t/validate_card.t0000644000175000017500000000111112730043120017107 0ustar ivanivan#mostly just a quick test of validate_card() as the new name for validate() # and the :NEW import tag to bring it in my @test_table=( '4111 1111 1111 1111', '5454 5454 5454 5454', ); my @bad_table=( '4111 1111 1111 1112', '5454 5454 5454 5455', ); use Test::More tests => 4; #haha no scalar(@test_table) + scalar(@bad_table); use Business::CreditCard qw( :NEW ); foreach my $card (@test_table) { ok( validate_card($card), "validate_card($card)" ); } foreach my $card (@bad_table) { ok( ! validate_card($card), "! validate_card($card)" ); } 1; Business-CreditCard-0.36/t/validation.t0000644000175000017500000000074611772171262016512 0ustar ivanivan use Test::More tests => 1; use Business::CreditCard; ok( test_card_validation() ); sub test_card_validation { my %test_table=( '10830529' => 'Isracard', '010830529' => 'Isracard', ); while( my ($k, $v)=each(%test_table) ){ if(!validate($k)){ warn "Card $k - should be a valid $v but validation failed\n"; return; } } return 1; } Business-CreditCard-0.36/CreditCard.pm0000644000175000017500000003113112730047301016251 0ustar ivanivanpackage Business::CreditCard; require Exporter; use vars qw( @ISA $VERSION @EXPORT @EXPORT_OK %EXPORT_TAGS $Country ); @ISA = qw( Exporter ); $VERSION = "0.36"; @EXPORT = qw( cardtype validate generate_last_digit ); @EXPORT_OK = qw( receipt_cardtype validate_card ); $EXPORT_TAGS{NEW} = [ qw( validate_card cardtype receipt_cardtype ) ]; $Country = 'US'; =head1 NAME C - Validate/generate credit card checksums/names =head1 SYNOPSIS use Business::CreditCard; print validate("5276 4400 6542 1319"); print cardtype("5276 4400 6542 1319"); print generate_last_digit("5276 4400 6542 131"); Business::CreditCard is available at a CPAN site near you. =head1 DESCRIPTION These subroutines tell you whether a credit card number is self-consistent -- whether the last digit of the number is a valid checksum for the preceding digits. The validate() subroutine returns 1 if the card number provided passes the checksum test, and 0 otherwise. The cardtype() subroutine returns a string containing the type of card. The list of possible return values is more comprehensive than it used to be, but additions are still most welcome. Possible return values are: VISA card MasterCard Discover card American Express card enRoute JCB BankCard Switch Solo China Union Pay Laser Isracard Unknown "Not a credit card" is returned on obviously invalid data values. Versions before 0.31 may also have returned "Diner's Club/Carte Blanche" (these cards are now recognized as "Discover card"). As of 0.30, cardtype() will accept a partial card masked with "x", "X', ".", "*" or "_". Only the first 2-6 digits and the length are significant; whitespace and dashes are removed. With two digits, Visa, MasterCard, Discover and Amex are recognized (versions before 0.36 needed four digits to recognize all Discover cards). With four digits, almost all cards except some Switch cards are recognized. With six digits (the full "BIN" or "IIN"), all cards are recognized. Six digits are also required for receipt_cardtype(). The generate_last_digit() subroutine computes and returns the last digit of the card given the preceding digits. With a 16-digit card, you provide the first 15 digits; the subroutine returns the sixteenth. This module does I tell you whether the number is on an actual card, only whether it might conceivably be on a real card. To verify whether a card is real, or whether it's been stolen, or to actually process charges, you need a Merchant account. See L. These subroutines will also work if you provide the arguments as numbers instead of strings, e.g. C. =head1 PROCESSING AGREEMENTS Credit card issuers have recently been forming agreements to process cards on other networks, in which one type of card is processed as another card type. By default, Business::CreditCard returns the type the card should be treated as in the US. You can change this to return the type the card should be treated as in a different country by setting C<$Business::CreditCard::Country> to your two-letter country code. This is probably what you want to determine if you accept the card, or which merchant agreement it is processed through. You can also set C<$Business::CreditCard::Country> to a false value such as the empty string to return the "base" card type. This is probably only useful for informational purposes when used along with the default type. Here are the currently known agreements: =over 4 =item Most Diner's club is now identified as Discover. (This supercedes the earlier identification of some Diner's club cards as MasterCard inside the US and Canada.) =item JCB cards in the 3528-3589 range are identified as Discover inside the US and territories. =item China Union Pay cards are identified as Discover cards in the US, Mexico and most Caribbean countries. =back =head1 RECEIPT REQUIREMENTS Discover requires some cards processed on its network to display "PayPal" on receipts instead of "Discover". The receipt_cardtype() subroutine will return "PayPal card" for these cards only, and otherwise the same output as cardtype(). Use this for receipt display/printing only. Note: this subroutine is not exported by default like the others. Before 0.36, you needed to call this subroutine fully-qualified, as Business::CreditCard::receipt_cardtype() In 0.36 and later, you can import it into your namespace: use Business::CreditCard qw( :DEFAULT receipt_cardtype ); =head1 ORIGINAL AUTHOR Jon Orwant The Perl Journal and MIT Media Lab =head1 MAINTAINER Current maintainer is Ivan Kohler . Lee Lawrence , Neale Banks and Max Becker contributed support for additional card types. Lee also contributed a working test.pl. Alexandr Ciornii contributed code cleanups. Jason Terry contributed updates for Discover BIN ranges. =head1 COPYRIGHT AND LICENSE Copyright (C) 1995,1996,1997 Jon Orwant Copyright (C) 2001-2006 Ivan Kohler Copyright (C) 2007-2016 Freeside Internet Services, Inc. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available. =head1 BUGS (paraphrasing Neil Bowers) We export all functions by default. It would be better to let the user decide which functions to import. And validate() is a bit of a generic name. The question is, after almost 2 decades with this interface (inherited from the original author, who probably never expected it to live half this long), how to change things to behave in a more modern fashion without breaking existing code? "use Business::CreditCard " turns it off? Explicitly ask to turn it off and list that in the SYNOPSIS? =head2 validate() and @EXPORT transition plan First (done in 0.36): validate_card() is the new name for validate(). Both work for now. New-style usage (not recommended for code that needs to support B:CC before 0.36): use Business::CreditCard qw( :NEW ); You get validate_card(), cardtype() and receipt_cardtype(). You can also ask for them explicitly / individually: use Business::CreditCard qw( validate_card cardtype receipt_cardtype ); Second (we're at now now): Waiting for 0.36+ to become more prevalent. Third: Recommend new-style usage. Maybe asking for a specific minimum version turns it on too? Fourth: (this is the incompatible part): Don't export validate() (or anything else [separately?]) by default. This is the part that will break things and we probably won't do for a long time, until new-style usage is the norm and the tradeoff of breaking old code is worth it to stop or namespace pollution. Maybe do a 1.00 releaes with the current API and 2.00 is when this happens (with a 1.99_01 pre-release)? =head1 SEE ALSO L is a wrapper around Business::CreditCard providing an OO interface. Assistance integrating this into the base Business::CreditCard distribution is welcome. L is a framework for processing online payments including modules for various payment gateways. http://neilb.org/reviews/luhn.html is an excellent overview of similar modules providing credit card number verification (LUHN checking). =cut ## ref http://neilb.org/reviews/luhn.html#Comparison it looks like ## Business::CCCheck is 2x faster than we are. looking at their implementation ## not entirely a fair comparison, we also do the equivalent of their CC_clean, ## they don't recognize certain cards at all (i.e. Switch) which require ## an expensive check before VISA, Diners doesn't exist anymore, Discover is ## a lot more than just 6011*, they don't handle processing agreements, etc. sub cardtype { # Allow use as a class method shift if UNIVERSAL::isa( $_[0], 'Business::CreditCard' ); my ($number) = @_; $number =~ s/[\s\-]//go; $number =~ s/[x\*\.\_]/x/gio; return "Not a credit card" if $number =~ /[^\dx]/io; #$number =~ s/\D//g; { local $^W=0; #no warning at next line return "Not a credit card" unless ( length($number) >= 13 || length($number) == 8 || length($number) == 9 #Isracard ) && 0+$number; } return "VISA card" if $number =~ /^4[0-8][\dx]{11,17}$/o; return "MasterCard" if $number =~ /^5[1-5][\dx]{14}$/o || $number =~ /^2 ( 22[1-9] | 2[3-9][\dx] | [3-6][\dx]{2} | 7[0-1][\dx] | 720 ) [\dx]{12}$/xo || $number =~ /^2[2-7]xx[\dx]{12}$/o; return "American Express card" if $number =~ /^3[47][\dx]{13}$/o; return "Discover card" if $number =~ /^30[0-5x][\dx]{13,16}$/o #diner's: 300-305, 30x || $number =~ /^309[5x][\dx]{12}$/o # 3095, 309x || $number =~ /^36[\dx]{12,17}$/o # 36 || $number =~ /^3[89][\dx]{14,17}$/o # 38 and 39 || $number =~ /^60[1x]{2}[\dx]{12,15}$/o #discover: 6011 601x 60xx || $number =~ /^64[4-9x][\dx]{13,16}$/o # 644-649, 64x || $number =~ /^65[\dx]{14,17}$/o # 65 || ( $number =~ /^62[24-68x][\dx]{13,16}$/o && $Country =~ /^(US|MX|AI|AG|AW|BS|BB|BM|BQ|VG|KY|CW|DM|DO|GD|GP|JM|MQ|MS|BL|KN|LC|VC|MF|SX|TT|TC)$/oi ) #China Union Pay identified as Discover in US, Mexico and Caribbean || ( $number =~ /^35(2[89x]|[3-8][\dx]|xx)[\dx]{12,15}$/o && $Country =~ /^(US|PR|VI|MP|PW|GU)$/oi ); #JCB cards in the 3528-3589 range are identified as Discover in US, Puerto Rico, US Virgin Islands, Northern Mariana Islands, Palau and Guam return "Switch" if $number =~ /^49(03(0[2-9]|3[5-9])|11(0[1-2]|7[4-9]|8[1-2])|36[0-9]{2})[\dx]{10}([\dx]{2,3})?$/o || $number =~ /^564182[\dx]{10}([\dx]{2,3})?$/o || $number =~ /^6(3(33[0-4][0-9])|759[0-9]{2})[\dx]{10}([\dx]{2,3})?$/o; #redunant with above, catch 49* that's not Switch return "VISA card" if $number =~ /^4[\dx]{12,18}$/o; #"Diners Club enRoute" return "enRoute" if $number =~ /^2(014|149)[\dx]{11}$/o; return "JCB" if $number =~ /^(3[\dx]{4}|2131|1800)[\dx]{11}$/o; return "BankCard" if $number =~ /^56(10[\dx][\dx]|022[1-5])[\dx]{10}$/o; return "Solo" if $number =~ /^6(3(34[5-9][0-9])|767[0-9]{2})[\dx]{10}([\dx]{2,3})?$/o; return "China Union Pay" if $number =~ /^62[24-68][\dx]{13}$/o; return "Laser" if $number =~ /^6(304|7(06|09|71))[\dx]{12,15}$/o; return "Isracard" if $number =~ /^[\dx]{8,9}$/; return "Unknown"; } sub receipt_cardtype { # Allow use as a class method shift if UNIVERSAL::isa( $_[0], 'Business::CreditCard' ); my ($number) = @_; $number =~ s/[\s\-]//go; $number =~ s/[x\*\.\_]/x/gio; #ref Discover IIN Bulletin Feb 2015_021715 return "PayPal card" if $number =~ /^6(01104|506[01]0)[\dx]{10,13}$/o; cardtype($number); } sub generate_last_digit { # Allow use as a class method shift if UNIVERSAL::isa( $_[0], 'Business::CreditCard' ); my ($number) = @_; die "invalid operation" if length($number) == 8 || length($number) == 9; my ($i, $sum, $weight); $number =~ s/\D//g; for ($i = 0; $i < length($number); $i++) { $weight = substr($number, -1 * ($i + 1), 1) * (2 - ($i % 2)); $sum += (($weight < 10) ? $weight : ($weight - 9)); } return (10 - $sum % 10) % 10; } ## this (GPLed) code from Business::CCCheck is apparantly 4x faster than ours ## ref http://neilb.org/reviews/luhn.html#Comparison ## maybe see if we can speed ours up a bit # my @ccn = split('',$ccn); # my $even = 0; # $ccn = 0; # for($i=$#ccn;$i >=0;--$i) { # $ccn[$i] *= 2 if $even; # $ccn -= 9 if $ccn[$i] > 9; # $ccn += $ccn[$i]; # $even = ! $even; # } # $type = '' if $ccn % 10; # return $type; sub validate { validate_card(@_); } sub validate_card { # Allow use as a class method shift if UNIVERSAL::isa( $_[0], 'Business::CreditCard' ); my ($number) = @_; my ($i, $sum, $weight); return 0 if $number =~ /[^\d\s]/; $number =~ s/\D//g; if ( $number =~ /^[\dx]{8,9}$/ ) { # Isracard $number = "0$number" if length($number) == 8; for($i=1;$i= 13 && 0+$number; for ($i = 0; $i < length($number) - 1; $i++) { $weight = substr($number, -1 * ($i + 2), 1) * (2 - ($i % 2)); $sum += (($weight < 10) ? $weight : ($weight - 9)); } return 1 if substr($number, -1) == (10 - $sum % 10) % 10; return 0; } 1; Business-CreditCard-0.36/README0000644000175000017500000000134011772171262014577 0ustar ivanivanBusiness::CreditCard These subroutines tell you whether a credit card number is self-consistent -- whether the last digit of the number is a valid checksum for the preceding digits. If you additionally want to process the credit card electronically, see Business::OnlinePayment Original author is Jon Orwant , The Perl Journal and MIT Media Lab Current maintainer is Ivan Kohler . Please don't bother Jon with emails about this module. Lee Lawrence , Neale Banks and Max Becker contributed support for additional card types. Lee also contributed a working test.pl. Business-CreditCard-0.36/Changes0000644000175000017500000000761012730047273015217 0ustar ivanivanRevision history for Perl extension Business::CreditCard. 0.36 Tue Jun 14 11:36:05 PDT 2016 - Allow (and doc) import of receipt_cardtype - validate_card() is a new synonym for validate(), starting a long-term plan to stop exporting validate() or anything else by default. - Best-effort cardtype() when only the first two digits are available (identify masked 60xx as Discover) 0.35 Tue Feb 9 14:43:38 PST 2016 - Fix bug identifying 49* Visa cards introduced in 0.34, patch from Ed J, thanks! - doc: Clarify processing agreements don't apply to Canada 0.34 Fri Feb 5 07:24:00 PST 2016 - 19 digit Visa and Discover cards - MasterCard 222100-272099 range - Canada does not process JCB 3529-3589 as Discover, but Puerto Rico, US Virgin Islans, Northern Mariana Islands, Palau and Guam do - China Union Pay only processed as Discover in the US, Mexico and the Caribbean, not elsewhere outside China - 14 digit Discover remain only in 36* - receipt_cardtype subroutine supporting Discover's new receipt requirements 0.33 Sat Sep 13 16:13:15 PDT 2014 - With $Country explicity to CA, fix identification of JCB 3529-3589 as Discover - Allow use of our subroutines as class methods, patch from Adam Kennedy, thanks! - Add tests for processing agreement / country functionality 0.32 Thu Feb 21 16:02:42 PST 2013 - Add Israeli Isracard (no checksum yet) - Add LICENSE=>perl to Makefile.PL; add license to META.yml, closes: cpan #27735 - Documentation: Add link to Neil Bowers' review of CC check modules - Rearrange cardtype() for performance - Fix Discover identification of 39 and 3529-3589 prefixes, patch from Jason Terry, thanks! 0.31 Mon Oct 19 18:51:35 PDT 2009 - Add LICENSE section to POD documentation - Add META.yml to MANIFEST - Add Irish Laser card, thanks to Eoin Redmond for the heads-up. - Add documentation on what this module *is* and *is NOT* about. - Spelling fix in docs - correct misdocumentation of $Business::CreditCard::Country - Move test.pl to test/t and change to using Test::More, modify MANIFEST and Makefile.PL accordingly (thanks to Alexander Ciornii) - Silence unwanted warnings (thanks to Alexander Ciornii) - Discover cards starting with 644-649 are now recognized - Most Diner's Club cards (300-305, 3095 and 36) now processed as Discover - China Union pay now includes 624-626 and 628 in addition to 622 (and still identified as Discover outside China) - JCB identified as Discover in the US 0.30 Mon Dec 18 23:24:25 PST 2006 - back after two and a half years; happy hanukkah! - added note about B:CC:Object - added new Discover 65 prefix - check for Switch before Visa as Switch has some BINs in ^4 - accept masked numbers in cardtype() - add handling of card network peering arrangements, controllable via $Business::CreditCard::Country - identify Diner's club ^36 cards as MasterCard in US and Canada - identify China Union Pay cards as Discover cards outside China - identify China Union Pay cards 0.28 Thu Jul 1 01:17:32 PDT 2004 - added Switch and Solo cards, patch from Max Becker - added proper Changes file - added documentation on cardtype() return values from tmurray@agronomy.org (closes: cpan #3330) 0.27 20 Jan 2002 - small typo for amex cards 0.26 10 Jul 2001 0.25 10 Jul 2001 - *sigh* 0.24 11 Jun 2001 - added enRoute, JCB, BankCard, rewrote with regexes 0.23 3 May 2001 - silly bug in test.pl 0.22 1 Feb 2001 - new maintainer, MakeMaker installation 0.21 17 Jan 97 - short numbers and numbers with letters are no longer kosher. 12 Jul 96 - created