OkHi Documentation
  • 👋Welcome Home
  • OVERVIEW
    • OkHi Product Overview
    • Integration process overview
    • Verification terminology
    • Case Studies
  • Best Practices
    • Integration Best Practices
    • Live Examples
    • Tips for PMs & QA
      • Testing & QA Guide
      • Publishing to app stores
        • Google Play store
        • Apple App Store
    • Tips for designers
  • Code Libraries
    • Developer Quick Start
      • Environment setup
      • Release Notes
    • Android Guide
      • Android Dependencies
      • Migrating to the latest library
    • iOS Guide
    • React Native Guide
      • React Native Dependencies
      • React Native troubleshoot guide
    • Expo React Native Guide
    • Flutter Guide
      • Flutter Dependencies
    • JS library
      • API Reference
      • OkCollect Webhook
      • Changelog
    • WooCommerce Plugin
      • Changelog
  • Verification Status
    • Customer Dashboard
    • Verification Status Updates
      • Webhook v3
        • Webhook Signature Verification Guide
      • Webhook v2
      • Verification Status API
      • Proof Of Address Certificate API
      • FAQs
    • API reference docs
  • Troubleshooting
    • Error Responses
    • Common technical pitfalls
    • How to reduce "Unknowns"
    • FAQs
      • Technical FAQs
      • Compliance FAQs
    • Get in touch
Powered by GitBook
On this page
  • Installation
  • Configuration
  • Permissions
  • Background Modes
  • Configure OkVerify
  • Credentials
  • Create and verify addresses
  • Digital Verification (Default)
  • Physical Verification
  • Address book only
  • Physical + Digital Verification
  • Tips & Tricks
  • Create an address and verify it later
  • Making it yours (Customise address creation experience)
  • Create home or work addresses
  • Error handling
  • Prepare for submission to the Google Play store
  • Server side integration
  • Accessing address properties
  • Handling verification events
  • Testing
  • Next steps

Was this helpful?

  1. Code Libraries

iOS Guide

Learn about OkHi's integration for verifying addresses.

PreviousMigrating to the latest libraryNextReact Native Guide

Last updated 20 days ago

Was this helpful?

Installation

The OkHi libraries are fully documented and compatible with apps supporting iOS 12 and above. You would require the latest versions of Xcode & Swift.

To install the library:

1 In Xcode, select File > Add Packages... and enter the following URL as the repository URL

Copy

https://github.com/OkHi/ios-okhi

2. Select exact version 1.9.52

3. Add the OkHi library package product to the target of your app

pod init

3. Add pod 'OkHi' to your Podfile and update iOS target to 12 and above as follows.

platform :ios, '12.0'

target 'MyAwesomeApp' do
  pod 'OkHi', '~> 1.9.45'
end

4. Run the following command:

pod install

5. Don’t forget to use the .xcworkspace file to open your project in Xcode, instead of the .xcodeproj file, from here on out.

Configuration

Permissions

Add the following permissions to your Info.plist located under the root directory of your iOS project.

<dict>
    <key>NSLocationAlwaysUsageDescription</key>
    <string>Grant to enable verifying your addresses.</string>
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>Grant to enable creating addresses at your current location.</string>
    <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
    <string>Grant to enable creating and verifying your addresses.</string>
</dict>

Background Modes

OkHi iOS library obtains and transmits verification signals in the background, to enable this make sure to add Location updates and Background fetch at Background Modes under Signing & Capabilities of your target

Configure OkVerify

As part of verification it is crucial to obtain app usage information, to enable this call the onStart static method available in the OkVerify module whenever your app launches. We recommended calling it at your SceneDelegate's sceneDidBecomeActive method like so. The SceneDelegate file is located at the root of your iOS project.

import UIKit
import OkHi

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
  func sceneDidBecomeActive(_ scene: UIScene) {
    OkVerify.onStart() // <- add this
  }
}

Credentials

import UIKit
import OkHi

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        let okHiAppContext = OkHiAppContext().withAppMeta(name: "OkHi Global", version: "1.0.0", build: "1")
        let okHiAuth = OkHiAuth(
            branchId: "<my_branch_id>",
            clientKey: "<my_client_key>",
            environment: .prod,
            appContext: okHiAppContext
        )
        OkCollect.initialize(with: okHiAuth)
        OkVerify.initialize(with: okHiAuth, launchOptions: launchOptions)
        return true
    }
}

Create and verify addresses

Always use your phone number or a phone number you own during testing as a message will be sent to this number after an address is created.

We recommend that you persist the verification state of the user in your app local storage. This state can be used to ensure that a user may only verify a predefined number of addresses. Usually one address for most use cases.

Digital Verification (Default)

import UIKit
import OkHi

class ViewController: UIViewController {
    
    private let okCollect = OkCollect()
    private let okVerify = OkVerify()
    private let okhiConfig = OkHiConfig().withUsageTypes(usageTypes: [.digitalVerification]).enableAppBar().enableStreetView()
    private let okHiTheme = OkHiTheme().with(logoUrl: "https://cdn.okhi.co/icon.png").with(appBarColor: "#333").with(appName: "OkHi")
    
    override func viewDidLoad() {
        super.viewDidLoad()
        okCollect.delegate = self
        okVerify.delegate = self
    }
    
    @IBAction func onVerifyAddressClick(_ sender: UIButton) {
      guard let vc = okCollect.viewController(with: createOkHiUser(), okHiTheme: okHiTheme, okHiConfig: okhiConfig) else { return }
      self.present(vc, animated: true, completion: nil)
    }
    
    private func startAddressVerification(response: OkCollectSuccessResponse) {
        okVerify.startAddressVerification(response: response)
    }
    
    private func createOkHiUser() -> OkHiUser {
        return OkHiUser(phoneNumber: "+2457...")
            .with(email: "jane@okhi.co")
            .with(firstName: "Jane")
            .with(lastName: "Doe")
            .with(appUserId: "abcd1234")
    }
    
    private func showMessage(title: String, message: String) {
        DispatchQueue.main.async {
            let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "Okay", style: .default))
            self.present(alert, animated: true, completion: nil)
        }
    }
}

// MARK: - OkCollectDelegate
extension ViewController: OkCollectDelegate {
    func collect(didEncounterError error: OkHiError) {
        showMessage(title: "Error: \(error.code)", message: error.message)
    }
    
    func collect(didSelectAddress response: OkCollectSuccessResponse) {
        startAddressVerification(response: response)
    }
}


// MARK: - OkVerifyDelegate
extension ViewController: OkVerifyDelegate {
    func verify(_ okverify: OkVerify, didChangeLocationPermissionStatus requestType: OkVerifyLocationPermissionRequestType, status: Bool) {
        print("permission changed")
    }
    
    func verify(_ okverify: OkVerify, didInitialize result: Bool) {
        print("init done")
    }
    
    func verify(_ okverify: OkVerify, didEncounterError error: OkVerifyError) {
        showMessage(title: "Error: \(error.code)", message: error.message)
    }
    
    func verify(_ okverify: OkVerify, didStartAddressVerificationFor locationId: String) {
        showMessage(title: "Success", message: "Started verification for \(locationId)")
    }
    
    func verify(_ okverify: OkVerify, didStopVerificationFor locationId: String) {
        showMessage(title: "Success", message: "Stopped verification for \(locationId)")
    }
    
    func verify(_ okverify: OkVerify, didUpdateLocationPermissionStatus status: CLAuthorizationStatus) {
        print("permission updated")
    }
    
    func verify(_ okverify: OkVerify, didUpdateNotificationPermissionStatus status: Bool) {
        print("notification permission updated")
    }
}

Physical Verification

If you'd like to only have physical verification done you can include the usage type as part of the okhiConfig object that's passed to OkCollect

private let okhiConfig = OkHiConfig()
  .withUsageTypes(usageTypes: [.physicalVerification])
  .enableAppBar()
  .enableStreetView()

Address book only

If you'd like to only create the address and still obtain usage data that will help verification later, you can include the usage type as part of the config object that's passed to OkCollect

private let okhiConfig = OkHiConfig()
  .withUsageTypes(usageTypes: [.addressBook])
  .enableAppBar()
  .enableStreetView()

Physical + Digital Verification

It's possible to have both physical and digital verification to run at the same time for a given address. Include both usage types as part of the array.

private let okhiConfig = OkHiConfig()
  .withUsageTypes(usageTypes: [.digitalVerification, .physicalVerification])
  .enableAppBar()
  .enableStreetView()

Tips & Tricks

Create an address and verify it later

It's possible to create an address, obtain usage data that will help verification and initiate either physical and/or digital at a later time.

The example assumes:

  1. You've securely stored previous address information either on device or server and have access to the locationId obtained in the success response of okcollect.

import UIKit
import OkHi

class ViewController: UIViewController {
    
    private let okCollect = OkCollect()
    private let okVerify = OkVerify()
    private var okhiConfig = OkHiConfig().withUsageTypes(usageTypes: [.addressBook]).enableAppBar().enableStreetView()
    private let okHiTheme = OkHiTheme().with(logoUrl: "https://cdn.okhi.co/icon.png").with(appBarColor: "#333").with(appName: "OkHi")
    
    override func viewDidLoad() {
        super.viewDidLoad()
        okCollect.delegate = self
        okVerify.delegate = self
    }
    
    @IBAction func onCreateAddressClick(_ sender: UIButton) {
        guard let vc = okCollect.viewController(with: createOkHiUser(), okHiTheme: okHiTheme, okHiConfig: okhiConfig) else { return }
        self.present(vc, animated: true, completion: nil))
    }
    
    @IBAction func onVerifySavedAddressClick(_ sender: UIButton) {
        // fetch location ID info from your db source
        let okhiLocationId = DB.fetchOkHiLocationId()
        
        // construct OkHiLocation obj
        let okhiLocation = OkHiLocation(identifier: okhiLocationId)
        
        // assuming you want to initate digital verification
        okhiConfig = OkHiConfig().withUsageTypes(usageTypes: [.digitalVerification]).enableAppBar().enableStreetView()
        
        // pass new config to okcollect
        guard let vc = okCollect.viewController(with: createOkHiUser(), okhiLocation: okhiLocation, okHiTheme: okHiTheme, okHiConfig: okhiConfig) else { return }
        
        self.present(vc, animated: true, completion: nil)
    }
    
    private func startAddressVerification(response: OkCollectSuccessResponse) {
        okVerify.startAddressVerification(response: response)
    }
    
    private func createOkHiUser() -> OkHiUser {
        return OkHiUser(phoneNumber: "+254....")
            .with(email: "jane@okhi.co")
            .with(firstName: "Jane")
            .with(lastName: "Doe")
            .with(appUserId: "abcd1234")
    }
    
    private func showMessage(title: String, message: String) {
        DispatchQueue.main.async {
            let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "Okay", style: .default))
            self.present(alert, animated: true, completion: nil)
        }
    }
}

// MARK: - OkCollectDelegate
extension ViewController: OkCollectDelegate {
    func collect(didEncounterError error: OkHiError) {
        showMessage(title: "Error: \(error.code)", message: error.message)
    }
    
    func collect(didSelectAddress response: OkCollectSuccessResponse) {
        DB.saveAddress(user: response.user, location: response.location)
        startAddressVerification(response: response)
    }
}


// MARK: - OkVerifyDelegate
extension ViewController: OkVerifyDelegate {
    func verify(_ okverify: OkVerify, didChangeLocationPermissionStatus requestType: OkVerifyLocationPermissionRequestType, status: Bool) {
        print("permission changed")
    }
    
    func verify(_ okverify: OkVerify, didInitialize result: Bool) {
        print("init done")
    }
    
    func verify(_ okverify: OkVerify, didEncounterError error: OkVerifyError) {
        showMessage(title: "Error: \(error.code)", message: error.message)
    }
    
    func verify(_ okverify: OkVerify, didStartAddressVerificationFor locationId: String) {
        showMessage(title: "Success", message: "Started verification for \(locationId)")
    }
    
    func verify(_ okverify: OkVerify, didStopVerificationFor locationId: String) {
        showMessage(title: "Success", message: "Stopped verification for \(locationId)")
    }
    
    func verify(_ okverify: OkVerify, didUpdateLocationPermissionStatus status: CLAuthorizationStatus) {
        print("permission updated")
    }
    
    func verify(_ okverify: OkVerify, didUpdateNotificationPermissionStatus status: Bool) {
        print("notification permission updated")
    }
}

Making it yours (Customise address creation experience)

It is possible to completely transform the default appearance of OkCollect to better match your brand by creating a okhiTheme object and passing it to OkCollect as shown bellow.

 private let okHiTheme = OkHiTheme()
   .with(logoUrl: "https://cdn.okhi.co/icon.png")
   .with(appBarColor: "#333")
   .with(appName: "OkHi")

Create home or work addresses

You may turn off either of the OkHi address types. This is to allow your users to create either home or work addresses to better suit your use-case. By default both address types are on.

let okHiConfig = OkHiConfig()
  .enableStreetView()
  .enableAppBar()
  .withAddressTypes(work: true, home: false)

Error handling

Both the OkCollectDelegate and OkVerifyDelegate have an didEncounterError method where you can handle errors. You have access to error.code and error.message which you can use to futher debug the address creation or verification process.

extension ViewController: OkCollectDelegate {
    func collect(didEncounterError error: OkHiError) {
        showMessage(title: "Error: \(error.code)", message: error.message)
    }
}

extension ViewController: OkVerifyDelegate {
    func verify(_ okverify: OkVerify, didEncounterError error: OkVerifyError) {
        showMessage(title: "Error: \(error.code)", message: error.message)
    }
}

Prepare for submission to the Google Play store

Submitting an app to App Store that has background location permissions has a few extra requirements. Follow these guide to know what to expect and how to handle the extra requirements:

Server side integration

Accessing address properties

const handleOnSuccess = async (response: OkCollectSuccessResponse) => {
    console.log(response.user.id); // access user properties
    console.log(response.location.id); // access location properties
    await sendToServer(response.user, response.location) // send address info to your server
    await response.startVerification(); // start verification
}

Handling verification events

Testing

Title
Scenario
How to test

Create an address

Address creation succeeds and verification is initiated

Launch OkHi's address manager via the button you created and create an address. A sticky notification appears on android.

Dashboard

When verification is initiated, the address shows up on OkHi Dashboard

Check OkDash, you should see a list of all the addresses created. It takes ~3min for addresses to show up on OkDash

Proof of address

When an address is verified, the webhook receives the status update and the app shows the correct verification status.

A proof of address certificate is made available on OkDash.

Install your app on your personal device that you move around with and create your home address. Check okDash in 3 days for your proof of address certificate once your address has been verified.

Business logic

When an address is verified or not, the correct business logic is applied successfully.

Conduct a comprehensive test with multiple users, wherein they create various addresses to observe diverse outcomes. These outcomes may include successful creation of home addresses, entering incorrect addresses, refusing to grant necessary location permissions, or uninstalling the app immediately after initiating the address verification process, among other scenarios.

Next steps

Review integration examples

If you haven’t already, install the latest version of .

2. If you don’t have an existing , run the following command at the root directory of your project, to create one:

In your AppDelegate.swift file configure the OkHi Auth object with your clientKey and branchId. Sign up . Make sure to also setup your app's context with meta data about your application

See full integration example .

See full integration example .

See full integration example .

See full integration example .

You created an address using addressBook usage type. See .

See full integration example .

On the client/app, within your onSucess handler you can access both user and address information which you can use to transit securely to your servers. See the API reference for complete list of properties on and .

Once an address has been created and you've configured a webhook in the OkHi , you'll be able to receive updates regarding address verification in your backend, which you can use to enable certain services in your app. The OkHi Dashboard allows you to do much more; please see the full documentation here.

Review

CocoaPods
Podfile
here
here
here
here
here
here
Publishing to App Store
user
location
Customer Dashboard
webhook
Digital Verification Example
Physical Verification Example
Digital and Physical Verification Example
Create and verify an address later Example
OkHi integration best practices
here