Credit Card Checker

Share your advanced PureBasic knowledge/code with the community.
tss
New User
New User
Posts: 4
Joined: Sat Feb 19, 2005 12:23 pm

Credit Card Checker

Post by tss »

I don't know if anyone will find this useful, but I converted the code for a Credit Card validator routine from the ruby gem - creditcard (Author is Lucas Carlson I believe - http://rubyforge.org/projects/creditcard/).

The only card type I didn't convert was the "switch" type. If someone knows what this regular expression is doing: ^6(3(33[0-4][0-9])|759[0-9]{2})\d{10}(\d{2,3})?$

then I could add that as well. (I don't know Regular Expressions well enough just yet).

By the way, this was just done for something fun to do, so the code can probably be optimized quite a bit. I'm still new to Purebasic.

Code: Select all

; Reference: http://www.beachnet.com/~hstiles/cardtype.html

;	# Returns a string containing the type of card from the list of known information below.
;	# == Known card types
;	#	*Card Type*                       *Prefix*                         *Length*
;	#	mastercard                        51-55                            16
;	#	visa                              4                                13, 16
;	#	american_express                  34, 37                           15
;	#	diners_club                       300-305, 36, 38                  14
;	#	enroute                           2014, 2149                       15
;	#	discover                          6011                             16
;	#	jcb                               3                                16
;	#	jcb                               2131, 1800                       15
;	#	bankcard                          5610, 56022[1-5]                 16
;	#	solo                              63, 6767                         16,18,19


; Determines the Credit Card type
Procedure.s CreditCardType(CardNumber.s)
  If Mid(CardNumber, 1, 1) = "4" And (Len(CardNumber) = 13 Or Len(CardNumber) = 16)
    ProcedureReturn "visa"
  ElseIf (Mid(CardNumber, 1, 1) = "3" And Len(cardNumber) = 16) Or ((Mid(CardNumber, 1, 4) = "2131" Or Mid(CardNumber, 1, 4) = "1800") And Len(CardNumber) = 15)
    ProcedureReturn "jcb"
  ElseIf Val(Mid(CardNumber, 1, 2)) >= 51 And Val(Mid(CardNumber, 1, 2)) <= 55 And Len(CardNumber) = 16
    ProcedureReturn "mastercard"
  ElseIf (Mid(CardNumber, 1, 2) = "34" Or Mid(CardNumber, 1, 2) = "37") And Len(CardNumber) = 15
    ProcedureReturn "american_express"
  ElseIf (Mid(CardNumber, 1, 2) = "36" Or Mid(CardNumber, 1, 2) = "38" Or (Val(Mid(CardNumber, 1, 3)) >= 300 And Val(Mid(CardNumber, 1, 3)) <= 305)) And Len(CardNumber) = 14
    ProcedureReturn "diners_club"
  ElseIf (Mid(CardNumber, 1, 4) = "2014" Or Mid(CardNumber, 1, 4) = "2149") And Len(CardNumber) = 15
    ProcedureReturn "enroute"
  ElseIf Mid(CardNumber, 1, 4) = "6011" And Len(CardNumber) = 16
    ProcedureReturn "discover"
  ElseIf (Mid(CardNumber, 1, 4) = "5610" Or (Val(Mid(CardNumber, 1, 6)) >= 560221 And Val(Mid(CardNumber, 1, 6)) <= 560225)) And Len(CardNumber) = 16
    ProcedureReturn "bankcard"
  ElseIf (Mid(CardNumber, 1, 2) = "63" Or Mid(CardNumber, 1, 4) = "6767") And (Len(CardNumber) = 16 Or Len(CardNumber) = 18 Or Len(CardNumber) = 19)
    ProcedureReturn "solo"
  EndIf 
  ProcedureReturn "Invalid Card Type"
EndProcedure

; Checks if the Credit Card Number is valid or not
Procedure.l ValidCreditCard(CardNumber.s)

  sum.l    = 0
  major.l  = 0
  minor.l  = 0

  If Len(CardNumber) > 0
    ; Loop through the individual digits in the number - in reverse order
    For tmp = Len(CardNumber) To 1 Step -1
      If tmp%2 = 0 ; Is this an ODD number
        sum+Val(Mid(CardNumber, tmp, 1))
      Else ; Must be an EVEN number
        minor = Val(Mid(CardNumber, tmp, 1)) * 2
        If minor > 10
          minor = minor%10
          major = 1 ; Can never be more than this
        Else
          major = 0
        EndIf
        sum+major+minor
      EndIf
    Next
    
    If sum%10 = 0
      ProcedureReturn #True
    Else
      ProcedureReturn #False
    EndIf
 
  Else
    ProcedureReturn #False
  EndIf
    
EndProcedure

Debug CreditCardType("4574602227004976")
Debug "True = " + Str(#True)
Debug "False = " + Str(#False)
Debug "Valid = " + Str(ValidCreditCard("4574602227004976"))
Debug "Valid = " + Str(ValidCreditCard(StrQ(4574602227004976)))
minirop
User
User
Posts: 24
Joined: Tue Nov 28, 2006 12:21 am

Re: Credit Card Checker

Post by minirop »

tss wrote:The only card type I didn't convert was the "switch" type. If someone knows what this regular expression is doing: ^6(3(33[0-4][0-9])|759[0-9]{2})\d{10}(\d{2,3})?$
6
***3
******33, 0 to 4, 0 to 9 // this line and
******759, 0 to 9 two times // this line are or'ed
10 digits
two, three or no digit

the *** are for the ( )
citystate
Enthusiast
Enthusiast
Posts: 638
Joined: Sun Feb 12, 2006 10:06 pm

Post by citystate »

the regular expression '^6(3(33[0-4][0-9])|759[0-9]{2})\d{10}(\d{2,3})?$' is looking for a number in these ranges:

6333000000000000 to 6333499999999999
6759000000000000 to 6759999999999999
63330000000000000 to 63334999999999999
67590000000000000 to 67599999999999999
633300000000000000 to 633349999999999999
675900000000000000 to 675999999999999999
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

Because of a bug in the original validiator I wrote my own:

Code: Select all

EnableExplicit

;Info: http://www.beachnet.com/~hstiles/cardtype.html
Procedure validCard(number$)
  Protected i,u,digit$,new$,sum
  For i=Len(number$) To 1 Step -1
    digit$ = Mid(number$,i,1)
    If u%2
      digit$ = Str(Val(digit$)*2)
      ;Debug digit$
    EndIf
    new$ = digit$+new$
    u+1
  Next
  ;Debug new$
  For i=1 To Len(new$)
    sum = sum + Val( Mid(new$,i,1))
  Next
  ;Debug sum
  If sum%10 = 0
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
EndProcedure

Debug validCard("49927398716")
I like logic, hence I dislike humans but love computers.
Post Reply