Credit Cards

This page is about accepting, storing and processing credit cards.


A brief, high level overview of accepting payments on-line, with a focus on credit cards is at http://selfpromotion.com/credit.t

-- ChuckEsterbrook - 18 Mar 2002


This information comes courtesy of Jeff Johnson:

How to Store Credit Card Numbers

For starters, you'll likely store them in a SQL database. You'll want to encrypt them for safekeeping, but might also choose to store the last 4 digits as plain text so that customer service reps can tell a customer which card they used (without seeing the whole number).

You can encrypt them using either M2Crypto or the Python rotor library.


The rotor module implements an encryption algorithm used in the second world war. Beware that data encrypted with this algorithm are easily cracked!

--AlbertBrandl

Here's an interesting link about credit card handling, including the pitfalls of not retaining card information: http://www.arsdigita.com/books/panda/ecommerce#credit_cards

-- PaulBoddie - 06 Mar 2002


Here's what Jeff Johnson said:

I store them encrypted using the rotor library, I might use M2Crypto if I were to do it again but so far rotor is fine. I also store the last 4 digits as plain text so CSRs can tell the customer which card they used without seeing the whole number. Then, I store the hash so we can search the database and compare numbers without passing the actual number. Here's my code, altered a little for security reasons:

def decryptCreditCard(self,number):
 r = rotor.newrotor(???,???)
 number = binascii.a2b_hex(number)
 number = r.decrypt(number)
 number = re.sub(r"\D","",number)
 return number

def encryptCreditCard(self,number):
 number = re.sub(r"\D","",number)
 r = rotor.newrotor(???,???)
 number = r.encrypt(number)
 number = binascii.b2a_hex(number)
 return number

def creditCardShaHex(self,number):
 number = re.sub(r"\D","",number)
 return binascii.b2a_hex(sha.new(number).digest())

def creditCardFromNumber(self,number):
 number = re.sub(r"\D","",number)
 numberShaHex = self.creditCardShaHex(number)
 sql = " select creditCardID,number,expiration,numberShaHex,numberPart from CreditCard where numberShaHex = '%s' " % numberShaHex
 rs = self.recordset("DEG",sql)
 if rs:
       return rs[0]
 else:
       return None

def creditCardFromID(self,creditCardID):
 sql = " select creditCardID,number,expiration,numberShaHex,numberPart from CreditCard where creditCardID = %s " % creditCardID
 rs = self.recordset("DEG",sql)
 if rs:
       return rs[0]
 else:
       return None

def insertCreditCard(self,number,expiration):
 # Get rid of non-digits (\D).
 number = re.sub(r"\D","",number)
 expiration = re.sub(r"\D","",expiration)

 # Encrypt the number before storing it.
 numberRotor = self.encryptCreditCard(number,expiration)
 # To find a credit card in the database, get the sha hex value, then query the database.
 numberShaHex = self.creditCardShaHex(number)
 # If a customer wants to know which card they used, read the last 4 digits back to them.
 numberPart = number[-4:]

 sql = """ select nextval('CreditCardSeq') as creditCardID """
 rs = self.recordset("DEG",sql)
 creditCardID = rs[0].creditCardID

 sql = """
       insert into CreditCard
       (creditCardID,number,expiration,numberShaHex,numberPart)
       values
       (%(creditCardID)d,'%(numberRotor)s','%(expiration)s','%(numberShaHex)s','%(numberPart)s')
       """ % locals()
 rs = self.recordset("DEG",sql)
 return creditCardID

SSL

You'll need SSL for encryption. You can run Apache 1.3.x + mod_ssl and get SSL certs from a variety of companies. http://google.com/search?q=buy+ssl+certificates

You can use stunnel to talk SSL to the credit card company.

-- ChuckEsterbrook - 04 Mar 2002