stymiee

Notifying Users Their Credit Card Is About to Expire Without PCI Compliance Issues

by All Star on ‎11-30-2010 01:48 PM (13,441 Views)

According to Authorize.Net:

 

The Authorize.Net Customer Information Manager (CIM) allows merchants to create customer profiles that are stored on Authorize.Net's secure servers. By providing quick access to stored customer information, CIM is ideal for businesses that:

 

  • Process recurring transactions where the date and/or amount is different each month (e.g. utility companies).
  • Process usage charges - where you only bill when the service is used. (e.g. pay-as-you-go cell phones).
  • Are concerned with PCI compliance.
  • Want to provide returning customers with the convenience of not having to re-enter personal data.

One common piece of functionality CIM developers wish to implement is a reminder feature that notifies users that their credit card is about to expire and they should update it with their website. A common question asked by developers is, "How do I do this without having PCI compliance issues since it involves storing the expiration date on my website"? The answer is actually very simple:

 

Store the notification date instead of the expiration date!

 

PCI compliance covers the security of credit card information and is applied if a merchant chooses to store the expiration date of a customer. However, if you store the date you wish to begin notifying the customer that their credit card is about to expire you won't have to worry about PCI compliance as it doesn't cover non-credit card related information. If you use a standard period of time to begin the notifications, like one month before the card expires, determining exactly when the credit card expires is as simple as a little bit of math.

 

Example in PHP

 

    $expiration_month = (int) $_POST['exp_month'];
    $expiration_year  = (int) $_POST['exp_year'];

    $one_month_before expirarion = date("Y-m-d", strtotime($expiration_year . '-' . $expiration_month . '-01 - 1 month'));

 

This example is very simple thanks to PHP's large built in library of functions. We begin by receiving the submitted expiration month and year of the credit card. We then use PHP's built in strtotime() function to do some date math for us. We provide it with the expiration date, being sure to add the days to it so it is a valid date, and then tell the strtotime() function to subtract one month from it. We then use the date() function to convert the unix timestamp returned by strtotime() into a MySQL friendly format. Now we have the date one month before the credit card is set to expire and can store it for later retrieval, probably by a cron job, that will notify the customer that it is time to update their credit card information on file.

 

There you have it. An easy solution to a common problem!

Comments
by SamHeller on ‎11-30-2010 02:44 PM

This seems to be more of a semantic game than an actual method of assuring PCI compliance. It seems like I could use the same logic to add 10 to each four number group of a card number and store that as a "verification hash". It would be reversible, but I wouldn't technically be storing the card information. 

by All Star on ‎12-01-2010 06:45 AM

Sam, when it comes to security and PCI compliance this goes beyond semantics. In the example you provided all you're really doing is using a poor encryption method for the credit card number. Obviously that is violation of the PCI standards and a very bad idea. All we're doing in this case is using the expiration date to help us determine when the customer needs to be notified that they need to update their payment profile. We don't store the expiration date, we don't label it as the expiration date, and we don't use it to determine the expiration date for any kind of credit card processing or record keeping. This is very different then simply making a lazy form of encryption for the expiration date. If we did that and used the expiration date to process transactions or display somewwhere on the website then we'd be gaming the system which would be a violtion of PCI standards. 

by simeyla on ‎02-22-2011 09:23 PM

Sometimes I think you guys really don't get what us developers have to deal with - and end up making completely unnecessary decisions about how your APIS work as a result, causing untold unnecessary headaches.

 

Regarding whether or not expiration date can be stored here's an extract from https://www.pcisecuritystandards.org/pdfs/pci_fs_data_storage.pdf

 

Data elements:  Name, Service Code, Expiration Date

Storage Permitted: Yes

Protection Required: Yes (1)

 

(1) These data elements must be protected if stored in conjunction with the PAN.  This protection should be per PCI DSS requirements for general protection of the cardholder data environment. Additionally, other legislation (e.g., related to consumer personal data protection, privacy, identity theft, or data security) may require specific protection of this data, or proper disclosure of a company’s practices if consumerrelated personal data is being collected during the course of business. PCI DSS, however, does not apply if PANs are not stored, processed, or transmitted

 

So... what I see from this is no problem whatsoever in Authorize.NET storing expiration date and transmitting it to us. Given that CIM does NOT give us expiration dates or even card types through the API I also see no problem in me storing this information myself. Since I am not storing the PAN the PCI restrictions do not apply.

 

Right?

 

by Administrator Administrator on ‎02-24-2011 01:43 PM

Hey simeyla,

 

I would recommend contacting a QSA to determine if what you're proposing is OK in the context of your particular implementation. Authorize.Net cannot make such determinations for you as we are not a QSA and don't know all the details of your configuration. Check out this blog post for a list of PCI resources including where to find a QSA.

 

Thanks,

 

Michelle

Developer Community Manager

by simeyla on ‎02-24-2011 02:37 PM

@Michelle,

 

Appreciate your response. I just wish there was better guidance for users of CIM as to what our best practices are with respect to expiration dates and card types. If I log on as a customer and get presented with a list of my cards I expect to see last 4 digits, card type and expiration date. Anything less and I'm suspicious. Achieving this basic functionality is something I would have expected from CIM and its very frustrating that in the two years since it was released all I've ever seen is people complaining and no true guidance on how to handle the situation. Judging by the PCI PDF that I referenced - storing expiration dates + card types (whether thats the CIM or my own database) is fine unless it's stored in conjunction with the PAN. I fail to see what security risk there is in exposing this through the API.

 

If such guidance is available I would very much appreciate being pointed in the right direction,

 

-Simon

by on ‎09-05-2011 08:36 AM

Seems like a sophism to just add x amount of time to the expiration date and then claim it's a different number and therefore now safe to store. Maybe if the amount of time were random and could reach up to a year from the expiration date, but that would obviously cause functionality problems. There's simply no way to notify people without having the expiration date be exposed in your database and/or programming, and if the best you can do is obfuscate slightly, then what's the point of trying to hide it in the first place?

 

This really boils down to whether it's safe to store the expiration date separate from the credit card number or not.

by alanm123 on ‎09-03-2012 08:08 PM

AuthNet folks,

 

I agree with TJ on not saving any sensitive data.  I don't want to store the exp date on my server, even if it's obfuscated. I want the AuthNet to keep all sensitive information.  That's what I'm paying for with the CIM fee.  (Also, I can't easily save the expiration date on my server if I used the online Customer Information Manager site to enter the card.)  

 

What I would like is the ability to either:

  • read the actual expiration from the xml getCustomer..Request.  I just want to know if it's expired. I don't have the card number, so according to pciSecurityStandards it's not a problem.
  • read a flag (expired) sent with each paymentProfile.  Or expiring in the next xxx days.

But I disagree, TJ, with the wording of your statement that there's "....no way to notify people without having the expiration date be exposed in your database and/or programming..."   That's an odd statement, I think.  The thing is, my programming was exposed, if you want to call it that, just to send it to you in the first place -- I was already entrusted with all the sensitive data. It's up to me to comply with security rules about storage. If I was going to store it, I would have already!  :smileyindifferent:  (By the way, you guys have weird emoticons! :womanmad:)

 

by wiltshs on ‎04-14-2013 10:56 PM

I truly don't understand why authorize.net can't do this, but what is extra frustrating is that no one from authorize.net will even engage on the subject.  There's no discussion on how roadmap items are considered, just a black hole of "developer suggestions".  Come on guys!

by galenww on ‎12-29-2013 03:27 AM

For recurring transactions, Authorize.net can be configured from the merchant interface to send out (internal) expiration notices to an e-mail address associated with a user profile. These e-mails can, with some coding, be processed to generate expiration notices for customers. It's far from an ideal solution, given the unreliability of e-mail, the number of moving parts and the complexity beyond what should be necessary, but it works.

 

Note that these e-mails themselves don't reveal the expiration date; instead, they report that the card will expire before the next scheduled transaction. This is rather like alanm123's suggestion to expose a flag via the API that reports whether or not the CC will be expiring.

About the Author
  • Authorize.Net Developer Community Manager
Announcements
Labels