Credit/Debit card validation and type detection in Swift using ATGValidator

Suraj Thomas K
Ounass
Published in
4 min readMar 9, 2020

Payments using credit and debit cards are an integral part of eCommerce journey. If you have an app that sells any sort of merchandise that’s not app content and not related to iOS ecosystem, you would have already exposed a way to make payments using credit/debit cards.

It’s pretty common for users to enter credit card numbers incorrectly, and showing an error message to the user after an error from payment gateway is something unintuitive. We can change this flow by pointing out to the user if the entered card number is invalid while the user is entering it. And even better we can detect the type of card while the number is being entered. Please note that we will be doing this locally and no communication is needed with any servers for this. Let’s see how we can give a reassuring experience to the user while they are entering credit/debit card number.

We can use ATGValidator for doing this few lines of code. ATGValidator can be added using both Cocoapods and Carthage. We will be using Cocoapods in this article.

ATGValidator is a validation framework written completely in Swift, and has validation rules as it’s backbone. It provides a lot of prebuilt validation rules and supports adding your own validation rules. ATGValidator supports a form validator which can be used to club together multiple input fields and use their validation results as a single unit.

Prerequisites:- Xcode, Cocoapods (If you are not familiar with Cocoapods, have a look at this link first.)

Starter project - You can download the starter project from here.

Once the starter project is downloaded, unzip and open it in Xcode.

When you compile and run the downloaded project, you can see a text field for credit/debit card number entry.

There is no validation added yet, and when you tap on the continue button it just prints out the value entered in the text field.

Let’s add some validation to the fields.

The first thing to do is to add ATGValidator as a dependency in Podfile. For that, open Podfile in a text editor and uncomment the line (remove the # from the line) where ATGValidator is mentioned.

pod ‘ATGValidator’, ‘~> 1.0’

Now open the project directory in Terminal, and run

pod install

This will download and link the framework with the project and generate an xcworkspace file. Double click on the generated CardValidationSample.xcworkspace file to open it in Xcode.

Add the following line to ViewController.swift below UIKit import

import ATGValidator

Now we can set up the credit card field for validations. Add the following lines of code to the end of viewDidLoad method.

// Line 1
cardNumberTextField.validationRules = [
PaymentCardRule(acceptedTypes: [.visa])
]
// Line 2
cardNumberTextField.validateOnInputChange(true)
// Line 3
cardNumberTextField.validationHandler = { result in
if
self?.cardNumberTextField.text?.isEmpty ?? true {
self?.cardTypeIndicator.text = nil
} else {
self?.cardTypeIndicator.text = (result.status == .success ? "✅" : "❌")
}
self?.cardTypeIndicator.isHidden = self?.cardTypeIndicator.text?.isEmpty ?? true
}

Line 1 sets up a PaymentCardRule on the card number text field with visa as the only supported type.

Line 2 instructs the framework to run the validation algorithm whenever the text changes in the text field.

Line 3 registers a validation handler to be called whenever the validation algorithm is run. If the card number field is empty, it will hide the status label. If it is not empty, the label will be set with either a green tick or red cross symbol based on validation status.

Now run the app and enter a sample visa card number;

4111 1111 1111 1111

See it in action below;

We are not done yet. :-) We can show the type of the card number being entered with ATGValidator. In fact, all the heavy lifting is done by the framework already, and we need to just use the value.

To disable the continue button by default, add the following lines of code to just below of super.viewDidLoad()

continueButton.alpha = 0.5
continueButton.isEnabled = false

Now add .mastercard to the list of supported cards as given below;

cardNumberTextField.validationRules = [
PaymentCardRule(acceptedTypes: [.visa, .mastercard])
]

Update the validation handler part in viewDidLoad as follows;

cardNumberTextField.validationHandler = { [weak self] result in
if
self?.cardNumberTextField.text?.isEmpty ?? true {
self?.cardNumberStatusLabel.text = nil
} else {
var statusString = (result.status == .success ? "✅" : "❌")
if let type = result.value as? PaymentCardType {
statusString = type.rawValue + " " + statusString
}
self?.cardNumberStatusLabel.text = statusString
}
self?.cardNumberStatusLabel.isHidden =
self?.cardNumberStatusLabel.text?.isEmpty ?? true
self
?.continueButton.isEnabled = result.status == .success
self?.continueButton.alpha = result.status == .success ? 1.0 : 0.5
}

Build and run the project. You can find a list of test credit cards from PayPal here. Here is it in action;

Please note that the payment card rule trims all whitespace in the text field input, so you can auto-format the credit card number while entering to have a separator between every 4 digits.

Also, ATGValidator supports the following card types out of the box.

American Express
MasterCard
Maestro
Visa
Visa Electron
Discover
Diners Club

Hope you found this article helpful. If so, please do not forget to clap :-)

--

--