File Coverage

blib/lib/Business/CreditCard.pm
Criterion Covered Total %
statement 42 58 72.4
branch 39 58 67.2
condition 39 54 72.2
subroutine 4 6 66.6
pod 1 5 20.0
total 125 181 69.0


line stmt bran cond sub pod time code
1             package Business::CreditCard;
2              
3             require Exporter;
4 4     4   242035 use vars qw( @ISA $VERSION @EXPORT @EXPORT_OK %EXPORT_TAGS $Country );
  4         29  
  4         6958  
5              
6             @ISA = qw( Exporter );
7              
8             $VERSION = "0.39";
9              
10             @EXPORT = qw( cardtype validate generate_last_digit );
11             @EXPORT_OK = qw( receipt_cardtype validate_card );
12             $EXPORT_TAGS{NEW} = [ qw( validate_card cardtype receipt_cardtype ) ];
13              
14             $Country = 'US';
15              
16             =head1 NAME
17              
18             C - Validate/generate credit card checksums/names
19              
20             =head1 SYNOPSIS
21              
22             ##
23             # new-style, supported since 0.36 released Jun 14 2016
24             ##
25              
26             use Business::CreditCard qw( 0.36 :NEW );
27            
28             print validate_card("5276 4400 6542 1319");
29             print cardtype("5276 4400 6542 1319");
30              
31              
32             ##
33             # old interface, deprecated but still supported for backwards compatibility
34             ##
35              
36             use Business::CreditCard;
37            
38             print validate("5276 4400 6542 1319");
39             print cardtype("5276 4400 6542 1319");
40            
41              
42             Business::CreditCard is available at a CPAN site near you.
43              
44             =head1 DESCRIPTION
45              
46             These subroutines tell you whether a credit card number is
47             self-consistent -- whether the last digit of the number is a valid
48             checksum for the preceding digits.
49              
50             The validate_card() subroutine returns 1 if the card number provided passes
51             the checksum test, and 0 otherwise.
52              
53             The cardtype() subroutine returns a string containing the type of
54             card. The list of possible return values is more comprehensive than it used
55             to be, but additions are still most welcome.
56              
57             Possible return values are:
58              
59             VISA card
60             MasterCard
61             Discover card
62             American Express card
63             enRoute
64             JCB
65             BankCard
66             Switch
67             Solo
68             China Union Pay
69             Laser
70             Isracard
71             Unknown
72              
73             "Not a credit card" is returned on obviously invalid data values.
74              
75             Versions before 0.31 may also have returned "Diner's Club/Carte Blanche" (these
76             cards are now recognized as "Discover card").
77              
78             cardtype() will accept a partial card masked with "x", "X", ".",
79             "*" or "_". Only the first 2-6 digits and the length are significant;
80             whitespace and dashes are removed. With two digits, Visa, MasterCard, Discover
81             and Amex are recognized (versions before 0.36 needed four digits to recognize
82             all Discover cards). With four digits, almost all cards except some
83             Switch cards are recognized. With six digits (the full "BIN" or "IIN"), all
84             cards are recognized. Six digits are also required for receipt_cardtype().
85              
86             The generate_last_digit() subroutine computes and returns the last
87             digit of the card given the preceding digits. With a 16-digit card,
88             you provide the first 15 digits; the subroutine returns the sixteenth.
89              
90             This module does I tell you whether the number is on an actual
91             card, only whether it might conceivably be on a real card. To verify
92             whether a card is real, or whether it's been stolen, or to actually process
93             charges, you need a Merchant account. See L.
94              
95             These subroutines will also work if you provide the arguments
96             as numbers instead of strings, e.g. C.
97              
98             =head1 PROCESSING AGREEMENTS
99              
100             Credit card issuers have recently been forming agreements to process cards on
101             other networks, in which one type of card is processed as another card type.
102              
103             By default, Business::CreditCard returns the type the card should be treated as
104             in the US. You can change this to return the type the card should
105             be treated as in a different country by setting
106             C<$Business::CreditCard::Country> to your two-letter country code. This
107             is probably what you want to determine if you accept the card, or which
108             merchant agreement it is processed through.
109              
110             You can also set C<$Business::CreditCard::Country> to a false value such
111             as the empty string to return the "base" card type. This is probably only
112             useful for informational purposes when used along with the default type.
113              
114             Here are the currently known agreements:
115              
116             =over 4
117              
118             =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.)
119              
120             =item JCB cards in the 3528-3589 range are identified as Discover inside the US and territories.
121              
122             =item China Union Pay cards are identified as Discover cards in the US, Mexico and most Caribbean countries.
123              
124             =back
125              
126             =head1 RECEIPT REQUIREMENTS
127              
128             Discover requires some cards processed on its network to display "PayPal"
129             on receipts instead of "Discover". The receipt_cardtype() subroutine will
130             return "PayPal card" for these cards only, and otherwise the same output as
131             cardtype().
132              
133             Use this for receipt display/printing only.
134              
135             Note: this subroutine is not exported by default like the others.
136             Before 0.36, you needed to call this subroutine fully-qualified, as
137             Business::CreditCard::receipt_cardtype()
138              
139             In 0.36 and later, you can import it into your namespace:
140              
141             use Business::CreditCard qw( :DEFAULT receipt_cardtype );
142              
143              
144             =head1 ORIGINAL AUTHOR
145              
146             Jon Orwant
147              
148             The Perl Journal and MIT Media Lab
149              
150             =head1 MAINTAINER
151              
152             Current maintainer is Ivan Kohler .
153              
154             Lee Lawrence , Neale Banks and
155             Max Becker contributed support for additional card
156             types. Lee also contributed a working test.pl. Alexandr Ciornii
157             contributed code cleanups. Jason Terry
158             contributed updates for Discover BIN ranges.
159              
160             =head1 COPYRIGHT AND LICENSE
161              
162             Copyright (C) 1995,1996,1997 Jon Orwant
163             Copyright (C) 2001-2006 Ivan Kohler
164             Copyright (C) 2007-2021 Freeside Internet Services, Inc.
165              
166             This library is free software; you can redistribute it and/or modify
167             it under the same terms as Perl itself, either Perl version 5.8.8 or,
168             at your option, any later version of Perl 5 you may have available.
169              
170             =head1 HOMEPAGE
171              
172             Homepage: http://perl.business/creditcard
173              
174             =head1 REPOSITORY
175              
176             The code is available from our public git repository:
177              
178             git clone git://git.freeside.biz/Business-CreditCard.git
179              
180             Or on the web:
181              
182             http://freeside.biz/gitweb/?p=Business-CreditCard.git
183             Or:
184             http://freeside.biz/gitlist/Business-CreditCard.git
185              
186             =head1 BUGS
187              
188             (paraphrasing Neil Bowers) We export all functions by default. It would be
189             better to let the user decide which functions to import. And validate() is
190             a bit of a generic name.
191              
192             The question is, after almost 2 decades with this interface (inherited from
193             the original author, who probably never expected it to live half this long),
194             how to change things to behave in a more modern fashion without breaking
195             existing code? "use Business::CreditCard " turns it off?
196             Explicitly ask to turn it off and list that in the SYNOPSIS?
197              
198             =head2 validate() and @EXPORT transition plan
199              
200             First (done in 0.36):
201              
202             validate_card() is the new name for validate(). Both work for now.
203              
204             New-style usage (not recommended for code that needs to support B:CC before 0.36):
205              
206             use Business::CreditCard qw( :NEW );
207              
208             You get validate_card(), cardtype() and receipt_cardtype(). You can also ask
209             for them explicitly / individually:
210              
211             use Business::CreditCard qw( validate_card cardtype receipt_cardtype );
212              
213              
214             Second:
215              
216             Waiting for 0.36+ to become more prevalent.
217              
218              
219             Third (we're at now now):
220              
221             Recommend new-style usage. Maybe asking for a specific minimum version turns
222             it on too?
223              
224              
225             Fourth:
226             (this is the incompatible part):
227              
228             Don't export validate() (or anything else [separately?]) by default.
229              
230             This is the part that will break things and we probably won't do for a long
231             time, until new-style usage is the norm and the tradeoff of breaking old code
232             is worth it to stop our namespace pollution. Maybe do a 1.00 release with the
233             current API and 2.00 is when this happens (with a 1.99_01 pre-release)?
234              
235             =head1 SEE ALSO
236              
237             L is a wrapper around Business::CreditCard
238             providing an OO interface. Assistance integrating this into the base
239             Business::CreditCard distribution is welcome.
240              
241             L is a framework for processing online payments
242             including modules for various payment gateways.
243              
244             http://neilb.org/reviews/luhn.html is an excellent overview of similar modules
245             providing credit card number verification (LUHN checking).
246              
247             =cut
248              
249             ## ref http://neilb.org/reviews/luhn.html#Comparison it looks like
250             ## Business::CCCheck is 2x faster than we are. looking at their implementation
251             ## not entirely a fair comparison, we also do the equivalent of their CC_clean,
252             ## they don't recognize certain cards at all (i.e. Switch) which require
253             ## an expensive check before VISA, Diners doesn't exist anymore, Discover is
254             ## a lot more than just 6011*, they don't handle processing agreements, etc.
255              
256             sub cardtype {
257             # Allow use as a class method
258 44 50   44 0 1625 shift if UNIVERSAL::isa( $_[0], 'Business::CreditCard' );
259              
260 44         62 my ($number) = @_;
261              
262 44         77 $number =~ s/[\s\-]//go;
263 44         92 $number =~ s/[x\*\.\_]/x/gio;
264              
265 44 50       71 return "Not a credit card" if $number =~ /[^\dx]/io;
266              
267             #$number =~ s/\D//g;
268             {
269 44         46 local $^W=0; #no warning at next line
  44         98  
270 44 50 66     205 return "Not a credit card"
      33        
271             unless ( length($number) >= 13
272             || length($number) == 8 || length($number) == 9 #Isracard
273             )
274             && 0+$number;
275             }
276              
277 44 100       89 return "VISA card" if $number =~ /^4[0-8][\dx]{11,17}$/o;
278              
279 41 100 100     140 return "MasterCard"
      66        
280             if $number =~ /^5[1-5][\dx]{14}$/o
281             || $number =~ /^2 ( 22[1-9] | 2[3-9][\dx] | [3-6][\dx]{2} | 7[0-1][\dx] | 720 ) [\dx]{12}$/xo
282             || $number =~ /^2[2-7]xx[\dx]{12}$/o;
283              
284 38 100       67 return "American Express card" if $number =~ /^3[47][\dx]{13}$/o;
285              
286 36 100 66     427 return "Discover card"
      100        
      66        
      100        
      100        
      100        
      100        
      100        
      100        
      100        
287             if $number =~ /^30[0-5x][\dx]{13,16}$/o #diner's: 300-305, 30x
288             || $number =~ /^309[5x][\dx]{12}$/o # 3095, 309x
289             || $number =~ /^36[\dx]{12,17}$/o # 36
290             || $number =~ /^3[89][\dx]{14,17}$/o # 38 and 39
291             || $number =~ /^60[1x]{2}[\dx]{12,15}$/o #discover: 6011 601x 60xx
292             || $number =~ /^64[4-9x][\dx]{13,16}$/o # 644-649, 64x
293             || $number =~ /^65[\dx]{14,17}$/o # 65
294             || ( $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
295             || ( $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
296              
297 22 50 33     89 return "Switch"
      33        
298             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
299             || $number =~ /^564182[\dx]{10}([\dx]{2,3})?$/o
300             || $number =~ /^6(3(33[0-4][0-9])|759[0-9]{2})[\dx]{10}([\dx]{2,3})?$/o;
301             #redunant with above, catch 49* that's not Switch
302 22 100       37 return "VISA card" if $number =~ /^4[\dx]{12,18}$/o;
303              
304             #"Diners Club enRoute"
305 21 100       50 return "enRoute" if $number =~ /^2(014|149)[\dx]{11}$/o;
306              
307 19 100       65 return "JCB" if $number =~ /^(3[\dx]{4}|2131|1800)[\dx]{11}$/o;
308              
309 8 100       20 return "BankCard" if $number =~ /^56(10[\dx][\dx]|022[1-5])[\dx]{10}$/o;
310              
311 7 50       15 return "Solo"
312             if $number =~ /^6(3(34[5-9][0-9])|767[0-9]{2})[\dx]{10}([\dx]{2,3})?$/o;
313              
314 7 100       16 return "China Union Pay"
315             if $number =~ /^62[24-68][\dx]{13}$/o;
316              
317 5 100       10 return "Laser"
318             if $number =~ /^6(304|7(06|09|71))[\dx]{12,15}$/o;
319              
320 4 100       17 return "Isracard"
321             if $number =~ /^[\dx]{8,9}$/;
322              
323 2         6 return "Unknown";
324             }
325              
326             sub receipt_cardtype {
327             # Allow use as a class method
328 0 0   0 0 0 shift if UNIVERSAL::isa( $_[0], 'Business::CreditCard' );
329              
330 0         0 my ($number) = @_;
331              
332 0         0 $number =~ s/[\s\-]//go;
333 0         0 $number =~ s/[x\*\.\_]/x/gio;
334              
335             #ref Discover IIN Bulletin Feb 2015_021715
336 0 0       0 return "PayPal card" if $number =~ /^6(01104|506[01]0)[\dx]{10,13}$/o;
337              
338 0         0 cardtype($number);
339             }
340              
341             sub generate_last_digit {
342             # Allow use as a class method
343 0 0   0 0 0 shift if UNIVERSAL::isa( $_[0], 'Business::CreditCard' );
344              
345 0         0 my ($number) = @_;
346              
347 0 0 0     0 die "invalid operation" if length($number) == 8 || length($number) == 9;
348              
349 0         0 my ($i, $sum, $weight);
350              
351 0         0 $number =~ s/\D//g;
352              
353 0         0 for ($i = 0; $i < length($number); $i++) {
354 0         0 $weight = substr($number, -1 * ($i + 1), 1) * (2 - ($i % 2));
355 0 0       0 $sum += (($weight < 10) ? $weight : ($weight - 9));
356             }
357              
358 0         0 return (10 - $sum % 10) % 10;
359             }
360              
361              
362             ## this (GPLed) code from Business::CCCheck is apparantly 4x faster than ours
363             ## ref http://neilb.org/reviews/luhn.html#Comparison
364             ## maybe see if we can speed ours up a bit
365             # my @ccn = split('',$ccn);
366             # my $even = 0;
367             # $ccn = 0;
368             # for($i=$#ccn;$i >=0;--$i) {
369             # $ccn[$i] *= 2 if $even;
370             # $ccn -= 9 if $ccn[$i] > 9;
371             # $ccn += $ccn[$i];
372             # $even = ! $even;
373             # }
374             # $type = '' if $ccn % 10;
375             # return $type;
376              
377 2     2 1 89 sub validate { validate_card(@_); }
378              
379             sub validate_card {
380             # Allow use as a class method
381 6 50   6 0 1082 shift if UNIVERSAL::isa( $_[0], 'Business::CreditCard' );
382              
383 6         14 my ($number) = @_;
384              
385 6         9 my ($i, $sum, $weight);
386            
387 6 50       49 return 0 if $number =~ /[^\d\s]/;
388              
389 6         28 $number =~ s/\D//g;
390              
391 6 100       25 if ( $number =~ /^[\dx]{8,9}$/ ) { # Isracard
392 2 100       7 $number = "0$number" if length($number) == 8;
393 2         7 for($i=1;$i
394 16         29 $sum += substr($number,9-$i,1) * $i;
395             }
396 2 50       7 return 1 if $sum%11 == 0;
397 0         0 return 0;
398             }
399              
400 4 50 33     23 return 0 unless length($number) >= 13 && 0+$number;
401              
402 4         12 for ($i = 0; $i < length($number) - 1; $i++) {
403 60         79 $weight = substr($number, -1 * ($i + 2), 1) * (2 - ($i % 2));
404 60 100       124 $sum += (($weight < 10) ? $weight : ($weight - 9));
405             }
406              
407 4 100       21 return 1 if substr($number, -1) == (10 - $sum % 10) % 10;
408 2         8 return 0;
409             }
410              
411             1;
412              
413