• Credit

    US flag
  • Credit

    US flag

Android SDK Setup

This section will explain how to setup the Fusion card SDK for your android application.

Get access to the Cards Sdk

We host all our SDKs on a remotely accessible Maven Repository. Add the following lines of code to your project-level build.gradle file.

Switch Theme
Expand More
Copy
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
allprojects {
    repositories {
        ....
        maven {
            credentials  {
                username = "<usename>"
                password = "<password>"
            }
            url 'https://apollo-sdk.zetaapps.in/repository/maven-releases/'
            authentication {
                basic(BasicAuthentication)
            }
        }
        ....        
    }
}
Code Copied

Adding Card SDK to your android project

The following instructions will guide you in adding the cards SDK to your android project and enabling the flow of transactions.

  1. Add the following cards SDK dependency on your app-level gradle file (usually named as app.gradle or build.gradle)
Switch Theme
Expand More
Copy
1
2
3
4
5
dependencies {
    ............
    implementation 'in.zeta.apollo:cards:<latest-version>'
    .............
}
Code Copied
  1. If you’re using Kotlin as the primary programming language, add the following JVM target to your project.
Switch Theme
Expand More
Copy
1
2
3
4
5
6
7
android {
  ........
  kotlin_options = {
         jvmTarget = "1.8"
  }
  .......
}
Code Copied
  1. If you face any issues with packaging, use the following custom packaging options.
Switch Theme
Expand More
Copy
1
2
3
4
5
6
7
8
android {
..........
  packagingOptions {
     exclude 'META-INF/library_release.kotlin_module'
     exclude 'META-INF/DEPENDENCIES'
  }
.......
}
Code Copied

Adding permissions to Android Manifest

Add the following permissions to your app’s AndroidManifest.xml. Cards SDK uses these permissions to get the network state.

Switch Theme
Expand More
Copy
1
2
3
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
Code Copied

Adding the Config file to your project

Zeta will provide you the cards.json file which needs to be copied into the ​​app/src/main/assets folder of your project. A sample config file will look like this:

Switch Theme
Expand More
Copy
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
{
 "tenantId": <tenantId>,
 "projectId": <projectId>,
 "appId": "<appId>",
 "sdkName": "<sdkName>",
 "platform": "android",
 "sdkVersion": "<latestSdkVersion>",
 "sdkConfigVersion": "<configVersion>",
 "sdkConfigCollectionId": "<sdkConfigCollectionId>",
 "sdkConfigItemId": "<sdkCOnfigItem>",
 "authId": "<authId>",
 "apiKey": "<apiKey>",
 "sdkAuthBaseUrl": "<baseUrl>",
 "cardsApiBaseUrl": "<baseUrl>",
 "omsBaseUrl": "<baseUrl>",
 "apolloUserBaseUrl": "<baseUrl>",
 "ifiTenantId": <ifiTenantId>,
……………………….
}
Code Copied

Adding theme and template files

Cards SDK provides you with the flexibility to define its theme and layout, so that it could adhere with your application’s design. Themes can be edited remotely so you don’t have to modify the build everytime you make any modifications. When working with first-time initializations, it’s preferable to ship a local copy of the files and define it in your project. Add the themes and layout files received from Zeta into the app/src/main/assets/collections folder of your project. If you don’t have the collections folder already, it is recommended to create a new folder and add the files into it.

Once you’ve added the theme files into the collections folder, the folder hierarchy will look like this:

Adding fonts to your project

Add your font files into the app/src/main/assets/fonts folder of your project. You can provide font files in either ttf or otf formats.

You have now successfully completed the initial steps in the SDK setup process.

Creating an instance for Card SDK

Once you have completed all the above steps, you are now ready to create an instance of CardsService. Add the following code to your project’s Application Class (create one if not already available). Inside the Class, add the following code.

Switch Theme
Expand More
Copy
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
private static final String IBXPLEXSANS_REGULAR_FONT_PATH = "fonts/IBMPlexSans-Regular.otf";
private static final String IBXPLEXSANS_MEDIUM_FONT_PATH = "fonts/IBMPlexSans-Medium.otf";
private static final String IBXPLEXSANS_SEMI_BOLD_FONT_PATH = "fonts/IBMPlexSans-SemiBold.otf";
private static final String IBXPLEXSANS_BOLD_FONT_PATH = "fonts/IBMPlexSans-Bold.otf";
private static final String OCRA_STD_FONT_PATH = "fonts/OCRAStd.otf";

private static final Map<String, String> fontMap = new HashMap<>();

static {
   fontMap.put("IBMPlexSans-Regular".toLowerCase(), IBXPLEXSANS_REGULAR_FONT_PATH);
   fontMap.put("IBMPlexSans-Medium".toLowerCase(), IBXPLEXSANS_MEDIUM_FONT_PATH);
   fontMap.put("IBMPlexSans-SemiBold".toLowerCase(), IBXPLEXSANS_SEMI_BOLD_FONT_PATH);
   fontMap.put("IBMPlexSans-Bold".toLowerCase(), IBXPLEXSANS_BOLD_FONT_PATH);
   fontMap.put("OCRAStd".toLowerCase(), OCRA_STD_FONT_PATH);
}

@Override
public void onCreate() {
   super.onCreate();

   setupCardsSdk();
}

private void setupCardsSdk() {
   new CardsServiceBuilder(this)
           .setLoggingEnabled(true)
           .setSecuredStoreTitle(R.string.title)
           .setSecuredStoreSubtitle(R.string.subtitle)
           .setFontMap(fontMap)
           .useDoor()
           .build();



   // Can get the CardsService instance once it is built.
   cardsService = CardsService.getInstance();
}
Code Copied
Switch Theme
Expand More
Copy
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
private val IBMPLEXSANS_REGULAR_FONT_PATH = "fonts/IBMPlexSans-Regular.otf"
private val IBMPLEXSANS_MEDIUM_FONT_PATH = "fonts/IBMPlexSans-Medium.otf"
private val IBMPLEXSANS_SEMI_BOLD_FONT_PATH = "fonts/IBMPlexSans-Semibold.otf"
private val IBMPLEXSANS_BOLD_FONT_PATH = "fonts/IBMPlexSans-Bold.otf"
private val OCRA_STD_FONT_PATH = "fonts/OCRAStd.otf"

private val fontMap: MutableMap<String, String> = HashMap()

init {
   fontMap["IBMPlexSans-Regular".toLowerCase()] = IBMPLEXSANS_REGULAR_FONT_PATH
   fontMap["IBMPlexSans-Medium".toLowerCase()] = IBMPLEXSANS_MEDIUM_FONT_PATH
   fontMap["IBMPlexSans-Semibold".toLowerCase()] = IBMPLEXSANS_SEMI_BOLD_FONT_PATH
   fontMap["IBMPlexSans-Bold".toLowerCase()] = IBMPLEXSANS_BOLD_FONT_PATH
   fontMap["OCRAStd".toLowerCase()] = OCRA_STD_FONT_PATH
}

override fun onCreate() {
   super.onCreate()
   setupCardsSdk()
}

private fun setupCardsSdk() {
   CardsServiceBuilder(this)
       .setLoggingEnabled(true)
       .setSecuredStoreTitle(R.string.title)
       .setSecuredStoreSubtitle(R.string.subtitle)
       .setFontMap(fontMap)
       .useDoor()
       .build()


   // Can get the CardsService instance once it is built.
   val cardsService = CardsService.getInstance()
}
Code Copied
  • setSecuredStoreTitle: Pass the string resource for your application name. This is used to display over the device lock screen during user authentication. Note: This is a mandatory field. An exception will be thrown if this is empty.

  • setSecuredStoreSubtitle: Pass the string resource for your sub-title that needs to be displayed over the lock screen. Note: This is a mandatory field. An exception will be thrown if this field is empty.

  • setFontMap: Create a font map and set it to the builder. The card SDK will then use the mentioned fonts while rendering the views offered by the SDK. The file names present on this map correspond to the files that are present inside the assets folder.

  Notes:
  You can invoke CardsServiceBuilder(..) only once per app session. To get an instance of CardsService anywhere in your application, use the below code snippet.
  It is recommended to create the CardsService instance as the first step when the app is launched. You can do it inside your Application class.
Switch Theme
Expand More
Copy
1
final CardsService cardsService = CardsService.getInstance();
Code Copied
Switch Theme
Expand More
Copy
1
val cardsService = CardsService.getInstance()
Code Copied

Authenticating Card SDK

Once the user has logged into your android app, you’ll already have a session recorded for the logged-in user. Authentication of that user is required in the issuer’s domain since their details are present with the issuer. This authentication will ensure that the logging-in user is an account holder on your application domain and this will prevent unauthorized entry.

You can authenticate the Cards SDK by invoking the SDK’s authenticateSDK function. The function expects a JWT token referred to as tenantAuthToken in the subsequent discussion. The tenantAuthToken contains the account holder ID in the issuer’s domain as “claim” of the JWT token. The tenantAuthToken needs to be computed securely in your backend as it needs sensitive information to create the token.

When the user is logging into the app, the logic should fetch the tenantAuthToken from your backend service. This is a one-time activity and can be clubbed with the login flow of your android application.

Validity of tenantAuthToken

The validity of the tenantAuthToken can be kept the same as the validity of the logged-in user of the mobile app.

Once the mobile app has fetched the tenantAuthToken, it should initiate the SDK Authentication flow as suggested in the code snippet below. This is a one-time activity and should be only done along with the login flow of the app.

Switch Theme
Expand More
Copy
1
2
final String tenantAuthToken = myBackendService.issueAuthToken(userInfo);
CardsService.getInstance().authenticateSDK(tenantAuthToken, accountHolderId);
Code Copied
Switch Theme
Expand More
Copy
1
2
val tenantAuthToken: String = myBackendService.issueAuthToken(userInfo)
CardsService.getInstance().authenticateSDK(tenantAuthToken, accountHolderId)
Code Copied

Setting up the SDK

This step triggers the actual setting up of the Cards SDK. Once this step is completed, the SDK will initiate background sync of the user’s card details. You will need to set up encrypted storage which is behind device lock or custom app pin authentication.

For secure storage, the SDK always prefers device lock over custom app pin authentication. Setting up secure storage may require the user to provide device lock authentication. For example, if the user has a fingerprint mechanism to unlock their mobile, we can simply utilize that data in our SDK. In the case of custom app pin authentication, users have to provide a 4-digit pin while logging in. The first invocation of the setupSDK function call may require user intervention. Any subsequent invocation will not require any user intervention.

Switch Theme
Expand More
Copy
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);

   CardsService.SdkInitListener sdkInitListener = (success, exp) -> {
       // Handle the response here ...
   };
   CardsService.getInstance().setupSDK(this, sdkInitListener, null, null);

   setupView();
}
Code Copied
Switch Theme
Expand More
Copy
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
   super.onCreate(savedInstanceState, persistentState)
   setContentView(R.layout.activity_main)

   val sdkInitListener = object: CardsService.SdkInitListener {
       override fun done(success: Boolean, exp: Throwable?) {
           // Handling of success/failure goes here.
       }
   }
   getInstance().setupSDK(this, sdkInitListener, null, null)

   setupView()
}
Code Copied

setupSDK call should be made during every app launch, right after the SDK authentication step. Ideally, you could add this as part of the onboarding flow of the app. During the subsequent app launches, the function should be called as early as possible. You can invoke the call inside the onCreate() method of the app launching activity on mobile. Under the hood, the setupSDK function enables the SDK to set up secure storage.

Once the secure storage is set up, the function triggers the SDK to sync the card details of that user in the background. The card details are fetched from the issuer’s domain, and the SDK then persists in the secure storage for subsequent offline access. This process will happen for the first time app launch, only if the secure storage is unlocked. For subsequent requests, the secure storage doesn’t need to be unlocked.

If in case the SDK needs the storage to be unlocked at any given time, the SdkInitListener will fire an event “Secure_Storage_Unlock_Required”.

SdkInitListener

The setupSDK function takes as input a listener which provides regular updates about the status of the SDK setup. The various events thrown by the listener are mentioned below:

  • Secure_Storage_Setup_Done: This event represents the completion of the secure storage setup. At this point, the SDK will trigger the background sync of the card details.
  • Background_Sync_Done: This event indicates that all the card details have been successfully synced from the server.
  • Card_Details_Persisted_To_Secure_Storage: Successful persistence of card details into the secure storage. This marks the completion of the setup now that the details are available for offline access.
  • Secure_Storage_Unlock_Required: Requirement for the SDK to unlock the secure storage.