I'm implementing a payment solution where the cardholder enters his card details on our own website.

We need to use 3D Secure for extra authentication of the cardholder.

Our payment gateway implements it with these steps:

  1. a form is created with these parameters:
    • the merchant ID
    • the card details
    • the payment amount
  2. upon submission of this form, the user is redirected to the 3D Secure authentication page. He then typically receives a SMS with a secret code he has to enter to authenticate the payment.
  3. upon successful authentication, the user is redirected to our website, along with some parameters, one of them being an authentication ID.
  4. we then perform a server-to-server authorization of the card, with these parameters:
    • the merchant ID
    • the card details
    • the payment amount
    • the 3D Secure authentication ID received above

All good. But there is a problem.

To be PCI DSS compliant, I cannot store the card number in any way. I can just process it and discard it immediately.

But because of the implementation above, I fail to see how I can not do that.

Let's say the user enter his card details on my website. The form posts to my server, which generates the web form for 3D Secure in step 1. So I generate the form, present it to the user's browser which will post it automatically, and discard the card details.

Now the user comes back to my website from the 3D Secure page with the authentication ID. Good stuff, but I do not have the card details anymore to do the authorization, because I could not store it in the meantime.

What did I miss?

  • 1
    "To be PCI DSS compliant, I cannot store the card number in any way." - I think you're mistaken. If you store the card info, you must follow the PCI DSS rules for storage. In your case it will likely be the lower end rules since the total number of cards you have stored is minimal, if you are only storing them for a minute or so.
    – TTT
    Dec 3, 2015 at 22:19
  • Interesting, do you have a reference URL for this?
    – BenMorel
    Dec 3, 2015 at 22:26
  • Here's some info on the levels: pcicomplianceguide.org/pci-faqs-2/#5, but it looks like those are based on how many you process per year, regardless of the fact that you might only be storing a small number at one time. You may have an edge case.
    – TTT
    Dec 3, 2015 at 22:31
  • Can you use a form hosted by the card processor? I find never knowing the card details is the best way to be PCI-DSS compliant. Dec 3, 2015 at 22:39
  • This could be the winner for you: security.stackexchange.com/questions/42966/…. In short, keep your temporary storage in RAM, don't persist it to disk.
    – TTT
    Dec 3, 2015 at 22:43

4 Answers 4


Typically payment APIs fall into 3 categories:

  1. payment page hosted on the merchant side and submitted to the merchant
  2. payment page hosted on the merchant side and only card data submitted to the payment provider (typically via a JavaScript SDK)
  3. payment page hosted on the payment provider side and submitted to the payment provider, the merchant receives a notification upon successful authorization

Assuming the payment provider didn't screw something up big-time you should be completely out of PCI DSS scope by options 2 & 3.

With option 2 you are not in PCI DSS scope, you never use credit card data, but a permanent or temporary token assigned to the transaction (like e4baf901-252b-4818-b826-7f89cad884db) by the JavaScript SDK of the payment processor. Other than this, the 3ds workflow is exactly like option 1, it's just that your API requests have a pan_token and not a pan attribute. See hosted fields API on Braintree as an example https://developers.braintreepayments.com/start/hello-client/javascript/v3

With option 3 you are not in PCI DSS scope, you don't really do anything, you just redirect your client to the payment provider or open the payment provider's page in an iframe or something, here's an example of this kind of API: https://ipgtest.webteh.hr/en/documentation/form

With option 1

That's a different story, yes, you are in PCI DSS scope, yes you need to have a valid certificate, depending on the region perform PEN tests, have a secured organization and all other "bad stuff", password policies, jump host for connection, secured (and preferably segmented) network, make sure the logs show nothing, "deny all" network configs, do audits yearly etc etc etc.

If you go down this road (and I really don't understand why you should, please, don't) at least you can avoid having an HSM and worry about encryption keys etc - meaning you should not store PCI DSS data to a hard drive.

Typically the simplest solution to avoid this is to store the credit card data in memcache with an expiration policy of 1h or less (15 minutes works for all implementations I did so far). The trick is to not write it on the disk (that's why not redis in most implementations for example), but a memory store like memcache is fair game. Just make sure that the access keys are something big and secure, like an uuid (ie e4baf901-252b-4818-b826-7f89cad884db).

It was not always like this in practice...

Historically, the payment companies have been very lax about merchant PCI DSS compliance, the only practical difference between "database full of PANs" and "no PANs ever touching the system" was "how many questions your self-assessment questionnaire has" (PCI DSS SAQ for merchants).

Only in very special cases when a merchant was identified as common point of sale for stolen cards was the merchant forced, very very reluctantly and with a lot of "understanding" by the credit card companies to undergo PCI DSS lvl2/lvl1 compliance audit.

This is however changing due to a series of breaches, and at least in some regions (like SEE Europe), the payment companies are now insisting on a migration away from option 1 to all merchants that do not have a full PCI DSS compliance certificate (not just an 'X' marking exercise in a SAQ questionnaire).


Are you asking how to do 3D verification without storing the card number or if the process you described is PCI compliant?

If it's the former it's probably best to ask your payment gateway provider directly to make sure doing it correctly, or provide a link to the documentation so you can be helped in a technical way.

If it's the latter it's going to depend on your situation. What SAQ are you and what level? Or are you doing a RoC? If you're aiming for SAQ A then you're right you can't touch that PAN at all, if you're going for SAQ A-EP you may get away with holding it in the browser temporarily. If it happens on your server then it's SAQ D. In other words depends on the scope you're willing to take on.

Technically you may be able to do it with an iframe and/or ajax if you have to do a full page redirect.

  • 2
    I just read a comparison of the SAQ levels, and am shocked that processing a card number on the server side in memory, for the duration of a single request is on the same SAQ level (SAQ D) as storing a card number in your database! The security implications are very different, IMHO.
    – BenMorel
    Dec 8, 2015 at 19:14
  • If you're just starting down the PCI path better get used to it unfortunately! Unless credit card data is part of your core offering try to use full page redirects or iframes, it sucks for the user experience but it'll make your life infinitely easier. If you're a service provider you'll have to go the whole hog (SAQ D) anyway you choose to implement it.
    – Richard
    Dec 8, 2015 at 21:58

This entire situation sounds wrong.

The typical flow of a user purchase or transaction in this kind of environment would be as follows:

  • Vendor site calls a payment provider API, passing details of the transaction: vendor ID, product name and identifier, cost breakdown, customer name and address if known, and sometimes other technical information such as redirect target.
  • Payment provider API returns the URL of a payment page for this transaction.
  • Vendor displays the payment page to the user, either via redirect or in an iframe. See the Visa guidelines for more info on the compliant methods. Note that this form and its contents never reach the vendor server or infrastructure; they are directly hosted by the payment provider.
  • The form is filled out by the user, and now contains credit card details which require handling in-line with PCI DSS.
  • The form is posted to the payment provider. This data never reaches the vendor directly, because doing so would mean their infrastructure would fall under the scope of PCI DSS and would need to be directly compliant, negating the whole purpose of a 3rd party payment provider.
  • The payment provider validates the details and attempts to take the funds.
  • If the customer's bank requires 3D Secure or a similar feature, another redirect occurs for additional validation.
  • If 3D Secure verification was successful, the payment provider takes payment from the card, and holds the funds for transfer to the vendor.
  • The payment provider either:
    • in the case of a redirect method, redirects the user's browser back to the vendor's completion page along with a cryptographically signed status (commonly SAML) proving to the vendor that the payment succeeded or failed, or;
    • in the case of an iframe or similar, the vendor's outer page polls a script which queries the payment provider API, to check for completion status. Once the payment completes, a signed message is passed back to the vendor to prove that the payment succeeded or failed.
  • The status data will usually include some card data, but most critically the PAN must be masked so that it is now considered a "partial PAN" within the PCI DSS guidelines, thus rendering it outside PCI scope.
  • The vendor now displays a "thank you for purchasing" page and can log the transaction as completed.

There are variances on this procedure, but the key feature is that the PAN and CVV / CV2 (and other sensitive fields) are never actually processed or held by the vendor. The payment provider handles all of this. Even when features like "remember my card" are in use, the usual implementation involves having the full PAN stored by the payment provider, the masked PAN stored by the vendor, and a customer ID stored on both sides tying them together so that the payment provider can auto-charge the card without the vendor needing to know what the PAN is.

Another key point is the handoff to 3D Secure or similar functionality. If you are the one handing off to that page, then you are the payment provider and you are absolutely within the PCI DSS scope. Keep in mind that you absolutely can be the payment provider and the vendor at the same time (take Amazon for example).

  • That's basically what we are: payment provider and vendor, but through Paybox. They allow us to take the card details on our HTTPS website, and communicate with their authorization servers through an API. As far as I understood while on the phone with them, we are in a limited PCI DSS scope as we do not store card details, but only use them in-memory, transiently, for the duration of an HTTP request. Note that they also provide an option to host the payment pages, but it's a business choice to host the payment form and avoid redirecting the customer to an external service.
    – BenMorel
    May 3, 2016 at 23:24

There is no contradiction between the definition of PCI compliance and the function that 3D Secure provides.

Utilization of 3D Secure, a fraud prevention scheme, may be required of a merchant as a condition of the contract between a merchant and its acquiring bank. This contract allows the merchant to collect credit cards and provide them to the bank, sometimes through a payment processor, to issue charges against, the funds from which go into the merchant's bank account.

That contract also includes provisions that require the merchant to comply with all the rules- for governance, architecture, development and so forth- produced by the PCI consortium. This is what it means to be PCI compliant- to adhere, in an auditable way, to all of the rules produced by the consortium.

So, use of 3D Secure can be a component, a part, of PCI compliance.

Now, PCI rules apply to what are called "in-scope" systems. Any system that has any visibility whatsoever to card data for any length of time is subject to PCI rules, and any systems that have network visibility, for certain definitions of visibility, to those in-scope systems with card visibility are also in-scope.

PCI is like pregnancy- there is no halfway. If systems see a card, then they are in scope, and adherence to these rules is required.

PCI is also like a disease- it spreads. If systems see a card, it is in scope, and all the systems that can see the system that sees a card are also in scope.

Again, in what you are describing, there is no contradiction. Applications running on systems you control can see cards. Those systems and applications are in scope. End of story.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .