Netcetera Android 3DS SDK Demo Application

This section describes the Netcetera Android 3DS SDK Demo Application.

Netcetera Android 3DS SDK Demo Application

This document provides details about the use of the Netcetera Android 3DS SDK Demo Application and sample how the Netcetera Android 3DS SDK can be integrated.

Requestor Application

The Netcetera Android 3DS SDK Demo Application represents an example integration of the Netcetera Android 3DS SDK. Along with this document, it serves as a guide for an easier integration of the Netcetera Android 3DS SDK in an application or library.

The demo application simulates a real life payment action. It contains all the cases from the frictionless and challenge flow.

When the application is started, the initial screen is payment details screen. Depending on the selected scenario, the application will present the appropriate flow.

For presenting the integration steps in proper order the Netcetera Android 3DS SDK Demo Application is configured to work with Netcetera requestor backend which is internal component and not available with 3DS SDK product. The communication protocol between the merchant application and the PSP is proprietary for that particular PSP backend only and out of the scope for our Netcetera 3DS SDK products.

Appropriate adjustments to the application shall be made in order the application to work and perform transactions.

App architecture

Regarding the app architecture, the NCA demo application implements simplified version of MVP pattern. It uses a Activity for the View, a presenter that contains the presentation logic, and use cases that contain the business logic about the use of the SDK. The application folder structure is organised by features and screen types.

Example for structure of the presentation, the src/main/.../splash folder contains the following files: * SplashContract.java - contains the interface that the view and presenter will communicate with. * SplashActivity.java - contains the view implementation of the SplashContract. * SplashPresenter.java - contains the presenter implementation of the SplashContract

Example structure of use case, the src/main/.../initialization folder contains the following files: * ThreeDSInitialization.java - use case for initialization of the ThreeDS2Service * InitializationCallback.java - callback for the result of ThreeDSInitialization

The same structure will be followed for other presentation implementations and use cases.

Intended to be used by different use cases, the Android SDK demo application uses the ThreeDS2Service as singleton instance. For getting this instance, simple Dependencies container is used. This can be found in src/main/.../Dependencies.java

The creation of the transaction in the Android SDK Demo Application is done by tapping on the submit button. The pre-defined scenarios of the frictionless and challenge flows can be found in PrefillDataPresenter. By selecting a scenario in PrefillDataActivity, you select the example which will be shown once you tap on submit.

The authentication request is created in AuthenticationRequestBuilder. Depending on the response received from the server, the application decides whether or not to opt for a challenge. An example implementation of the authentication request can be found in DsAuthentication, while the method which calls this request is located in MainPresenter.

SDK Usage

At the start of the Netcetera 3DS Android Demo Application in the SplashActivity, the Netcetera Android 3DS SDK is initialized by invoking ThreeDSInitialization. For the initialization to be successful, the Netcetera Android 3DS SDK needs to be configured with valid DS Configuration and valid licence key. Here is how this is done in this demo application:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Override
public void initializeSDK() {
  try {
    ConfigParameters configParameters = createConfigParameters();
    String deviceLocale = LocaleUtils.getDeviceDefaultLocale(applicationContext);
    UiCustomization uiCustomization = createUiCustomization();
 
    threeDS2Service.initialize(applicationContext, configParameters, deviceLocale, uiCustomization);
    callViewIfExists(SplashContract.View::onInitialized);
  } catch (SDKAlreadyInitializedException e) {
    callViewIfExists(SplashContract.View::onInitialized);
  } catch (SDKRuntimeException | InvalidInputException e) {
    callViewIfExists(SplashContract.View::onInitializationFailed);
  }
}
 
private UiCustomization createUiCustomization() {
  return new UiCustomization();
}
 
private ConfigParameters createConfigParameters() {
  ConfigParameters configParameters = DSConfigurator.configure(new ConfigParameters());
  return SdkConfigurator.provideLicensedParams(configParameters);
}

Once the SDK has been initialized, access the warnings generated during the initialization. This is done by ThreeDS2Service.getWarnings() method. For example this is performed in MainPresenter and here is the code snipped from there:

1
2
3
4
5
6
7
@Override
public void processThreeDSWarnings() {
  List<Warning> warnings = threeDS2Service.getWarnings();
  if (!warnings.isEmpty()) {
    callViewIfExists(view -> view.showWarnings(warnings));
  }
}

By tapping the submit button on the main screen, creation of transaction and sending of the Authentication Request will be performed. This logic can be found in MainPresenter.

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
@Override
public void submitTransaction(Activity activity, TransactionModel transactionModel) {
  final String dsId;
  try {
    dsId = DsIdMatcher.directoryServerIdForCard(activity, transactionModel.getAccountNumber());
  } catch (InvalidCardNumber e) {
    callViewIfExists((view -> view.onInvalidCardNumber(e.getMessage())));
    return;
  }
 
  requestStartTime = System.currentTimeMillis();
 
  Transaction transaction = threeDS2Service.createTransaction(dsId, MESSAGE_VERSION);
  AuthenticationRequestParameters authenticationRequestParameters = transaction.getAuthenticationRequestParameters();
 
  callViewIfExists(view -> view.onTransactionStarted(transaction.getProgressView(activity)));
 
  DsAuthentication dsAuthentication = new DsAuthentication(Dependencies.provideDsInterface());
  dsAuthentication.authenticate(transactionModel,
      authenticationRequestParameters,
      new DsAuthentication.AuthenticationCallback() {
        @Override
        public void onAuthenticated(AuthenticationResponse authenticationResponse) {
          handleResponseWithDelay(activity, transaction, authenticationResponse);
        }
 
        @Override
        public void onAuthenticationFailed(Throwable throwable) {
          logger.warn("Failed AuthenticationRequest.", throwable);
          callViewIfExists(view -> view.onTransactionFailed(throwable.getMessage()));
        }
      });
}

Proguard configuration

The release build type of the Netcetera Demo Application has set minifyEnabled to true, meaning that during the release task, the source code of the application and its dependencies will go through optimization and obfuscation.

For better tuning which parts of the code to be optimise and obfuscated, Proguard is used.

Proguard is taken as example configuration as most common measure of simple protection of a given application or library. The same approach should be used when using other similar tools.

Configuration Proguard files

The app/build-resources/proguard-files folder of the Netcetera Demo Merchant application, contains Proguard configuration files that are needed in order the Netcetera Android 3DS SDK to function as expected. One thing to note is that this configuration files are just an example that work for the Netcetera Demo Merchant application and may be further optimized or may not even work in a different integration environment.

The configuration for the Netcetera Android 3DS SDK is included as part of this folder as netcetera-3ds-sdk-rules.pro.

There is a separate configuration for the dependencies of the SDK that require configuration. * bouncycastle-rules.pro * okhttp-rules.pro * gson-rules.pro * okio-rules.pro * retrofit-rules.pro * logger-rules.pro * jose4j-rules.pro

Proguard Gradle setup

In the build.gradle this configurations shall be listed in order to be taken into consideration one code optimization is performed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
buildTypes {
  release {
    minifyEnabled true
    proguardFiles getDefaultProguardFile('proguard-android.txt'),
      'build-resources/proguard-rules/proguard-rules.pro',
      'build-resources/proguard-rules/netcetera-3ds-sdk-rules.pro',
      'build-resources/proguard-rules/bouncycastle-rules.pro',
      'build-resources/proguard-rules/okhttp-rules.pro',
      'build-resources/proguard-rules/gson-rules.pro',
      'build-resources/proguard-rules/okio-rules.pro',
      'build-resources/proguard-rules/retrofit-rules.pro',
      'build-resources/proguard-rules/logger-rules.pro',
      'build-resources/proguard-rules/jose4j-rules.pro'
  }
}

Logging

As the Netcetera Android 3DS SDK uses SLF4J for logging purposes, one simple configuration is to use SLF4J implementation that is using the Android Logcat. Additionally by providing different configurations for release and debug build type, logging in debug and release builds can be on different level.

Adding logback-android as dependency

To achieve this, first add logback-android logging framework as dependency in build.gradle:

1
2
3
4
5
dependencies {
  compile 'org.slf4j:slf4j-api:1.7.25'
  compile 'com.github.tony19:logback-android:1.3.0-3'
}

The configuration of logback-android is done via adding logback.xml configuration in the assets directory.

Example Debug configuration for logback-android

Sample configuration for debug builds that usually will be placed in src/debug/assets/. It will log Netcetera Android 3DS SDK info level and above in Android Logcat:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<configuration>
  <appender name="LOGCAT" class="ch.qos.logback.classic.android.LogcatAppender">
    <encoder>
      <pattern>%msg%n</pattern>
    </encoder>
  </appender>
 
  <!-- Write Netcetera Android 3DS SDK WARN (and higher-level) messages to the logcat -->
  <logger name="com.netcetera.threeds.sdk" level="WARN"/>
 
  <!-- Write global WARN (and higher-level) messages to the logcat -->
  <root level="WARN">
    <appender-ref ref="LOGCAT"/>
  </root>
</configuration>

Example Release configuration for logback-android

Sample configuration for release builds that usually will be placed in src/release/assets/. It will not log any Netcetera Android 3DS SDK in Android Logcat:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<configuration>
  <appender name="LOGCAT" class="ch.qos.logback.classic.android.LogcatAppender">
    <encoder>
      <pattern>%msg%n</pattern>
    </encoder>
  </appender>
 
  <!-- Don't write any messages from the Netcetera Android 3DS SDK to logcat -->
  <logger name="com.netcetera.threeds.sdk" level="OFF"/>
 
  <!-- Write global WARN (and higher-level) messages to the logcat -->
  <root level="WARN">
    <appender-ref ref="LOGCAT"/>
  </root>
</configuration>