/* 采用 Luhm 校验方法计算: 1,将未带校验位的 15 位卡号从右依次编号 1 到 15,位于奇数位号上的数字乘以 2 2,将奇位乘积的个十位全部相加,再加上所有偶数位上的数字 3,将加法和加上校验位能被 10 整除。 */ function luhm($s) { $n = 0; for ($i = strlen($s); $i >= 1; $i--) { $index=$i-1; //偶数位 if ($i % 2==0) { $n += $s{$index}; } else {//奇数位 $t = $s{$index} * 2; if ($t > 9) { $t = (int)($t/10) + $t%10; } $n += $t; } } return ($n % 10) == 0; }
网上盛传一个采用Luhm校验方法对银行卡卡号进行效验的函数,据笔者测试发现,该函数只能效验16位银行卡卡号,无法效验19位的银行卡卡号,能够效验19位银行卡卡号的函数经笔者整理如下:
function luhm($bankNo) { // 奇数之和 $sumOdd = 0; // 偶数之和 $sumEven = 0; // 长度 $length = strlen($bankNo); $wei = []; for ($i = 0; $i < $length; $i++) { $wei[$i] = substr($bankNo, $length - $i - 1, 1);// 从最末一位开始提取,每一位上的数值 } for ($i = 0; $i < $length / 2; $i++) { $sumOdd += $wei[2 * $i]; if(!isset($wei[2 * $i + 1])) continue;// 如果为19位卡号,要防止报Notice: Undefined offset错误 if (($wei[2 * $i + 1] * 2) > 9) $wei[2 * $i + 1] = $wei[2 * $i + 1] * 2 - 9; else $wei[2 * $i + 1] *= 2; $sumEven += $wei[2 * $i + 1]; } if (($sumOdd + $sumEven) % 10 == 0) { return true; } else { return false; } }