I really dislike filling out web forms. There are some fancy tools to avoid the hassle, but it would be even better if the forms weren't so long in the first place. While thinking about payments for online downloads, I wondered what the smallest possible credit card payment form would be. I came up with:
I used PayPal's DirectPay documentation (PDF) as my guideline for what's required by a typical payment processor. I've separated the list of required fields into those for which you have to ask the customer and those that can be inferred from the customer's earlier responses.
- Ask the Customer
- Credit card number
- Street part of address
- Zip code
- Infer from the above responses
- Credit card type (inferred from CC number)
- City (inferred from zip code)
- State (inferred from zip code)
This exercise assumes that only U.S. payments are accepted, so I've left off the Country field. That could probably also be inferred from the zip code for many countries. Below are details about how to infer the bottom fields from the top ones.
Credit card type
Google Checkout was the first site that I saw implement this. Each credit card type has a unique prefix for their card numbers. The code for inferring the card type from the card number is pretty straightforward:
/* cc_num is the credit card number */
if ( cc_num.match(/^4(\d{12}|\d{15})$/) ) return 'visa';
if ( cc_num.match(/^5[1-5]\d{14}$/) ) return 'mc';
if ( cc_num.match(/^3(4|7)\d{13}$/) ) return 'amex';
if ( cc_num.match(/^6011\d{12}$/) ) return 'discover';
return 'unknown';
Once the customer is done typing his card number, you can display a credit card type logo to show that you've inferred the information.
City and State
In the common case, the city and state can be easily inferred from the zip code. Load the U.S. zip code list onto your server. Look up the customer's zip code in the list and send those on to the payment processor.
Unfortunately, some zip codes cover multiple cities. For instance, in some databases the zip code 82327 is associated with both Hanna, WY and Elmo, WY. I doubt that most credit card processors pay any attention to the exact city in the payment request. If that's right, just choose the first city in the list and submit that one.
If I'm wrong and the payment processor does care, you'll need a little more user interface. The list of zip codes with colliding cities should be fairly small. It should be trivial to include that information in a small JavaScript function. If your customer enters one of these zip codes, make an AJAX request to find out which cities are applicable and update your form on the fly to include a city selector. The customer can resolve the problem by choosing from the list of possible cities.
Optional Fields
Most credit card forms ask for the credit card expiration date and the CVV2 number. PayPal doesn't require those two fields as long as you set your security thresholds low enough. For inexpensive digital downloads, it's probably acceptable to use those lower thresholds.
In the typical case, this tiny credit card form should only require about 18 key presses plus the length of the customer's street address. Since the form is so small it could easy be launched as a CSS overlay when a customer clicks a payment link. If the payment is rejected, show a rejection message in the overlay. If it's accepted, redirect the user to the link he just paid to access.