原文
不小心在推特上瀏覽到一個文章,很好的詮釋了什么是swifty的swift代碼瓷马。
如何檢測一個信用卡類型呢叭喜,參數(shù)如下表格所示(主要的4個,還有各種亂七八糟的)
Issuing Network | IIN ranges | Card Number Length |
---|---|---|
American Express | 34, 37 | 15 |
MasterCard | 51–55,2221–2720 | 16 |
Visa | 4 | 13, 16, 19 |
Discover | 65,6011,644–649,622126–622925 | 16, 19 |
Option 1: if大法
先來試試最粗暴的算法:
如果是4開頭就是visa靖榕,如果是3開頭則可能是Amex, Diners, or JCB标锄,如果是6開頭則可能是Discover
這里有段現(xiàn)成的代碼 PaymentKit,翻譯成swift大概就是這樣
// ...
// Discover
if cardString.hasPrefix("6011") || cardString.hasPrefix("65") {
return .discover
}
else if cardString.hasPrefix("622") {
// If the number has a prefix in the range 622126-622925, it's Discover
let prefixLength = 6;
if (cardString.characters.count >= prefixLength) {
let prefixIndex = number.index(cardString.startIndex, offsetBy: prefixLength)
let sixDigitPrefixString = cardString.substring(to: prefixIndex)
let sixDigitPrefixInt = Int(sixDigitPrefixString)!
if sixDigitPrefixInt >= 622126 && sixDigitPrefixInt <= 622925 {
return .discover;
}
}
return .unknown
}
else if cardString.hasPrefix("64") { ... }
// ...
這特么是什么鬼代碼茁计,別人維護起來得多痛苦料皇,尤其是銀行玩點幺蛾子多改下的時候,修改這些代碼簡直是噩夢
Option 2:正則大法
現(xiàn)在我們用正則來替代if大法
//amex starts with 34 or 37 and is 15 digits
case .amex:
return "^3[47][0-9]{13}$"
很cooool 很簡潔是吧,現(xiàn)在來看看.masterCard:
//MasterCard starts with 51 through 55
//or 2221 through 2720. All have 16 digits.
case .masterCard:
return "^(?:5[1-5][0-9]{2}|" +
"222[1-9]|" +
"22[3-9][0-9]|" +
"2[3-6][0-9]{2}|" +
"27[01][0-9]|" +
"2720)" +
"[0-9]{12}$"
...
黑人問號践剂?鬼譬??
正則表達式是個很強大的工具舷手,但是正則在表達式在表達數(shù)值范圍時候就顯得不那么優(yōu)雅了拧簸,更別說是這種可變長度的數(shù)字,而且還很不好懂男窟,這也pass盆赤。
一個更簡潔,具有變現(xiàn)力點代碼:
我們用的是swift歉眷,肯定有一種更好的方式來處理類似的情況牺六,先別換編譯器的嘲笑,我們先寫點偽代碼汗捡,
case .amex: prefix = ["34", "37"]
length = [15]
case .diners: prefix = ["300"..."305", "309", "36", "38"..."39"]
length = [14]
case .discover: prefix = ["6011", "65", "644"..."649", "622126"..."622925"]
length = [16]
case .jcb: prefix = ["3528"..."3589"]
length = [16]
case .masterCard: prefix = ["51"..."55", "2221"..."2720"]
length = [16]
case .visa: prefix = ["4"]
length = [13, 16, 19]
現(xiàn)在判斷的規(guī)則是不是變的相當?shù)暮啙嵜髁耸缂剩绾巫龅侥兀憧梢韵瓤创a CardParser.swift.
強大的ENUM:
CardType是swift的中枚舉類型扇住,swift枚舉是個強大的武器不但可以進行模式匹配還可以驗證規(guī)則:
enum CardType {
case visa
case masterCard
...
var segmentGroupings: [Int] {...}
var cvvLength: Int {...}
...
func isValid(_ accountNumber: String) -> Bool {...}
func isPrefixValid(_ accountNumber: String) -> Bool {...}
}
visa.cvvLength // 3
visa.isPrefixValid("4") // true
visa.isValid("4") // false
強大的協(xié)議
待續(xù)