
When you first encounter credit card processing APIs, the array of options and data values can be daunting. It can be challenging to know what is important and what is just noise. Luckily, I’ve had some experience with multiple payment processors and I’ve learned what you need to store, what you can safely discard, and what you absolutely must discard.
Keep API Requests
As time passes, you are probably going to get some weird responses from the credit card processor. There are a million and one ways for credit card transactions to fail, from mistyped zip codes, to wrong expiration dates, to overseas cards with strange address verification rules. It’s pretty much impossible to predict ahead of time what failure scenarios you will see, and every processor is different. My advice is to just expect failures and be ready to troubleshoot them when they arise.
Once you’re in production and seeing some of these failures, it’s nice to be able to inspect the request and response with the processor’s API. So, at the bare minimum, you should be logging what you send and receive. But, if you want to take it a step further, create a separate model to represent API interactions.
With most processing APIs, they can POST updates about a transaction back to your server. Instead of just logging and then processing them, store the raw postbacks in their own table and link each one back to the order or transaction you’re already storing in your database. That way, when something strange happens, you can easily inspect the chain of events for a particular transaction. This is much, much easier than trying to match up timestamps in a log file and recreate the event chain that way.
Keep Extra User Data
Often when dealing with an external API, requests will return all kinds of extra information that you don’t really need. Credit card processing is no different. However, be extra careful before discarding any of that information, and keep way more than you think you’ll need, especially if it’s just a case of adding a few more columns to a database table.
For example, the processor may return a name and email to you of the buyer. If you already have a User model in your application, why keep this data? It’s just redundant, right? Wrong. Often the name and email someone uses to sign up for a website is completely different than what they use for a credit card purchase.
Ultimately, the goal here is to minimize confusion when dealing with support requests. I have found that a majority of charge inquiries take the form of, “Why did you charge my card?” No additional information, no reference to the user account, credit card used, or anything like that. Sometimes they’ll sign it with a name, and most likely your ticket system captures an email address.
At this point, it would be nice to be able to answer their question without peppering them with additional questions. The more info you store, the more avenues you can use to retrieve their account. Believe me, the 1000th email you write asking, “Can you please tell me the email you used when you signed up?” is pretty boring. And before you comment, just adding instructions to your ticket submit form won’t help. People don’t read that stuff. They just dash off a quick question and expect you to know exactly who they are.
For reference, here’s a quick list of things you should store, even if you don’t think you’ll ever need it:
- Buyer’s name
- Buyer’s email
- Payment processor’s customer id
- Payment processor’s transaction id
- Card type (Visa, Mastercard, etc.)
- Last 4 digits of the card
- Card expiration date
- Payment processor’s card id
Don’t Even Touch Sensitive Data
One major exception to the previous section is PCI compliance. Keep nothing that brings you into the sphere of PCI compliance, such as the entire card number or the security code on the back. Hopefully it’s well known by now, but you should always keep that information at arms length from your database. For example, Stripe’s javascript library is designed in order to prevent sensitive information from ever being sent to your server. That’s the best policy: avoid touching the card number at all.
Regardless of what processor you use, you should architect your application to avoid storing any PCI-level details of the card. The last 4 digits and expiration date are fine, but if you’re storing (or even touching) the entire number, you’re asking for trouble.
If you follow this advice and everything goes smoothly, you’ll never need to look at most of the data you’re storing. However, the first time you get an irate customer or a crazy transaction failure you’ll be glad you went the extra mile to store and catalog the transaction details.