Accounts SDK for iOS

The Accounts SDK is a solution to ease the integration with the Alviere services.

Features

  • Account Management
  • Account Addresses Management
  • Account Dossiers Management

Requirements

  • iOS 13.0+
  • Xcode 15+
  • Swift 5.5+

Installation

Swift Package Manager

1. Add the dependency to your project. Open your project and navigate to your project’s settings. Select the tab named Swift Packages and click on the add button + at the bottom left.

image

2. Enter the url of Accounts SDK for the iOS repository (https://github.com/Alviere/alviere-accounts-ios) in the text field and click Next.

image

3. On the next screen, select the SDK version and click Next.

image

4. Select the AccountsSDK package and click Finish.

image

5. Repeat the same process for AlCore SDK (https://github.com/Alviere/alviere-core-ios). The current version is compatible with AlCore SDK version 0.9.0 and up.

CocoaPods

1. Get the latest version of CocoaPods, if you haven’t already.

2. Create the Podfile by running the following command, if you don’t have one already.

pod init

3. Add this line to your Podfile.

pod 'AccountsSDK'

4. Run the following command to install the library. Also, run this to update to newer releases in the future.

pod install

Carthage

1. Get the latest version of Carthage, if you haven’t already.

2. Add the following entries in your Cartfile:

binary https://raw.githubusercontent.com/Alviere/alviere-core-ios/master/AlCore.json
binary https://raw.githubusercontent.com/Alviere/alviere-camera-ios/master/AlCamera.json
binary https://raw.githubusercontent.com/Alviere/alviere-accounts-ios/master/AccountsSDK.json

3. Run the following command to download the latest version of the SDK.

carthage update --use-xcframeworks

4. Follow the Manual instructions below to embed the SDK into your project.

Manual

1. Get the latest versions of AccountsSDK.xcframework, its dependencies, and AlCore.xcframework and embed it into your application by dragging and dropping the files onto the Frameworks, Libraries and Embedded Content project section, as shown below.

image

2. Depending on the location of the xcframeworks on the filesystem you may need to change the Framework Search Paths build setting to avoid the error: fatal error: ‘AccountsSDK/AccountsSDK.h’ file not found. For example, the Xcode project below have it set to FRAMEWORK_SEARCH_PATHS = $(PROJECT_DIR)/../ since the xcframeworks files are shared between them and are kept in the directory that also contains the project directories.

image

Usage

To initialize the Accounts SDK for iOS, you need to set the Environment at the entry point of your application. For example, you can do this on your AppDelegate file on the application(_:,didFinishLaunchingWithOptions:) method, as shown below.

import AlCore

...

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Setup Alviere SDK.
    if !AlCoreSDK.shared.setEnvironment(.sandbox) {
        print("Error initializing SDK.")
    }
    return true
}

After this setup, you just need to import the Accounts SDK for iOS on the files where you want to use the features.

import AccountsSDK

Optionally, if you will use the Add/Update/Replace Dossier features you have to adjust your app’s permissions for camera usage. You just need to add the NSCameraUsageDescription in your Info.plist file. Right-click somewhere outside the table and select Add Row. Now add the entries like below.

image

Or if you prefer to do this step with code, right-click on Info.plist and select Open As > Source Code. Add the lines below somewhere inside the <dict> </dict>.

<!-- Permission to be include in Info.plist -->
<key>NSCameraUsageDescription</key>
<string>This will let you easily take pictures of your Documents so we can verify your identity.</string>

When writing the permission request message always follow the iOS Human Design Guidelines as a guideline.

Account Management

List Accounts

To list accounts, use listAccounts where you will need to pass the auth_token.

let response = try await AlAccounts.shared
    .listAccounts(
        token: authToken,
        query: query
    )

This action will return a Account list or throw an EventError. The keys for the EventError metadata field are defined on the Metadata enum.

Get Account

To get an account, use getAccount where you will need to pass the auth_token and pass the accountUuid.

let response = try await AlAccounts.shared
    .getAccount(
        token: authToken,
        accountUuid: accountUuid
    )

This action will return a Account or throw an EventError. The keys for the EventError metadata field are defined on the Metadata enum.

Update Account

To update an account, use updateAccout where you will need to pass the auth_token, pass the accountUuid and the AccountUpdateRequest model with the data.

let request = AccountUpdateRequest( ... )

let response = try await AlAccounts.shared
    .updateAccout(
        token: authToken,
        accountUuid: accountUuid,
        data: request
    )

This action will return a Account or throw an EventError. The keys for the EventError metadata field are defined on the Metadata enum.

Account Addresses Management

Create Account Address

To create an address, use createAddress where you will need to pass the auth_token, pass the accountUuid and the AccountAddressRequest model with the data.

let request = AccountAddressRequest( ... )

let response = try await AlAccounts.shared
    .createAddress(
        token: authToken,
        accountUuid: accountUuid,
        data: request
    )

This action will return a AccountAddress or throw an EventError. The keys for the EventError metadata field are defined on the Metadata enum.

List Account Addresses

To list addresses, use listAddresses where you will need to pass the auth_token and pass the accountUuid.

let response = try await AlAccounts.shared
    .listAddresses(
        token: authToken,
        accountUuid: accountUuid
    )

This action will return a AccountAddress list or throw an EventError. The keys for the EventError metadata field are defined on the Metadata enum.

Update Account Address

To update an address, use updateAddress where you will need to pass the auth_token, pass the accountUuid, pass the addressUuid and the AccountAddressRequest model with the data.

let request = AccountAddressRequest( ... )

let response = try await AlAccounts.shared
    .updateAddress(
        token: authToken,
        accountUuid: accountUuid,
        addressUuid: addressUuid,
        data: request
    )

This action will return a AccountAddress or throw an EventError. The keys for the EventError metadata field are defined on the Metadata enum.

Delete Account address

To delete an address, use deleteAddress where you will need to pass the auth_token, pass the accountUuid and pass the addressUuid.

try await AlAccounts.shared
    .deleteAddress(
        token: authToken,
        accountUuid: accountUuid,
        addressUuid: addressUuid
    )

This action will not return a response but can throw an EventError. The keys for the EventError metadata field are defined on the Metadata enum.

Account Dossier Management

Create Account Dossier

To create a dossier, use createDossier where you will need to pass the auth_token, pass the accountUuid and the AccountDossierRequest model with the data.

let request = AccountDossierRequest( ... )

let response = try await AlAccounts.shared
    .createDossier(
        token: authToken,
        accountUuid: accountUuid,
        data: request
    )

This action will return a AccountDossier or throw an EventError. The keys for the EventError metadata field are defined on the Metadata enum.

List Account Dossiers

To list dossiers, use listDossiers where you will need to pass the auth_token and pass the accountUuid.

let response = try await AlAccounts.shared
    .listDossiers(
        token: authToken,
        accountUuid: accountUuid
    )

This action will return a AccountDossier list or throw an EventError. The keys for the EventError metadata field are defined on the Metadata enum.

Get Account Dossier

To get a dossier, use getDossier where you will need to pass the auth_token, pass the accountUuid and pass the dossierUuid.

let response = try await AlAccounts.shared
    .getDossier(
        token: authToken,
        accountUuid: accountUuid,
        dossierUuid: dossieruuid
    )

This action will return a AccountDossier or throw an EventError. The keys for the EventError metadata field are defined on the Metadata enum.

Update Account Dossier

To update a dossier, use updateDossier where you will need to pass the auth_token, pass the accountUuid, pass the dossierUuid and the AccountDossierUpdateRequest model with the data.

let request = AccountDossierUpdateRequest( ... )

let response = try await AlAccounts.shared
    .updateDossier(
        token: authToken,
        accountUuid: accountUuid,
        dossierUuid: dossierUuid,
        data: request
    )

This action will return a AccountDossier or throw an EventError. The keys for the EventError metadata field are defined on the Metadata enum.

Replace Account Dossier

To replace a dossier, use replaceDossier where you will need to pass the auth_token, pass the accountUuid, pass the dossierUuid and the AccountDossierUpdateRequest model with the data.

let request = AccountDossierUpdateRequest( ... )

let response = try await AlAccounts.shared
    .replaceDossier(
        token: authToken,
        accountUuid: accountUuid,
        dossierUuid: dossierUuid,
        data: request
    )

This action will return a AccountDossier or throw an EventError. The keys for the EventError metadata field are defined on the Metadata enum.

Delete Account Dossier

To delete a dossier, use deleteDossier where you will need to pass the auth_token, pass the accountUuid and pass the dossierUuid.

try await AlAccounts.shared
    .deleteDossier(
        token: authToken,   
        accountUuid: accountUuid,
        dossierUuid: dossierUuid
    )

This action will not return a response but can throw an EventError. The keys for the EventError metadata field are defined on the Metadata enum.

Upload Account Dossier

Upload Account Dossier UI Presentation

ℹ️

Be aware that you should request camera permission before presenting the upload dossier UI or it will be requested when presented.

To deposit a check, use createDossierUploadView where you will need to pass the auth_token, pass the cameraToken, pass the documentTypes, pass the AccountDossierUploadRequest model with the data and pass the onCompletion handler.

let cameraToken = try await AlCore.shared.getCameraToken(accountUUID: accountUUID)
let request = AccountDossierUploadRequest( ... )

struct MyView: View {
    var body: some View {
        AlAccounts.userInterface.createDossierUploadView(
            token: authToken,
            cameraToken: cameraToken,
            documentTypes: [.driverLicenseFront, driverLicenseBack, .selfie],
            data: request,
            overlay: nil, // Optional custom overlay.
            loading: nil, // Optional custom loading.
            failure: nil // Optional custom error.
        ) {
            switch $0 {
            case let .success(dossier):
                // Handle success.
            case let .failure(error):
                // Handle error
            }
        }
    }
}

Capture Document UI Presentation

ℹ️

Be aware that you should request camera permission before presenting the capture document UI or it will be requested when presented.

To capture a check, use createCaptureDocumentView where you will need to pass the cameraToken, pass the cameraConfig and pass the onCompletion handler.

let cameraToken = try await AlCore.shared.getCameraToken(accountUUID: accountUUID)

struct MyView: View {
    var body: some View {
        AlAccounts.userInterface.createCaptureDocumentView(
            cameraToken: cameraToken,
            cameraConfig: cameraConfig,
            overlay: nil // Optional custom overlay.
        ) {
            switch $0 {
            case let .success(capture):
                // Handle success.
            case let .failure(error):
                // Handle error
            }
        }
    }
}

Overlay Customization

To customize the Overlay you can provide a ALCameraOverlayStyle implementation.

class MyOverlayStyle: ALCameraOverlayStyle {
    func makeTitle(content: Content) -> some View {
        // Customize content.
    }

    func makeDescription(content: Content) -> some View {
        // Customize content.
    }

    func makeStep(content: Content) -> some View {
        // Customize content.
    }

    func makeHint(content: Content) -> some View {
        // Customize content.
    }

    func makeSuccess(content: Content) -> some View {
        // Customize content.
    }

    func makeAcceptButton(content: Content) -> some View {
        // Customize content.
    }

    func makeRetakeButton(content: Content) -> some View {
        // Customize content.
    }

    func makeShutterButton(content: Content) -> some View {
        // Customize content.
    }

    func makeFlashButton(content: Content) -> some View {
       // Customize content.
    }

    func makeCloseButton(content: Content) -> some View {
        // Customize content.
    }
}

ALCameraOverlayView()
    .alCameraOverlayStyle(MyOverlayStyle())

You can also implement your own overlay. An ALCameraContext environment object with all the data and bindings required to create the overlay will be provided.

struct MyOverlayView: View {
    @EnvironmentObject
    var context: ALCameraContext

    var body: some View {
        // Implement overlay here.
    }
}

To provide a custom overlay configuration you can create a ALCameraConfiguration with your overlay configuration. An ALCameraContext environment object with all the data and bindings required to create the overlay will be provided.

struct MyFrameView: View {
    @EnvironmentObject
    var context: ALCameraContext

    var body: some View {
        // Implement frame here.
    }
}

var cameraConfig = ALCameraConfiguration.checkFront
cameraConfig.overlay.title = "my_title_string_key"
cameraConfig.overlay.description = "my_description_string_key"
cameraConfig.overlay.frame = MyFrameView()

AlAccounts.userInterface.createCaptureDocumentView(
    cameraToken: cameraToken,
    cameraConfig: cameraConfig
) { ... }

Loading Customization

To customize the Loading you can provide a custom view.

struct MyLoadingView: View {
    var body: some View {
        // Implement loading here.
    }
}

Failure Customization

To customize the Failure you can provide a ALFailureStyle implementation.

class MyFailureStyle: ALFailureStyle {
    func makeMessage(content: Content) -> some View {
        // Customize content.
    }

    func makeRetryButton(content: Content) -> some View {
        // Customize content.
    }

    func makeCancelButton(content: Content) -> some View {
        // Customize content.
    }
}

ALFailureView()
    .alFailureStyle(MyFailureStyle())

You can also implement your own failure. An ALFailureContext environment object with all the data and bindings required to create the failure will be provided.

struct MyFailureView: View {
    @EnvironmentObject
    var context: ALFailureContext

    var body: some View {
        // Implement failure here.
    }
}

UI Localization

To localize the UI you will need to create a ALCameraConfiguration with your bundle and string table. The keys you need to provide are listed in Text and Localization.

var cameraConfig = ALCameraConfiguration.checkFront
cameraConfig.bundle.bundle = myBundle
cameraConfig.bundle.table = "myStringsCatalog"

AlAccounts.userInterface.createCaptureDocumentView(
    cameraToken: cameraToken,
    cameraConfig: cameraConfig
) { ... }

Fraud Prevention Service

The Accounts SDK has a built-in fraud prevention service. This service is automatically activated when you Update an User Account. If you already have an account created and want to activate the service on the next app run you just need to set the accountUuid on the service as the user id. For example, you can do this on your AppDelegate file on the application(_:,didFinishLaunchingWithOptions:) method, as shown below.

import AlCore

...

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Setup Alviere SDK.
    if !AlCoreSDK.shared.setEnvironment(.sandbox) {
        print("Error initializing SDK.")
    }

    // Start fraud prevention service.
    AlCoreSDK.shared.startFraudPrevention()
    AlCoreSDK.shared.setUserId(accountUuid)
    return true
}

To fully enable the service you need to do a small setup by adding the add the LSApplicationQueriesSchemes array in your Info.plist file. Right-click somewhere outside the table and select Add Row. Now add the entries like below.

image

Or if you prefer to do this step with code, right-click on Info.plist and select Open As > Source Code. Add the lines below somewhere inside the <dict> </dict>.

<!-- Fraud prevention setup to be included in Info.plist -->
<key>LSApplicationQueriesSchemes</key>
<array>
  <string>cydia</string>
</array>

Text and Localization

The Accounts SDK for iOS allows you to customize the UI text. To do so, you will need to redefine the localization key that you want to change on your Localizable.strings file. The next section details a list of the current localization keys. Currently, the SDK only provides english localization.

Localization Keys

Key English Value
alviere_sdk_camera_driver_license_back Driver’s License Back
alviere_sdk_camera_driver_license_back_description Place ID on a flat surface. Please no fingers, hands or reflections.
alviere_sdk_camera_driver_license_front Driver’s License Front
alviere_sdk_camera_driver_license_front_description Place ID on a flat surface. Please no fingers, hands or reflections.
alviere_sdk_camera_failure_view_cancel Cancel
alviere_sdk_camera_failure_view_message An error occurred
alviere_sdk_camera_failure_view_retry Try again
alviere_sdk_camera_hint_angle_too_large Angle too large
alviere_sdk_camera_hint_busy_background Busy background
alviere_sdk_camera_hint_data_obstructed Data obstructed
alviere_sdk_camera_hint_face_center Center face in the oval
alviere_sdk_camera_hint_face_get_closer Get closer
alviere_sdk_camera_hint_face_get_farther Get farther
alviere_sdk_camera_hint_face_hold_device_upright Hold device upright
alviere_sdk_camera_hint_face_hold_still Hold still
alviere_sdk_camera_hint_face_low_lighting Increase light on face
alviere_sdk_camera_hint_face_no_face No face detected
alviere_sdk_camera_hint_face_smile Smile!
alviere_sdk_camera_hint_face_stop_smiling Stop smiling
alviere_sdk_camera_hint_glare Reduce glare
alviere_sdk_camera_hint_hold_steady Hold still
alviere_sdk_camera_hint_low_contrast Low contrast
alviere_sdk_camera_hint_not_identity_back Not document back
alviere_sdk_camera_hint_not_identity_front Not document front
alviere_sdk_camera_hint_not_passport Not passport
alviere_sdk_camera_hint_not_sharp Not sharp
alviere_sdk_camera_hint_nothing Nothing detected
alviere_sdk_camera_hint_rotation Reduce rotation
alviere_sdk_camera_hint_too_bright Too bright
alviere_sdk_camera_hint_too_close Too close
alviere_sdk_camera_hint_too_dim Too dim
alviere_sdk_camera_hint_too_far Too far
alviere_sdk_camera_id_document_back ID Document Back
alviere_sdk_camera_id_document_back_description Place ID on a flat surface. Please no fingers, hands or reflections.
alviere_sdk_camera_id_document_front ID Document Front
alviere_sdk_camera_id_document_front_description Place ID on a flat surface. Please no fingers, hands or reflections.
alviere_sdk_camera_ine_document_back INE Back
alviere_sdk_camera_ine_document_back_description Place ID on a flat surface. Please no fingers, hands or reflections.
alviere_sdk_camera_ine_document_front INE Front
alviere_sdk_camera_ine_document_front_description Place ID on a flat surface. Please no fingers, hands or reflections.
alviere_sdk_camera_mc_document_back Matrícula Consular Back
alviere_sdk_camera_mc_document_back_description Place ID on a flat surface. Please no fingers, hands or reflections.
alviere_sdk_camera_mc_document_front Matrícula Consular Front
alviere_sdk_camera_mc_document_front_description Place ID on a flat surface. Please no fingers, hands or reflections.
alviere_sdk_camera_passport Passport
alviere_sdk_camera_passport_description Place ID on a flat surface. Please no fingers, hands or reflections.
alviere_sdk_camera_preview_accept Accept photo
alviere_sdk_camera_preview_retake Retake
alviere_sdk_camera_preview_success Success
alviere_sdk_camera_preview_title Photo preview
alviere_sdk_camera_proof_of_address Proof of Address
alviere_sdk_camera_proof_of_address_description Place ID on a flat surface. Please no fingers, hands or reflections.
alviere_sdk_camera_proof_of_funds Proof of Funds
alviere_sdk_camera_proof_of_funds_description Place ID on a flat surface. Please no fingers, hands or reflections.
alviere_sdk_camera_selfie Face
alviere_sdk_camera_selfie_description Smile to automatically grab your picture.
alviere_sdk_camera_step %lld %lld Step %1$lld of %2$lld