# iOS 📱

Our `InsuranceCardScan` swift package makes it easy to add health insurance card scanning and eligibility verification to any iOS application in **5 minutes or less.**

### Installation

Find the [Add Package Dependency](https://developer.apple.com/documentation/swift_packages/adding_package_dependencies_to_your_app) menu item in Xcode, File > Swift Packages.

Then enter the Github repository for the package:

```bash
https://github.com/CardScan-ai/insurance-card-scan-ios
```

### Usage

Import the package into your Xcode project files:

```swift
import InsuranceCardScan
```

### Basic Example:

Create the `CardScannerViewController` using the generated session token, present in the current view controller and register a callbacks to handle updates and errors.

```swift
import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var cardScanButton: UIButton!

    @IBAction private func didTapScanCard(_ sender: UIButton) {
        startCardScanning()
    }

    private func startCardScanning() {
        // Replace <GENERATED_USER_TOKEN> with the user token generated from the server
        // See https://docs.cardscan.ai/authentication#end-user

        let userToken = "<GENERATED_USER_TOKEN>"
        
        let onSuccessCallback: (InsuranceCard) -> Void = { card in
            print("Card Scanned Successfully! - \(card)")
        }

        let onErrorCallback: (CardScanError) -> Void = { error in
            print("Card Scanning Error: \(error.localizedDescription)")
        }
        
        // Configure and present the CardScanViewController
        let config = CardScanConfig(sessionToken: userToken, live: false, onSuccess: onSuccessCallback, onError: onErrorCallback)
        let cardScanViewController = CardScanViewController()
        cardScanViewController.config = config
        
        // Present the CardScanViewController
        present(cardScanViewController, animated: true)
    }
}

```

### Available Properties <a href="#available-properties" id="available-properties"></a>

`CardScanViewController` should be passed a `CardScanConfig` instance with properties for server connection, callback handling and UI customization.

```swift
CardScanConfig(
  // Required
  sessionToken: token,
  live: false,
  onSuccess: onSuccess,

  // Recommended
  onCancel: onCancel,
  onError: onError,

  //eligibility
  eligibility: eligibility,
  onEligibilitySuccess: onEligibilitySuccess,
  onEligibilityError: onEligibilityError,

  // Optional
  backsideSupport: scanBackside,
  onRetry: onRetry,
  onProgress: onProgress,
  
  // Camera Options
  cameraOptions: cameraOptions,

  // UI Customization
  messages: messages,
  messageStyle: messagesStyle,
  autoSwitchActiveColor: autoSwitchActiveColor,
  autoSwitchInactiveColor: autoSwitchInactiveColor,
  progressBarColor: progressBarColor,
  widgetBackgroundColor: widgetBackgroundColor,
  logging: logging,
)

```

### **Main** Properties

<table><thead><tr><th width="289">Prop</th><th width="112">Required</th><th width="135">Type</th><th>Description</th></tr></thead><tbody><tr><td>live</td><td>false</td><td>Boolean</td><td>Toggle the production or sandbox version. <strong>Default</strong>: false</td></tr><tr><td>sessionToken</td><td>true</td><td>String</td><td>A JWT token for the current user, see <a href="../authentication">Authentication</a></td></tr><tr><td>onSuccess</td><td>true</td><td>Function</td><td>Called on successful scan. The first argument is the scanned card.</td></tr><tr><td>onCancel</td><td>false</td><td>Function</td><td>Triggered when the user cancels the Scanning UI.</td></tr><tr><td>onError</td><td>false</td><td>Function</td><td>Called when an error is returned by the API or the ViewController fails to initialize.</td></tr><tr><td>onProgress</td><td>true</td><td>Function</td><td>Progress updates during the card scanning process.</td></tr><tr><td>onRetry</td><td>false</td><td>Function</td><td>Called when a failed scan triggers a retry.</td></tr><tr><td>backsideSupport</td><td>false</td><td>Boolean</td><td>Enable scanning of the front and back side of the card.<br><strong>Default</strong>: false</td></tr><tr><td>eligibility</td><td>false</td><td>object</td><td>Request payload for the optional post-scan eligibility verification. See: <a data-mention href="../advanced-features/eligibility-verification">eligibility-verification</a></td></tr><tr><td>onEligibilitySuccess</td><td>false</td><td>Function</td><td>Called on successful eligibility request. The eligibility response is pass as an argument.</td></tr><tr><td>onEligibilityError</td><td>false</td><td>Function</td><td>Called when an error is returned by the eligibility API.</td></tr><tr><td>cameraOptions</td><td>false</td><td>object</td><td>Configures the camera's orientation during scanning.</td></tr></tbody></table>

### UI/UX Customization Properties

The iOS widget is designed to be customizable. Please see the [#customization](#customization "mention") section of UI Components to adjust these elements to match your application's branding and theme:

[customization](https://docs.cardscan.ai/ui-components/customization "mention")

{% hint style="info" %}
**Note:** All UI/UX Props are optional
{% endhint %}

<table><thead><tr><th width="329.3333333333333">Prop</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>messages</td><td>[String: String]</td><td>Customize the text displayed by the UI.</td></tr><tr><td>messageStyle</td><td>MessageStyle</td><td>Set the size, color and background color of the text displayed by the UI.</td></tr><tr><td>autoSwitchActiveColor</td><td>UIColor</td><td>Set the color of the auto scan switch</td></tr><tr><td>autoSwitchInactiveColor</td><td>UIColor</td><td>Set the color of the disabled auto scan switch</td></tr><tr><td>progressBarColor</td><td>UIColor</td><td>Set the color of the progress bars or bounding box that surrounds the card scanning area.</td></tr><tr><td>widgetBackgroundColor</td><td>UIColor</td><td>Set the main background color for the widget.</td></tr></tbody></table>

## Callbacks

### onSuccess Callback

The `onSuccess` callback is triggered when the card scanning process completes successfully. This function receives the scanned card data as an argument.

#### Usage

Define a function that receives the scanned card data and pass it to the `CardScanConfig`.

```swift
let handleCardScanSuccess: (InsuranceCard) -> Void = { card in
    print("Card scanned successfully: \(card)")
}

let config = CardScanConfig(
    sessionToken: "<GENERATED_USER_TOKEN>",
    onSuccess: handleCardScanSuccess
)

let cardScanViewController = CardScanViewController(config: config)
present(cardScanViewController, animated: true)

```

### onError Callback

The `onError` callback is executed when there is a failure during the card scanning process. This function receives an error object as an argument.

#### Usage

Define a function that receives an error object and pass it to the `CardScanConfig`.

```swift
let handleCardScanError: (CardScanError) -> Void = { error in
    print("Scanning failed: \(error.localizedDescription)")
}

let config = CardScanConfig(
    sessionToken: "<GENERATED_USER_TOKEN>",
    onError: handleCardScanError
)
```

In this example, the `handleCardScanError` function logs the error object to the console when a scanning failure occurs.

By using the `onSuccess` and `onError` props, you can handle successful and failed scanning events, allowing you to implement custom actions or display appropriate messages to the user.

{% hint style="info" %}
You can find examples of the[#error-screens](#error-screens "mention") at the bottom of this document
{% endhint %}

Possible errors returned to the `onError` callback.

```typescript
struct CardScanError: Error {
    let message: String
    let type: String
    let code: Int
}
```

<table><thead><tr><th width="235.66666666666666">Error Type</th><th>Error Code</th><th>Error Message</th></tr></thead><tbody><tr><td>VideoError</td><td>670</td><td>Various system errors including: “Permission Denied” and “Camera not found”</td></tr><tr><td>VideoError</td><td>675</td><td>Various system media errors, including: “Permission Denied” and “The element has no supported sources.”</td></tr><tr><td>VideoError</td><td>676</td><td>Any and all other system related video capture &#x26; canvas capture errors.</td></tr><tr><td>WSError</td><td>640</td><td>“No websocket found - critical failure”</td></tr><tr><td>WSError</td><td>642</td><td>“Unknown error from websocket”</td></tr><tr><td>WSError</td><td><a href="https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent/code">1002-1003, 1007-1015</a></td><td>“The connection was closed abnormally”</td></tr><tr><td>ResponseError</td><td>HTTP Codes</td><td>Various HTTP errors returned from XMLHttpRequest and the CardScan.ai backend.</td></tr><tr><td>RequestError</td><td>Various</td><td>Various HTTP errors returned from Axios and XMLHttpRequest.</td></tr><tr><td>Unknown</td><td>606</td><td>Possible Axios setup errors, websocket setup errors, etc.</td></tr></tbody></table>

### onCancel Callback

The `onCancel` callback enables you to execute a custom function when the user cancels the card scanning process. This can be useful for tracking user behavior, navigating to a different part of the application, or displaying an appropriate message.

#### Usage

Pass a function to the `CardScanConfig` that will be executed when the user cancels the scanning process.

```swift
let handleCancel: () -> Void = {
    print("Scanning cancelled by the user.")
}

let config = CardScanConfig(
    sessionToken: "<GENERATED_USER_TOKEN>",
    onCancel: handleCancel
)
```

### onRetry Callback

The `onRetry` callback allows you to execute a custom function when a retry is triggered due to a scanning failure.

#### Usage

Pass a function to the `CardScanConfig` that will be executed upon retry.

```swift
let handleRetry: () -> Void = {
    print("Retry triggered.")
}

let config = CardScanConfig(
    sessionToken: "<GENERATED_USER_TOKEN>",
    onRetry: handleRetry
)
```

In this example, the `handleRetry` function logs the retry event to the console when a retry is triggered.

### onProgress Callback

The `onProgress` callback allows you to execute a custom function to report progress during the scanning process.

#### Usage

```swift
let handleProgress: (ScanProgress) -> Void = { progress in
    print("Card ID: \(progress.cardId) - Scan Count: \(progress.scanCount) - Card State: \(progress.cardState)")
}

let config = CardScanConfig(
    sessionToken: "<GENERATED_USER_TOKEN>",
    onProgress: handleProgress
)
```

In this example, the `handleProgress` callback logs the progress during a live scanning operation. When `backsideSupport` is enabled the scan counter will reset to zero when the card is flipped to scan the back side.

{% hint style="info" %}
For the majority of live scanning scenarios, the **scanning will be completed within 2-3 scans.** In situations with low light or occluded card elements, the scan count can go as high as 12.
{% endhint %}

## Additional Features

### Camera Options

Camera Configuration allow developers to preset the camera's view orientation for specific installation scenarios, such as mirrored cameras or kiosks. These settings ensure the camera view is correctly aligned and oriented during the initial setup of the application:

* `flipHorizontal`: Enables horizontal flipping of camera view, reversing the left to right sides of the image (aka mirrored)
* `flipVertical`: Enabled vertical flipping of camera view, swapping the top and bottom of the image when the camera or document is upside down.

```swift
let config = CardScanConfig(
    sessionToken: "<GENERATED_USER_TOKEN>",
    onSuccess: onSuccessCallback,
    cameraOptions: CameraOptions(
        flipHorizontal: true,
        flipVertical: false
    )
)
```

### Eligibility Verification

Eligibility Verification is crucial in healthcare for confirming a patient's insurance coverage and benefits before services are provided, streamlining billing and enhancing patient care.

By providing subscriber and provider details through our React component, users can initiate the verification process effortlessly. The widget offers real-time feedback with success and error callbacks, simplifying integration into your application's UI.

See [eligibility-verification](https://docs.cardscan.ai/advanced-features/eligibility-verification "mention") for more details.

### Camera Permissions 📸

Our SDK requires camera access to scan insurance cards. While the CardScan widget automatically requests camera permissions during widget load, it does not present any UI for handling permissions or manage permission failures, particularly on mobile devices.

**Requirement:** We require that developers handle camera permission requests ***before*** loading the CardScan widget. This will allow you to manage the permission flow consistently within your application, providing custom error handling and user feedback if permission is denied.

**Recommendation:** We recommend following best practices when requesting camera permissions:

* **Pre-flight the request:**

  Within your app, prompt the user with a clear explanation of why camera access is needed and ask for confirmation (Yes/No). This improves transparency, builds trust, and can reduce the likelihood of the user denying the request.
* **Handle permission rejection gracefully:**
  * **Soft rejection (user-level):** If the user declines the camera access within your app, provide a helpful message that explains the impact of this choice and give them the option to reconsider later.
  * **Hard rejection (system-level):** In case the user has previously denied the camera permission at the system level, guide them to the device settings where they can manually enable the camera access. Display an appropriate message explaining how to do this and the importance of enabling the permission for the app's functionality.
