舊香港身份證校驗

蕭風發表於2019-09-24

背景:前一陣子遇到了【舊】香港的身份證校驗的問題,分享出來,希望能幫助需要的人

一、校驗身份證

IdVerify::verifyHKIdCard($number)

二、檢驗身份證演算法

namespace App\Services;
class IdVerify
{
    //香港身份證首字母對應的數字
    private static $capitalNum = array(
        'A'=>10,
        'B'=>11,
        'C'=>12,
        'D'=>13,
        'E'=>14,
        'F'=>15,
        'G'=>16,
        'H'=>17,
        'I'=>18,
        'J'=>19,
        'K'=>20,
        'L'=>21,
        'M'=>22,
        'N'=>23,
        'O'=>24,
        'P'=>25,
        'Q'=>26,
        'R'=>27,
        'S'=>28,
        'T'=>29,
        'U'=>30,
        'V'=>31,
        'W'=>32,
        'X'=>33,
        'Y'=>34,
        'Z'=>35,
        ' '=>36,
    );

    /**
     *  香港身份證驗證
     * @param $number
     * @return bool
     */
  public static function verifyHKIdCard($number)
    {
        //將中文括號全部替換成英文括號
        if (strpos($number, "(") || strpos($number, ")")) {
            $number = str_replace('(', '(', $number);
            $number = str_replace(')', ')', $number);
        }

        $number_num = strlen($number);

        if (!in_array($number_num, array(10, 11))) {
            return false;
        }

        $first_num = substr($number, 0, 1);//取首字母
        $number_num == 10 && $number = ' ' . $number;
        $checkCode = substr($number, -2, 1);//取括號內的校驗碼

        if ((!preg_match('/^[A-Z]+$/', $first_num)) || !is_numeric(substr($number, 2, 6))) {
            return false;
        }

        $number_ex = explode('(', $number);
        $number_arr = str_split($number_ex[0]);

        $number_sum = 0;
        $i = 9;
        foreach ($number_arr as $k => $v) {
            if (isset(static::$capitalNum[$v]) || is_numeric($v)) {
                if (isset(static::$capitalNum[$v])) {
                    $number_total = (static::$capitalNum[$v] % 11) * $i % 11;
                } else {
                    $number_total = $v * $i % 11;
                }

                $i -= 1;
                $number_sum += $number_total;
            }

        }
        $result = $number_sum % 11;

        switch ($result) {
            case 1:
                $result = 'A';
                break;
            case 0:
                $result = 0;
                break;
            default:
                $result = 11 - $result;
                break;
        }

        if ($checkCode == $result) {
            return true;
        } else {
            return false;
        }
    }
}

相關文章