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:
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
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