Search code examples
iosvalidation

Validate credit card number


I am taking credit card number from user as input. I want to allow 16 numbers and want to format space after each 4 number. For that I have done following.

-(void)cardNumberValidation:(id)sender{
    UITextField *temp=sender;

    if ([temp.text length]>19) {
        txtCard.text= [temp.text substringToIndex:[temp.text length] - 1];
    }
    if ([temp.text length]==4) {
        txtCard.text=[NSString stringWithFormat:@"%@ ",temp.text];

        }
    if ([temp.text length]==9) {
        txtCard.text=[NSString stringWithFormat:@"%@ ",temp.text];
        }
    if ([temp.text length]==14) {
        NSString *lastChar = [txtCard.text substringFromIndex:[txtCard.text length] - 1];
        txtCard.text=[NSString stringWithFormat:@"%@ ",temp.text];
    }
}

But now when user will remove character after entering all then if it will reach to 15 character and then user will remove one more character then this code will add space after it and will not allow to remove it further.

Can anyone give me suggestion on this or any better way to do it.


Solution

  • Don't change the user's entered text, it will just cause confusion. Don't cause the user to think: WTF. The user entered the number in the way he understood, honor that as much as possible.

    Just sanitize what the user has entered. Generally just remove all leading, training and interspersed space characters, possibly any non-numeric characters. Then ensure the entered text is all numeric and of the correct length.

    Keep in mind that the number can have a length of 13 to 19 digits, American Express is 15 digits. See: Bank card number

    Consider the code:

    if ([temp.text length]>19) {
        txtCard.text= [temp.text substringToIndex:[temp.text length] - 1];
    }
    

    If the user entered an extra space character between groups the last digit will be deleted. It is all to easy to come up with such a scheme will avoid all possible pitfalls.
    Example: "1234 4567 9012 3456" would be truncated to "1234 4567 9012 345".

    Extra, Method to verify the check digit:

    + (BOOL)isValidCheckDigitForCardNumberString:(NSString *)cardNumberString {
        int checkSum = 0;
        uint8_t *cardDigitArray = (uint8_t *)[cardNumberString dataUsingEncoding:NSUTF8StringEncoding].bytes;
        int digitsCount = (int)cardNumberString.length;
        BOOL odd = cardNumberString.length % 2;
    
        for (int digitIndex=0; digitIndex<digitsCount; digitIndex++) {
            uint8_t cardDigit = cardDigitArray[digitIndex] - '0';
            if (digitIndex % 2 == odd) {
                cardDigit = cardDigit * 2;
                cardDigit = cardDigit / 10 + cardDigit % 10;
            }
            checkSum += cardDigit;
        }
    
        return (checkSum % 10 == 0);
    }
    
    BOOL checkDigitValid = [TestClass isValidCheckDigitForCardNumberString:@"371238839571772"];
    NSLog(@"check digit valid: %@", checkDigitMatch ? @"yes" : @"no");
    

    Output:

    check digit valid: yes