怎样判断一张银行卡是信用卡

x33g5p2x  于2021-11-11 转载在 其他  
字(4.4k)|赞(0)|评价(0)|浏览(248)

一 需求

财务软件中经常会判断一张银行卡是否是信用卡,这是一个比较普遍的需求。

二 算法1——这个算法是校验信用卡是否合法,不是用来判断一个银行卡是不是信用卡

算法来源:Java实现信用卡校验_南 墙-CSDN博客

当你输入信用卡号码的时候,有没有担心输错了而造成损失呢?其实可以不必这么担心,因为并不是一个随便的信用卡号码都是合法的,它必须通过 Luhn 算法来验证通过。

该校验的过程:

1 从卡号最后一位数字开始,逆向将奇数位(1、3、5等等)相加。

2 从卡号最后一位数字开始,逆向将偶数位数字,先乘以2(如果乘积为两位数,则将其减去9),再求和。

3 将奇数位总和加上偶数位总和,结果应该可以被10整除。

示例

卡号是:5432123456788881

逆向奇数位为 4 2 2 4 6 8 8 1 和 = 35

逆向偶数位乘以2(有些要减去9)的结果:1 6 2 6 1 5 7 7,求和 = 35。

最后 35 + 35 = 70 可以被10整除,认定校验通过。

三 算法2——这个算法也是校验信用卡是否合法,不是用来判断一个银行卡是不是信用卡

算法来源:第六章第三十一题(金融应用:信用卡号的合法性验证)(Financial: credit card number validation) - 编程练习题答案_putongdeyang-CSDN博客

四 实现

package CreditCard;

import java.util.ArrayList;
import java.util.List;

/**
* @className: CreditCard
* @description: 信用卡博客参考
* https://ccdcapi.alipay.com/validateAndCacheCardInfo.json?_input_charset=utf-8&cardBinCheck=true&cardNo=6259553770002775
* https://www.cnblogs.com/ygw1010/p/9448374.html
* https://blog.csdn.net/putongdeyang/article/details/106242021
* @date: 2021/10/30
* @author: cakin
*/
public class CreditCard {
    public static void main(String[] args) {
        List<String> list = new ArrayList();
        list.add("356XXXXX2780");
        list.add("6228XXX5012");
        list.add("62170XXXX999690147");
        list.add("62XXXXXXXXX651");
        list.add("6XXXXX002775");
        // 该算法不对
        System.out.println("-----------------------算法1------------------------");
        checkCreditCardWrong(list);

        // https://blog.csdn.net/putongdeyang/article/details/106242021
        List<Long> list1 = new ArrayList();
        System.out.println("-----------------------算法2------------------------");
        list1.add(35682XX27232780L);
        list1.add(6228XX0210783865012L);
        list1.add(621XX4229999690147L);
        list1.add(621XX63800289732L);
        list1.add(6226XX011176880L);
        list1.add(6217XX100020631719L);
        list1.add(622XX3878253741579L);
        list1.add(62XX67000008674794L);
        list1.add(6XX4850290872651L);
        list1.add(6259XX3770002775L);
        checkCreditCardRight(list1);
    }

    private static void checkCreditCardRight(List<Long> list) {
        list.stream().forEach(number ->{
            if (isVa1id(number) && divide(number))
                System.out.println(number + "是信用卡");
            else
                System.out.println(number + "不是信用卡");
        });
    }
    
    // Step 0
    public static boolean isVa1id(long number) {
        if (prefixMatched(number,4) || prefixMatched(number,5) ||
                prefixMatched(number,37) || prefixMatched(number,6)) {
            return (number + "").length() >= 13 && (number + "").length() <= 16;
        }
        else
            return false;
    }

    // Get the result from Step 2
    public static int getEven(long number) {
        int getEven = 0;
        for (int i = 0; i < (number+"").length(); i+=2) {
            char n = (number + "").charAt(i);
            int num = Integer.parseInt(Character.toString(n));
            if (num * 2 > 9)
                num = (num * 2 / 10) + (num * 2 % 10);
            else if (num * 2 < 10)
                num = num * 2;
            getEven += num;
        }
        return getEven;
    }

    // Get the result from Step 3
    public static int getOdd(long number) {
        int getOdd = 0;
        for (int i = 1; i < (number+"").length(); i+=2) {
            char n = (number + "").charAt(i);
            int num = Integer.parseInt(Character.toString(n));
            getOdd += num;
        }
        return getOdd;
    }

    // Return sum
    public static int sumOfOddAndEven(long number) {
        return getEven(number) + getOdd(number);
    }

    // Return true if the digit d is a prefix for number
    public static boolean prefixMatched(long number, int d) {
        String strNumber = number + "";
        int charNumber0 = Integer.parseInt(strNumber.substring(0,(d+"").length()));
        return charNumber0 == d;
    }

    public static boolean divide(long d) {
        return sumOfOddAndEven(d) % 10 == 0;
    }

    private static void checkCreditCardWrong(List<String> list) {
        list.stream().forEach(item -> {
            int sum1 = 0, sum2 = 0;
            for (int i = item.length() - 1, j = 1; i >= 0; i--, j++) {
                if (j % 2 == 1)
                    sum1 = sum1 + (item.charAt(i) - '0');
                else {
                    int temp = (item.charAt(i) - '0') * 2;
                    if (temp >= 10)
                        temp = temp - 9;
                    sum2 = sum2 + temp;
                }
            }
            if ((sum1 + sum2) % 10 == 0)
                System.out.println(item + "是信用卡");
            else
                System.out.println(item + "不是信用卡");
        });
    }
}

注:银行卡属于敏感信息,进行了简单脱敏处理。

五 测试结果

-----------------------算法1------------------------
XXXXXXXXXXXX是信用卡
XXXXXXXXXXXX5012是信用卡
XXXXXXXXXXXX0147是信用卡
XXXXXXXXXXXX2651是信用卡
XXXXXXXXXXXX2775是信用卡
-----------------------算法2------------------------
XXXXXXXXXXXX780不是信用卡
XXXXXXXXXXXX3865012不是信用卡
XXXXXXXXXXXX90147不是信用卡
XXXXXXXXXXXX9732是信用卡
XXXXXXXXXXXX6880是信用卡
XXXXXXXXXXXX631719不是信用卡
XXXXXXXXXXXX41579不是信用卡
XXXXXXXXXXXX8674794不是信用卡
XXXXXXXXXXXX72651是信用卡
XXXXXXXXXXXX02775是信用卡

注:银行卡属于敏感信息,进行了简单脱敏处理。

六 结论

这两个算法得出的结论不一致,不能判断一张银行卡是否是信用卡,实际卡的类型也和上面两种算法得出的结论不一致。

如果真的想判断一张卡的类型是否是信用卡,想通过在网上搜索一个比较好的算法,似乎不太靠谱,因为中国有中国的算法,国外有国外的算法。各银行有各银行的算法,不是一个简单的算法就能兼容所有场景。

比较靠谱的有两种方案:

1 对接中国银联,它的兼容性应该是最强的,也是万能的。

2 对接上游API支付接口,看上游API支付接口是否提供了查询银行卡类型的API,如果有就万幸了,如果没有,看对接方能否提供,如果不能提供,就只有采用方案1了。

相关文章