OkHi Documentation
v6.0.0
Ask or search…
K

React Native Guide

Learn about OkHi's integration for verifying addresses.

1. Set up OkHi (Client-side)

The React Native Library internally uses the native iOS and android libraries. To install the OkHi React Native library, run one of the following commands in your project's directory (depending on which package manager you use):
yarn
npm
yarn add react-native-okhi react-native-webview
npm install react-native-okhi react-native-webview
Next, configure your android and iOS apps as follows:

Android

​Add the following permissions to your AndroidManifest.xml located under android/app/src/main/AndroidManifest.xml
<manifest ...>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
...
<application>
...
</application>
</manifest>
All OkHi react-native libraries target android devices >= SDK 21. Make sure you're targeting at-least the same and set compileSdkVersion & targetSdkVersion to 33 by modifying your android/build.gradle file
ext {
minSdkVersion = 21
compileSdkVersion = 33
targetSdkVersion = 33
..//
}
In your android/build.gradle add the OkHi Maven repo to the list of repositories i.e
allprojects {
repositories {
maven { url "https://repo.okhi.io/artifactory/maven" } // <- add this
..//
}
}

iOS

You would require the latest versions of Xcode & Swift.
Enable Background modes in your application.
OkHi obtains verification signals in the background, to enable this make sure to add "Location updates" and "Background fetch" to your Background Modes under Signing & Capabilities of your target.
Enable location updates, background fetch background modes
Enable "Allow Non-modular includes in Framework modules"
in the Build Settings, filter for "allow non-modular" and Enable "Allow Non-modular includes in Framework modules"
Enable "Allow Non-modular includes in Framework modules"
Filter from "other c++", and add -fcxx-modules to both debug and release
add -fcxx-modules to both debug and release
All OkHi react-native libraries target ios devices >= 12. Make sure you're targeting at-least the same by modifying your both your Podfile and deployment target.
Podfile located under: ios/Podfile
platform :ios, '12.0'
Add necessary permissions to your info.plist file located under /ios/MyApp
<key>NSLocationWhenInUseUsageDescription</key>
<string>String that explains why you need this permission</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>String that explains why you need this permission</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>String that explains why you need this permission</string>
Finally install all required pods by running the following command in the ios directory
pod install
Set up OkVerify in your AppDelegate file
Open your AppDelegate.h file located under ios/MyApp/AppDelegate.h and add the following lines
#import <React/RCTBridgeDelegate.h>
#import <UIKit/UIKit.h>
@import OkHi; // <= add this!
@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate>
@property (nonatomic, strong) UIWindow *window;
@property (strong, nonatomic) OkVerify *okverify; // <= and this!
@end
Enable background monitoring
Open your AppDelegate.m file located under ios/MyApp/AppDelegate.m and add the following lines
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.okverify = [[OkVerify alloc] init]; // add this!
if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]) // add this!
[self.okverify startMonitoring];
//.. rest of default react native code
return YES;
}

OkHi initialization

Add the following initialisation code to your App.js file in such a way that the code is executed whenever your app is opened.
Replace my_branch_id and my_client_key with the keys provided to you after sign up.
import React, {useEffect} from 'react';
import {View} from 'react-native';
import * as OkHi from 'react-native-okhi';
import AddressScreen from './AddressScreen';
const App = () => {
useEffect(() => {
OkHi.initialize({
credentials: {
branchId: '', // your branch ID
clientKey: '', // your client key
},
context: {
mode: 'prod',
},
notification: {
title: 'Address verification in progress',
text: 'Tap here to view your verification status.',
channelId: 'okhi',
channelName: 'OkHi Channel',
channelDescription: 'OkHi verification alerts',
},
})
.then(() => console.log('init done'))
.catch(console.log);
}, [])
return (
<View>
<AddressScreen />
</View>
);
};
export default App;
Test
To confirm that initialisation is working as expected, the `init done` log should be printed out in your console every time your app is opened.

Building with pro-guard enabled

If you have minifyEnabled set to true in your build.gradle file located android/app/build.gradle, you'll need to modify your proguard-rules.pro file, located android/app/proguard-rules.proas shown bellow to include classes required by the library to run.
-dontwarn sun.reflect.**
-dontwarn java.beans.**
-dontwarn sun.nio.ch.**
-dontwarn sun.misc.**
-keep class com.esotericsoftware.** {*;}
-keep class java.beans.** { *; }
-keep class sun.reflect.** { *; }
-keep class sun.nio.ch.** { *; }
-keep class com.snappydb.** { *; }
-dontwarn com.snappydb.**
# If you don't use OkHttp as a dep and the following
-dontwarn org.codehaus.mojo.animal_sniffer.*
-dontwarn javax.annotation.**
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase
-dontwarn org.codehaus.mojo.animal_sniffer.*
-dontwarn okhttp3.internal.platform.ConscryptPlatform
-dontwarn org.conscrypt.ConscryptHostnameVerifier

2. Create and verify an address (Client-side)

Add a button to your UI that would enable launching of OkHi address collection tool.
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.
See below an example using AsyncStorage.
AddressScreen.jsx
AddressScreen_with_asyncStorage.jsx
import React, {useState} from 'react';
import {Button, View} from 'react-native';
import {
isLocationServicesEnabled,
OkHiLocationManager,
request,
openAppSettings
} from 'react-native-okhi';
const AddressScreen = () => {
const [launch, setLaunch] = useState(false);
// TODO 1: Change these to your own user details
const user = {
phone: '+234xxxxx', // It is important to provide your actual phone number, as a message will be sent to this number
firstName: 'Gift',
lastName: 'Moore',
email: '[email protected]', // It is important to use your actual email address, an email may be sent to the provided address
};
const handleOnPress = () => {
// TODO 2: Show a location permissions educational primer before requesting for background location permissions.
request('always', null, async (status, error) => {
if (status === 'authorizedAlways') {
setLaunch(true);
}
/* TODO 3:
When the user does not grant location permission the first time.
1. Show a primer to educate them on how to do this in settings
2. Provide a button to send them to settings.
You may use `openAppSettings()`
*/
});
};
const handleOnSuccess = response => {
console.log(response);
response
.startVerification()
.then(async locationId => {
console.log('started verification for: ' + locationId);
})
.catch(error => {
console.log(error.code);
console.log(error.message);
})
.finally(() => {
setLaunch(false);
});
};
return (
<View>
<Button title="Create address" onPress={handleOnPress} />
<OkHiLocationManager
launch={launch}
user={user}
onCloseRequest={() => setLaunch(false)}
onError={console.log}
onSuccess={handleOnSuccess}
config={{streetView: true}}
/>
</View>
);
};
export default AddressScreen;
1
import React, {useEffect, useState} from 'react';
2
import {ActivityIndicator, Button, Text, View} from 'react-native';
3
import {
4
isLocationServicesEnabled,
5
OkHiLocationManager,
6
request,
7
openAppSettings
8
} from 'react-native-okhi';
9
import AsyncStorage from '@react-native-async-storage/async-storage';
10
11
const AddressScreen = () => {
12
const [launch, setLaunch] = useState(false);
13
const [loading, setLoading] = useState(true);
14
const [homeAddressId, setHomeAddressId] = useState(null);
15
// TODO 1: Change these to your own user details
16
const user = {
17
phone: '+2348000000000',
18
firstName: 'Gift',
19
lastName: 'Moore',
20
21
}
22
const persistAddressId = async (id, type) => {
23
try {
24
await AsyncStorage.setItem(`OkHiAddress:${type}`, id);
25
} catch (error) {
26
// Error saving data
27
}
28
};
29
const retrieveAddress = async type => {
30
try {
31
const res = await AsyncStorage.getItem(`OkHiAddress:${type}`);
32
return res;
33
} catch (error) {
34
// Error retrieving data
35
}
36
};
37
useEffect(() => {
38
setLoading(true);
39
retrieveAddress('home')
40
.then(res => {
41
setHomeAddressId(res);
42
})
43
.finally(() => {
44
setLoading(false);
45
});
46
}, []);
47
48
const style = {
49
flex: 1,
50
justifyContent: 'center',
51
alignItems: 'center',
52
};
53
54
const rationale = {
55
title: 'Location permissions',
56
text: "To verify your address, allow YOUR_APP_NAME_HERE to check your phone's location, even when you're not using the app",
57
successButton: {label: 'Grant'},
58
denyButton: {label: 'Deny'},
59
};
60
61
const handleOnPress = () => {
62
// TODO 2: Show a location permissions educational primer before requesting for background location permissions.
63
request('always', rationale, async (status, error) => {
64
const locationServicesAvailable = await isLocationServicesEnabled();
65
console.log(error);
66
if (status === 'authorizedAlways' && locationServicesAvailable) {
67
setLaunch(true);
68
}
69
/* TODO 3:
70
When the user does not grant location permission the first time.
71
1. Show a primer to educate them on how to do this in settings
72
2. Provide a button to send them to settings.
73
You may use `openAppSettings()` helper function
74
*/
75
});
76
};
77
78
const handleOnSuccess = response => {
79
console.log(response);
80
response
81
.startVerification()
82
.then(async locationId => {
83
console.log('started verification for: ' + locationId);
84
await persistAddressId(locationId, 'home');
85
setHomeAddressId(locationId);
86
})
87
.catch(error => {
88
console.log(error.code);
89
console.log(error.message);
90
})
91
.finally(() => {
92
setLaunch(false);
93
});
94
};
95
96
const RenderLoader = () => {
97
return (
98
<View style={style}>
99
<ActivityIndicator />
100
</View>
101
);
102
};
103
104
if (loading) {
105
return <RenderLoader />;
106
}
107
if (homeAddressId) {
108
return <Text>Verification started for {homeAddressId}</Text>;
109
}
110
return (
111
<View style={style}>
112
<Button title="Create address" onPress={handleOnPress} />
113
<OkHiLocationManager
114
launch={launch}
115
user={user}
116
onCloseRequest={() => setLaunch(false)}
117
onError={console.log}
118
onSuccess={handleOnSuccess}
119
config={{streetView: true}}
120
/>
121
</View>
122
);
123
};
124
125
export default AddressScreen;
If you're targeting Android versions >= 8 and you're using the OkVerify library you need to make sure your users select on "Allow always" when granting permissions otherwise the verification process won't work.
Test
If verification has started successfully:
Android:
  • a persistent notification should show, indicating that verification is on going
iOS
  • when you simulate a change in the location of the device, you should see the GPS icon lighting up at the top of the screen
Common issues:
  • if background location permission is not granted, verification will not start

3. Add address endpoint (Server-side)

Here's a sample address payload that the client would get on successful address collection:
{
"user": {
"id": "B5QgvjE8WC",
"phone": "+234xxxxx",
"firstName": "Gift",
"lastName": "Moore"
},
"location": {
"id": "8F0yPK1Zdj",
"lat": 6.442849499999999,
"lon": 3.424421,
"plusCode": "6FR5CCVF+4Q",
"propertyName": "10",
"streetName": "Raymond Njoku Street",
"title": "Raymond Njoku Street",
"subtitle": "10",
"url": "https://okhi.me/8F0yPK1Zdj",
"streetViewPanoId": "ufxEWf-zpKLcTxIe04o6Bg",
"streetViewPanoUrl": "https://maps.googleapis.com/maps/api/streetview?size=640x640&fov=45&location=6.44275037195316%2C3.424513218681455&heading=321.4785708568841&pitch=-9.5945875978788",
"userId": "B5QgvjE8WC",
"displayTitle": "10, Raymond Njoku Street",
"country": "Nigeria",
"state": "Lagos",
"city": "Eti-Osa",
"countryCode": "ng"
}
}
Create a secure endpoint on your server that your app can use to pass address details to your server. Remember to handle corner cases such as, address updates & multiple addresses if your app supports it.
Node
1
//Secure new address endpoint
2
app.post("/users/addresses", async (req) => {
3
const { user, location } = req.body;
4
const { id, firstName, lastName, phone } = user;
5
const {
6
id: locationId, displayTitle, title, subtitle, country, state, city, countryCode, lat, lon, plusCode, propertyName, streetName, url, streetViewPanoId, streetViewPanoUrl
7
} = location;
8
console.log(user, location);
9
// Store the location.id. Used to match webhook updates
10
return;
11
});

4. Handle verification events (Server-side)

OkHi sends verification status updates over a few days while verification is on going. Follow the webhook guide to setup a webhook and receive these verification status updates and run actions such as upgrading a user's KYC level.

5. Push Notification (Optional & Client-side)

Available only for Android, OkHi can reduce unknowns by strategically pinging a users device for location updated. See the code below and also click here to learn more about the full implementation and requirements.
const user: OkHiUser = {
phone: "+234xxxx",
firstName: "Jane",
lastName: "Doe",
fcmPushNotificationToken: "<MY_PUSH_NOTIFICATION_TOKEN>" //Add to your OkHi user object
}

6. Show verification status in app(Server- & Client-side)

Create a secure endpoint to enable your app to retrieve address details, including the verification status received from the webhook
Node
// Secure address retrieval endpoint
app.get("/users/addresses", (req) => {
// Get data from db. Example result:
const dbResult = {
"id": "8F0yPK1Zdj",
"status": "verified",
"displayTitle": "10, Raymond Njoku Street",
"title": "Raymond Njoku Street",
"subtitle": "10",
"country": "Nigeria",
"state": "Lagos",
"city": "Eti-Osa",
"countryCode": "ng",
}
return dbResult;
});
Show the resulting address details and status on the address page in your app.

7. Test the integration

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 OkDash
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.

8. Customise the integration

Create a location permissions primer (Required)

Create your custom location permissions primer to educate your user on the requirement for location permissions. Make sure to follow our design best practices to ensure you meet the Google Play store and AppStore requirements.

Customise OkCollect (optional)

It is possible to completely transform the default appearance of OkHiLocationManager to better match your brand by providing values to the theme prop
const theme = {
colors: {primary: '#005D67'},
appBar: {
backgroundColor: '#005D67',
logo: 'https://mydomain.com/logo.png'
},
};
<OkHiLocationManager
user={user}
launch={launch}
theme={theme} // customizes apperance of buttons and app bar
style={styles.locationManager} // customizes apperance of the wrapping container
onSuccess={handleOnSuccess}
onCloseRequest={handleCloseRequest}
onError={handleOnError}
/>

Customising address type

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.
<OkHiLocationManager
...// normal configuration
config={{ addressTypes: { home: true, work: false } }}
/>

Customise notification icon & color

You can specify a custom default icon and a custom default color by adding these lines inside the application tag to set the custom default icon and custom color. You'll need to have already created the icon resource in your android application. Icon assets can be created by following these steps
<application>
<!-- Set custom default icon for OkVerify's foreground service -->
<meta-data android:name="io.okhi.android_background_geofencing.foreground_notification_icon" android:resource="@drawable/ic_person_pin" />
<!-- Set custom default icon color for OkVerify's foreground service -->
<meta-data android:name="io.okhi.android_background_geofencing.foreground_notification_color" android:resource="@color/colorAccent" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

9. Getting ready to go live

Production credentials

Notify us that you'd like to cut a production build so we can supply production credentials.

Prepare for submission to Google Play store and App Store

Submitting an app to Google Play store and 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:

Troubleshooting

Incase you run into problems while integrating, review common issues here:

Next steps