//////////// UPDATE! //////////////////
So I looked around on开发者_开发技巧 the net and after finding a few formulas and testing. I found a formula that works. 1. Reverse the card number 2. For every other digit double the number 3. For the digits that you didn't double, add them in the new "doubled" string 4. Add all the numbers up together - ONE BY ONE 5. Divide by ten, if there is no remainder, the card number is valid - might not be "approved" but the numbers are atleast in the correct sequence.
For example take card number "4866 3060 7833 1744"
- reverse - 4471 3387 0603 6684
- create a string with every other number starting with the 2nd number "47376364"
- now create a string with every number doubled "814617126128"
- now append a string with the digits that you did not use in step 1 to the string with the numbers doubled "41380068" (new string will be 81461712612841380068 )
- now sum the string, using EACH INDIVIDUAL character (totals 77 )
- now divide the sum (77) by 10. If there is a remainder, the card is invalid (77/10 = 7.7)INVALID CARD
Here is the source for this http://www.brainjar.com/js/validation/default2.asp
Because I love you all, and you have all helped me in so many ways, I thought Id share the code I put together to do this formula. Thanks to Mike Crandall again, who helped me reverse the first string and I took it from there.
This is using the Luhn Formula
My .h File
#import <UIKit/UIKit.h>
@interface CCValidatorViewController : UIViewController {
NSString * ccNumber;
NSString * validCard;
NSString * isAMEX;
}
@property (nonatomic, retain)NSString * ccNumber;
@property (nonatomic, retain)NSString * isAMEX;
@property (nonatomic, retain)NSString * validCard;
- (NSString *) validateCard:(NSString *)ccNumberString;
@end
My .m file
- (void)viewDidLoad {
[super viewDidLoad];
ccNumber = @"4866306078331744"; //invalid card number
ccNumber = [self validateCard:ccNumber];
NSLog(@"%@",validCard);
}
- (NSString *) validateCard:(NSString *)ccNumberString{
validCard = @"";
NSString * ccNumberReversed = @"";
NSString * doubleNumbers = @"";
NSString * everyOtherNumber = @"";
NSString * lastChar = @"";
NSString * intDoubled;
NSString * stringToSum;
NSUInteger count = [ccNumberString length];
NSUInteger len = 1;
NSRange r;
//since American Express is American Express....., we have to do something special for them.... assholes....
r = NSMakeRange( 0, 1);
lastChar = [ccNumberString substringWithRange:r];
if ([lastChar compare:@"3"] ==0) {
isAMEX = @"YES";
}
else {
isAMEX = @"NO";
}
//reverse the string
for ( int i=0; i<count; i++){
r = NSMakeRange( count-i-1, len);
lastChar = [ccNumberString substringWithRange:r];
ccNumberReversed = [ccNumberReversed stringByAppendingString:lastChar];
}
//double every other number
int loc = 1;
int ttr = ccNumberReversed.length/2;
for ( int i=0; i<ttr; i++){
r = NSMakeRange( loc, len);
loc = loc+2;
lastChar = [ccNumberReversed substringWithRange:r];
int dv = [lastChar intValue];
dv = (dv * 2);
intDoubled = [NSString stringWithFormat:@"%d",dv];
doubleNumbers = [doubleNumbers stringByAppendingString:intDoubled];
}
// get every other number starting at index 0
loc = 0;
if ([isAMEX compare:@"YES"] ==0) {
ttr = ccNumber.length/2+1;
}
else {
ttr = ccNumber.length/2;
}
for ( int i=0; i<ttr; i++){
r = NSMakeRange( loc, len);
loc = loc+2;
lastChar = [ccNumberReversed substringWithRange:r];
everyOtherNumber = [everyOtherNumber stringByAppendingString:lastChar];
}
//combine both strings so we can sum them up
stringToSum = [doubleNumbers stringByAppendingString:everyOtherNumber];
// add all the numbers up one by one and divide by 10... if no remainder - its a valid card
loc = 0;
ttr = stringToSum.length;
int stringSum = 0;
for ( int i=0; i<ttr; i++){
r = NSMakeRange( loc, len);
lastChar = [stringToSum substringWithRange:r];
int cc = [lastChar intValue];
stringSum = stringSum+cc;
loc ++;
}
if (stringSum%10 == 0) {
validCard = @"YES";
}
else {
validCard = @"NO";
}
return validCard;
}
********** Original Post *******************
Does anyone have any code they can share that will validate a credit card number before posting to API?
While im asking, are there going to be any issues from apple if I am selling tickets to a movie theater within my app?
This app is very similar to fandango but for a private chain of theaters (about 13 in all).
Thanks in advance!
I was able to answer my own question, shared it above in the "updated" area.
Here is some code that will likely work (uses the Luhn Algorithm):
-(BOOL) validateCardNumber:(NSString *)cardNumber
{
const char *str = [cardNumber UTF8String];
int n, i, alternate, sum;
n = strlen(str);
if ( n < 13 || n > 19 )
return NO;
for ( alternate = 0, sum = 0, i = n-1; i>-1; –i) {
if ( !isdigit(str[i]))
return NO;
n = str[i] – ‘0′;
if ( alternate ) {
n*=2;
if ( n > 9 )
n = ( n % 10 ) + 1;
}
alternate = !alternate;
sum += n;
}
return ( sum % 10 == 0 );
}
Credit to Donald Bellenger for this method.
If you are selling things from inside your app, it is very likely that apple will reject it unless you are using in-app sales (in which case, you shouldn't need any credit card validation).
in response to your question about in-app purchases and buying movie tickets, even if you do use in-app purchases Apple will likely reject it as you are selling real world goods and not things that can be used WITHIN the app. It says this in the Review Guidelines. Besides, you want Apple taking 30%?
-(void)validation_check:(NSString*)pass_value
{
NSMutableArray *character;
unsigned long long odd_no;
unsigned long long new_odd_no;
unsigned long long even_no;
unsigned long long new_even_no;
unsigned long long multiplied_even_no;
unsigned long long changed_even_no;
unsigned long long final_value;
unsigned long long revers_card_no;
unsigned long long card_no;
unsigned long long check_reverse;
new_odd_no = 0;
new_even_no = 0;
card_no = [pass_value longLongValue];
character = [[NSMutableArray alloc]init];
//-------reversing order of entered card number---------
for(int i = 0; i<[pass_value length];i++)
{
check_reverse =(card_no % 10);
card_no = (card_no / 10);
[character addObject:[NSString stringWithFormat:@"%qu",check_reverse]];
revers_card_no=revers_card_no*10+check_reverse;
check_reverse=card_no;
}
pass_value = [NSString stringWithFormat:@"%qu",revers_card_no];
//--------checking for even and odd numbers--------
for(int j=0;j<[character count];j++)
{
if(j % 2 == 0)
{
odd_no = [[character objectAtIndex:j]longLongValue];
new_odd_no = new_odd_no+odd_no;
}
else
{
//------doubling the value of even no's--------
even_no = [[character objectAtIndex:j]longLongValue];
multiplied_even_no=even_no*2;
NSLog(@"%qu",multiplied_even_no);
//-------if even is a single digit--------
if((multiplied_even_no % 10) == 0)
{
if(multiplied_even_no == 10)
{
new_even_no = 1+new_even_no;
}
else
{
new_even_no = multiplied_even_no + new_even_no;
}
}
//----------if there is multiple digits in even no---------
else
{
int x=(multiplied_even_no % 10);
int y=multiplied_even_no /10;
changed_even_no = x+y;
new_even_no = new_even_no + changed_even_no;
}
}
}
//--------calculating final value--------
final_value = new_even_no + new_odd_no;
NSLog(@"%qu",final_value);
if((final_value % 10) == 0)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"Card No is valid" delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil];
[alert show];
card_textField.text=nil;
}
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"Card No is not valid" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Try again" ,nil];
[alert show];
card_textField.text=nil;
}
}
精彩评论