iOS Dynamic SDK Integration
Sample Project
You can find the sample project for a complete iOS Integration in dynamic mode.
If you require more control over the journey and order of the steps or show custom screens between ID verification steps, you can use IDWise SDK in dynamic mode. This mode allows you to start specific steps and for you application to regain control after each step. Please note this integration mode requires more code and responsibility on your side.
For an overview for end to end sequence diagram refer to Dynamic SDK Integration Overview.
Starting a new journey in dynamic mode
IDWise SDK is designed to start on top of a UIViewController in your application. Each user onboarding or verification transaction is named a user journey.
To start a new dynamic journey just provide the UIViewController from which you want the flow to start then call IDWise.initialize
method first with your provided client key and then you can call IDWise.startDynamicJourney
method. If initialization is failed for any reason, you will get an error object with a code and a message explaining the reason of the error. In the following example, we called initialize method and then called startJourney method.
The IDWiseSDK.initialize method accepts clientKey and theme as It's parameters.The theme parameter is for specifying the theme (dark or light). If you want the SDK to be in the same theme mode as set in system display settings, you need to pass IDWiseSDKTheme.systemDefault
. However, if the OS is in dark mode and you want the SDK to be in light mode (or vice versa), you can pass the appropriate value for the theme parameter.
Possible values for the theme parameter include IDWiseSDKTheme.light
,IDWiseSDKTheme.dard
and IDWiseSDKTheme.systemDefault
.
IDWiseSDKTheme.light // to specify light theme mode for SDK
IDWiseSDKTheme.dark // to specify dark theme mode for SDK
IDWiseSDKTheme.systemDefault // to specify the same theme as of operating system
IDWise.initialize(clientKey: "<YOUR_CLIENT_KEY>",theme: .systemDefault) { error in
// Deal with error here
print(error?.message)
}
IDWise.startDynamicJourney(journeyDefinitionId: "<FLOW_ID>", referenceNumber: "<YOUR_REFERENCE_NO>", locale: "en", journeyDelegate: self, stepDelegate: self)
This will make IDWise SDK start a journey and make it the current journey. You can next start steps of this journey and guide the user through completing the necessary steps in the desired order.
This method takes following parameters:
journeyDefinitionId
: (aka Flow ID) This is a unique identifier that identifies your journey flow. IDWise shares this with you when you register to use IDWise system.referenceNumber
: (Optional) This parameter allows you to attach a unique identifier (such as a reference number) with the user undergoing the current journey. It's beneficial for connecting the journey to the user and/or the application that initiated it. You will receive this reference number in the webhook request.locale
(Optional) : Language code of the language to be used to display the journey user interface. This is either an ISO 639-1 (2-letter for example en) or IETF BCP 47 (2-letter plus extended language specified for example zh-HK or zh-CN)journeyDelegate
: This parameter is used to provide a set of event handlers to handle the different events that are triggered from IDWise SDK. These events indicate the lifetime of a journey and provide oppurtunity for your application to react to certain journey events.stepDelegate
: This parameter is used to provide a set of event handlers to handle the different events that are triggered from IDWise SDK. These events indicate the lifetime of a verification step and provide oppurtunity for your application to react to certain step events.
Resuming a Journey
Step 1
You can resume any exiting incomplete journey at any time. Following is sample code how to resume an existing journey in Dynamic Mode:
IDWise.resumeDynamicJourney(journeyDefinitionId: "<FLOW_ID>"// provided by IDWise,
journeyId: "<JOURNEY_ID>",
locale: "en",
journeyDelegate: self,
stepDelegate: self)
This method takes following parameters:
flowId
: (also called Journey Definition ID): This is a unique identifier that identifies your journey flow. IDWise shares this with you when you register to use IDWise system.journeyId
: Identifier of the journey you want to resume. You get this identifier inonJourneyStarted
callback when you started the journey first time.locale
(Optional) : Language code of the language to be used to display the journey user interface. This is either an ISO 639-1 (2-letter for exampleen
) or IETF BCP 47 (2-letter plus extended language specified for examplezh-HK
orzh-CN
)journeyDelegate
: This parameter is used to provide a set of event handlers to handle the different events that are triggered from IDWise SDK. These events indicate the lifetime of a journey and provide opportunity for your application to react to certain journey events.stepDelegate
: This parameter is used to provide a set of event handlers to handle the different events that are triggered from IDWise SDK. These events indicate the lifetime of a verification step and provide opportunity for your application to react to certain step events.
Step 2
As resumeDynamicJourney
is an async method so you need to wait for its completion before starting a step. Once resumeDynamicJourney
method completes, the onJourneyResumed
callback from journeyDelegate
will be invoked. You can conform to IDWiseSDKJourneyDelegate
protocol like this:
extension ViewController:IDWiseSDKJourneyDelegate {
func onError(error: IDWiseSDKError) {
// Your code to handle errors
}
func JourneyCancelled() {
// Your code to handle cancellation
}
func JourneyStarted(journeyID: String) {
// Your code to handle starting a fresh journey
// STEP_ID is the id of the step you want to start that is not concluded
DispatchQueue.main.async {
IDWise.startStep(stepId: "STEP_ID")
}
}
func onJourneyResumed(journeyID: String) {
// STEP_ID is the id of the step you want to start that is not concluded
DispatchQueue.main.async {
IDWise.startStep(stepId: "STEP_ID")
}
}
func JourneyFinished() {
// Your code to handle journey completion
}
}
Starting the Steps
After calling startJourney
method and subsequently when JourneyStarted
method is triggered successfully, you can call the IDWise.startStep
method.
IDWise.startStep(stepId: String)
IDWise.startStep
method takes the following parameter:
stepId: ID of the step you want to start. (Will be provided by IDWise for each step)
You can also pass a PDF or an Image as Data
and for that you can use following method named startStepFromFileUpload
.
Important Note: Size of the Data should be less then or equal to 4Mb. Following is an example
IDWise.startStepFromFileUpload(stepId: String, data: Data)
IDWise.startStepFromFileUpload
method takes the following parameter:
stepId: ID of the step you want to start. (Will be provided by IDWise for each step)
data: Data representation of an image file or a PDF file ( Data bytes must be less than or equal to 4Mb )
The methods in IDWiseStepDelegate
will be triggered as step is handled and processed
Skipping the Step
When onJourneyStarted(...)
or onJourneyResumed(...)
are triggered successfully, you can call the IDWise.skipStep(...)
to skip any verification Step.
IDWise.skipStep(stepId: String)
This method takes only one parameter:
stepId
: ID of the step you want to skip. (Will be provided by IDWise for each step)
The step events (provided in IDWiseSDKStepCallback parameter provided to startDynamicJourney or resumeDynamicJourney method) will be triggered as step is skipped.
Step Callbacks
We can implement the protocol IDWiseSDKStepDelegate
as an extension on the ViewController same way as above to recieve the step events:
extension ViewController:IDWiseSDKStepDelegate {
// This method will be triggered when user has captured the image/selfie from the camera
func onStepCaptured(stepId: Int, capturedImage: UIImage) {
// An example of showing custom UI
LoadingView.show()
}
//This method will be triggered when Image processing is completed at the backend.
//stepId will be the Id of the step that is just completed
func onStepResult(stepId: Int,stepResult: StepResult?) {
// An example of showing custom UI
LoadingView.hide()
if let result = stepResult {
print(result.document?.documentType)
}
}
// This method will be triggered when user press the back button and IDWise UI is dimissed and control is back with HostingApp
func onStepCancelled(stepId: String) {
}
// This method will be triggered when hosting app calls IDWise.skipStep and step is skipped successfully
func onStepSkipped(stepId: String) {
}
func onStepConfirmed(stepId: String) {
}
}
-
onStepCaptured
: This handler will be triggered when user has captured the document or selfie. Control will be returned to your application by this point and you can show any UI or run business logic to guide the user through the rest of the journey. At this point the captured image will have started uploading to backend in the background but would have not finished processing. This method is triggered up to two times (if document has two sides). -
onStepResult
: This handler will be triggered when step has finished processing. stepResult will contain information about the corresponding step. Your application can show any UI or can perform any business logic in this method. This method is always triggered only once per step even If document has two sides. -
onStepCancelled
: This handler will be triggered when step is cancelled by the user. This can happen when user presses back button until IDWise UI is dismissed and control is back with hosting application. -
onStepSkipped
: This handler will be triggered when hosting app will call IDWise.skipStep(stepId:).This callback will only be called If step is skipped successfully.
From stepResult
variable in onStepResult(...)
callback, you can receive the extracted fields. And if the validation is failed, you can get the failure code as stepResult.failureReasonCode
StepResult contains following information
Field | Type | Description |
---|---|---|
recognition | DocumentRecognition | Document recognition information |
extractedFields | Map of String and FieldValue | Information extracted from the document such as Name and Birth Date |
hasPassedRules | Boolean | Whether the step passes the validity checks |
isConcluded | Boolean | Whether the user can still retry the step or not |
status | String | Processing status one of (In Progress , Submitted , Not Submitted ) |
errorUserFeedbackCode | String | A code that can be used to indicate the error. All the error feedback codes can be found here. |
errorUserFeedbackDetails | String | details for the error message directed at the user, providing feedback in case an error occurs during the step. |
errorUserFeedbackTitle | String | A title for the error message directed at the user, providing feedback in case an error occurs during the step. |
nfcResult | NFCResult | Result from NFC chip reading |
The DocumentRecognition object contains the following information related to the scanned document.
Field | Type | Description |
---|---|---|
issuingCountryCode | String | Country of issue as ISO 3166-1 alpha-3 country code |
issuingCountryName | String | Name of country of issue |
documentType | String | Type of the Document, either a Identity Card , Passport , Commercial Licence , Driving Licence , Practice Permit , Residence Permit , Utility Bill , Vehicle Licence , Vaccination Card , Work Permit , Car Registration , Travel Document , Car Ownership , Visa , Vehicle Registration , Proof of Address , Other Forms , Insurance Certificate , Birth Certificate , Registration Certificate , Tax Document , National Insurance Document , Military ID , Voter Card , Archive Only . |
The FieldValue object has the following properties
Field | Type | Description |
---|---|---|
value | String | The value of the field |
The NFCResult object contains the following data extracted from the Document via reading the NFC chip
Field | Type | Description |
---|---|---|
facePhoto | Bitmap | Image of the user which is extracted from NFC chip scanning |
extractedFields | Map of String and FieldValue | Information extracted from the NFC chip scanning |
All extractedFields
from the NFC can be found here
Finishing the Journey
You need to call this IDWise.finishDynamicJourney()
method to mark the journey complete. This method will mark the current dynamic journey as finished. The method will throw error through onError(error: IDWiseSDKError)
if anything goes wrong.
Get Summary of the Verification Journey
You can call this method IDWise.getJourneySummary(callback: @escaping ((JourneySummary?,IDWiseSDKError?)->()))
method anytime to get status of your journey. You will receive a callback with JourneySummary
or an IDWiseSDKError
in case anything fails at server side or in authentication.
IDWise.getJourneySummary(callback: { summary,error in
})
JourneySummary
contains the following information
Field | Type | Description |
---|---|---|
journeyId | String | A unique identifier for the user journey. |
isCompleted | Boolean | A boolean field that indicates if the journey is completed or not. |
stepSummaries | List of StepSummary | An array of objects that detail the steps the user has gone through in the journey. Each object in this array contains a definition and a result. |
journeyResult | JourneyResult | Result and Status of the verification Journey as described below |
StepSummary
contains the following information
Field | Type | Description |
---|---|---|
definition | StepDefinition | An object that describes the step. |
result | StepResult | An object that contains the result of the step. |
StepDefinition
contains the following information
Field | Type | Description |
---|---|---|
step_id | Int | An identifier for the step within the journey. |
JourneyResult
contains the following information
Field | Type | Description |
---|---|---|
completedSteps | Int | Number of completed steps in the journey |
interimRuleAssessment | InterimRuleAssessment | Enum for the combined Interim rules assessment result [Passed, Failed] |
interimRuleDetails | HashMap<String, RuleDetail> | Hashmap of all the Rules Assessment Results applicable |
RuleDetail
contains the following information
Field | Type | Description |
---|---|---|
name | String | Name of the Rule |
result | Result of the Rule Assessment | Enum for the combined Interim rules assessment result [Passed, Failed, CouldNotApply] |
Error Feedbacks
You can access the table of error feedbacks, which includes descriptions for each of the feedback codes on here
Unloading the SDK
You can unload the SDK when it is no longer required to free up the resources
IDWise.unloadSDK()
Sample Project
You can find the sample project for a complete iOS Integration in dynamic mode.
Managing Device Orientation
IDWise SDK only supports portrait orientation for Its screens. If you are supporting multiple orientations other than portrait then you either need to lock your full app to portrait or you can use our helper class that locks the orientation for our SDK screens only.
- You need to add following struct in your code.
struct AppUtility {
static func lockOrientation(_ orientation: UIInterfaceOrientationMask) {
if let delegate = UIApplication.shared.delegate as? AppDelegate {
delegate.orientationLock = orientation
}
}
/// OPTIONAL Added method to adjust lock and rotate to the desired orientation
static func lockOrientation(_ orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation:UIInterfaceOrientation) {
self.lockOrientation(orientation)
UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation")
UINavigationController.attemptRotationToDeviceOrientation()
}
}
- You need to add following code in your AppDelegate.swift class.
/// set orientations you want to be allowed in this property by default
var orientationLock = UIInterfaceOrientationMask.all
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return self.orientationLock
}
- Now before starting Initialising and starting IDWise journey, you can lock the orientation using follow code.
AppUtility.lockOrientation(.portrait)
- After IDWise journey is finished or cancelled, you can unlock the orientation again so It can again support multiple orientations for your application screens.
extension ViewController:IDWiseSDKJourneyDelegate {
func onError(error: IDWiseSDKError) {
}
func JourneyStarted(journeyID: String) {
}
func onJourneyResumed(journeyID: String) {
}
func JourneyCancelled() {
AppUtility.lockOrientation(.all)
}
func JourneyFinished() {
AppUtility.lockOrientation(.all)
}
}
Error Codes
Error Code | Error Description |
---|---|
11 | Invalid/Empty Parameter (Client key is empty or Invalid) |
22 | SDK is not initialized. Please Call IDWise.initialize(:) first |
33 | Wrong API credentials (Client Key) provided |
44 | Empty journeyId is provided to resume journey. |
45 | Provided file size is exceeding the maximum file size |
66 | No step found against provided stepId to start. |
70 | Invalid step Id provided, please provide a valid stepId. |
-101 | An unexpected error occurred while processing the request.Make sure you have Internet connected |
-102 | Network seems to be not connected, Please try again with network connected. |
55 | This method is not supported in this Journey Mode |
NFC Extracted Fields
Field Name |
---|
Full Name |
First Name |
Last Name |
Birth Date |
Expiry Date |
Issue Date |
Document Number |
Issuing Authority |
Issuing Country |
Issuing Country Code |
Machine Readable Zone |
Machine Readable Zone Type |
Nationality |
Nationality Code |
Personal Number |
Sex |
Keep in touch
Please get in touch if you want to make any adjustments or customisations to your users journey.
Please feel free to jump on a chat by visiting our website: <www.idwise.com>
Updated about 2 months ago