Determining credit/debit card type - iphone

I'm writing a POS application for the iPhone/iPod combination, using the same exact hardware used in Apple Stores:: EasyPay.
Ok, my hurdle is this: how do I identify which credit card type is being used as text is entered in the uitextfield?
I assume I've to use textField:shouldChangeCharactersInRange:replacementString:? However, I've got ideas floating around, but I simple cannot put them together to form code :/
Any help is appreciated!

Maybe I didn't uderstand your problem, but I think you can have a BIN's list (Bank Identification Number). For example, most credit card numbers beginning with '4' are Visa. If they begin with '5', they are probably Mastercard. This is only an example, you should have a complete list to identify each possible card. Unfortunately, a complete and updated list is paid, but you can have a good list searching for free information on the Web, like here.

You can make a reasonable stab at guessing the card type from the first six digits of the card number, which is known as the Issuer Identification Number (IIN)
The trouble is, you'll struggle to get a complete list of IINs. Even the major acquirers struggle to keep an up to date list, as issuers frequently add or remove ranges.
Luckily, the card type shouldnt generally matter. You should be able to perform basic validation of the length, and luhn check digit, then submit the card to the processor for validation and authorization.

You can contact Visa/MC and sign up for the BIN list updates. Visa is free but I believe MC has a fee. Once you sign up, you will get a cd mailed to you with the current BIN ranges monthly.
You can also go through a processor or ISO (independent sales org) if you are working with one. I assume since you have a payment app you have some sort of relationship with an ISO that sets ups merchant accounts for your customers. The ISO should be able to get the BIN list for you from the processor and probably for free.

I think you are on the right track with textField:shouldChangeCharactersInRange:replacementString:, as this gets called each time the user changes the content in the text field. It sounds like you do not actually want to change the textField, but instead want to change another, related control that identifies the card type. You can use the algorithm described in Determine Credit Card Type By Number as a helper function to adjust credit card type accordingly when the user begins typing.
You may want to skip the full verification until the input string has the correct number of characters.
Update: an interesting response in the same thread mentions that actually letting the user pick credit card type is a good idea because it at least shows the user the list of credit cards you accept.

Related

PCI Compliance/PayPal API

So after MUCH research online, I'm coming to the one place I know someone will be able to help me!
We have a site that WILL accept credit card payments via PayPal's Classic API. More specifically, we'll be accepting credit cards for recurring payments. I know I have to be PCI compliant, and after speaking to PayPal today, I have been told (in writing) that:
"Once your account has processed over 20 transaction in the last 3 weeks (or 100 in a year), you will be able to register with Trustwave to become PCI compliant."
AND that I
"do not need to prove your compliance before reaching these levels"
Not sure what it is, but something doesn't sit right with me. Mainly, that I think I should be PCI compliant from the get-go. I think what they're saying is that I won't need to prove anything until then, but that I should be PCI compliant.
If anyone could give me a bit of guidance on this, it would be great. Here's a little bit more about our situation:
We will not store ANY customer card details on any system we run.
We send the details to the PayPal API by a regular old HTML POST form.
Recurring payments don't allow for a hosted solution by Paypal, so we are required to do it via our own form.
I'm sure I'm missing something here, but know that someone here will have had experience/be able to point me in the right direction!
Cheers guys!
You do indeed fall under PCI requirements immediately as a web page in your environment captures card-holder data and then transmits (the key term) it to PayPal. PCI/DSS does not have a volume threshold below which it does not apply.
Perhaps the thing that doesn't feel right is that they are happy to brush off any and all responsibility for your PCI compliancy by presenting the option of signing up with "Trustwave" whom I guess will present you with a SAQ to fill in and then take care of your quarterly scans.

Is there a secure way to guarantee credit card uniqueness?

So, like any reasonably competent web development shop, we wear cotton gloves when we touch credit cards, and we use Braintree SecureVault to store them so we are clear of PCI Compliance issues.
However now we want to offer a free trial for our service, which pretty much relies on being able to guarantee that a given credit card is only used once for a free trial. Ideally we would be able to hash the credit card number itself to guarantee uniqueness. The problem there is that set of valid credit card numbers is small, so it's going to be easy to brute force the credit card numbers. Salting tactics are useless as far as I can see, because if someone has access to the database of hashes, they will most likely have the code as well, and thus the salting algorithm.
The best two ideas so far are:
A) Keeping the hashes isolated in a set, with no relation to their billing information. Therefore if the hashes are brute-forced, all they have is a list of credit card numbers that were used at some point in time, with no personal information or knowledge of whether it's even still valid. The main weakness here is that we do have record of the last-4 which could potentially be used to match them up to some extent.
B) Hash without the full number and deal with the false positives and negatives. Hashing on name, last-4 and expiration ought to be fairly unique. False positive is like winning the lottery, we can deal with it at customer support. False negative could be induced by modifying the name, we are not clear on what assurances we have about the precision of name matching (potentially affected both by the gateway and merchant account is my understanding), so this could open a loophole.
Thoughts? Suggestions? Battle-tested Wisdom?
High-level: Use Existing Payment Systems
I think that this approach -- using credit card numbers to determine if a user already has taken advantage of a free trial and should be ineligible for a subsequent free trial -- is misguided. Firstly, you will drive away potential customers by requiring a credit card upfront (which many users don't give out unless they are actually ready to buy), instead of requiring it only after the trial period has ended.
Secondly, you are reinventing the wheel. There are a plethora of "app stores" (the Chrome webstore, the Android marketplace, the iTunes app store, etc.) which provide builtin mechanisms for payment and trial periods. Using these systems will give your product increased visiblity to consumers, will offer your potential customers multiple different payment methods (making them more inclined to buy), and will also save you the hassle of implementing this mechanism yourself. Plus, users generally prefer to give out their credit card to the least number of companies possible; not only would you have to implement this complex mechanism yourself, but you would also have to get users to trust you enough to use it.
Lower-level: Implementation Details
Any hash mechanism can have collisions, hence you would still need to deal with this problem. You should obviously use full disk encryption and other best security practices with your servers. The risk of having both the database and the salting algorithm compromised at the same time can be reduced by hosting the backend database service on a separate machine from the one that hosts this code. The main vulnerability of hashing is brute force attacks. And the best way to deal with them is to just make brute forcing expensive enough that it isn't worth the attacker's while. Using a separate salt for each entry (e.g. the customer's name, the customer's zip code, etc. as part of the salt) will make using rainbow tables ineffective. Of course making the data, itself, less valuable to attackers (e.g. not including the full credit card number) is also a good way to discourage these kinds of attacks. In any case, I again advise you to take advantage of the many app stores instead of implementing this yourself.
Forgive me if I missed something, but why can't you just have a table of "UsedCreditCards" that just has a single column, which is a SHA512 hash of the credit card number and maybe the expiration date. This could not be reversed, and by keeping it in another table and not storing any other data about the code, you could easily check to see if a credit card number has been used before.
I am not sure if this would violate PCI or anything (I don't think so, but I could be wrong)

What should I do if a user types an unrecognized city?

I'm trying to develop an easy way for users to enter addresses.
I've got a database of postal codes and cities already, so if a user enters his street address and postal code, I can (usually) retrieve the city, province, and country automatically. However, if this information is missing from my database, they'll be required to fill it in.
I'm trying to decide what this should look like. Should I just display the 2 fields (street and postal code) by default, and then after they've filled it out, use AJAX to validate the postal code, and if it's not found, make the rest of the fields appear? This has the drawback that they may be part way through the rest of the form before it appears.
I could take the opposite approach and hide the extra fields only if the postal code is found. But then they might fill out information they didn't need to by the time its validated. Or is there some middle ground?
Just trying to figure out the quickest and easiest/user-friendly way for people to enter addresses. Suggestions?
I've done this before. I had the user enter street and zip code, then they had to choose what city they were from in case there was more than one to choose from. I didn't hide any fields, but there wasn't anything to choose from until the postal code was validated via AJAX. It seemed to work quite well not hiding anything.
However, between the two options that you mentioned, I would go with the first one. That one is closest to what has worked for me.
i'd say try to implement something like predictive search which takes both, city an zip field, as search params.
for example you've typed your zip code, click (or tab) to the city field, you get a list of cities where this postal code applies.
but don't force the user to take one of the entries in the list.
with that you can auto-populate your database if the user's city isn't already in it.
that's something i'd like to have :)
Addresses are usually "value objects" meaning they are read only to an entity (such as a customer), which means you should probably let them pick out an existing address or create a new address.
That said, this also depends on your target audience. Are they good at entering addresses? For example, I always throw up a pop-up control for dates so there isn't a chance they would pick an invalid date.
You could look at how Navigation systems work. They always ask for a destination. Mine does an auto complete on the street first, then house number, then city / zip. Just look at the more popular units.
just disable the extra fields while they fill in their lookup information. You AJAX calls shouldn't be that slow. If they are then you have some serious problems to address other than this.
But you are on the right path.
I would start by having them enter just the Postal Code, and I'd probably submit the form and return two different forms depending on whether or not you have the available data in your database.
One word of warning: people can get extremely sensitive about vanity addresses. Your database probably says that 94027 is Redwood Shores, CA, but if you tell someone who thinks that he live in Atherton that he lives in Redwood City, he's going to get pissed. Sometimes, it is better not to do extra work when people are entering address information.

Do you break up addresses into street / city / state / zip?

My current app needs to store address information for a user. I'm currently debating whether to use the customary street address / city / state / zip textboxes and dropdowns or to go with Google's method of simply having everything on one line. Any thoughts on the pros/cons of storing address information in either of these manners?
You should split it up. It will make it far easier to do reporting down the road. What happens if you want to pull up all the residents of a state or zip code, or city? If you use all one field, you will be stuck and wish you had split it up.
Also, users will forget to put in all the information you need if you don't prompt them for it.
Judging by the user-input tag on your post, I assume you are referring to how the user enters the data, and now how you are storing the data in your back-end database.
Presumably your database will still need to store this information as separate fields, if you want to be able to sort and analyse the information (e.g. for reporting and statistics purposes).
In this case, I think it would depend on how confident you are that you could parse the addressing information properly into its individual fields.
One hybrid option would be to allow the user to enter the address as a single line, and then do a best-effort parsing of the information into the separate fields. This is similar to how Outlook manages addresses for contacts - you enter all of the information into a single memo field, and then it splits it up for you. You can then correct if it interpreted any of the fields wrong.
I would be very much against just having a single text field where users enter their address. You'd be surprised how many people will leave out their zip code or some other important info if you don't have a specific field for it. Also, as others have mentioned, it make reporting much easier to report on this information later if all the data is pre-parsed. As other users mentioned, programs like outlook will parse this information, but only because the source of the data is often the signatures of emails, which is something that is never in a consistent format.
I tend to split it up, allows searching to be done for a specific section of the address and you can limit the addresses you want to handle by knowing the formatting i.e. Only ship to east coast addresses.
1) You should split it.
2) May I recommend you read this before you attempt to do international address input?
I concur with Kibbee. I was even surprised to see people don't even read the field's labels, inverting first and last name, postal code and city, etc.
No, you can't determinate if a postal code is valid, in a Web application targeting international customers...
Some countries have alpha characters in postal code, various lengths, no state info, etc.
Definitely split the input. If you can help it--and depending upon your business requirements--it may be wise to perform address verification at the point of entry. This will allow you to know that your addresses are going into your database clean and allow you to do a number of other things such as fraud prevention. Having a verified address can help reduce shipping costs if you're shipping physical goods to your customers and can help reduce credit card merchant fees by ensuring the correct ZIP Code is submitted during AVS verification.
In the interest of full disclosure, I'm the founder of SmartyStreets. We offer CASS-certified address verification services. Users can upload a list for scrubbing (CSV/Excel/etc) to our website or use our address verification web service API called LiveAddress.

Limiting impact of credit card processing scripts/bots

I'm involved in building a donation form for non-profits. We recently got hit by a fast round of low dollar submissions. Many were invalid cards, but a few went through. Obviously someone wrote a script to check a bunch of card numbers for validity, possibly so they can sell them later.
Any ideas on how to prevent or limit the impact of this in the future?
We have control over all aspects of the system (code, webserver, etc). Yes the form runs over https.
When a flood of invalid transactions from a single IP address or small range of addresses is detected, block that address / network.
If a botnet is in use, this will not help. You can still detect floods of low dollar amount submissions and so deduce when you are under attack; during these times, stall low dollar amount submissions to make them take longer; introduce CAPTCHAs for low dollar amount donations; consult your bank's fraud prevention department in case they can make use of your server logs to catch the perpetrators.
Force donors to create accounts in order to make donations; protect account creation with a CAPTCHA, and rate limit donations from any one account.
Raise the minimum permissible donation to a point where it no longer makes financial sense for the scammers to use you in this way.
Instead of CAPTCHAs, which will annoy users, you might want to take advantage of the fact that most people have javascript enabled while bots don't. Simply create a small piece of javascript that when run inserts a particular value in a hidden field.
For those that have Javascript disabled you can show the CAPTCHA (use the <noscript> tag), and you can then accept a submission only if either of these measures check out.
For maximum annoyance to evildoers you could make the difference between the succeed message and the failure message computationally hard to distinguish (say everything is the same, except for one picture that displays the message) but easy to understand for humans.
limit submissions from the same IP address to one per minute, or whatever reasonable period of time it would take for a real person to fill out the form
Raising the minimum donation to a point where it no longer makes financial sense for the scammers to use you in this way will help in general.
This. How many legitimate donations do you get for under 5 bucks, anyway?