Last active
April 4, 2020 10:15
-
-
Save jstorm31/cb8148c8887618130302a026a4c2282b to your computer and use it in GitHub Desktop.
Swift Czech bank account validation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Rewritten from PHP code excerpt from https://www.kutac.cz/pocitace-a-internety/jak-poznat-spravne-cislo-uctu | |
import Foundation | |
final class Utils { | |
static let bankCodes: Set = [100, 300, 600, 710, 800, 2010, 2020, 2030, 2060, 2070, 2100, 2200, 2220, 2240, 2250, 2260, 2275, 2600, 2700, 3030, 3050, 3060, 3500, 4000, 4300, 5500, 5800, 6000, 6100, 6200, 6210, 6300, 6700, 6800, 7910, 7940, 7950, 7960, 7970, 7980, 7990, 8030, 8040, 8060, 8090, 8150, 8190, 8198, 8199, 8200, 8215, 8220, 8225, 8230, 8240, 8250, 8255, 8260, 8265, 8270, 8272, 8280, 8283, 8291, 8292, 8293, 8294, 8296] | |
/// Validates Czech bank account number | |
static func isValid(bankAccount: String) -> Bool { | |
let bankAccountRegex = try! NSRegularExpression(pattern: "^(?:([0-9]{1,6})-)?([0-9]{2,10})\\/([0-9]{4})$") | |
let range = NSRange(location: 0, length: bankAccount.utf16.count) | |
let match = bankAccountRegex.firstMatch(in: bankAccount, options: [], range: range) | |
guard match != nil else { | |
return false | |
} | |
let parts = bankAccount.split(separator: "/") | |
let accountNumber = parts.first!.split(separator: "-") | |
let bankCode = parts.last! | |
guard bankCodes.contains(Int(bankCode) ?? 0) else { | |
return false | |
} | |
// Main part | |
let main = accountNumber.last!.padding(toLength: 10, withPad: "0", startingAt: 0) | |
guard Utils.bankAccountChecksum(main) % 11 == 0 else { | |
return false | |
} | |
// Optional prefix | |
if parts.count == 2 { | |
let prefix = accountNumber.first!.padding(toLength: 10, withPad: "0", startingAt: 0) | |
guard Utils.bankAccountChecksum(prefix) % 11 == 0 else { | |
return false | |
} | |
} | |
return true | |
} | |
} | |
private extension Utils { | |
static func bankAccountChecksum(_ part: String) -> Int { | |
let weights = [6, 3, 7, 9, 10, 5, 8, 4, 2, 1] | |
return part.enumerated().reduce(0) { (checksum, item) in | |
let (index, char) = item | |
return checksum + weights[index] * (Int(String(char)) ?? 0) | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import XCTest | |
@testable import App | |
final class UtilsTests: XCTestCase { | |
func testValidBankAccount() { | |
XCTAssertTrue(Utils.isValid(bankAccount: "111333/2700")) | |
XCTAssertTrue(Utils.isValid(bankAccount: "86-199488014/3030")) | |
} | |
func testInvalidBankAccount() { | |
XCTAssertFalse(Utils.isValid(bankAccount: "notBankAccountAtAll")) | |
XCTAssertFalse(Utils.isValid(bankAccount: "1235234/haha")) | |
XCTAssertFalse(Utils.isValid(bankAccount: "234534636/2700")) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment