選單

驗證信用卡號怎麼做?正確順序與常見錯誤

驗證信用卡號不只要算校驗位,還要處理字元、長度與前綴,順序錯了就會送出註定失敗的請求並給出誤導的錯誤訊息。本文給出一套站得住腳的檢查順序。

發佈於

  • 測試資料
  • 支付

把校驗位算對就宣稱完成了「驗證信用卡號」,是這個領域最常見的簡化。真正該做的檢查有四件事:字元是否合法、長度是否符合該卡組織、前綴是否落在已公告的號段內、校驗位是否正確。這四項的順序不是隨便排的——排錯了,使用者會拿到看不懂的提示,而系統會白白送出註定失敗的授權請求。這篇把順序、常見的實作陷阱與該補的測試案例一次講完。

驗證到底在防什麼

先釐清目的,才不會把檢查做得過頭或不足。這套檢查的功能是攔下「手誤」與「明顯錯誤的輸入」,不是判斷這張卡能不能刷。它擋得住打錯一位、少填一位、把兩張卡的號碼接在一起、貼上時混進字母的情況;它擋不住偽造,因為任何人都能算出通過檢查的號碼。

認清這個定位之後,有兩個實務結論。第一,這些檢查應該在使用者還在畫面上時就跑一次,讓他馬上修正,而不是等送出後才由伺服器退回。第二,檢查失敗時的訊息應該引導使用者「再看一次卡片」,而不是暗示系統出錯。

前後端要驗,還是只驗一邊?

「前端驗過了,後端不用再驗」是一個常見但危險的命題。前端驗證是為了體驗,在使用者還盯著畫面時就指出問題,省下一次往返;後端驗證是為了正確性,因為任何繞過瀏覽器的請求都能送出任意內容,而畸形資料一旦進了資料庫,清理成本遠高於當下多寫幾行判斷。

所以兩邊都要做,而且規則必須一致。實務上最好讓兩邊共用同一份前綴與長度定義,否則哪天某個卡組織新增號段,就會出現「前端放行、後端拒絕」這種最讓使用者困惑的組合。

一套站得住腳的檢查順序

建議照下面的順序處理,每一步只在前一步通過時才繼續:

  1. 先去除雜訊。 移除空白、連字號與其他分隔符號,也順手處理全形數字,否則從中日韓輸入法貼上的號碼會整批失敗。
  2. 再檢查字元集。 只允許數字。這一步要放在長度檢查之前,因為「含有字母」和「位數不對」是兩種不同的問題,混在一起訊息就會含糊。
  3. 然後檢查長度範圍。 先做一般性的範圍判斷,再依偵測到的卡組織檢查精確長度。
  4. 接著偵測卡組織。 比對前綴,而且要由長到短比對;結果也可能同時符合兩個組織,此時需要明確的優先順序。
  5. 最後才跑校驗和。 計算方式見 Luhn 演算法。
  6. 回報結構化的結果。 回傳的內容應該包含是否合法、偵測到的卡組織、以及失敗的原因,而不是只有一個是或否。

把校驗和放在最後還有個效率上的好處:前面幾項都是便宜的字串比對,校驗和必須走過每一位數字。先擋掉明顯錯誤的輸入,能省下大量計算,批次處理時特別有感。

前端該先做哪一項檢查?

有,而且判斷依據很單純:越便宜的檢查越前面,越能給出具體提示的檢查越前面。

字元檢查幾乎不花時間,又能立刻告訴使用者「這裡有不能出現的字元」,所以排第一。長度檢查同樣便宜,而且能指出「你少填了兩位」這種使用者可以自行修正的訊息。卡組織偵測需要比對多個前綴區間,稍貴一些,但它決定了後面要用哪一套長度規則,所以必須在校驗和之前。校驗和是最後一道,也是最貴的一道。

反過來說,如果把校驗和排在最前面,使用者貼上一串長度不對的號碼時,只會看到「卡號有誤」這種無法行動的提示,而他其實只是少複製了兩位數字。

錯誤訊息該怎麼寫

驗證失敗時的訊息品質,決定使用者能不能自己把問題解決。

失敗原因 該避免的寫法 較好的寫法
含非數字字元 卡號無效 卡號只能包含數字
位數不符 卡號無效 請確認卡號是否完整
無法辨識前綴 卡號無效 目前不支援這個卡組織
校驗失敗 系統錯誤 卡號可能有誤,請再確認一次

最後一列特別重要:校驗失敗通常代表使用者打錯字,訊息應該引導他重看一次卡片,而不是讓他以為系統壞了。另外,任何訊息與紀錄都不該包含完整號碼,需要顯示時只用遮罩後的形式——只露出前六位與後四位。

給開發者:實作時容易踩的坑

以下是反覆出現在程式碼審查裡的問題,每一項都值得對照自己的實作看一眼:

  • 不要用整數型別存整串號碼。 19 位數會超過許多語言 32 位整數的上限,而且前導零會被吃掉,位數判定就跟著錯。
  • 加倍的起點要從最右邊算。 這是最大的錯誤來源,尤其是號碼長度為奇數時。
  • 加倍後大於 9 要減 9,或等價地把兩個位數相加;兩種寫法都可以,挑一種並在註解裡說明。
  • 空字串與單一位數字要明確處理。 有些實作會讓空字串通過,因為總和是 0,而 0 能被 10 整除。
  • 清理與驗證要分開。 驗證函式不該順手修改傳入的字串,否則呼叫端會拿到意料之外的內容。
  • 限制輸入長度上限。 沒有限制的超長輸入會被送進昂貴的迴圈裡,成為一種低成本的濫用管道。

值得補上的測試案例包括:只改動一位的正確號碼、相鄰兩位對調的號碼、0 與 9 互換這種校驗和抓不到的經典例外、帶前導零的號碼、超長輸入、以及全形數字與混用分隔符號的貼上內容。這些畸形的輸入不需要真實卡片就能構造,本站的虛擬信用卡工具也能提供結構正確的一批號碼當作對照組——它們結構正確、從未發行,只適合測試,無法完成任何實際交易。

下一步

要理解卡號的三段結構與前綴範圍,讀信用卡號格式;要挑選各卡組織的測試號段,讀各卡組織測試卡號;要確認測試資料本身的合規界線,讀 PCI DSS 測試資料。

繼續閱讀

信用卡號產生器(測試用)相關文章