--- title: ID驗證系列|信用卡卡號驗證 date: 2021-03-07 22:59 is_modified: false disqus: cynthiahackmd categories: - "先備知識" tags: - "編碼規則" - "Javascript" - "臺灣ID驗證系列" --- {%hackmd @CynthiaChuang/Github-Page-Theme %} <br> 趁著演講者在講些五四三的時候,來補我的不務正業系列,這次來看看信用卡卡號驗證。 <!--more--> <p class="illustration"> <img src="https://i.imgur.com/60gBFeq.jpg?1" alt="信用卡"> 信用卡(圖片來源: <a href="https://www.shutterstock.com/zh-Hant/discover/image-footage-music?kw=shutterstock&c3apidt=p15867520243&gclid=Cj0KCQiA0-6ABhDMARIsAFVdQv-8MA9Y7Q9L9uCanv_OyNtEbjV-ydbXQfXYXYP0NkXR6z705PN5MAkaAgBNEALw_wcB&gclsrc=aw.ds">shutterstock</a>) </p> ## 編號規則 信用卡的編碼規則,相較之下稍微稍微複雜點。根據 [ISO/IEC 7812 標準](https://zh.wikipedia.org/wiki/ISO/IEC_7812),信用卡一般在 **13~19** 碼,但 Mastercard 旗下似乎有 **12** 碼簽帳金融卡(Debit Card)。而在臺灣比較常見的長度是 ==16 碼==,因此下面在說明多以 16 碼來說明,但不管幾碼編碼規則其實都是相同的。 <br> 長達 16 碼的信用卡卡號,其實是由 3 部分所組成的,以一張卡號為 `4311-4656-0640-6131` 的 Visa 信用卡為例: <table> <tbody> <tr> <th colspan="6">發卡機構代碼</th> <th colspan="9">個人帳戶號碼</th> <th>檢核碼</th> </tr> <tr> <td>4</td> <td>3</td> <td>1</td> <td>1</td> <td>4</td> <td>6</td> <td>5</td> <td>6</td> <td>0</td> <td>6</td> <td>4</td> <td>0</td> <td>6</td> <td>1</td> <td>3</td> <td>1</td> </tr> </tbody> </table> <br> - **發卡機構代碼(Issuer Identification Numbers,IIN)** IIN 有時被稱為銀行識別號碼(Bank Identification Number,BIN),這是用來辨別卡片的主要資訊,由 [行業標識碼(Major Industry Identifier,MII)](https://zh.wikipedia.org/wiki/ISO/IEC_7812#%E8%A1%8C%E4%B8%9A%E6%A0%87%E8%AF%86%E7%AC%A6)為首所組成的 **6 碼**數字。 因此可以從左起第 1 碼數字能看出發卡組織的端倪。一般來說,5 開頭是萬事達卡、4 是 Visa為、3 是美國運通與 JCB、62 是中國銀聯。不過這些編碼似乎會因為商業聯盟與組織營運,如果要查確切的對應,可能得去查查[美國國家標準協會(American National Standards Institute,ANSI)](https://www.ansi.org/) 的 IIN 資料庫。 - **帳戶號碼(Primary Account Number, PAN)** 中間位數由發卡單位自定義,一般由 **6~12** 碼數字所組成。其意義並沒有硬性規定,可能會包含分行之類的訊息,但也有可能只是流水號。 - **檢核碼(Checking Number)** 顧名思義就是用檢查這組信用卡的卡號真偽的一個數字,由 [Luhn 演算法](https://zh.wikipedia.org/wiki/Luhn%E7%AE%97%E6%B3%95)計算所得出。 <br> 在找資料的時候發現,有些文章的檢查規則是照著 Luhn 演算法的生成規則一步步計算的,但我想檢查不是生成,有些動作可以適度的化簡: 1. **設定權重** 由右到左為每個數字賦予一個權重,其中奇數位的權重是 1、偶數位的權重是 2: | Index | $n_{15}$ | $n_{14}$ | $n_{13}$ | $n_{12}$ | $n_{11}$ | $n_{10}$ | $n_9$ | $n_8$ | $n_7$ | $n_6$ | $n_5$ | $n_4$ | $n_3$ | $n_2$ | $n_1$ | $n_0$ | | ----- | -------- | -------- | -------- | -------- | -------- | -------- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | | 卡號 | 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 | $m_{15}$ | $m_{14}$ | $m_{13}$ | $m_{12}$ | $m_{11}$ | $m_{10}$ | $m_9$ | $m_8$ | $m_7$ | $m_6$ | $m_5$ | $m_4$ | $m_3$ | $m_2$ | $m_1$ | $m_0$ | | ----- | -------- | -------- | -------- | -------- | -------- | -------- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | | 乘積 | 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 的倍數**,則為有效卡號: $$ (m_{0}+m_{1}+m_{2}+m_{3}+m_{4}+m_{5}+m_{6}+m_{7}+m_{8}+m_{9}+m_{10}+m_{11}+m_{12}+m_{13}+m_{14}+m_{15})\%10 = 0 $$ 將上面的例子套回計算式後: $$ \begin{aligned} &(1+6+1+3+0+8+6+0+6+1+6+8+1+2+3+8)\%10 \\ &= 60\%10\\ &= 0 \end{aligned} $$ 餘數為 0,表為有效卡號。 ## 程式碼 ```javascript= 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. 協同撰寫。[發卡行識別碼](https://zh.wikipedia.org/wiki/%E5%8F%91%E5%8D%A1%E8%A1%8C%E8%AF%86%E5%88%AB%E7%A0%81)。檢自 維基百科 (2021-02-04)。 2. 協同撰寫。[ISO/IEC 7812](https://zh.wikipedia.org/wiki/ISO/IEC_7812)。檢自 維基百科 (2021-02-04)。 3. Claire (2019-01-10)。[卡號與安全機制篇](https://ipromise.com.tw/blog/post/creditcard-bin-number)。檢自 愛承諾金融網 (2021-02-04)。 4. 協同撰寫。[Luhn算法](https://zh.wikipedia.org/wiki/Luhn%E7%AE%97%E6%B3%95)。檢自 維基百科 (2021-02-04)。 5. Roger Jang 。[10-4 常用資料規則](http://mirlab.org/jang/books/javascript/dataRule.asp?title=10-4%20%B1%60%A5%CE%B8%EA%AE%C6%B3W%ABh)。檢自 JavaScript 程式設計與應用:用於網頁用戶端 (2021-02-04)。 6. 支付圈 (2017-05-02)。[銀行卡號編碼規則](https://kknews.cc/finance/85jp284.html)。檢自 每日頭條 (2021-02-04)。 7. 溫子豪 (2016-08-22)。[解開信用卡卡號秘密 檢查碼輕鬆算防偽卡](https://www.cardu.com.tw/news/detail.php?nt_pk=4&ns_pk=30424)。檢自 卡優新聞網 (2021-02-04)。 ## 更新紀錄 :::spoiler 最後更新日期:2021-03-07 - 2021-03-07 發布 - 2021-02-04 完稿 - 2021-02-04 起稿 ::: <br><br> > **本文作者**: 辛西亞.Cynthia > **本文連結**: [辛西亞的技能樹](https://cynthiachuang.github.io/Check-Credit-Card/) / [hackmd 版本](https://hackmd.io/@CynthiaChuang/Check-Credit-Card) > **版權聲明**: 部落格中所有文章,均採用 [姓名標示-非商業性-相同方式分享 4.0 國際](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en) (CC BY-NC-SA 4.0) 許可協議。轉載請標明作者、連結與出處!
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.