Try   HackMD

趁著演講者在講些五四三的時候,來補我的不務正業系列,這次來看看信用卡卡號驗證。

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
信用卡(圖片來源: shutterstock

編號規則

信用卡的編碼規則,相較之下稍微稍微複雜點。根據 ISO/IEC 7812 標準,信用卡一般在 13~19 碼,但 Mastercard 旗下似乎有 12 碼簽帳金融卡(Debit Card)。而在臺灣比較常見的長度是 16 碼,因此下面在說明多以 16 碼來說明,但不管幾碼編碼規則其實都是相同的。


長達 16 碼的信用卡卡號,其實是由 3 部分所組成的,以一張卡號為 4311-4656-0640-6131 的 Visa 信用卡為例:

發卡機構代碼 個人帳戶號碼 檢核碼
4 3 1 1 4 6 5 6 0 6 4 0 6 1 3 1

  • 發卡機構代碼(Issuer Identification Numbers,IIN)
    IIN 有時被稱為銀行識別號碼(Bank Identification Number,BIN),這是用來辨別卡片的主要資訊,由 行業標識碼(Major Industry Identifier,MII)為首所組成的 6 碼數字。

    因此可以從左起第 1 碼數字能看出發卡組織的端倪。一般來說,5 開頭是萬事達卡、4 是 Visa為、3 是美國運通與 JCB、62 是中國銀聯。不過這些編碼似乎會因為商業聯盟與組織營運,如果要查確切的對應,可能得去查查美國國家標準協會(American National Standards Institute,ANSI) 的 IIN 資料庫。

  • 帳戶號碼(Primary Account Number, PAN)
    中間位數由發卡單位自定義,一般由 6~12 碼數字所組成。其意義並沒有硬性規定,可能會包含分行之類的訊息,但也有可能只是流水號。

  • 檢核碼(Checking Number)
    顧名思義就是用檢查這組信用卡的卡號真偽的一個數字,由 Luhn 演算法計算所得出。


在找資料的時候發現,有些文章的檢查規則是照著 Luhn 演算法的生成規則一步步計算的,但我想檢查不是生成,有些動作可以適度的化簡:

  1. 設定權重
    由右到左為每個數字賦予一個權重,其中奇數位的權重是 1、偶數位的權重是 2:

    Index
    n15
    n14
    n13
    n12
    n11
    n10
    n9
    n8
    n7
    n6
    n5
    n4
    n3
    n2
    n1
    n0
    卡號 4 3 1 1 4 6 5 6 0 6 4 0 6 1 3 1
    權重 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1
  2. 乘積計算
    將卡號每碼與其對應的權重一一相乘,若乘積大於 10 則取兩位數之和。

    Index
    m15
    m14
    m13
    m12
    m11
    m10
    m9
    m8
    m7
    m6
    m5
    m4
    m3
    m2
    m1
    m0
    乘積 8 3 2 1 8 6 10 6 0 6 8 0 12 1 6 1
    取和 8 3 2 1 8 6 1 6 0 6 8 0 3 1 6 1
  3. 10的倍數
    將取和完成的數值進行加總,若總和為 10 的倍數,則為有效卡號:

    (m0+m1+m2+m3+m4+m5+m6+m7+m8+m9+m10+m11+m12+m13+m14+m15)%10=0

    將上面的例子套回計算式後:

    (1+6+1+3+0+8+6+0+6+1+6+8+1+2+3+8)%10=60%10=0

    餘數為 0,表為有效卡號。

程式碼

function verifyId(id) { id = id.replace(/-/g,"").trim(); let len = id.length; if(len<12 || len >19){ return false; } let revId = id.split("").reverse(); let checkSum = revId.reduce(function(prev, curr, idx){ curr = parseInt(curr); let w = (idx+1) % 2 == 0 ? 2: 1; let res = curr * w if(res>=10){ res = parseInt(res/10) + res%10 ; } return prev + res; }, 0); return checkSum % 10 == 0 } console.log(verifyId("4311-4656-0640-6131"));

這組程式碼能加 log 的地方也只有長度檢查的部份,所以就不再寫一版有 log 的了。是說原本想寫 Clojure,不過 Clojure 還不是很熟練,邊寫還要邊查語法,有點太花時間了,改天再來補 Clojure 的程式碼好了。

參考資料

  1. 協同撰寫。發卡行識別碼。檢自 維基百科 (2021-02-04)。
  2. 協同撰寫。ISO/IEC 7812。檢自 維基百科 (2021-02-04)。
  3. Claire (2019-01-10)。卡號與安全機制篇。檢自 愛承諾金融網 (2021-02-04)。
  4. 協同撰寫。Luhn算法。檢自 維基百科 (2021-02-04)。
  5. Roger Jang 。10-4 常用資料規則。檢自 JavaScript 程式設計與應用:用於網頁用戶端 (2021-02-04)。
  6. 支付圈 (2017-05-02)。銀行卡號編碼規則。檢自 每日頭條 (2021-02-04)。
  7. 溫子豪 (2016-08-22)。解開信用卡卡號秘密 檢查碼輕鬆算防偽卡。檢自 卡優新聞網 (2021-02-04)。

更新紀錄

最後更新日期:2021-03-07
  • 2021-03-07 發布
  • 2021-02-04 完稿
  • 2021-02-04 起稿



本文作者: 辛西亞.Cynthia
本文連結辛西亞的技能樹 / hackmd 版本
版權聲明: 部落格中所有文章,均採用 姓名標示-非商業性-相同方式分享 4.0 國際 (CC BY-NC-SA 4.0) 許可協議。轉載請標明作者、連結與出處!