iOS integration guide
Scan a payment card for fraud protection with Bouncer Scan for iOS.

Requirements

  • Xcode 11 or higher
  • iOS 11 or higher for integration
  • iOS 11.2 or higher for using the scanning view controllers
  • iOS 13 or higher for our name and expiration models. The number model will
    work on older versions of iOS and it will always return nil for the name and
    expiration fields.

iPad Support

CardScan defaults to a formSheet for the iPad, which handles all screen orientations and autorotation correctly. However, if you'd like to use it in full screen mode instead, make sure to select the Requires full screen option in your Info.plist file via XCode, or else non-portrait orientations won't work.

Installation

CardVerify is published to the bouncer private repositories. Please request access to this repository by emailing [email protected] with a request for access.
CardVerify is available through CocoaPods. To install it, simply add the following line to your Podfile:
1
pod 'CardVerify', :http => 'https://api.getbouncer.com/v1/downloads/sdk/card_verify/<your_api_key_here>/cardverify-ios-2.1.5.tgz'
Copied!
Next, install the new pod. From a terminal, run:
1
pod install
Copied!
Or, if you have previously integrated Bouncer, update your Podfile and update CardVerify:
1
pod update CardVerify
Copied!
When using Cocoapods, you use the .xcworkspace instead of the .xcodeproj. Again from the terminal, run:
1
open YourProject.xcworkspace
Copied!

Note: The Podfile can specify the iOS platform target to be lower than 11.2. However, as stated in the requirements CardVerify will only run on iOS 11.2 or higher.

Set up permissions

CardScan uses the camera, so you'll need to add an description of camera usage to your Info.plist file:
XCode iOS camera permission
The string you add here will be what CardScan displays to your users when CardScan first prompts them for permission to use the camera.
iOS camera prompt
Alternatively, you can add this permission directly to your Info.plist file:
1
<key>NSCameraUsageDescriptionkey>
2
<string>We need access to your camera to scan your cardstring>
Copied!

Configure the CardVerify module

CardVerify can be configured and run through Swift or Objective-C. CardVerify requires an API key, which can be generated for your app through the Bouncer API console. Note that for CardVerify, you will need permissions added to your API key to perform validation. Please contact [email protected] once you've created your API key to have permissions added.
The CardScan SDK will send anonymous stats to Bouncer's servers. This code snippet shows what we send.
Apps using CardVerify must configure the library at launch.
Swift
Configure the library when your application launches by adding CardScan to your AppDelegate.swift file. If you are planning to use a navigation controller or support rotation, also be sure to add supportedOrientationMaskOrDefault.
1
import UIKit
2
import CardVerify
3
4
@UIApplicationMain
5
class AppDelegate: UIResponder, UIApplicationDelegate {
6
7
func application(
8
_ application: UIApplication,
9
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?
10
) -> Bool {
11
Bouncer.configure(apiKey: "<your_api_key_here>")
12
// do any other necessary launch configuration
13
return true
14
}
15
16
func application(
17
_ application: UIApplication,
18
supportedInterfaceOrientationsFor window: UIWindow?
19
) -> UIInterfaceOrientationMask {
20
// if you are planning to embed scanViewController into a navigation
21
// controller, put this line to handle rotations
22
return ScanBaseViewController.supportedOrientationMaskOrDefault()
23
}
24
}
Copied!

Using Bouncer Scan for high-risk transactions

There are two main uses for the CardVerify module: verify a card for a high-risk transaction and block if the scan is invalid using the VerifyCardViewController and proactively running fraud models when users add a card using the VerifyCardAddViewController.

Using VerifyCardViewController for high-risk transactions

When you use the VerifyCardViewController the view controller will scan the card that your user is using for the high-risk transaction and block the transaction if the scan is invalid or detects telltale signs of fraud. If the user tries to scan a different card, the VerifyCardViewController will show an error state by outlining in red the card rectangle in the UI but will continue scanning to detect the correct card. Because this flow is for high-risk transactions, we provide a VerifyCardExplanationViewController that you can use to provide context for your users. The overall flow will look like this in most cases:
To use this flow:
Swift
1
import UIKit
2
import CardVerify
3
4
class ViewController: UIViewController, VerifyCardExplanationResult, VerifyCardResult {
5
@IBAction func buttonPressed() {
6
let vc = VerifyCardExplanationViewController()
7
vc.lastFourForDisplay = self.lastFourOnFile
8
vc.cardNetworkForDisplay = self.networkOfCardOnFile
9
vc.expiryOrNameForDisplay = nameOnFile ?? expiryOnFile ?? ""
10
vc.delegate = self
11
12
self.present(vc, animated: true, completion: nil)
13
}
14
15
// MARK: -Explanation protocol implementation
16
func userDidPressScanCardExplaination(_ viewController: VerifyCardExplanationViewController) {
17
// Start the Verification process
18
guard let lastFour = lastFourOnFile, let bin = binOnFile else { return }
19
let vc = VerifyCardViewController(userId: "1234", lastFour: lastFour, bin: bin, cardNetwork: nil)
20
vc.verifyCardDelegate = self
21
22
viewController.present(vc, animated: true, completion: nil)
23
}
24
25
func userDidPressPayAnotherWayExplanation(_ viewController: VerifyCardExplanationViewController) {
26
dismiss(animated: true)
27
// let the user select a different card for this transaction
28
}
29
30
func userDidPressCloseExplanation(_ viewController: VerifyCardExplanationViewController) {
31
dismiss(animated: true)
32
}
33
34
// MARK: -VerifyCardResult protocol
35
func userCanceledVerifyCard(viewController: VerifyCardViewController) {
36
dismiss(animated: true)
37
}
38
39
func fraudModelResultsVerifyCard(viewController: VerifyCardViewController, creditCard: CreditCard, encryptedPayload: String?, extraData: [String : Any]) {
40
// at this point the scan is done, send the encrypted payload
41
// to your servers which will get the result from Bouncer's
42
// servers
43
}
44
}
Copied!

Using VerifyCardAddViewController to verify cards when users add them

Our VerifyCardViewController flow verifies a specific card for a high-risk transaction and our VerifyCardAddViewController flow proactively verifies any cards that users add to your platform. To support this flow, you should use the VerifyCardAddViewController instead of the VerifyCardViewController, and implement the optional fraudModelResultsVerifyCardAdd protocol method in the VerifyCardAddResult protocol:
1
import CardVerify
2
import UIKit
3
4
class VerifyAddFlowViewController: UIViewController, VerifyCardAddResult {
5
@IBAction func buttonPressed() {
6
// Start the Verification process
7
let vc = VerifyCardAddViewController(userId: "1234")
8
vc.cardAddDelegate = self
9
vc.enableManualEntry = true
10
11
viewController.present(vc, animated: true, completion: nil)
12
}
13
14
// MARK: -VerifyCardAddResult protocol implementation
15
func userDidCancelCardAdd(_ viewController: UIViewController) {
16
dismiss(animated: true)
17
}
18
19
func fraudModelResultsVerifyCardAdd(viewController: UIViewController, creditCard: CreditCard, encryptedPayload: String?, extraData: [String: Any]) {
20
// at this point the scan is done, send the encrypted payload
21
// to your servers which will get the result from Bouncer's
22
// servers
23
24
// depending on the results from Bouncer + if the card matched
25
// what you were expecting handle each case
26
}
27
28
func userDidScanCardAdd(_ viewController: UIViewController, creditCard: CreditCard) {
29
// The flow is complete, but fraud results aren't back yet
30
}
31
32
func userDidPressManualCardAdd(_ viewController: UIViewController) {
33
// The user pressed "manual entry", go directly to the card entry form
34
}
35
}
Copied!

Allowing users to scan any card during high risk transactions

You can also use VerifyCardAddViewController to verify high risk transactions without limiting them to the specific card that you have on file for the transaction. To support this flow, follow the instructions in the Using VerifyCardAddViewController section, but disable the button that allows users to enter card details manually by setting the enableManualEntry property on the VerifyCardAddViewController to false
Swift
1
import UIKit
2
import CardVerify
3
4
class ViewController: UIViewController, VerifyCardExplanationResult, VerifyCardAddResult {
5
@IBAction func buttonPressed() {
6
let vc = VerifyCardExplanationViewController()
7
vc.lastFourForDisplay = self.lastFourOnFile
8
vc.cardNetworkForDisplay = self.networkOfCardOnFile
9
vc.expiryOrNameForDisplay = nameOnFile ?? expiryOnFile ?? ""
10
vc.delegate = self
11
12
self.present(vc, animated: true, completion: nil)
13
}
14
15
// MARK: -Explanation protocol implementation
16
func userDidPressScanCardExplaination(_ viewController: VerifyCardExplanationViewController) {
17
// Start the Verification process
18
let vc = VerifyCardAddViewController(userId: "1234")
19
vc.cardAddDelegate = self
20
vc.enableManualEntry = false
21
22
viewController.present(vc, animated: true, completion: nil)
23
}
24
25
func userDidPressPayAnotherWayExplanation(_ viewController: VerifyCardExplanationViewController) {
26
dismiss(animated: true)
27
// let the user select a different card for this transaction
28
}
29
30
func userDidPressCloseExplanation(_ viewController: VerifyCardExplanationViewController) {
31
dismiss(animated: true)
32
}
33
34
// MARK: -VerifyCardAddResult protocol
35
func fraudModelResultsVerifyCardAdd(viewController: UIViewController, creditCard: CreditCard, encryptedPayload: String?, extraData: [String: Any]) {
36
// at this point the scan is done, send the encrypted payload
37
// to your servers which will get the result from Bouncer's
38
// servers
39
40
// depending on the results from Bouncer + if the card matched
41
// what you were expecting handle each case
42
}
43
44
func userDidScanCardAdd(_ viewController: UIViewController, creditCard: CreditCard) {
45
// don't do anything here, wait for the fraud result to come back
46
}
47
48
func userDidPressManualCardAdd(_ viewController: UIViewController) {
49
preconditionFailure("Manual button not shown")
50
}
51
52
func userDidCancelCardAdd(_ viewController: UIViewController) {
53
dismiss(animated: true)
54
}
55
}
Copied!

Local Verification

This is a less stringent verification flow than network verification, as the verification logic runs locally on the device. In cases where it is not viable to send a payload to Bouncer servers, this can be used to verify the authenticity of a card, but will be less accurate than network verification.
Once you conform to the verifyCardDelegate and cardAddDelegate protocol when utilizing VerifyCardViewController and VerifyCardAddViewController, the function fraudModelResultsVerifyCardAdd and fraudModelResultsVerifyCard will provide an encrypted payload and a field called extraData.
extraData is a dictionary that contain the results of the local verification. The following will list the available result values:

Local Verification Extra Data

Key
Value Type
"isCardValid"
Bool
"validationFailureReason"
String?
Swift
1
import UIKit
2
import CardVerify
3
4
extension ViewController: VerifyCardResult {
5
func userCanceledVerifyCard(viewController: VerifyCardViewController) {
6
dismiss(animated: true)
7
}
8
9
func fraudModelResultsVerifyCard(viewController: VerifyCardViewController, creditCard: CreditCard, encryptedPayload: String?, extraData: [String : Any]) {
10
// at this point the scan is done, you will receive the encrypted payload
11
// and the local verification result in extraData. Parse the extraData dictionary
12
// to extract the local verification values.
13
14
let localIsValid = extraData["isCardValid"] as? Bool ?? false
15
let localValidationFailureReason = extraData["validationFailureReason"] as? String ?? ""
16
}
17
}
18
19
extension ViewController: VerifyCardAddResult {
20
func fraudModelResultsVerifyCardAdd(viewController: UIViewController, creditCard: CreditCard, encryptedPayload: String?, extraData: [String: Any]) {
21
// at this point the scan is done, you will receive the encrypted payload
22
// and the local verification result in extraData. Parse the extraData dictionary
23
// to extract the local verification values.
24
25
let localIsValid = extraData["isCardValid"] as? Bool ?? false
26
let localValidationFailureReason = extraData["validationFailureReason"] as? String ?? ""
27
}
28
29
func userDidScanCardAdd(_ viewController: UIViewController, creditCard: CreditCard) {
30
// don't do anything here, wait for the fraud result to come back
31
}
32
33
func userDidPressManualCardAdd(_ viewController: UIViewController) {
34
preconditionFailure("Manual button not shown")
35
}
36
37
func userDidCancelCardAdd(_ viewController: UIViewController) {
38
dismiss(animated: true)
39
}
40
}
Copied!

Model Downloading

By default, the SDK will download updates to ML models used to extract card information. To disable model downloading, set the following flag to false before calling configure in your AppDelegate:
Swift
Objective-C
1
Bouncer.downloadModels = false
2
Bouncer.configure(apiKey: "API_KEY")
Copied!
1
Bouncer.downloadModels = false;
2
[Bouncer configureWithApiKey:@"API_KEY"];
Copied!
Subsequently you can initiate a download by using this function. Note, downloading is idempotent -- you can call this function as many times as you'd like and CardVerify will download the models at most once.
1
Bouncer.downloadModelsIfNotCached()
Copied!
It can take a few minutes to download models if your customer has a slow network connection, so we recommend either letting Bouncer download models during the configure call or calling the downloadModelsIfNotCached method as early as possible to give the models enough time to download.

Customizing

This library is built to be customized to fit your UI. We provide translated strings and localization support by default for all UI elements in our flows, and we provide mechanisms for you to set these strings yourself. See the customization documentation for more details.

Supporting more cards

Though Bouncer Scan supports several cards, you may need to add support for cards specific to your business, instructions can be found in the card support docs.

Authors

Sam King, Jaime Park, Adam Wushensky

License

A licensing agreement is required to use this library.
All contributors must agree to the CLA.
Last modified 7d ago