ethanwa / Credit-Card-Scanner-and-Validator-for-Swift

Uses the iOS Vision text recognizer framework to visually read credit card numbers and expiration dates. Then uses the Luhn algorithm to make sure the CC number is valid. Also checks against a list of prefix numbers to determine card type (Mastercard, Visa, Discover, Amex, etc).
MIT License
17 stars 3 forks source link

Language: Swift 5 Platform: iOS 13+ License: MIT

Credit and Debit Card Scanner and Validator

Requires iOS 13 or above.

Uses the iOS Vision text recognizer framework to visually read credit and debit card numbers and expiration dates. During the recognition process, it uses the Luhn algorithm to make sure the CC number is valid. It also checks against a list of prefix numbers to determine card type (Mastercard, Visa, Discover, Amex, etc).

How to Use

It's very simple to use. Add the CCScannerDelegate to your UIViewController, initialize the CCScanner class, set the delegate, and start the scanner. The delegate method will be called returning you the card information.

Here's an extremely easy example to follow:

import UIKit

class ViewController: UIViewController, CCScannerDelegate {

    let ccScanner = CCScanner()

    override func viewDidLoad() {
        super.viewDidLoad()
        self.ccScanner.delegate = self
    }

    @IBAction func startButton() {
        self.ccScanner.startScanner(viewController: self)
    }

    func ccScannerCompleted(cardNumber: String, expDate: String, cardType: String) {

        // do something with the data
        print(cardNumber, expDate)
    }
}

Why did I make this?

I have noticed lately that many apps on the App Store, including Apple's own Wallet app, now use card scanning to automatically pull credit/debit numbers from a live camera view and populate them into fields. This makes entering payment information a lot easier and faster for customers in apps that don't or can't use Apple Pay. Afterall, the faster the checkout, the more likely you will win that sale, right?

There are also a few other projects here on GitHub that are nice, but they dont have the accuracy for various card numbering formats, nor the validation for worldwide use, to truely be something an international company could depend on. Their code is cleaner than mine though, if that matters. ;)

I don't have an app to use this code in personally, but I was intrigued to see if I could build something better and faster than what a lot of these other apps use. Even Apple's Wallet CC reader is frustratingly slow (and sometimes doesn't work at all) with credit cards that have the numbers in vertical blocks and not in a horizontal line (like the Capital One Venture card I have), or not being able to get the Exp Date 50% of the time. So I built this, and I think it is better performing, and I'd like to share the code with the world and you to use as you wish. I'm hoping that this side project over time will become useful to people and businesses, especially in places like pop-up shops, third-world countries, consumers on the go, and other places that don't have immediate access to swipe, EMV, or NFC tech.

Optional Settings

.fastest
.fast
.normal (default)
.accurate
.veryaccurate
.all (default)
.noneExceptCustom
.visa                     // Visa
.mastercard               // Mastercard
.americanExpress          // American Express
.discover                 // Discover
.chinaTUnion              // China T-Union
.chinaUnionPay            // China Union Pay
.dinersClubInternational  // Diners Club International
.interPayment             // Interpayment
.jcb                      // JCB
.maestroUK                // Maestro UK
.maestro                  // Maestro
.dankort                  // Dankort
.mir                      // MIR
.npsPridnestrovie         // NPS Pridnestrovie
.troy                     // Troy
.utap                     // UTAP
.custom                   // Custom Card (see below)
let targetCard = self.ccScanner.createCardType.new(binRange: "639463", lengthRange: "16")
self.ccScanner.addCustomCards(cards: [targetCard])

Both of these variables can be set in ranges, like this:

let targetCardRangeOne = self.ccScanner.createCardType.new(binRange: "639463-639465", lengthRange: "16-19")

You can add as many custom cards, or as many various ranges, as you wish:

self.ccScanner.addCustomCards(cards: [targetCard, oldNavyStoreCard])

Current Known Limitations, Issues, and Extra Details