Div |
---|
class | developer-cookbook-inner-page-title |
---|
|
HTML Table |
---|
| Table Row (tr) |
---|
Table Cell (td) |
---|
| Learn how to integrate Cipher SDK on iOS device. |
|
|
|
Cipher SDK is a Two Factor Authentication (2FA) solution designed to provide a secure way of verifying transactions. This is achieved by enabling customers to verify their identity. Cipher Cipher SDK ensures a safe implementation of 2FA with minimum friction without the need of OTP generation .
In this article, SDK integration is documented in both Swift and Objective C languages.
Before you begin
Take care of the following prerequisites before you begin with SDK setup:
Fusion uses tenantAuthToken
to authenticate the SDK. To know how to create tenantAuthToken
, see Authenticating SDKwith SDK set up:
Getting Started with iOS Cipher SDK
Follow the steps below to integrate SDK:
- Download the Framework which contains the structure and required libraries for your Project.
- Now install the SDK in your First, you should add the SDK to your project or app.
- Prepare the the SDK setupset up.
- Add the implementation for Secured Store setup.
- Configure the API operations of Cipher service.
- Now the SDK setup set up is ready to begin with verifying the SDK.
- Finally, call Logout API to clear the session data.
Anchor |
---|
DownloadApolloFramework | DownloadApolloFramework- with integration process.
Anchor |
---|
| Adding the SDK |
---|
| Adding the SDK |
---|
|
Step 1: Download Adding the
FrameworkIn Fusion, the SDKs are built on top of a Framework which is a combined set of libraries to help you easily create a production-ready app, by providing a unified platform from where you can manage your app and observe the analytics of the app. The XC Framework packaging is used to package different variants of the Framework to support any platform such as iOS, macOS and others.
To add the Framework into your project, SDK
The iOS Cipher SDK is compatible with apps supporting iOS with version 10 and above. To add the SDK to your project, follow these steps:
Download and extract the below zip folder containing
an XCFramework The iOS Card SDK is compatible with apps supporting iOS 9 and above. To install the SDK, follow these steps:
an XCFramework for Cipher SDK.
Div |
---|
|
View file |
---|
name | Cipher_XCFramework.zip |
---|
height | 150 |
---|
|
|
Anchor |
---|
InstalltheSDK | InstalltheSDK | Step 2: Install the SDKDrag & drop the XCFramework manually manually into your project's target.
Image ModifiedClick Click Embed & sign under the under the XCFramework in in your project's target.
Image Modified
- Set Set Allow Non-modular Includes in Framework Modules to to "YES" under underTarget > > Build Settings.
Set Set Enable Bitcode to to "NO" under underTarget > > Build Settings.
SetuptheSDKSetuptheSDKStep 32:
Set Setting up the SDK
Follow the steps below to set up the SDK:
Configuration :You must add cipher.plist
(properties list file) to your project as it contains all the configurations Add the configuration file
A configuration file contains all the properties necessary for activating the SDK.
You You should add the file to your project (app/src/main/assets/) to prepare your app to work with the SDK. You will receive the configuration file named cipher.plist
file through email.
If you haven't received the file,
contact contact Zeta.
:To enable authentication using face recognition (Face ID), add a value to the NSfaceIdUsageDescription
(Privacy - Face ID Usage Description) with a message in the info.plist file.
However, this step is not needed if the app is providing its own secure store access.Initialize the SDK
:
The Cipher build is initialized with tenant secure store, if a new secure store is not required by the tenant. Create the ApolloCipher
instance in your AppDelegate file. Initialize it inside the [application didFinishLaunchingWithOptions:]
method of your Application class. Keep the instance for ApolloCipher
globally accessible.
Div |
---|
class | customtabs remove-codeblock-space |
---|
|
|
instancelet import CipherFramework
@UIApplicationMain
Class AppDelegate {
var cipher: ApolloCipher?
func application:(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionKey: Any]?) -> Bool {
let builder = ApolloCipherBuilder()
|
|
|
|
.setSecureStore(tenantSecureStore builder.setSendPushForSandbox(true) // |
|
|
|
AppSecuredStoreAccess. Set this false when you are archiving for App Store. By Default, this is set as false.
builder.setSecureStore(securedStoreAccess) //AppSecuredStoreAccess - To be provided when using |
|
|
|
the
setViewContext(viewController)//AninstanceofUIViewControllertoshowmodals. Not required if using tenant secured store
.build()
= builder.build()
//…
}
//...
} |
|
|
|
instance | #import <CipherFramework/CipherFramework.h>
@interface AppDelegate()
@property (nonatomic, strong) ApolloCipher *cipher;
@end
@implementation AppDelegate
-(BOOL) application:(UIApplication*) application didFinishLaunchingWithOptions:(NSDictionary *) launchOptions {
ApolloCipherBuilder *builder = [ApolloCipherBuilder new];
[builder |
|
|
|
setSecureStore:appSecureStoreAccesssetSendPushForSandbox: YES]; // Set this as NO when you are archiving for App Store. By Default, this is set as NO.
[builder setSecureStore:securedStoreAccess]; // AppSecuredStoreAccess |
|
|
|
. - To be provided when using |
|
|
|
the tenant secured store.
self.cipher = [builder |
|
|
|
setViewContext:viewController]; An instance of UIViewController to show modals. Not required if using tenant secured store
ApolloCipher *cipher = [builder build]; Anchor |
---|
SetuptheSecuredStore | SetuptheSecuredStore | Step 4: Set up the Secured StoreFor setting up
Anchor |
---|
| IntegratingtheSDK |
---|
| IntegratingtheSDK |
---|
|
Step 3: Integrating the SDKCipher SDK is a stateful SDK. Before you start using the Cipher SDK features, take care of the following:
Registering the SDK
Cipher SDK registration triggers the authentication of the SDK using an authentication token. This token is also called a JSON Web Token (JWT) token. Please ensure to set a valid JWT token every time to register the SDK. We recommend calling the method inside the following Application function. To know how to create the authentication token, see Authenticating SDK. You require this token in Authentication API request.
Div |
---|
dir | lrt |
---|
class | customtabs remove-codeblock-space |
---|
|
Div |
---|
| Div |
---|
| Code Block |
---|
theme | Midnight |
---|
title | Registering the SDK |
---|
linenumbers | true |
---|
| func applicationDidBecomeActive(_ application: UIApplication) {
cipher?.authenticate(tenantToken: tenantTokenView.text)
//...
} |
|
Div |
---|
| Code Block |
---|
theme | Midnight |
---|
title | Registering the SDK |
---|
linenumbers | true |
---|
| - (void)applicationDidBecomeActive:(UIApplication *)application {
[self.cipher authenticateWithToken:<JWT_TOKEN>];
//...
} |
|
|
|
Note |
---|
If you are using Scenes for iOS 13, do the registration in the sceneDidBecomeActive method in your applicable SceneDelegate . |
Setting up the Secured Store
Cipher SDK maintains various pieces of sensitive information like Super PIN, secrets. The SDK stores this sensitive information in a Secured Store. Cipher SDK supports the following Secured Store implementations:
SDK implementation
Cipher SDK provides an implementation of the Secured Store out of the box. The SDK provided secured store supports the following:
SDK Super PIN:
The SDK uses 4 digit SDK PIN, if you haven't enabled the device lock to access your custom secured store. In this case, the SDK prompt you to set up the SDK PIN for securing sensitive data.
Note |
---|
Ensure you run setModalPresenterScreen before accessing the Super PIN and Swipe to Authenticate functionalities . |
Hosting app’s custom implementation
If you want your custom secured Store, provide an implementation for AppSecuredStoreAccess
using setSecureStore:
in CipherBuilder
. This interface enables the secured store to store sensitive data.
For setting up the Secured Store, you must provide an implementation for AppSecuredStoreAccess
protocol. This protocol enables the Cipher SDK to securely store/retrieve sensitive data into your secure store. The protocol is responsible for four different functionalities as mentioned below Secured Store. To adhere to the protocol, implement the following functionalities:
dataforKey:completion
: to fetch data from the store for a particular key.
setDataforKey:completion
: to set data in the store for a particular key.
resetAllData
: to reset all the data in store.
containsKey
: to check if data for a key exists.
If you haven't provided access to your Secured Store and the device lock is also disabled, contact Zeta for assistance.
Div |
---|
class | customtabs remove-codeblock-space |
---|
|
Div |
---|
| Div |
---|
| Code Block |
---|
theme | Midnight |
---|
title | App Secured Store Access protocol |
---|
linenumbers | true |
---|
| @protocol AppSecuredStoreAccess {
func data(forKey key: String, completion: ((Error?, Data?) -> Void)? = nil)
func setData(_ data: Data?, forKey key: String, completion: ((Error?) -> Void)? = nil)
func resetAllData()
func containsKey(_ key: String) -> Bool
} |
|
Div |
---|
| Code Block |
---|
theme | Midnight |
---|
title | App Secured Store Access protocol |
---|
linenumbers | true |
---|
| @protocol AppSecuredStoreAccess
- (void)dataForKey:(NSString *_Nonnull)key
completion:(nullable void (^)(NSError * _Nullable error, NSData * _Nullable data))completion;
- (void)setData:(NSData *_Nullable)data forKey:(NSString *_Nonnull)key completion:(nullable void (^)(NSError * _Nullable error))completion;
- (void)resetAllData;
- (BOOL)containsKey:(NSString *_Nonnull) key; |
|
|
|
Anchor |
---|
ConfiguretheSDK | ConfiguretheSDK | Step 5: Configure the SDKSetting up the state change listener
You can configure instruct the SDK by providing the implementation for the following APIs based on your requirement:
Authenticate the SDK
An authentication token is required to authenticate the SDK. This is an initial state of the SDK which is achieved on clean install.
Check the state of Cipher SDKIf a call to isTenantAuthTokenRequired()
returns true, you should provide tenantAccessToken
by triggering authenticate(tenantToken:String!)
.
Div |
---|
dir | lrt |
---|
to perform actions based on your configurations. After the Secured Store is set up, you can decide the actions to be taken as shown in the code snippet below:
Div |
---|
class | customtabs remove-codeblock-space |
---|
|
Div |
---|
| Div |
---|
| Code Block |
---|
theme | Midnight |
---|
title | Cipher state change listener |
---|
linenumbers | true |
---|
collapse | true |
---|
| cipher?.add(listener: <ApolloCipherStateChangeListenerImplementation>)
cipher?.authenticate(tenantToken: tenantTokenView.text)
// In Implementation of ApolloCipherStateChangeListener protocol
- (func) stateChanged {
if(cipher?.isSecureStoresetupRequired())
cipher?.setModalPresenterScreen(<TopViewController>)
cipher?.set upSecuredStore()
} else if (cipher?.canGenerateSuperPin()) {
//Now Cipher SDK is ready to generate Super PIN and handle Swipe To Authenticate requests
} else {
cipher?.logout()
}
} |
|
Div |
---|
| Code Block |
---|
theme | Midnight |
---|
title | Cipher state change listener |
---|
linenumbers | true |
---|
collapse | true |
---|
| [self.cipher addStateChangeListener:<ApolloCipherStateChangeListenerImplementation>]
[self.cipher authenticateWithToken:<JWT_TOKEN>];
// In Implementation of ApolloCipherStateChangeListener protocol
- (void) stateChanged {
if ([self.cipher isSecureStoreset upRequired]) {
[self.cipher setModalPresenterScreen:<TopViewController>]
[self.cipher setupSecuredStore];
} else if ([self.cipher canGenerateSuperPin]) {
//Now Cipher SDK is ready to generate Super PIN and handle Swipe To Authenticate requests
} else {
[self.cipher logout]
}
} |
|
|
|
Setting up Swipe to Authenticate
The Swipe to Authenticate flow is set up along with the setting up the state change listener flow. At Zeta, we use Apple Push Notification Service (APNs) to deliver Swipe to Authenticate notifications to your app . You should set up push notifications for your app if you have not done that already. Here are the details on how to do this. After setting up the push notifications for your app, share your p8 file, team id and push notification key with our team at Zeta . We will use your APNs key to deliver notifications to your app from our server.
Syncing the push token
You should override your [application:didRegisterForRemoteNotificationsWithDeviceToken:]
inside your AppDelegate
and convert the received push token to string. Now call updatePushToken: method whenever you receive a callback for the new push token . This helps the SDK to keep the push token synced in our servers and ensure a hassle-free push experience. You can use the following code snippet:
Div |
---|
class | customtabs remove-codeblock-space |
---|
|
Div |
---|
| Div |
---|
| Code Block |
---|
theme | Midnight |
---|
title | Syncing the push token |
---|
linenumbers | true |
---|
| func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }
let token = tokenParts.joined()
cipher?.updatePushToken(token)
} |
|
Div |
---|
| Code Block |
---|
theme | Midnight |
---|
title | Syncing the push token |
---|
linenumbers | true |
---|
| - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
const unsigned *tokenBytes = [deviceToken bytes];
NSString *hexToken = [NSString stringWithFormat:@"%08x%08x%08x%08x%08x%08x%08x%08x",
ntohl(tokenBytes[0]), ntohl(tokenBytes[1]), ntohl(tokenBytes[2]),
ntohl(tokenBytes[3]), ntohl(tokenBytes[4]), ntohl(tokenBytes[5]),
ntohl(tokenBytes[6]), ntohl(tokenBytes[7])];
[self.cipher updatePushToken:hexToken];
} |
|
|
|
Listen to Swipe to Authenticate Push
When you receive a push notification inside the overridden didReceiveRemoteNotificationmethod
of your AppDelegate
, you should relay that remote notification received to Cipher SDK . You can use processSwipe2PayRemoteNotification:presentingWindow
method to relay the push message object to the Cipher SDK . You can use the following code snippet:
Div |
---|
class | customtabs remove-codeblock-space |
---|
|
|
isTenantAuthTokenRequired(title | Listen to Swipe to Authenticate Push |
---|
linenumbers | true |
---|
| func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> |
|
|
|
boolVoid) {
if let cipher = cipher {
if cipher.canProcessRemoteNotification(userInfo) {
cipher.processSwipe2PayRemoteNotification(userInfo, presenting: window!)
}
}
} |
|
Div |
---|
| Code Block |
---|
theme | Midnight |
---|
title | Listen to Swipe to Authenticate Push |
---|
linenumbers | true |
---|
| - ( |
|
|
|
BOOL isTenantAuthTokenRequired Info |
---|
- We recommend updating
tenantAuthToken token at every app launch. This ensures hassle-free creation of auth resource by the SDK whenever needed. tenantAuthToken must be generated on the server-side as it involves signing the data with a private key. The private key must never be compromised.
|
Create an authentication tokenThis method authenticates a tenant user by providing a tenantAuthToken
to the SDK.application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
if([self.cipher canProcessRemoteNotification:userInfo]) {
[self.cipher processSwipe2PayRemoteNotification:userInfo presentingWindow:self.window];
}
} |
|
|
|
API Reference
Cipher SDK provides a set of public APIs which are useful to set up the SDK and access its functionalities.
Authentication
This API authenticates and provides you the access to the SDK. You should pass the authentication token (tenantToken
) in this API request.
Div |
---|
class | customtabs remove-codeblock-space |
---|
|
Div |
---|
| Div |
---|
| Code Block |
---|
| authenticate(tenantToken: |
|
|
|
String Div |
---|
| Code Block |
---|
| - (void) authenticateWithToken:(NSString *) tenantToken |
|
|
|
Set up Secured Store
If a call to isSecureStoreSetUpRequiredisSecureStoresetupRequired()
returns returns true, you are ready to set up the Secured Store by triggering the setUpSecuredStorethe setupSecuredStore()
.
- Check the state of Cipher SDK
If this method returns true, the SDK requires a Secured Store setup set up.
Div |
---|
class | customtabs remove-codeblock-space |
---|
|
Div |
---|
| Div |
---|
| Code Block |
---|
| isSecureStoreSetUpRequiredisSecureStoresetupRequired()-> bool |
|
Div |
---|
| Code Block |
---|
| - (BOOL) isSecureStoreSetUpRequiredisSecureStoresetupRequired |
|
|
|
- Call setUpSecuredStore setupSecuredStore API
This method triggers setup set up of secure storage. Ensure this method is called only if isSecuredStoreSetupRequiredif isSecuredStoresetupRequired()
returns returns true, else this leads the SDK into an unusable state. Post this step, SDK will be able to setup set up the Super PIN.
Div |
---|
class | customtabs remove-codeblock-space |
---|
|
Div |
---|
| Div |
---|
| Code Block |
---|
| setUpSecuredStoresetupSecuredStore() -> void |
|
Div |
---|
| Code Block |
---|
| - (void) setUpSecuredStoresetupSecuredStore |
|
|
|
Generate Super PIN
If a call to canGenerateSuperPin()
returns returns true, you can generate a Super PIN to secure the store by triggering triggering generateSuperPin(completion: String, Error)
.
- Check the state of Cipher SDK
If this method returns true, the Super PIN setup set up is done. If the Super PIN functionality doesn’t work, the SDK might be in an error state. In such scenario, logout logout and then run the whole SDK from beginning.
Div |
---|
class | customtabs remove-codeblock-space |
---|
|
Div |
---|
| Div |
---|
| Code Block |
---|
| canGenerateSuperPin()-> bool |
|
Div |
---|
| Code Block |
---|
| - (BOOL) canGenerateSuperPin |
|
|
|
- Create Super PIN
This method returns the Super PIN on providing authentication to the Secured Store or a device lock. Use this Super PIN to authorize the payment.
Div |
---|
class | customtabs remove-codeblock-space |
---|
|
Div |
---|
| Div |
---|
| Code Block |
---|
| generateSuperPin(completion:SuperPinFetchBlock) -> (String?, Error?)->Void ) -> voidvoid |
|
Div |
---|
| Code Block |
---|
| - (void) generateSuperPinWithCompletion:(SuperPinFetchBlock) completion |
|
|
|
Set up the modal presenter screen
Set the parent ViewController on top of which we want to show the PIN or device lock. This option should be used when the secured store is set up using the SDK’s implementation .
Div |
---|
dir | lrt |
---|
class | customtabs remove-codeblock-space |
---|
|
Div |
---|
| Div |
---|
| Code Block |
---|
| setModalPresenterScreen:(_ modalPresenter: UIViewController) |
|
Div |
---|
| Code Block |
---|
| - (void) setModalPresenterScreen: (UIViewController *)modalPresenter; |
|
|
|
Handle notification
You can listen to any change in the state of Cipher SDK integration such as, when an authentication token is required, is Secured Store set up required, can Super PIN be generated. To listen to SDK updates, you must implement the protocol ApolloCipherStateChangeListener.
Div |
---|
dir | lrt |
---|
class | customtabs remove-codeblock-space |
---|
|
Div |
---|
| Div |
---|
| Code Block |
---|
| canProcessRemoteNotification(_ userInfo: NSDictionary) -> bool |
|
|
|
void) generateSuperPinWithCompletion:(SuperPinFetchBlock) completionBOOL) canProcessRemoteNotification:(NSDictionary *)userInfo |
|
|
|
Please ensure that you call this method on every update of the firebase push token. See Monitor token generation for more details.
Div |
---|
dir | lrt |
---|
class | customtabs remove-codeblock-space |
---|
|
Div |
---|
| Div |
---|
| Code Block |
---|
| updatePushToken(_ pushToken:String) |
|
Div |
---|
| Code Block |
---|
| - (void) updatePushToken:(NSString *) pushToken |
|
|
|
Manage Listener
You can listen to any change in the state of Cipher SDK integration such as, when an authentication token is required, is Secured Store set up required, can Super PIN be generated.
Anchor |
---|
CipherServiceActions | CipherServiceActions | Step 6: Verify the SDKYou can instruct the SDK to perform actions based on your configurations. After the Secured Store is setup, you can decide the actions to be taken as shown in the code snippet below:set up a remote notification to process the Swipe to Authenticate.
Div |
---|
class | customtabs remove-codeblock-space |
---|
|
|
title | Adding implementation |
---|
linenumbers | true |
---|
collapse | true |
if(cipher.isTenantAuthTokenRequired()) {
// The SDK is in uninitialized state. You should provide ‘tenantAccessToken’ by triggering 'cipher.authenticate(with:)' API
} else if (cipher.isSecureStoreSetUpRequired()) {
// You are ready to setup the Secure Store by triggering 'setUpSecuredStore()' API
} else if (cipher.canGenerateSuperPin()) {
// You are ready to trigger 'cipher.generateSuperPin(completion:)' API
} else {
// The SDK is in a corrupt state. You can trigger logout() API to reset the SDK
}processSwipe2PayRemoteNotification:(_ userInfo:NSDictionary, presentingWindow window:UIWindow) |
|
|
|
title | Adding implementation |
---|
linenumbers | true |
---|
collapse | true |
---|
if([_cipher isTenantAuthTokenRequired]) {
// The SDK is in uninitialized state. You should provide ‘tenantAccessToken’ by triggering [_cipher authenticateWithToken:] API
} else if ([_cipher isSecureStoreSetUpRequired]) {
// You are now ready to setup the secure store by triggering [_cipher setUpSecuredStore] API
} else if ([_cipher canGenerateSuperPin]) {
// You are ready to trigger [_cipher generateSuperPinWithCompletion:] API
} else {
// The SDK is in a corrupt state. You can trigger [_cipher logout] API to reset the SDK
} |
Anchor |
---|
Logout | Logout | Step 7: Logout- (void) processSwipe2PayRemoteNotification:(NSDictionary *)userInfo presentingWindow:(UIWindow *) window |
|
|
|
Logout
When a user logs out from the app, ensure that you clear all the session data.
A A default call to Logout method is important for the SDK to work properly in next login session.
A simple logout is available by using:
Div |
---|
class | customtabs remove-codeblock-space |
---|
|
|
title | Logout |
self.cipherManagertitle | Logout |
cipherManagerExceptions and Error Codes
This section explains section explains various exceptions and error codes thrown by the Cipher SDK and how to handle themhandle them. Exceptions provide system error codes along with Throwable message, that helps to recognize and troubleshoot the issue.
All the exceptions thrown will have the following fields in addition to the messagethe message:
code
: Error code related to the response.traceId
: Trace ID which can be provided to Zeta support for identifying the root cause.errorType
: Type of error.
There are two kinds of exception that Cipher SDK can throw:
SdkAuthException
CipherException
The following table lists the error codes, descriptions and possible solutions. If If the issue persists, contact contact Zeta.
Error Code | Description |
---|
3000
| Exception thrown due to bad request. |
3001 | Internal server error. Try again. |
1001 | Internal SDK error. Try logging out and out and then log in. |
2000 | Authentication of tenantAuthToken JWT token can fail due to the following potential reasons: - Token is signed with an invalid private key.
- Token does not contain the configured claim.
- Token has expired.
|
2001 | Internal error caused while trying to authenticate the user. |
1001 | Error occurred when the user cancels the secure store setupset up. |
Info |
---|
There will be other error codes that will be thrown from the SDK with appropriate message. For any assistance, contact contact Zeta. |