js实现Luhn算法(模10算法、校验银行卡)

3,426 阅读3分钟

Luhn算法

Luhn算法(Luhn algorithm),也称为“模10”(Mod 10)算法,是一种简单的校验和算法,一般用于验证身份识别码,例如发卡行识别码、国际移动设备辨识码(IMEI),美国国家提供商标识号码,或是加拿大社会保险号码。该算法由IBM科学家Hans Peter Luhn创造,专利于1954年1月6日申请,1960年8月23日颁证,美国专利号2950048。

该算法现已属于公有领域并得到了广泛的应用,例如ISO/IEC 7812-1。它不是一种安全的加密哈希函数,设计它的目的只是防止意外出错而不是恶意攻击

描述

Luhn算法会通过校验码对一串数字进行验证,校验码通常会被加到这串数字的末尾处,从而得到一个完整的身份识别码。

我们以数字“7992739871”为例,计算其校验位:

  1. 从校验位开始,从右往左,偶数位乘2(例如,1*2=2),如果乘积为两位数,则然后将两位数字的个位十位相加(例如,16:1+6=7,18:1+8=9);
  2. 把得到的数字加在一起(本例中得到67);
  3. 将数字的和取模10(本例中得到7),再用10去减(本例中得到3),得到校验位。
原始数字7992739871x
偶数位乘2718947691672x
将数字相加7994769772x 

实现

通过上面的描述可以知道,实现Luhn算法步骤:

  • 1、从右到左给卡号字符串编号,最右边第一位是1,最右边第二位是2,最右边第三位是3
  • 2、从右向左遍历,对每一位字符t执行第三个步骤,并将每一位的计算结果相加得到一个数s
  • 3、对每一位的计算规则:如果这一位是奇数位,则返回t本身,如果是偶数位,则先将t乘以2得到一个数n,如果n是一位数(小于10),直接返回n,否则将n个位数十位数相加返回
  • 4、如果s能够整除10,则此号码有效,否则号码无效

js实现

function testPaycard(payCard) {
    // 非数字
    if (!/(^\d{16}$)|(^\d{19}$)/.test(payCard)) {
        return false
    }
    const everyNum = String(payCard).split(''); // 将银行卡的所有数字拆分
    everyNum.forEach((num, index) => {
        if (index % 2 === 0) { // 从右往左  偶数位
            num = Number(num).toString(2) + '0'; // 转换为二进制,并将二进制左移一位
            num = parseInt(num, 2); // 转回十进制
            num = (num / 10 | 0) + num % 10; // 当前数字每位的和
            everyNum[index] = num; 
        }
    });
    // 统计总和 % 10是否整除
    return everyNum.reduce((tol, num) => tol + parseInt(num), 0) % 10 === 0; 
}

验证

testPaycard(6226094425653290)
// true
testPaycard(6226097143099498)
// true
testPaycard(6226094043514957)
// true

ps: 你们可以用自己的银行卡试试,但是有些特殊的银行不是用这种算法。

参考链接: baike.baidu.com/item/Luhn%E…