Hacker News new | past | comments | ask | show | jobs | submit login
How to Correctly Detect Credit Card Type (creditcardjs.com)
162 points by davekt on March 31, 2014 | hide | past | favorite | 65 comments



Hi, my credit card company is not listed there, yet it exists: my IIN is 6371.

I'm afraid this is not completely accurate at all. There are many credit card IINs and those are just a very few and will not work with some international cards (including international visa cards). Those numbers are issued by the American Bankers Association - in accordance to ISO 7812. They are not attached to a credit card flag, but to a company and a single company can have only one IIN. What happens is that Visa is composed of many companies in many countries, that's why they have many IINs which may or may not start with the same numbers, there are no strict rules about that.

The number this website calls 'prefix' is actually named IIN and it's composed of 6 characters, not 4 (nor 2 or 3). They are disposed in groups of 4 for a variety of reasons and no issuer owns whole lots of IINs.

The only completely correct way to detect a credit card is to just contact ABA to obtain a list of issued IINs.

This is what an issued IIN looks like, we also have many:

https://drive.google.com/file/d/0B-Sa2A0cesh4eDVMY3NwQ3ZEVlZ...

I also built a thing to help me parse those numbers (ruby):

https://github.com/eduardordm/iso7812


I can confirm this is the case, which is why services like http://www.binlist.net/ exist.


I suppose the idea is to determine the so called "card scheme" (Visa, Master, etc), not necessarily the IIN. E.g. for some payment processors, the merchant service charges are different according to the card scheme (it does't depend on the issuer). I undertand this is a simplification and it might not work for cards that don't belong to major networks, but it's good enough for a lot of businesses.

For example, if I have a business here in Japan, I doubt I could easily charge a card issued by your company (I'll be happy to be proven wrong).

Ps: brasileiro aqui.


Oi!!

The general idea is this: IIN is issued to visa branches around the world each branch can only have one IIN. Problem is, visa is not the only issuer of visa cards. Many banks and financial institutions can also issue in lieu of visa and have their own IINs as they please. My visa credit card starts with 2 because it was issued by an airline under a mileage program. I never had problem using it online but most websites won't show the correct card type.

Merchants are not charged according to a card type, the charges applied to merchants have nothing to do with visa. Visa is only doing processing service for a bank. Banks are the ones who charges merchants and pay visa a percentage of the fee the bank charges you. Because banks can't handle the volume of merchants, they usually have gateways or other companies to do that for them.

My company also issue visa cards and we use the same IIN: 6371.


Thank you for the clarification. However, my point is that some gateways do charge according to the card type.


Are you the guy with the Rails app that has something like 5000 models (one for each ATM)?


Yes, we do have around that number of tables which reflected into those thousands of models. Many of them are related to storing 'frozen' regulation data. One example: every X time we need to create something very similar to a IRS forms (electronic) and send it to a bunch of government agencies because the data sent must be available for reports we can't just store a text file. One of those regulations requires hundreds of tables:

https://www.fazenda.sp.gov.br/sped/downloads/GUIA_PRATICO_DA...

Some systems are very sensitive to transient data and pretty much needs to store all of it, depending on how you plan to use that data later it can add a good number of tables to your software.


I think you're missing the point which is just to loosely suss out the 4 or so major card brands.


Wouldn't that be an article called "How to loosely suss out the 4 or so major card brands" rather than "How to correctly detect credit card type"? [Their emphasis]


Is that someone's real data or just some example data? You don't want it to be misused / abused.


Please don't rely on this.

For example of the extra detail that is really involved, see: http://en.wikipedia.org/wiki/List_of_Issuer_Identification_N... - e.g. 504837 is ATM only despite looking like a MasterCard.

Card identification also occasionally changes - Diners was bought by MasterCard, Visa used to be 13 digits, etc.

I'd be really wary of hard-coding this anywhere. If it passes the Luhn algorithm and the first digit is ok, consider just passing it on to your processor and seeing if it gets approved. Add a black list of known-not-to-be-valid prefixes if you'd like. But a whitelist of valid prefixes will break one day without warning while also not really being the full list of valid prefixes you think it is.

If you really need to be doing this, you can pay for a regular feed from a processor, but the only use case I've ever seen for truly needing that was to identify debit cards by number.

I've had cashiers force through faked manual auths on 19 digit private bank debit cards, which I assume is fraud disguised as incompetence. But I think dealing with a few weird cases (with proper auditing in place) is better than declining a legit card because they expanded the valid prefixes and your code wasn't updated.


> Diners was bought by MasterCard

MasterCard didn't acquire Diners, it was just a partnership where Diners cards were branded as MasterCard and processed through MasterCard's network. Later Discover acquired Diners, and now they're processed through Discover's network.

But fair point - brand prefixes occasionally change, and if you hardcode them they'll eventually become out of date.


This really should be the first comment in this thread.


Another usability tip on credit card forms: Don't use drop-downs for the expiration date.

People are just typing them directly off the card, let them type them. Don't force them to deal with large and annoying select boxes. Stripe checkout[1] is a good example of how to do it (though by no means were they the first to do this, just a popular example).

1: https://stripe.com/docs/checkout


The home page of this article has a section comparing text inputs vs drop downs [1].

[1] http://creditcardjs.com/#drop-down-for-expiration


I can type right into a drop down, and 99 times out of 100 it will do the right thing.

(Sometimes it's weird with a list of states, where it might be sorted by the state abbreviation while showing the state name or vice versa.)


Unfortunately, many payment systems represent the dropdown for the months with zero-padding while others are without. Usually, typing the 0 (because it's on the card) will – if it's not included in the dropdown – not select the correct month. This can cause frustration for the end user. The best way to input credit card information, would be to only have text-fields.


agreed but on mobile I find spinning through the drop-down more annoying than typing the exp date.


I really hate the spinner for all the date selectors on iOS - it's cute, but a keypad is way faster.


Why is detecting credit cards even useful?

I know what card I have, you telling me "Yep that's a VISA card" isn't really that helpful. Yes, I might enter the first four digits wrong and see the wrong card icon light up may help me a little, but aren't I just as likely to enter the last 12 digits wrong. In the case of VISA you're pretty much just telling me "Yep, that first one is a 4".


Saving one click can increase conversions, and if you're doing any real volume even a tiny fraction of a percent can more than pay for the time involved in implementing something like that.

As to why it can't be detected and just neither asked nor shown, it's handy to show people where the CVV2 number is, and how many digits, as many people don't understand what it is even after repeated use. You'd be surprised how often I call in a food order with my Amex and have them tell me it's a 3 digit number on the back of the card. Even someone who takes CC numbers all day doesn't know that an Amex's CVV2 is a 4 digit number on the front, so you can't expect average Joe Amex user to know better.

Also it's nice to group the digits properly when I'm typing them in. So it's nice to have a form at least detect it, even for me.


Funnily enough, the form in the original post validated my credit card number as Amex and then validated a 3-digit CVV number as OK.


Some amex cards have a 3 digit cvv [1].

[1] http://ecommerce.shopify.com/c/shopify-discussion/t/heads-up...


I find it useful when they have the list of cards they take on there, and one lights up (or they are all lit up and the other 3 choices gray out). The thing that they are suggesting with showing me the text of the card seems pretty bogus to me. I know that I'm entering an AMEX or Discover; but I have no idea if the website actually takes them without having some indication of the choices before I start typing.


Wouldn't it save the user one click to select what card they've got?


I think the GP is questioning whether that piece of information is even necessary to process the transaction.


"We can't take American Express".

It's a valid thing to say, and a valid thing for you to detect and notify the user about. You know, before they finish typing everything else they have to type in.


There's no need for the user to select it. Just collect the numbers and send it off to your payment gateway. If the card type is unsupported, which would be rare for anyone using a standard gateway that supports all major cards, then display an error message.


In the UK it is quite common to not accept AMEX and other cards such as whatever 'Maestro' is. Therefore you do have to show what you do accept so people know to use a sensible-to-the-retailer card.


Maestro is huge in Germany. Many people do not have CC cards, but every singe adult has an EC / Maestro card. And we are really annoyed when they don't work abroad (though they do work with ATMs worldwide in most cases).


Maestro used to be Switch. They were popular at one time for under 18 year olds for some reason. AMEX is really seen as a premium option here in the UK, for travellers and those with rich blood.


Maestro is in effect a card network, the under 18 popularity stemmed from having a line of cards that were low transactionality, it was the first issuer in the UK to really give cards to under 18's.


There's a check digit, so calculating isValidCC should be trivial.


Why does it even matter if you show the credit card type when the user is typing it in? If the first 6 numbers determine the card type, then handling card type can be done on the backend. Why make the effort to show users information that they already know, ie. card type?


It helps to display the card type while you type because then I know that I am typing something reasonable and I know that I am not entering incorrectly. Of course, the entire card number could still be wrong which can only be validated by the server/backend processor but overall, displaying the type gives a level of "instant" comfort. It also gives users peace of mind that they system knows what they are doing. Think non technical users who don't understand the diff b/w client side vs server side validation. For them, it will be comfortable to see that the system interprets their card type which might give them more comfort. No data to back this up but just something I might think as a user.


I get your point, but to tell that a card is a VISA you just need to enter "4". I don't think it makes much of a difference really, just avoid showing in card type info and no one wonders.

It might be better to let the customer pick their card type, that you could also better inform them that you do not accept their card type.


One scenario where immediate detection is helpful is for unsupported card types. The server detection would require users first fill all their card data only to discover they need to start over.


I'd say in part because you want to give people a UX they are comfortable with. Sites for years have been asking for "Card type", and so a user may suspect something is wrong if they don't need to enter it and show no indication you know what it is.


That seems unlikely, but I've certainly been wrong about UI questions before. I'd be very curious if anyone has any data supporting this idea.


No data, but as a user I do expect to see a card type selector or indicator, even though I rationally know its superfluous.


Unfortunately I don't have actual numbers for you, but a company I used to work for that did a fair bit of CPO had good data that removing that selector reduced conversions (the most interesting thing to come out of that study was that, at the time and with our client base, removing the actual card logos (e.g. leaving only the textual names) increased conversions).


I've seen sites (can't remember which ones off the top of my head) that do autodetect your credit card type while typing it in. I wasn't phased by it.


Importance on the front-end isn't that high. Though we use it to change messaging around where the CVV is located. You do need to detect it on the backend as you have to pass it to the payment gateway, i assume the reason is to determine which network to put the transaction on. Some gateways take care of this step for you but most of older or lower level ones don't.


Maybe so that the user has something visual to show them they haven't miss typed that start of the number?


The root lesson here is pretty simple but important: you should usually avoid using regular expressions in places where readability and ease of update is a concern.

Using a complicated one line regular expression to do all the magic is fun, but its a nightmare to maintain and figure out how it works later on.


The data structure they mention using is an 'inversion map' which in their case is a mapping of numeric ranges to values.

I did some quick searching and didn't find it... I wonder how they implement a key search in the inversion map. I assume you do something like populate a tree with the range transition points and then you can search in O(log n).

A search on the tree would have to find the node with the highest value that was <= the requested value, or the lowest value that was >= the requested value.

I assume the work of constructing the tree would have to be amortized over multiple searches to make it worth the effort. Could you do better than O(n) without building a tree?

In creditcardjs.com's case, they have overlapping ranges, which means you can possibly return multiple values for a given key.


Would be nice to combine this with [skeuocard](http://kenkeiter.com/skeuocard/)


I'm using jquery-payment from Stripe. Should I switch?


You should be fine. I use it along with the technique in this blog post to make a nice stripe form that dynamically displays the card logo....

https://yoast.com/checkout-field-validation/


There's a small bug with the security code tooltip. Click the ? to open the tooltip (shows AMEX), focus the card number field, select-all (cntrl-a/cmd-a), then type "4". It still shows AMEX in the tooltip instead of visa. Closing it and opening it will still show AMEX.


Interesting to read about inversion maps. I'm a bit confused - why would I want to purchase a license vs. using something open source like https://github.com/wangjohn/creditly?


Relevant to the post.

Gizmodo (strangely) posted an interesting article on how on credit card numbers work: http://gizmodo.com/how-credit-card-numbers-work-1493331190


Visa starts its 16 digit string with "4" Mastercard starts with "5" Amex starts with "3" and only has 15 digits Discover starts with "6"



4147 20XX XXXX XXXX broke the design.


This seems hopeless all the time the prefixes actually overlap. e.g. according to this, both Laser and Maestro use 6304


I'd rather have one clean regex than dozens of lines of code to do the same thing.


I think the correct answer is: "Don't bother"



Or you could just use stripe. Just saying ;).


Does this integrate with Recurly?


$299!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


How many develop hours do you think it takes to get a full feature checkout working?

From the comments here I believe that some more work is needed for the card detection, however, to 'roll your own' with your employer paying? Could cost more than $299.

Personally I think there is a lot to be said for basic checking and having a drop-down for the card type with the accepted card types spelt out for people. Oh, and with a Paypal option for those that don't like putting their card details into random websites.


It's hardly a full feature checkout..

Correct me if I'm wrong, but it just seems like a user-friendly form with client side validation. You still need to integrate it with a payment processor, hook it into your checkout process where you capture delivery, billing and order information.

I also think it's not worth $299, especially when each license is per-website only.


Amex starts with "3" Visa starts with "4" Mastercard starts with "5" Discover starts with "6"




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: