# Development Guide

{% tabs %}
{% tab title="Android" %}

### Usage

1. Retrieve the `MRZKey` by passing passport number, date of birth, and expiry date

```
val mrzKey = PassportUtils().getMRZKey("A32869311", "890921", "190528")
```

1. License key is needed to trigger the process. Start the process by calling `readPassport` on `PassportReader`. After process finished successfully or with an error, the callback method will be inovked with the results

```
PassportReader.readPassport(this, LICENSE_KEY, mrzKey) { success, passport, error ->  
	Log.d("RESULT", "issuccess =>" + success)  
    Log.d("RESULT", "data =>" + passport)  
    Log.d("RESULT", "err =>" + error)  
}
```

#### MRZ key <a href="#user-content-mrz-key" id="user-content-mrz-key"></a>

| Parameter      | Type   | Required format |
| -------------- | ------ | --------------- |
| passportNumber | String |                 |
| dateOfBirth    | String | yyMMdd          |
| dateOfExpiry   | String | yyMMdd          |

***\*Note: if expiry date is 21 SEPT 2022, the valid format to pass is 220921***

### &#x20;<a href="#user-content-result-callback" id="user-content-result-callback"></a>

### Result callback <a href="#user-content-result-callback" id="user-content-result-callback"></a>

* result callback has 3 params as follow:

| Params    | Possible value                                                                                                                  |
| --------- | ------------------------------------------------------------------------------------------------------------------------------- |
| success   | will be true if the process finish successfully ,otherwise false                                                                |
| passport  | if its successful,the passport object will contains the info described in the following table. Otherwise, passport will be null |
| exception | if its successful, exception will be null otherwise, it contains the exception that occurred during the process                 |

After the successful processing, you will be able to retrieve the following info:

| Parameter          | Type   |
| ------------------ | ------ |
| documentType       | String |
| documentNumber     | String |
| personalNumber     | String |
| name               | String |
| gender             | String |
| nationality        | String |
| dateOfBirth        | String |
| documentExpiryDate | String |
| faceImgPath        | String |
| {% endtab %}       |        |

{% tab title="iOS" %}

### Usage

Start by importing `OkayNFC` module into your swift file.

```
import OkayNFC
```

### Scan NFC

1\. Instantiate the `PassportReader` class

```
private let passportReader = PassportReader()
```

2\. Retrieve the MRZ key by passing in `passport number`, `birthdate` and `expiryDate`

```
let mrzKey = PassportUtils().getMRZKey(passportNumber: passportNumber, dateOfBirth: birthDateString, dateOfExpiry: expiryDateString)
```

3\. License key is needed to trigger the process. Start the process by calling `readPassport` on `passportReader`. You may handle the result in the completion handler.

```
passportReader.readPassport(license: licenseKey, mrzKey: mrzKey,
    customDisplayMessage: { (displayMessage) in
        switch displayMessage {
            case .requestPresentPassport:
                return "Hold your iPhone near an NFC enabled passport."
            default:
                // Return nil for all other messages so we use the provided default
                return nil
        }
    }, completed: { (passport, error) in
        if let passport = passport {
            // handle passport result
        }
        else {
            // handle error
        }
    })
```

###

### Required Inputs

#### MRZ Key

| Parameter      | Type   | Default | Required format |
| -------------- | ------ | ------- | --------------- |
| passportNumber | String | nil     |                 |
| dateOfBirth    | String | nil     | yyMMdd          |
| dateOfExpiry   | String | nil     | yyMMdd          |

#### Data Group <a href="#user-content-data-group" id="user-content-data-group"></a>

| Parameter                                | Description |
| ---------------------------------------- | ----------- |
| DG1                                      | MRZ Data    |
| DG2                                      | Image       |
| DG7, DG11, DG12, DG14, DG15, COM and SOD | -           |

### NFCViewDisplayMessage

```
case .requestPresentPassport:
    return "Hold your iPhone near an NFC enabled passport."
case .authenticatingWithPassport(let progress):
    let progressString = handleProgress(percentualProgress: progress)
    return "Authenticating with passport.....\n\n\(progressString)"
case .readingDataGroupProgress(let dataGroup, let progress):
    let progressString = handleProgress(percentualProgress: progress)
    return "Reading \(dataGroup).....\n\n\(progressString)"
case .error(let tagError):
    switch tagError {
        case NFCPassportReaderError.TagNotValid:
            return "Tag not valid."
        case NFCPassportReaderError.MoreThanOneTagFound:
            return "More than 1 tags was found. Please present only 1 tag."
        case NFCPassportReaderError.ConnectionError:
            return "Connection error. Please try again."
        case NFCPassportReaderError.InvalidMRZKey:
            return "MRZ Key not valid for this document."
        case NFCPassportReaderError.ResponseError(let description, let sw1, let sw2):
            return "Sorry, there was a problem reading the passport. \(description) - (0x\(sw1), 0x\(sw2)"
        default:
            return "Sorry, there was a problem reading the passport. Please try again"
    }
case .successfulRead:
    return "Passport read successfully"
```

#### readPassport

| Parameter            | Type                               | Default | Required   |
| -------------------- | ---------------------------------- | ------- | ---------- |
| licenseKey           | String                             | nil     | compulsory |
| mrzKey               | String                             | nil     | compulsory |
| tags                 | \[DataGroupId]                     | \[]     | optional   |
| skipSecureElements   | Bool                               | true    | optional   |
| skipCA               | Bool                               | false   | optional   |
| skipPACE             | Bool                               | false   | optional   |
| customDisplayMessage | (NFCViewDisplayMessage) -> String? | nil     | optional   |

### &#x20;<a href="#user-content-result-okaynfcresult" id="user-content-result-okaynfcresult"></a>

### Result (OkayNFCResult) <a href="#user-content-result-okaynfcresult" id="user-content-result-okaynfcresult"></a>

| Parameter          | Type   | Default |
| ------------------ | ------ | ------- |
| documentType       | String | ""      |
| documentNumber     | String | ""      |
| personalNumber     | String | ""      |
| name               | String | ""      |
| gender             | String | ""      |
| nationality        | String | ""      |
| dateOfBirth        | String | ""      |
| documentExpiryDate | String | ""      |
| faceImgPath        | URL    | nil     |

### Error Handling (NFCPassportReaderError)

The error received in the completed handler

```
case ResponseError(String, UInt8, UInt8)
case InvalidResponse
case UnexpectedError
case NFCNotSupported
case NoConnectedTag
case D087Malformed
case InvalidResponseChecksum
case MissingMandatoryFields
case CannotDecodeASN1Length
case InvalidASN1Value
case UnableToProtectAPDU
case UnableToUnprotectAPDU
case UnsupportedDataGroup
case DataGroupNotRead
case UnknownTag
case UnknownImageFormat
case NotImplemented
case TagNotValid
case ConnectionError
case UserCanceled
case InvalidMRZKey
case MoreThanOneTagFound
case InvalidHashAlgorithmSpecified
case InvalidDataPassed(String)
case NotYetSupported(String)
case InvalidLicenseKey
case PermissionDenied
case Error(String)
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://api2-ekycapis.innov8tif.com/okayid-mobile-sdk/okayid-nfc-mobile-sdk-all/development-guide.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
