Jump to content

Store CC BINs for all gateways?


vitalmyth
 Share

Recommended Posts

Hi everyone!

 

First, thank you for this wonderful cart and community, I am loving my first attempts at development for PrestaShop so far.

 

I am new to web development in general but have been making solid progress doing some customizations for fraud prevention. One of the things I always want to help merchants do is to look at the BIN of a credit card, because this can help prevent a lot of fraud. On some carts that I've developed for, it is very straightforward to get the credit card number, because it is stored in an array, e.g. $order_info['payment_info']. This is the same place it is stored during the checkout process regardless of the payment gateway.

 

However, it seems that this is not the case for PrestaShop? Is it correct that every payment gateway stores the cc info in its own unique way?

 

If possible, I would like to know how I can get the BIN information whenever a credit card is used in the store, with any payment gateway. Is it available in something that is accessible by all modules? Or do I have to do something like...

if (selected payment method == 'authorizeaim') {
$bin = substr($this->pcc->card_number, 6);
} elseif (selected payment method == 'stripe') {
$bin = substr($result_json->card->number, 6);
} elseif (selected payment method == 'othergateway') {
$bin = substr($othergateway_card_details['cc_number'], 6);
} ...

The above code is not valid, just demonstrating the process of doing something different to retrieve the BIN depending on which payment gateway is being used. Thanks for any help!

Share this post


Link to post
Share on other sites

What payment module(s) do you use? as with at least some of them, like PayPal, the whole credit card entering is all taken away from the shop itself, and taken care of my Paypal itself. There's no credit card info kept in the shop when using PayPal  (not even the login info/password of Paypal, for that matter). Never looked at other payment methods in depth, but could imagine that this is the case in more of them.

 

Do you use one, that (seemingly) keeps the credit card info on site?? Let me know which one.

 

pascal

Share this post


Link to post
Share on other sites

I'm trying to develop an module that will work for this purpose (storing and displaying BIN, among other things, in the admin backend) for ANY payment gateway that doesn't direct off-site for cc data entry.

 

Two examples:

 

AuthorizeNet accesses card data with an object called "pcc," but this object is a complete mystery to me:

$this->pcc->card_number = (string)substr($response[50], -4);

FirstData accesses it this way:

$transaction_details = Tools::jsondecode($this->_firstDataCall('{"gateway_id": "'.Configuration::get('FIRSTDATA_GATEWAY_ID').'", "password": "'.Configuration::get('FIRSTDATA_PASSWORD').'", "transaction_type": "CR", "transaction_tag": "'.(int)$transaction['transaction_tag'].'", "authorization_num": "'.Tools::safeOutput($transaction['authorization_num']).'"}'));

...

'firstdata_cc_number' => substr($transaction_details->cc_number, -4),

etc. I think there might be a common way of getting this information regardless of the gateway used, like $_POST['card_number'] or something?

 

edit: I just realized as soon as I posted that AuthorizeNet is actually using the $response array to get the card data. This array is passed to the setTransactionDetail function, but I can't find where this function is called or how $response is defined...very confused:

public function setTransactionDetail($response)
Edited by vitalmyth (see edit history)

Share this post


Link to post
Share on other sites

this could be a complete violation of PCI compliance.  Why would you want to store this information on a server that is accessible to the internet, and possibly on a shared hosting server.

 

Leave the credit information information exactly where it is meant to be kept (on the payment gateway), which already has been PCI compliance tested and secure.  The merchant just needs to deal with the fact that they have to log into their merchant account to see it.

Share this post


Link to post
Share on other sites

I assume you are trying to reference the "Truncation" requirement in 3.4.  Does this requirement you reference mention what part of the PAN you are allowed to truncate?

3.4 Render PAN unreadable anywhere it is stored (including on portable digital media, backup media, and in logs) by using any of the following approaches: One-way hashes based on strong cryptography (hash must be of the entire PAN), Truncation (hashing cannot be used to replace the truncated segment of PAN), Index tokens and pads (pads must be securely stored), Strong cryptography with associated key-management processes and procedures

It also does not address storing the information on a shared hosting environment, connected to the Internet.  You should read up on requirement 1.3

 

What exactly are you trying to accomplish, why are you trying to save this information?

 

Also, have you already looked at the order_payment database table and OrderPayment class?

Share this post


Link to post
Share on other sites

http://kencochrane.net/blog/2012/01/developers-guide-to-pci-compliant-web-applications/

https://www.owasp.org/index.php/Handling_E-Commerce_Payments

 

I see this comment everywhere in my research, that you are allowed to store up to the first 6 digits and last 4 digits of the card number, but must truncate or encrypt the rest. I have zero concern about any other digits on the card than the first 6, so I'd rather just truncate the remainder.

 

The first 6 digits (called the BIN, bank identification number) only contain information that points to the card type (Visa = first digit 4, MasterCard = first digit 5, etc) and the issuing bank. When you lookup the BIN in a BIN database (e.g. exactbins.com), you can see which country the card comes from. This is important for evaluating which orders to approve and decline, especially for merchants with a lot of international business.

 

I think the OrderPayment class is exactly what I was looking for. Thank you very much! I will update once I try to use it.

Share this post


Link to post
Share on other sites

By storing this information in a mysql database connected to the internet on a shared web host, you are putting the merchant into a PCI risk classification, and making it more difficult for them to become compliant.

 

I would suggest taking a different approach, which would be to review the BIN at submission and record a score, or store the card type and country for the merchant to review directly.

 

You also keep referencing websites that are NOT the PCI website.  They have zero merit to me unless it is PCI making the statement directly that it is acceptable.

Share this post


Link to post
Share on other sites

I would suggest taking a different approach, which would be to review the BIN at submission and record a score, or store the card type and country for the merchant to review directly.

This is a great idea, I will definitely try this approach instead. The only relevant information is the issuing country, so I'll try to get that information and just not store the BIN at all. This will also save the merchant the step of having to actually manually look up the BIN. Thank you

Share this post


Link to post
Share on other sites

Thanks again for the suggestions. So my new design is:

 

hookActionValidateOrder

// get CC number somehow, regardless of which gateway is used ***this is where I'm having my problem

$bin = substr(card_number, 6);

// send $bin to an API and get a $card_country in response

INSERT INTO vitalmyth_data (id_order, card_country) VALUES (id_order, card_country);

 

and then I also hookAdminOrder to display this country with a configured message about how it relates to the risk of the transaction.

 

I tried the OrderPayment class, and it seems that the gateways I've looked into don't use this class. When I install AuthorizeNet or Stripe in test mode, none of the columns in order_payment get any data input, they're all blank.

 

Is the info available as something like $_POST['card_number']? Or do I need to have a switch statement for whichever gateway is active, and use the proper getCardDetail() (or whatever that gateway's function is called) for each gateway (if available)?

Share this post


Link to post
Share on other sites

you assume that every payment module collects this information.  Many modules redirect off site and don't have it, many modules only deal with this information in memory, many don't store it at all, many store it in custom tables created by the module.

 

You will have to take it case by case, and solve for each payment module separately.  Certainly if the module does not make use of the OrderPayment class.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...

Important Information

Cookies ensure the smooth running of our services. Using these, you accept the use of cookies. Learn More