在一般消費平台會需要刷卡,並要填入信用卡單,再填寫第一欄的時候會發現卡片會自己辨識是屬於哪類的信用卡,有 Master Card,VISA,JCB,美國運通卡號只有 15 碼,不再這次驗證範圍。這次剛好在課程中學到信用卡驗證器,就來依照條件實作看看吧!
信用卡號產生器
可自行輸入信用卡 16 碼,或是用產生器。
信用卡驗證流程
- 從左邊算起來的第一個數字為發卡行,Master Card 是 5 開頭,Visa 是 4,JCB 則是 3。
- 前 15 位數經過加權後加總,會得出一個數字,先把這數字除以 10 取餘數,如果結果是 0,那檢查碼就是 0,否則就是用 10 減去之後的結果。
- 權重的部分你可以這樣記:
- 左邊數起奇數位是
*2
。 - 偶數位是
*1
。 - 若是在計算的過程中某一位數加權後的結果比 10 大,那請減去 9。
舉例來說,5412-3456-7890-1232 這個卡號的第一位是 5,代表這是 MasterCard 的卡。
- 左邊數起奇數位是
奇數位加總
- 奇數位加總為:
5*2
+1*2
+3*2
+5*2
+7*2
+9*2
+1*2
+3*2
,原本應該是:10 + 2 + 6 + 10 + 14 + 18 + 2 + 6。 - 前面有說過「如果比 10 大,請減去 9」,所以就是 1(10-9) + 2 + 6 + 1(10-9) + 5(14-9) + 9(18-9) + 2 + 6 = 32。
偶數位加總
- 偶數位加總為:4 + 2 + 4 + 6 + 8 + 0 + 2 = 26,乘以 1 之後還是 26。
第 16 碼檢查碼,不用算進偶數列。
卡片是否可用
把 32 跟 26 相加,得到 58,58 % 10 = 8
,因此檢查碼就是 10-8 = 2
,而卡號的第 16 碼也是 2,因此這個卡號是沒有問題的。
任務需求
輸入信用卡號
輸入為一個信用卡卡號,皆為 16 碼,每 4 碼以 -
做為分隔。
EX. 5412-3456-7890-1232
輸出
若是信用卡不合法,請輸出 INVALID,合法則輸出信用卡的發卡行,只會有 VISA 與 MASTER CARD 兩種結果。
實作信用卡驗證架構
所使用的卡號為 5412-3456-7890-1232
首先,觀察到信用卡號中間的 dash 符號,在計算時是不需要出現的。
所以可以先給一個變數存卡片號碼,並使用 replace 方法把 dash 的內容拿掉,這樣之後才能加總。
1 | let cardNum = "5412-3456-7890-1232"; |
奇偶數加總、取出奇偶數
1 | //奇偶數相加 |
加權後的數字
題目有提到,前 15 位數經過加權後加總,會得出一個數字,先把這數字除以 10 取餘數,如果結果是 0,那檢查碼就是 0,否則就是用 10 減去之後的結果,這一段文字可以先改成步驟來寫。
resultNum = sum % 10;
- 如果
resultNum = 0;
檢查碼 = resultNum;
- 否則就是
resultNum = 10-resultNum;
可是步驟這樣寫有點難變成虛擬碼,可以換個角度來想,
resultNum = sum % 10;
- 如果
resultNum !=0;
- 是
resultNum = 10-resultNum;
這樣就可以試著改成程式碼,
1 | let resultNum = sum % 10; |
判斷驗證是否成功架構
- 第 16 碼是檢查碼,如果與檢查碼不符,就是 INVALID。
- 如果第一碼是 5 就是 MASTER CARD,不然就是 VISA,為什麼沒有 JCB,因為這次任務只需要這兩種卡片。
1 | if (resultNum !== newCardNum[15] * 1) { |
目前 console 出來的結果會是 INVALID,因為還沒奇偶數的運算。
截至目前為止的架構已經寫好,不明確的地方都用函式填空法完成,完整程式碼如下:
1 | let cardNum = "5412-3456-7890-1232"; |
if (resultNum !== newCardNum[15] * 1)
跟if (resultNum !== Number(newCardNum[15]) )
都是把字串轉成數字的方式。
奇偶數列運算實作
目前得到的卡號: 5412345678901232
。
先做簡單的偶數列
- 因為偶數位比較單純,所以先來做偶數位,觀察數列,偶數位從第 1 個開始。(程式式從第 0 位開始)。
- 看到要取順序,就要想到用 for 迴圈,並且偶數最末位為第 14 個,數列為第 13 個。
- 因為要跳兩位取得數字,故要 i+=2。
1 | function evenNum(newCardNum) { |
步驟說明:
- 先設定偶數數列總數 sum 起始為 0。
- 並且數列長度小於等於 13 個數列,並透過 i+=2 取得偶數列的數字。
- sum 會依序跑 newCardNum 的每個數字,跑到偶數列就存到 sum 的變數中。
- 確認 console 結果為預期。
- 回傳到 sum。
奇數列加總實作
- 與偶數列方法雷同,所以把偶數函式中的方法先複製到奇數列的函式內。
- 奇數列從第 0 個開始,最後一碼是第 15 個。
1 | function oddNum(newCardNum) { |
- 題目有提到奇數列有加權重(數字*2),大於 10 的話要減 9,這邊的程式碼要加上運算。
- 把運算結果回傳給 sum。
1 | function oddNum(newCardNum) { |
驗證一下 sum 的結果
驗證結果如下,是如預期的結果。
1 | let sum = evenNum(newCardNum) + oddNum(newCardNum); |
最終答案會是 MASTER CARD。
完整程式碼與 Demo
DEMO: https://codepen.io/hnzxewqw/pen/LYbVjpN?editors=1111
1 | let cardNum = "5412-3456-7890-1232"; |
小結
- 先把需求架構寫出來,不要急著寫答案。
- 利用函式填空法專注於程式邏輯的編寫。
- 透過
console.log
把不確定的地方都印出來檢查是否與預期的相同。