1

I am adding a "confirm your payment" page to my new ASP.NET MVC 3 project. After validating the input, I then display a confirm page to allow the user to make sure they entered everything correctly. My next problem is how do I "store" the data entered so that I can process the payment after they click "Confirm". Obviously, I don't want to create hidden fields with the full credit card number.

I am using sessions for our shopping cart, but does that encrypt the data so that a credit card number could not be hacked? What is the recommended approach on this? The searches I have done on Google hasn't really turned up much.

I am display the information what they entered on the previous page (to confirm the data entry). Properly masking the credit card number of course.

Payment Information

Name on Credit Card: Name

Credit Card Number: XXXX XXXX XXXX 1111

Expiration Date: 10/2011

Card Verification Code: 100

Total to be Charged: $50.86

All numbers on this post are fake of course.

Here is the code I am using so far.

    //
    // POST: /Checkout/AddressAndPayment
    [HttpPost]
    public ActionResult AddressAndPayment(Cart cart, PaymentForm formData)
    {
        if (cart.Items.Count() == 0)
        {
            ModelState.AddModelError("", "Sorry your cart is empty!");
        }

        if (ModelState.IsValid)
        {
            var viewModel = new AddressPaymentViewModel
            {
                FormData = formData,
                Cart = cart
            };

            return View("Confirm", viewModel);
        }
        else
        {
            var viewModel = new AddressPaymentViewModel
            {
                FormData = formData,
                Cart = cart,
                States = States.GetStatesDDL(),
                CreditCardTypes = CreditCartTypes.GetCreditCardTypesDDL()
            };
            return View(viewModel);
        }
    }

    //
    // GET: /Checkout/Confirm
    public ViewResult Confirm()
    {
        return View();
    }

So from there, when I run

    //
    // POST: /Checkout/Confirm
    [HttpPost]
    public ViewResult Confirm(Cart cart, PaymentForm formData)
    {
        return View();
    }

I need to still have the form data to send to the credit card processor.

Is there a better way to do this? What is the "best practice"?

Another method I have seen is to do a "PreAuth" and "PostAuth" with the credit card processor and not store that data period, just an order id.

Community
  • 1
  • 1
Mike Wills
  • 20,959
  • 28
  • 93
  • 149
  • Best practice is to let someone who knows what they're doing deal with the payment, you bounce the user to them with the customer and order details, then get bounced back to you for the confirmation. This also saves you spending ten of thousands on ultra-secure infrastructure and auditing. – cjk Sep 28 '11 at 21:19

4 Answers4

3

After researching our options. We decided to do a Pre Authorization transaction. So all we have to store is the Order Id from the processor, then upon confirming the details, we will send a Post Authorization transaction to actually post the payment.

Mike Wills
  • 20,959
  • 28
  • 93
  • 149
0

You could store the Model into a Session Variable before loading up the confirmation page. Remember that Session Variables are not necessarily only variables, but can be an entire object.

Session["submitted_data"] = util.Encrypt(Model); //Util.Encrypt would be your custom Encryption lib

EDIT

Oops, missed the CC credentials bit.

This is a little more tricky. You can either ask for credit card credentials AFTER the order confirmation page, OR you can create a Temp_Confirmation table in your database. From there you would encrypt the CC credentials, store it in the DB until after they go past the confirmation page (store the table GUID in a hidden field), and retrieve it on the other end. Just make sure to Encrypt and Decrypt, and also delete the record once you're done with it.

Chase Florell
  • 46,378
  • 57
  • 186
  • 376
0

Don't actually show the credit card number on that page. Just show the last four digits so they can verify they are using the right credit card.

I know you probably want to display it to verify they didn't type it incorrectly. Besides the fact that few users will ever double check the entire credit card number, you can catch the majority of potential errors by validating the credit card number against the Luhn Algorithm. If the credit card number is incorrectly entered the chances of it getting past the Luhn algorithm is very, very small. Then you can request them to re-enter the card number before getting to the summary page.

John Conde
  • 217,595
  • 99
  • 455
  • 496
  • I added what I am doing now (before this post). But how do I pass this information to the next action that will actually process the payment? – Mike Wills Sep 28 '11 at 19:26
0

Conceptually you just need to "save" the information server-side for processing later. There is no reason to send this information back down to the client as hidden fields, cookies, parms, or anything else. Now, given you need to save it server-side you have a couple of options:

1) Session state - advantage, it's there now, it's cleaned up automatically, and (maybe) it's memory-only. Disadvantages, you only have one of them per session. With the advent of tabbed browsing we've found that storing anything transactional in session-state is problematic.

2) Save in DB - advantage, it's simple to save and simple to retrieve. You can retrieve it in the same session, or in another session, or even from another machine so long as you have the correct keys. Disadvantages, you're persisting the info and you need to clean it up.

I'd select option 2. Just write the info into a table and then read it back when you need it. You should of course encrypt the CC number, but that's a trivial task.

Walden Leverich
  • 4,416
  • 2
  • 21
  • 30
  • Encrypting card numbers to server side is a bad idea. Encryption is easy. Key management is not. Plus, the full weight of PCI-DSS auditing falls onto your shoulders. – PaulG Sep 29 '11 at 16:31
  • Well yes, but if you're going to store them you need to encrypt them. In some (many?) cases it would be simpler to hand the problem off to a third-party processor, but that doesn't work well as you get to larger organizations that handle the entire process themselves. – Walden Leverich Oct 27 '11 at 13:44