LUHN 信用卡验证在有效卡号上失败

Posted

技术标签:

【中文标题】LUHN 信用卡验证在有效卡号上失败【英文标题】:LUHN credit-card validation fails on a valid card number 【发布时间】:2014-01-20 17:56:12 【问题描述】:

在我的应用程序中,我想检查用户是否输入了我使用 LUHN 算法的有效卡号。我已将其创建为方法并在 mainactivity 中调用。但即使我提供有效的卡号,它也会显示无效。输入卡号时,我在两者之间给出了空格,我不知道,因为它没有正确验证。请帮我找出错误。

CreditcardValidation.java

public class CreditcardValidation 
    String creditcard_validation,msg;
    //String mobilepattern;
     public static boolean isValid(long number) 

            int total = sumOfDoubleEvenPlace(number) + sumOfOddPlace(number);
            if ((total % 10 == 0) && (prefixMatched(number, 1) == true) && (getSize(number)>=16 ) && (getSize(number)<=19 )) 
                return true;
             else 
                return false;
            
        

        public static int getDigit(int number) 

            if (number <= 9) 
                return number;
             else 
                int firstDigit = number % 10;
                int secondDigit = (int) (number / 10);

                return firstDigit + secondDigit;
            
        
        public static int sumOfOddPlace(long number) 
            int result = 0;

            while (number > 0) 
                result += (int) (number % 10);
                number = number / 100;
            

            return result;
        

        public static int sumOfDoubleEvenPlace(long number) 

            int result = 0;
            long temp = 0;

            while (number > 0) 
                temp = number % 100;
                result += getDigit((int) (temp / 10) * 2);
                number = number / 100;
            

            return result;
        

        public static boolean prefixMatched(long number, int d) 

            if ((getPrefix(number, d) == 5)
                    || (getPrefix(number, d) == 4)
                    || (getPrefix(number, d) == 3)) 

                if (getPrefix(number, d) == 4) 
                    System.out.println("\nVisa Card ");
                 else if (getPrefix(number, d) == 5) 
                    System.out.println("\nMaster Card ");
                 else if (getPrefix(number, d) == 3) 
                    System.out.println("\nAmerican Express Card ");
                

                return true;

             else 

                return false;

            
        

        public static int getSize(long d) 

            int count = 0;

            while (d > 0) 
                d = d / 10;

                count++;
            

            return count;

        

        public static long getPrefix(long number, int k) 

            if (getSize(number) < k) 
                return number;
             else 

                int size = (int) getSize(number);

                for (int i = 0; i < (size - k); i++) 
                    number = number / 10;
                

                return number;

            

        


        public String creditcardvalidation(String creditcard)
               
             Scanner sc = new Scanner(System.in);

              this.creditcard_validation= creditcard;
              long input = 0;
             input = sc.nextLong();
            //long input = sc.nextLong();
               if (isValid(input) == true) 
                   Log.d("Please fill all the column","valid");
                msg="Valid card number";

               
               else
                   Log.d("Please fill all the column","invalid");
                msg="Please enter the valid card number";

               

               return msg;
 
 


MainActivity.java

addcard.setOnClickListener(new OnClickListener() 
   
    @Override
    public void onClick(View v) 


            if(v.getId()==R.id.btn_add)
            
                creditcard= card_number.getText().toString();
                cv = new  CreditcardValidation();
                String mob = cv.creditcardvalidation(creditcard);
                 Toast.makeText(getActivity(), mob, 1000).show();``

【问题讨论】:

【参考方案1】:

参考下面的代码

 EditText cardNumber=(EditText)findViewById(R.id.cardNumber);
        String CreditCardType = "Unknown";

       /// Remove all spaces and dashes from the passed string
        String CardNo ="9292304336";///////cardNumber.getText().toString();           
        CardNo = CardNo.replace(" ", "");//removing empty space
             CardNo = CardNo.replace("-", "");//removing '-'
              twoDigit=Integer.parseInt(CardNo.substring(0, 2));
                                 System.out.println("----------twoDigit--"+twoDigit);
              fourDigit=Integer.parseInt(CardNo.substring(0, 4));
                                 System.out.println("----------fourDigit--"+fourDigit);
             oneDigit=Integer.parseInt(Character.toString(CardNo.charAt(0)));
                                System.out.println("----------oneDigit--"+oneDigit);

             boolean cardValidation=false;
            // 'Check that the minimum length of the string isn't <14 characters and -is- numeric
             if(CardNo.length()>=14)
             

                 cardValidation=cardValidationMethod(CardNo);

             

 boolean cardValidationMethod(String CardNo)
     
        //'Check the first two digits first,for AmericanExpress
        if(CardNo.length()==15 && (twoDigit==34 || twoDigit==37))
        return true;
        else
            //'Check the first two digits first,for MasterCard
            if(CardNo.length()==16 && twoDigit>=51 && twoDigit<=55)
                return true;
        else
            //'None of the above - so check the 'first four digits collectively
                if(CardNo.length()==16 && fourDigit==6011)//for DiscoverCard
                return true;
        else

            if(CardNo.length()==16 || CardNo.length()==13 && oneDigit==4)//for VISA
                return true;
            else
                return false;       
      

你也可以参考这个演示project

【讨论】:

【参考方案2】:

Scanner.nextLong() 将在遇到空格(或其他非数字字符)时停止阅读

例如,如果输入是1234 567 ..,那么nextLong()读取1234

但是,虽然信用卡中的空格 [可能] 会导致它无法使用上述代码进行 LUHN 验证,但我不保证删除空格会使其通过 - 我会使用更健壮的(以及-tested) 从一开始就实施。这样的代码不需要重写。

【讨论】:

修复的替代方法是什么。我必须在两者之间留出空格 @june 其他两个答案通过使用getDigitsOnly(cardNumber)(尽管未提供实现)或CardNo.replace(.., "") 解决了这个问题。您可以按照类似的方法首先对输入进行规范化 - 也就是说,在将其读取为 long 并应用 LUHN 之前,删除空格(和破折号等)。

以上是关于LUHN 信用卡验证在有效卡号上失败的主要内容,如果未能解决你的问题,请参考以下文章

当我们使用 Luhn 算法验证信用卡时,为啥要反转数字?

信用卡号码的 Luhn 或 Verhoeff 算法

是否有任何有效的信用卡号是其他有效信用卡号的初始子串?

C:信用卡号码检查器/ Luhn 算法

如何使用 Luhn 算法创建信用卡验证器?

通过卡号识别“信用卡”还是“借记卡”[重复]