views:

290

answers:

6

How do you securely pass credit card information between pages in PHP? I am building an ecommerce application and I would like to have the users to go through the checkout like this:

Enter Information -> Review -> Finalize Order

Problem is that I am not sure on how to safely pass credit information from when the user inputs them to when I process it (at the Finalize Order step). I heard using sessions is insecure, even with encryption.

Any help would be appreciated!

+3  A: 

Well, first you should be using the HTTPS protocol to ensure that the connection is encrypted.

After that, you could store the data in the $_SESSION super-global. The data is stored on your servers, so it is relatively safe.

You could do a similar technique where you insert the information into an Order database, where the key is a GUID or something else fairly random and unique. Then, when the person goes to modify/review their order, you should have the Order ID stored in the GET part of the URL (or if you're paranoid, a cookie/session variable):

 https://example.com/order?orderID=akjgflkhaslasdfkjhalsdjkljahs

To provide extra security, you could also store an IP Address in the Order Table, and make sure the IP and the Order ID match.

Chacha102
I am trying not to store the information on my server if possible
Alex
@Alex the confirm page is requested from the server. Where else are you going to store it? Client side?
Rimian
This is a violation of PCI-DSS becuase $_SESSION will write the data to the hard drive in plain text.
Rook
A: 

Not my area of expertise, but I think you want to store it in a session but also use a "synchro token" (or whatever the kids are calling it these days) to help avoid CSRF attacks.

Of course, you want to be using https (correctly), avoiding sensitive data in the URL and hidden fields, avoiding putting very sensitive information in any response at all, etc., etc.

Tom Hawtin - tackline
+6  A: 

I wouldn't store it anywhere. It's too much of a risk and probably not ethical.

Send a request to the payment gateway by posting a form over https and store the result of the transaction only.

You probably only care if the transaction was approved or declined. Who cares what the number is?

Rimian
I'm inclined to agree with the point made here that, if you're trying not to store the card information (which is not a bad idea), whatever PHP script you use to process the payment information submission form should just forward the information on to the payment gateway or wherever it needs to go. This means that the credit card information needs to be the very last thing you ask for as part of the checkout process.
David Zaslavsky
+1 , its common to review the order _before_ entering CC info. The business logic here is just backwards.
Tim Post
Actually, many sites (including amazon, newegg) have a review/confirmation page after you enter your info to make sure you put the CORRECT shipping/billing information
Alex
@alex That's right! Billing and Shipping information is confirmed but not the transaction details. From memory, Amazon will display the last 4 digits of the CC.
Rimian
+1  A: 

Don't store the credit card info in the session, don't store it to a database, don't store it to a file. Instead, write the cc info back to the review page in a hidden html inputs.

So the program flow would work like this:

  1. User posts payment and billing information to the server via an html form.
  2. Server verifies that this information is in the correct format (i.e., credit card has the appropriate number of digits, a billing address was entered, etc.)
  3. After verification the server writes back all the information submitted as hidden form input fields. This includes billing address, shipping address and credit card info.
  4. The form on the review page (with the hidden input fields) has a button labeled "Finish Order" / "Complete Order". This review form posts to the finalize order script.
  5. The finalize script stores billing/shipping info in your database and submits the credit card info to your payment gateway.

The advantages of this method are two-fold:

  1. You save the overhead and cost of additional PCI compliance that is required when storing credit info.
  2. This method stays within the security bounds of the SSL protocol. Meaning, encrypted credit card info will have to be submitted to your server in any instance - this method continues to rely solely on the efficacy of SSL, without introducing the complexities of persisting credit card data.

This last point raises another concern - by having a review page you're doubling the number of times the encrypted credit card data is being transmitted across the network. With this method there are 4 transmissions minimum: client to server, server to client, client to server (again) then server to gateway. Without review there are 2 transmissions minimum: client to server and server to gateway. Is the convenience of a review page worth the risk of extra transmissions? That's a decision you as a web developer (and your client) get to make.

pygorex1
I was thinking that, but should I do some kind of server-side encryption on the credit card information before I write them back as hidden form input fields? If so, how should I approach this method? Digtally sign it?
Alex
With this method you wouldn't be storing the cc info anywhere on the server, so you'll be able to rely on SSL encryption to transmit the cc data to/from the server.
pygorex1
A: 

I think I will have to agree. Storing creditcard numbers is too big a risk and the consequences could be far fetched.

The ideal way would be to pass the information to a third party processor and just use the result returned to mould your script logic.

if (transaction){
     // code goes here
}
else{
     // code goes here
}

Hope you get the point ... :)

Athrylith
A: 

One alternative is to use a payment profile service like Authorize.net's Customer Information Manager (there are others too). You store the payment info in a profile via their API, then use the profile ID when actually charging the card. This way you're never storing the data on your servers.

John Sheehan