You could go a long way by not assuming the first number is correct. As it stands, somebody who typos the very first number of their Visa as a 3 instead of a 4 gets told they're entering an invalid American Express. That's brutal, from a usability stand point. If the credit card number is invalid, it's simply invalid. It's not an invalid American Express unless they explicitly choose American Express from another drop-down.
Besides that small improvement, what you ask is impossible. The mod10 checksum algorithm cannot tell you which digit is incorrect.
By way of trying to explain why, consider the following simplified scenario:
- I have 5 digits, I don't know what they are
- The sum of the 5 digits is 50
- One of the following digits is off-by-one
Which of the following digits is incorrect?
It is impossible to tell. It could be any of those digits, any one of them might be off by -1. But
that doesn't begin to describe our trouble. I told you that only one digit is wrong. In your situation, you don't know how many are wrong. One digit might be off by -2, and another image might be off by +1. There are literally an infinite number of "wrong" states. Maybe all five numbers are wrong! Maybe the correct 5 numbers are 0 0 0 0 50. This is the problem you face with mod10/Luhn validation. It is absolutely impossible to tell which number/numbers is/are incorrect.
You asked in response to another answer if there is some other algorithm to tell if an individual digit is incorrect; that doesn't make any sense. Luhn is the algorithm. like it or not. The numbers weren't generated to fit any other algorithm, and you don't get to change the algorithm after it's in use by the entire world.
As an unrelated critique, your function shouldn't be returning human-readable error messages/success messages. It is horrible practice, and leads to unmaintainable, unlocalizable apps.