Integrating the Document Scan SDK

Starting in version 5.7.0, the Document Scan SDK can directly extract an MRZ and the derived MRZ_information key for you. If you have not yet used the Document Scan SDK, please first refer to its documentation for getting started.

Supporting MRZ Capture

Only a single option change is required to support MRZ capture: DSPassportOptions.mrzCaptureMethod. By default, this is set to .detect, which is slightly more efficient and supports iOS 12. By setting this to .recognize, you can enable full character recognition within the MRZ, which will be populated in the DSPassportResult.mrz:

import UIKit
import CFDocumentScanSDK

class ViewController: UIViewController, DSHandlerDelegate {

    private func startPassportScan() {
        let options = DSPassportOptions()
        options.mrzCaptureMethod = .recognize
        // Configure additional capture options, thresholds, prompts, etc.

        startScan(options: options) // Present scan controller
    }

    // MARK: - DSHandlerDelegate

    func handleScan(result: DSResult) {
        guard let passportResult = result as? DSPassportResult else {
            return
        }
        let mrzData = passportResult.mrz
        let mrzInformationKey = mrzData?.mrzInformationKey
    }

    func captureError(_ error: DSError) {
        print("Scan Error: \(error)")
    }

}

Preparing for API Submission

When submitting transactions to the CatfishAir API, NFC data can be attached to images for improved decisioning. After receiving a DSResult from the Document Scan SDK, you will have two images to send: DSResult.image and DSResult.flashImage. Before sending these to the API, apply changes from the PassportChipData:

private func handle(result: DSResult, chipData: PassportChipData) {
    let image = chipData.embeddedIn(image: result.image)
    let flashImage = chipData.embeddedIn(image: result.flashImage)

    // Refer to "Example AuthenticateDocument Network Call" in the Document Scan SDK documentation

    let imageData = [
        "frontImage": image,
        "frontFlashImage": flashImage
    ]

    networkClient.authenticateDocumentRequest(urlString: "<service_url>",
                                              imageData: imageData)
    { result in
        // Handle result
    }
}

Full Workflow

Combined with the included tutorial screens, you can spin up an end-to-end experience relatively fast:

import UIKit
import CFDocumentScanSDK
import CFNFCReaderSDK

class ViewController: UIViewController, DSHandlerDelegate {

    override func viewDidLoad() {
        showMRZTutorial()
    }

    private func startPassportScan() {
        let options = DSPassportOptions()
        options.mrzCaptureMethod = .recognize
        // Configure additional capture options, thresholds, prompts, etc.

        startScan(options: options) // Present scan controller
    }

    private func showMRZTutorial() {
        let tutorialVC = TutorialMRZViewController()
        tutorialVC.primaryAction = { [weak self] in
            self?.startPassportScan()
        }
        navigationController?.pushViewController(tutorialVC, animated: true)
    }

    private func showNFCTutorial(mrzInformationKey: String) {
        let tutorialVC = TutorialNFCViewController(mrzInformationKey: mrzInformationKey) { controller, result in
            switch result {
            case let .failure(error):
                // Handle error
                break
            case let .success(chipData):
                let image = chipData.embeddedIn(image: result.image)
                let flashImage = chipData.embeddedIn(image: result.flashImage)
                // Send to API
            }
        }
        navigationController?.pushViewController(tutorialVC, animated: true)
    }

    // MARK: - DSHandlerDelegate

    func handleScan(result: DSResult) {
        guard let passportResult = result as? DSPassportResult,
            let mrzInformationKey = passportResult.mrz?.mrzInformationKey else {
            print("Failed to read MRZ")
            return
        }
        showNFCTutorial(mrzInformationKey: mrzInformationKey)
    }

    func captureError(_ error: DSError) {
        print("Scan Error: \(error)")
    }

}