User Lifecycle & Card Management API & SDK

User registration and lifecycle management. Server-2-server integration. Mobile DC SDK

Introduction

The main purpose of Verestro Lifecycle API & SDK web service is to add and manage user and payment cards in a safe way. All data are transfered to Verestro Data Core system which is placed in PCI compliant zone and is fully secure. By registering in the database, the partner can use various services provided by the Verestro i.e. Card Issuing, Card tokenization, Money Transfers and more.

The API allows to mass import of data files to Verestro systems, such as: user, user with a card, or cards. Using the HTTPS REST protocol, Partner can add a new resource (user or cards), update their status, e.g. lock, unlock or completely remove a resource from system.

Once connected to the partner's application, the SDK enables full user management and securing the connection to all Verestro products. Our SDK was develop for iOS and Android  platforms.

The Mobile DC SDK is a core module dedicated to the management of users, devices, and cards in the Verestro system. Usage of other Verestro modules (f.e. UCP - Verestro Claud Payment) always depends on this SDK and Mobile DC must be always used.

Main responsibilities Lifecycle API:

  • user - end user management in system,
  • cards - card management in system,
  • addresses - module related to user resource.

Main responsibilities Lifecycle SDK:

Overview

Lifecycle API The main purpose of a web service is to add a user and payment cards in a safe way to dedicated database PCI DSS compliant systems, which are provided by Verestro. By registering in the database, the partner can use various services provided by the Verestro company, e.g. Card Issuing, Card tokenization, Money Transfers and more. The API allows to mass import of data files to Verestro systems, such as: user, user with a card, or cards. Using the HTTPS REST protocol, you can add a new resource (user or cards), update their status, e.g. lock, unlock or completely remove a resource from system.

LIfecycle API is an internal service secured by x509 certificate, which increases the safety of transported data. The API communicates with the data storehouse called DataCore. DataCore is internal service and one of crucial components of Verestro's product line-up. Its main responsibility is to provide secure, PCI-DSS compliant storage for cardholder data. DataCore manages the status of the user and their aggregates. All other product in implementation connect to DataCore which returns information about the user and his aggregates.

Security

Data Storage

Lifecycle API is a part of PCI zone of Verestro platform so it meets all standards and restrictions of secure data storage. All fragile data is secured and encrypted. 

We are using HashiCorp Vault as a Software HSM.

The master key isn't stored anywhere. It is reconstructed in unsealing process. It is used to encrypt encryption key. The data stored by Vault is stored encrypted. Therefore, to decrypt the data, Vault must decrypt the encryption key which requires the master key. Unsealing is the process of reconstructing this master key.

Instead of distributing this master key as a single key to an operator, Vault uses an algorithm known as Shamir's Secret Sharing to split the key into key shards. A certain threshold of shards is required to reconstruct the master key.

More information

When the Vault is initialized it generates an encryption key which is used to protect all the data. The encryption key is also stored with the data, but encrypted with another encryption key known as the master key. Once Vault retrieves the encryption key, it is able to decrypt the data in the storage backend, and enters the unsealed state.  Vault uses 256-bit AES to encrypt Encryption Key.

All sensitive data is encrypted in this way.

Encryption of fragile data

LC api allows to encrypt fragile card data. Detailed description is provided below.

JWE Standard

To encrypt fragile card data you should use JWE. If you are unfamiliar with this kind of standard please look at links below:
Wiki,
RFC,
Example.

The setup for Lifecycle JWE is presented below:

Public key used to generate JWE can be found here. //TODO: add file with public key for dev.

JWE Examples

During development you can use test methods that allows to generate and check your implementation of JWE:

PAYLOAD - json string used to generate JWE, for example:

{"pan":"5555444433331234","expiryDate":"2040-11-30"}

ISSUER - string provided by DC Team during integration
EXAMPLE_JWE - JWE to be validated and decoded 

Generate JWE
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Basic dGVzdDE6dGVzdDEyMw==' \
--header 'ISSUER-CODE: ISSUER' \
--header 'COLLECTION: internal'

Read JWE

curl --location --request POST 'https://datacore.upaidtest.pl/test/read-jwe-token' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Basic dGVzdDE6dGVzdDEyMw==' \
--header 'ISSUER-CODE: ISSUER' \
--header 'COLLECTION: internal' \
--data-raw '{
    "token" "EXAMPLE_JWE"
}'

Hash HMAC

Lifecycle also provides configuration called idType. It is simple tool that can be used if you can't store LC internal id's.
There are two main id types: useridType and cardIdType. All possible options for both are presented in LC API specification.
Here we are describing case when cardIdType is set to hash.
Hash value is as SHA-256 HMAC, please see links below for more details: 
RFC,
Wiki,
Java example.

Test value of key used to calculate HMAC in HEX

59c6d62dde38d8a2c32105a53336b8ef

To validate your implementation please check plain and hashed values below:

"5555444433332222"  "4f64c445c859f7e53209e0091a5faef7e8b3ebbad899fbf8c74df09a6bfe5646"
"6984576897634895763948576" "4b2eab65ab16183fa6ac8a8b12ad690890db98c5ce20e6d56aa037b723bbe842"
"someTestValue398048096859607" "9596a78a7382e90159d8ec78a8d37baff57d05f676c0607dd7fb24b0396270ce"

Lifecycle Import

Info

Lifecycle file import is a mechanism that allows you to create a file with multiple instructions for api. Each instruction is like an request. Instead of sending 10.000 requests to API, which may take ages, you can create single file with all those instructions and let our system handle it asynchronously. Once import is completed an report is generated which will contain errors and information about processed rows. Files with instructions should be uploaded onto SFTP. To get access details, a new integration needs to be set up for bank.

Requirements

File storage with directories:

/input for input files
/output for output files (reports)
/processed for files that were processed

Input

Input files should be uploaded onto storage into 'input' directory. Everyday at 12:07 am a cron job will run and process those files. 

File example

File format is json line (jsonl). In short this is a file that contains valid json in every line (separated by line break, not a comma etc.).

Each line is a single instruction for our import mechanism. Example file below:

{"method":"addUser","data":{"externalId":"48111111111","firstName":"First","lastName":"User","phone":"48111111111","email":"you@post.com","birthDate":"1979-10-06","wPIN":"1234","state":"VERIFIED"}}
{"method":"addUser","data":{"externalId":"48222222222","firstName":"Second","lastName":"User","phone":"48222222222","email":"me@post.com","birthDate":"1979-10-06","wPIN":"1234","state":"VERIFIED"}}
{"method":"addUser","data":{"externalId":"48333333333","firstName":"Third","lastName":"User","phone":"48333333333","email":"validemail@post.com","birthDate":"1979-10-06","wPIN":"1234","state":"VERIFIED"}}

Line explaination

Each line is a JSON with two keys:

method - name of method you're calling (supported methods below),
data - request body.

For example result of importing first line of example file is similar to making a request to /lifecycle/v1/users with body:

{"externalId":"48111111111","firstName":"First","lastName":"User","phone":"48111111111","email":"you@post.com","birthDate":"1979-10-06","wPIN":"1234","state":"VERIFIED"}

Supported methods

At the moment the only one supported method is addUser (https://datacore.upaidtest.pl/documentation-lifecycle/#api-Lifecycle-user_add).

Processing

Processing is handled asynchronously. It means that once file is read, every line will be changed into a "job" and then processed by our "workers". After reading whole file it is moved to processed directory. PS. This does not mean that the import is completed.

If workers encounter any troubles during handling their job an error message will be inserted into report file. Structure of error line is "X, ERROR_MESSAGE" where X is the line number from import file and ERROR_MESSAGE is just the error message. Examples presented in Output section.

Output

Once import is completed an line with rows processed information is inserted into the report file. You can find report files inside output directory. Report file name is $input_file_name_without_extension-report.csv. Example input/output file with names below.

Example input file

input_file.jsonl
{invalid json :((}
{"method":"addUser","data":{"externalId":"48222222222","firstName":"Second","lastName":"User","phone":"48222222222","email":"me@post.com","birthDate":"1979-10-06","wPIN":"1234","state":"VERIFIED"}}
{"method":"addUser","data":{"externalId":"48333333333","firstName":"Third","lastName":"User","phone":"48333333333","email":"validemail@post.com","birthDate":"1337","wPIN":"1234","state":"VERIFIED"}}
{"method":"thisWillNotWork","data":{"externalId":"4833"}}

Example output file

input_file-report.csv
1,INVALID_JSON
3,{"errors":{"phone":["VALUE_HAS_TO_BE_UNIQUE"],"birthDate":["DATE_IS_INVALID","DATE_FORMAT_IS_INVALID"]}}
4,INVALID_METHOD
 
Total rows processed: 4

Typical error messages:

INVALID_JSON - there was an error while trying to decode line (first line of example input file).
INVALID_METHOD - invalid/unsupported method (fourth line of example input file).
UNKNOWN_ERROR - unhandled error (contact DC team for more info).

As you may have noticed there is also an error message encoded in json format. This is the same response that you would receive in a normal api call.

PS. Successfully processed line doesn't produce any output in report file (that's why there is no status for 2nd line).

Lifecycle API usage

URL construction

/users/{id}/cards/{cardId}?userIdType={userIdType}&cardId=internalId

id - value defines user identifier.
userIdType - type of value that identifies user. Supported options:

Headers

Field 

Description 

Authorization 

Basic Access Authentication token. 

Accept 

application/json .

Content-Type 

application/json .

Accept-Language 

Options: en, pl, ...

Issuer-Code 

Wallet name. This value is provided by datacore team. 

Collection 

Collection name. Options: lifecycle .

Application-Id 

The unique name of the application, e.g. "admin-panel" .

X-B3-SpanId 

This is the id of the specific operation. Link .

X-B3-TraceId 

This is a global id that is used to identify a sequence of requests / responses in the whole system. This means that it should be passed between all websites in requests / responsives. In case it is null then of course you have to generate a new one, because it means that this is the first request from an external client. 

Technical documentation

                                                                                                                                                                                  @swagger="https://minio-beta.upaidtest.pl/datacore/api-doc-lifecycle.json"

Technical documentation MDC SDK

Introduction

Basic abbreviations and definitions

Field Description
FCM

Firebase Cloud Messaging

DC Data Core
MDC

Mobile DC module

MPA

Mobile Payment Application

UCP Verestro Cloud Payments
IBAN Back Account Number
JWT Json Web Token
JWE Json Web Encryption
OTP One-time password


What is Mobile DC SDK?

The Mobile DC SDK is a core module dedicated to the management of users, devices, and cards in the Verestro system.

Usage of other Verestro modules (f.e. UCP - Verestro Claud Payment) always depends on this SDK and Mobile DC must be always used.

Versioning and backward compatibility

SDK version contains three numbers. For example: 1.0.0.

Changes not breaking compatibility:

Technical overview

This section describes basic information about Mobile DC SDK, SDK setup, and available methods.

Basic configuration

Artifactory

SDK is available on the Verestro maven repository and can be configured in a project using the Gradle build system.

The username and password are provided by Verestro.

repositories{
	maven {
		credentials {
			username "<enter_username_here>"
			password "<enter_password_here>"
		}
	url "https://artifactory.upaid.pl/artifactory/libs-release-local/"
}

Versions

Mobile DC SDK is available in two versions: debug and release.

The difference between versions is debugged version allows to use of an application with a debugger connected.

Debug version is ended with appendix "-debug" in version name. Samples below:


For release version, used on production environment in application uploaded to Google Play:

dependencies{
	implementation 'pl.upaid.module:mobiledc:{version}'
} 


Debug version - could be used for application development:

dependencies{
	implementation 'pl.upaid.module:mobiledc:{version}-debug'
}


Min SDK Version

The minSdkVersion must be at least 23 (Android 6.0). In case of using SDK on lower Android API version declare in the application manifest.

  <uses-sdk tools:overrideLibrary= "pl.upaid.module.ucp, 
    pl.upaid.module.mobiledc, pl.upaid.module.mcbp,
    pl.upaid.module.security, com.mastercard.mpsdk, pl.upaid.nativesecurity" />


SDK cannot be initialized on a lower Android API version, and none of the SDK methods should be used on it.

Android APIs 31+ 

Android Worker uses PendingIntent which causes some problems with the newest Android APIs. To resolve this problem application Gradle dependency configuration must override this dependency.

dependencies{
	implementation 'androidx.work:work-runtime-ktx:2.7.1'
} 


Native libs extraction in AndroidManifest and Gradle.

Native libs should be packaged in application in uncompressed form due to security reasons.

This solution is also recommended by Google due to the smaller app install and download size.

Note: Starting from Android Gradle Plugin 4.2 an attribute is replaced with parameter android.packagingOptions.jniLibs.useLegacyOptions.


If you need to package native libraries in the compressed form please contact Verestro.

//AndroidManifest.xml

<application
    android:extractNativeLibs="false"
    ... >
</application>


//build.gradle

android {
    packagingOptions {
        jniLibs {
            useLegacyPackaging false
        }
    }
}

Source code obfuscation and optimization

As SDK is written in Kotlin the language we recommend adding following code to Gradle configuration:

android {
	...	 
	kotlinOptions {
    	freeCompilerArgs = [
        	    '-Xno-param-assertions',
        	    '-Xno-call-assertions',
        	    '-Xno-receiver-assertions'
    	]
	}

	packagingOptions {
    	exclude '/kotlin_metadata/**'
	}
	...
}


And use the newest tools for code shrinking, optimization, and obfuscation from Google by enabling R8 instead Proguard in the gradle.properties file:

android.enableR8=true

Android permissions

QUERY_ALL_PACKAGES

Module declares the usage of permission QUERY_ALL_PACKAGES, which is required since Android API 30 to list packages available on the device.
Permission is used for security tasks.

On 20.07.2022 Google Play introduced restrictions on high-risk permissions and the application sender could be obliged to send more information about this permission usage.

The application which uses this permission is usually a bank or financial institution - in such case permission may be granted to usage.
Read more https://support.google.com/googleplay/android-developer/answer/10158779?hl=en

In case of lack of agreement from Google Play permission could be removed on the application side AndroidManifest.xml file.
When removed application should declare package visibility to search known root packages.

In case of removing this permission please contact Verestro representative.


Sample code to remove QUERY_ALL_PACKAGES permission in the AndroidManigest.xml file and package visibility declaration:

<manifest package="com.sampleapp">
	
	<!-- remove permission from manifest -->
	<uses-permission
    	android:name="android.permission.QUERY_ALL_PACKAGES"
    	tools:ignore="QueryAllPackagesPermission"
    	tools:node="remove" />

	<!-- declare application visibility -->
	<queries>
        <package android:name="com.noshufou.android.su" />
        <package android:name="com.noshufou.android.su.elite" />
        <package android:name="eu.chainfire.supersu" />
        <package android:name="com.koushikdutta.superuser" />
        <package android:name="com.thirdparty.superuser" />
        <package android:name="com.yellowes.su" />
        <package android:name="stericson.busybox" />
        <package android:name="com.topjohnwu.magisk" />
        <package android:name="com.koushikdutta.rommanager" />
        <package android:name="com.koushikdutta.rommanager.license" />
        <package android:name="com.dimonvideo.luckypatcher" />
        <package android:name="com.chelpus.lackypatch" />
        <package android:name="com.ramdroid.appquarantine" />
        <package android:name="com.ramdroid.appquarantinepro" />
        <package android:name="com.android.vending.billing.InAppBillingService.COIN" />
        <package android:name="com.chelpus.luckypatcher" />
        <package android:name="com.devadvance.rootcloak" />
        <package android:name="com.devadvance.rootcloakplus" />
        <package android:name="de.robv.android.xposed.installer" />
        <package android:name="com.saurik.substrate" />
        <package android:name="com.zachspong.temprootremovejb" />
        <package android:name="com.amphoras.hidemyroot" />
        <package android:name="com.amphoras.hidemyrootadfree" />
        <package android:name="com.formyhm.hiderootPremium" />
        <package android:name="com.formyhm.hideroot" />
        <package android:name="org.projectvoodoo.otarootkeeper" />
    </queries>

MDC SDK Size

The size of SDK is dependent on the apk distribution system.

The table below shows the size of the module for apk and bundle file.

Format Size Notes
APK ~15,1 MB
Bundle ~2,5 MB - ~3,6 MB

Ranged size depends on the ABI of the device.

SDK contains native libraries used by different ABI. By using a bundle only the necessary version of the native library will be downloaded to a device.


Additional information

MDC SDK usage

This chapter describes the structure and basic usage of Mobile DC SDK.

Domains

Every described facade is divided into domains with different responsibilities.

Available domains:

Every domain contains domain-related methods.

Facade

The facade is an entry point to communication with Mobile DC SDK.

Contains an SDK initialization method and domains which allows to manage Verestro account.

Multiple facade types

Mobile DC SDK provides three public APIs with the same functionalities, the APIs are:

The difference between the APIs is a way of providing data to SDK methods and getting the results from them.

Input and output as information data are always the same.

This documentation presents I/O types in a Kotlin way as it’s easier to mark nullable fields (as a question mark).

Method structure

Every method described in documentation has same structure.

Execution type:


Method type:

Input

Input parameters with name, description and validation rules. For some methods input is result of different uPaid method.


Output

If present is delivered in success callback with data described below.


Callbacks


Sample usage:

//java sample

cardsService.getAll(
        new SuccessDataCallback<List<Card>>() {
            @Override
            public void onSuccess(List<Card> cards) {
                //show cards on UI
            }
        }, new FailureCallback() {
            @Override
            public void onFailure(@NotNull Throwable throwable) {
                //show error
            }
        });

SuccessDataCallback and FailureCallback could be replaced by lambda like in kotlin sample below

//kotlin sample

cardsService.getAll({ cards ->
    //show cards on UI
}, {
    //show error
})


Error handling

SDK returns errors by exceptions, which could be caught by the application and shown on UI with a detailed message.

Note: Exception message is only information for a developer and shouldn't be shown on the application UI to the user. Use reason code to add a suitable message on the application layer.

 The table below describes exceptions types.

Exception type Exception class Description
SDK Validation ValidationException

Every parameter provided in method is validated locally by SDK. For example, card number is validated with Luhn algorithm

Exception object contains field reason with detailed error code

Backend BackendException

Provides additional validation or error on backend side

Exception object contains field reasonCode and message

Application should get reason code and show suitable message or made action

Message should be never shown to user. Could be logged for error reporting and for developers

List of available raeson in table below

Internal Sdk CoreSdkException

Provides additional information about error in SDK

Exception object contains field reason and message

Application should get reason code and show suitable message or made action

Message should be never shown to user. Could be logged for error reporting and for developers

List of available raeson in table below

Process related -

As every process is different some methods could throw specified exception. Types of exception is described in method description

Network NetworkConnectionException Provide information about network connection error. Check table with possible reasons below
Internal UnknownException For unknown errors in SDK process


BackendException error codes

Reason code

Description

INTERNAL_ERROR

Error occurred on server

CRYPTOGRAPHY_ERROR

Error occurred during cryptography operation

VALIDATION_ERROR

Client sent invalid data

CARD_NO_OUTSIDE_RANGE_BINS

Card number is outside of preconfigured range

CARD_KIND_LIMIT_REACHED

Card kind limit reached

CARD_DELETED

Card was deleted and operation cannot be proceed

FAIL_3DS_VERIFICATION

3ds verification failed

FAIL_AUTHORIZATION

Fail authorization - error from card verification

TRANSACTION_DENIED

Transaction denied - error from card verification

FAIL_AUTHENTICATION

Invalid username or password

CARD_EXPIRED

Card expired

LIMITS_EXCEEDED

Limit of transactions has been exceeded

REJECTED_BY_BANK

Current transaction has been rejected by bank - error from card verification

INSUFFICIENT_FOUNDS

There is no enough founds on card to complete this transaction

INVALID_JWS_TOKEN

Specified JWS token is invalid

INVALID_FCM_TOKEN

Given FCM token is invalid

OPERATION_NOT_SUPPORTED

Method is not allowed

CANT_FIND_USER

Cannot find user by requested identifier

CANT_FIND_CARD

Cannot find card by requested identifier

CANT_FIND_DEVICE

Cannot find device by requested identifier

CANT_FIND_WPIN

Cannot find wallet pin

CANT_FIND_ADDRESS

Cannot find requested address

CANT_FIND_INVITATION

Cannot find invitation for the requested resource

RESOURCE_NOT_FOUND

Cannot find requested resource

USER_IS_LOCKED

Requested user is locked

CARD_IS_LOCKED

Requested card is locked

DEVICE_PERMANENTLY_LOCKED

Requested device is locked

DEVICE_TEMPORARILY_LOCKED

Requested device is temporary locked

BAD_LOGIN_LIMIT_REACHED

Number of incorrect login attempts is reached

BAD_WPIN_LIMIT_REACHED

Requested user is temporary locked

SMS_FAILCOUNT_REACHED

Sms fail count limit reached

TOO_MANY_REQUESTS

Too Many Requests

CARD_IS_ALREADY_VERIFIED

Requested card has been verified

USER_IS_NOT_VERIFIED

User is not verified. E.g. User had registered already however did not finish the verification step and is trying to pair/login

PAYMENT_ALREADY_SUCCESS

Requested payment has been already finished

INVALID_CARD

Card is invalid for this payment

USER_HAS_NOT_SET_A_PASSWORD

Requested user has not set password

DEVICE_LIMIT_REACHED

Number of device is reached

BAD_WPIN

The wallet pin does not match the requested user

SMS_LIMIT_EXCEEDED

Number of sent messages has reached the limit. Please try again later

FAIL_COUNT_LIMIT_REACHED

Attempt limit has exceeded

INITIALIZE_PROCESS_REQUIRED

Fail count limit has been reached and new process has not been initialized

INVALID_AUTHORIZATION_AMOUNT

Authorization amount is incorrect

CLIENT_UNAUTHORIZED

Client of the api is unauthorized(invalid/expired X-Client-Auth token)

USER_UNAUTHORIZED

User is unauthorized

VERIFICATION_FAILED

Requested card could not be verified

CARD_NOT_ENROLLED

Card does not participate in 3ds v2, please use 3ds v1

INVALID_AUTHENTICATION_ID

Authentication process id does not match card id

BackendException - additional error codes related to TransactionsHistoryService

Reason code

Description

TRANSACTION_ATTACHMENT_STATUS_APPROVED

Cannot update transaction or store new attachment. Attachment status in transaction is APPROVED

MAX_ATTACHMENTS_COUNT

Maximum number of attachments for given transaction

MAX_ATTACHMENT_SIZE_EXCEEDED

Maximum attachment size exceeded

EMPTY_ATTACHMENT

Empty attachment file

EMPTY_ATTACHMENT_NAME

Empty attachment file name

NOT_SUPPORTED_ATTACHMENT_FILE_TYPE

Attachment file type is not supported

CANT_FIND_TRANSACTION_ATTACHMENT

Cannot find transaction attachment


CoreSdkException error codes INTERNAL_ERROR

Reason code Description
DEVICE_NOT_PAIRED Device is not paired or trying to call the method without device pairing
SAFETYNET_ERROR An error during device authentication in Google SafetyNet service
PUSH_INVALID_SOURCE

Relates to push processing process. Push message should be consumed in another module

PUSH_INVALID_PUSH_CONTENT

Cannot process push message. The message is invalid or some process failed

BIOMETRIC_AUTHENTICATION_NOT_ENABLED Biometric public key is invalid
BIOMETRIC_AUTHENTICATION_ABORTED Cannot authenticate biometric signature
KEYSTORE_IS_NOT_SECURE Keystore is not secure. The device is not secured with PIN, pattern or password
CANNOT_GET_PUBLIC_KEY Internal error during SDK processing
SECURITY_EVENT_OCCURRED

Security event occurred during application usage. Data is cleared and the method can't be used.

Application is always informed about a security issue with onSecurityIssueAppeared callback initialized in setup() method

PIN_AUTHENTICATION_FAILURE

Provided PIN is invalid

PIN_AUTHENTICATION_FAILURE_LIMIT_EXCEEDED

PIN fail count is reached, every next try PIN authentication will finish with this status


PIN_AUTHENTICATION_NOT_POSSIBLE

PIN authentication is not possible until the user is at least once logged online with PIN

PIN_AUTHENTICATION_INTERNAL_ERROR

Something went wrong
PAIRING_IS_ALREADY_IN_PROGRESS Another pairing is now processed
PAYMENT_INSTRUMENT_DEFAULT_NOT_FOUND No default payment instrument for contactless payment found
PAYMENT_INSTRUMENT_NOT_FOUND Payment instrument with this id cannot be found in SDK
APPLICATION_PROCESS_NOT_KILLED Application process is not killed after SDK reset
TOKEN_NOT_ACTIVE Required token status is ACTIVE
PAYMENT_INSTRUMENT_NOT_FOUND Token with that id was not found in SDK
API_SERVICE_NOT_INITIALIZED API service was not initialized
DIGITIZATION_NOT_STARTED Digitization of that payment instrument was not started


NetworkConnectionException error codes

Reason code Description
UNKNOWN_HOST

Host is unreachable, check network connection and try again later

SOCKET_TIMEOUT Connection timeout, check network connection and try again later
UNKNOWN_HTTP_ERROR An unknown HTTP error


Firebase Cloud Messaging configuration 

Dependency

Add Firebase Cloud Messaging dependency entry to build.gradle.

...

implementation('com.google.firebase:firebase-messaging:22.0.0')

...

Initializing

All parameter required to initialize FCM can get from firebase console. 

val firebaseOptions =
            FirebaseOptions
                .Builder()
                .setApplicationId(applicationId)
                .setGcmSenderId(senderId)
                .setProjectId(projectId)
                .setApiKey(apiKey)
                .build()
FirebaseApp.initializeApp(this, firebaseOptions)

To initialize two FCM projects should add name parameter for second one.

//init default project
FirebaseApp.initializeApp(this, firebaseOptions)
 
//init additional project
FirebaseApp.initializeApp(this, firebaseOptionsOther, otherProjectName)

Getting FCM registration token

//getting token for default project
FirebaseMessaging.getInstance().token
    .addOnCompleteListener {
        //handle token
    }
  
  
//getting token for additional project
val messaging = FirebaseApp.getInstance("other").get(FirebaseMessaging::class.java)
messaging.token.addOnCompleteListener {
    //handle token
}


Security processes overview

This document contains short information about security mechanisms used by SDK. Only high-level functions are described, without technical specifications.

Security processes were designed to protect its assets, and ensure that the application using our product is installed on a safe environment.

SDK security mechanism starts just after initialisation of library. Because of process optimalization part of checks are made only once, other are called periodically.

Process check

Implementation of checking application process is one of many methods that SDK uses to protect itself from hooking tools.

It is based on validating app_process file, checking if it was not manipulated, or corrupted. Many popular hooking tools used nowadays uses that method to upload its hooks, modules, or cloaks over adding root access. Validating that file helps in analysis potential threats from hazardous software, and even checking root acces.

Root check

Checking root access is one of SDK most important security processes. SDK is analysing application enviromnent in following ways:

Emulator check

SDK validates application installment device by analyzing its properties and searching for evidences indicating that device is emulator.

Other packages check

Searches for well known applications connected with harmful hooking tools.

Especially aimed into finding evidences of magisk.

Debug check

Simple check is debugger connected, based on OS properties. Used only in release version.

SafetyNet Api - deprecated from version 2.3.17

API tool used for protecting application from tampering, harmful applications, and validating device OS. It availability depends on project configuration.

Usage of this process is configured od server side. If end application already performs this process it could be disabled during project configuration.

Play Integrity API

Due to Safetynet Attestation API planned deprecation it's replaced by Play Integrity API in Mobile DC version 2.13.7.

API tool used for protecting application from tampering, harmful applications, and validating device OS. It availability depends on project configuration.

Usage of this process is configured od server side. If end application already performs this process it could be disabled during project configuration.

When used, Play Integrity API must be enabled Google Play Developer Console - https://developer.android.com/google/play/integrity/setup#enable-responses.

Error codes handling in application

Table describes error codes which could be handled on application side with message to user about possible problem.

Other error codes cannot be handled on application side.

Code Meaning
80a1 Device is rooted
80b1 SDK cannot be used on emulator
811a User has installed some harmful application on device
8a9b User has attached debugger during SDK usage

Application Isolated Process

Overview

Starting from Mobile DC SDK version 2.4.3 SDK provides additional security checks which could be enabled in setup. method using "withOptionalDeveloperOptions" and enableAdditionalSecurityChecks parameter.

For some security processes SDK need to start services marked as isolatedProcess to ensure more security by splitting application from a security layer.
It may cause problems with initialize Application as this service will run under a special process that is isolated from the rest of the system and has no permissions of its own.

To avoid problems, check if application start from isolated process and do not invoke any additional action in your Application::onCreate.

Sample implementation

//Mobile DC setup configuration for enableAdditionalSecurityChecks 

val developerOptions = DeveloperOptions()
developerOptions.enableAdditionalSecurityChecks = true

MobileDcApiConfigurationBuilder()
 	// other require configuration
    .withOptionalDeveloperOptions(developerOptions)


//Sample Application declaration for handing isolated process

class SampleApplication : Application {

    override fun onCreate() {
        super.onCreate()

        if (isIsolatedProcess()) {
            return
        }
		
		//sample methods called in application
        startKoin()
        initializeMobileDcModule()
        initUcpModule()
        initFirebase()
		//other methods..
    }


	private fun isIsolatedProcess(): Boolean {
    	return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
        	android.os.Process.isIsolated()
    	} else {
        	try {
            	val activityManager = getSystemService(ACTIVITY_SERVICE) as ActivityManager
            	activityManager.runningAppProcesses
            	false
        	} catch (securityException: SecurityException) {
            	securityException.message?.contains("isolated", true) ?: false
        	} catch (exception: Exception) {
            	false
        	}
    	}
	}
}

This functionality is introduced to protect against magisk tool.

Magisk gives root access using daemon, which starts with system booting, with unrestricted SELinux context. When specific application needs access to /su it connects to daemon unix socket, process of granting access access is managed with Magisk Manager application.

Magisk Hide function hides /sbin paths for specific process, what obscures magisk presence in /proc/pid/mounts. This problems is solved with isolated processes introduced in android 4.1. They are started with new, fresh SELinux context without any permissions, what keeps magisk from removing it paths with /sbin. From this process view there is possibility to check mounted paths and find evidences of magisk presence.

Data signing and encryption


Configuration

Signing Data Configuration

Signature will be verified using public key certificate which was signed by preconfigured Root CA. DN from the certificate will be also validated. Root CA and DN will be set during onboarding. Client has two options:

Encryption Data Configuration

If the client decide to encrypt data, public key certificate from RSA 2048 should be set during onboarding. Public key certificate can be self-signed.

Signed Data Verification

Some methods requires signed data verification on client side. Public key certificate from RSA 2048 will be provided during onboarding and should be used for signature validation.


Data Encryption

Some data like Token Verification Code can be encrypted using JWE per RFC 7516.

Configured(see Encrypting Data Configuration in Confoguration chapter) public key certificate will be used to encrypt CEK(Content Encryption Key).

Algorithm used for encryption:

JWE header Name Description

alg

RSA-OAEP-256

Cryptographic algorithm used to encrypt CEK

enc

A256GCM

Identifies the content encryption algorithm used to perform authenticated encryption

Payload of the JWE will be json formatted object.

Client needs to perform decryption with private key using standard JWE library.

Sample code which shows how to decrypt JWE for given encryptedData and privateKey:

class RsaJweDecrypter {

    @Throws(Exception::class)
    fun decrypt(encryptedData: String, privateKey: PrivateKey): ByteArray {
        val parse = JWEObject.parse(encryptedData)
        parse.decrypt(RSADecrypter(privateKey))
        return parse.payload.toBytes()
    }
}


Data Signing

Some fields are signed using JWT per RFC 7519.

Data signing should be done on server side.

JWTs are composed of three sections: a header, a payload (containing a claim set), and a signature.

The header and payload are JSON objects, which are serialized to UTF-8 bytes, then encoded using base64url encoding.

The JWT’s header, payload, and signature are concatenated with periods (.). As a result, a JWT typically takes the following form:

{Base64url encoded header}.{Base64url encoded payload}.{Base64url encoded signature}

Object fields should be placed as claims in the token. Moreover there are some additional required claims that are needed to protect against replay attack:

Name Description

iat

The time at which the JWT was issued. UNIX Epoch timestamp, in seconds

jti

JWT ID - unique identifier for the JWT

JWT tokens have TTL which is validated against "issued at" time from claims (iat). TTL is 10 minutes.

JWT tokens should be signed using private key from the RSA 2048 key pair (see Signing Data Configuration in Configuration chapter).

JWT tokens must have additional header:

Name Description

x5c

Parameter contains the X.509 certificates chain (RFC7515#section-4.1.6)

This chain will be validated against preconfigured Root CA. DN from the public key certificate(from key pair which private key was used for signing) will be also validated (See Signing Data Configuration in Configuration chapter).

Sample code which shows how to build JWT for given claims, certificates and private key:

class JwtGenerator {
    
    fun generate(
        jwtClaimsSet: JWTClaimsSet,
        certificates: List<X509Certificate>,
        privateKey: PrivateKey
    ): String {

        val claims = buildFinalClaims(jwtClaimsSet)

        val certChains = certificates
            .map { it.encoded }
            .map { Base64.encode(it) }

        val jwsHeader = JWSHeader.Builder(JWSAlgorithm.RS256)
            .x509CertChain(certChains)
            .build()

        val signer = RSASSASigner(privateKey)

        val jwsObject = JWSObject(
            jwsHeader,
            Payload(claims.toJSONObject())
        )

        jwsObject.sign(signer)

        return jwsObject.serialize()
    }


    private fun buildFinalClaims(jwtClaimsSet: JWTClaimsSet): JWTClaimsSet {

        val epochSeconds = Instant.now().epochSecond

        return JWTClaimsSet
            .Builder(jwtClaimsSet)
            .claim("iat", epochSeconds)
            .jwtID(UUID.randomUUID().toString())
            .build()
    }
}



Signed data verification

Some fields are signed on Wallet Server using JWT per RFC 7519.

Wallet Server signs some data in response and signature has to be verified before this data are used. Data are signed using JWT per RFC 7519. JWTs are composed of three sections: a header, a payload (containing a claim set) and a signature.

The header and payload are JSON objects, which are serialized to UTF-8 bytes, then encoded using base64url encoding.

The JWT's header, payload, and signature are concatenated with periods (.).
As a result, a JWT typically takes the following form:

{Base64url encoded header}.{Base64url encoded payload}.{Base64url encoded signature}

Specific object fields are placed as claims in the JWT token.
Moreover there are some additional claims that are added to the JWT token to protect against replay attack:

Name Description

iat

The time at which the JWT was issued. UNIX Epoch timestamp, in seconds

jti

JWT ID - unique identifier for the JWT

JWT tokens are signed using private key from the RSA 2048 key pair. Public key certificate will be shared as part of configuration of given project and public key should be used for signature validation.

JWT tokens have additional header:

Name Description

kid

fingerprint of public key which's corresponding private key was used to sign data calculated as sha1Hex(publicKeyBytes)

Sample code which shows how to verify signed JWT:

class JWTVerifier {

        fun verify(
            signedData: String,
            rsaPublicKey: RSAPublicKey,
            iatToleranceSeconds: Long
        ): JWTClaimsSet {
            
            val signedJWT = SignedJWT.parse(signedData)
            val signatureResult = signedJWT.verify(RSASSAVerifier(rsaPublicKey))
            if (!signatureResult) {
                throw ValidationException("Invalid signature")
            }
            
            val jwtClaimsSet = signedJWT.getJWTClaimsSet()
            
            //optionally check iat with tolerance
            val isIatInAllowedTimeRange = jwtClaimsSet
                .getIssueTime()
                .toInstant()
                .plusSeconds(iatToleranceSeconds)
                .isAfter(Instant.now())
            
            if (!isIatInAllowedTimeRange) {
                throw ValidationException("Signed JWT expired")
            }
            
            return jwtClaimsSet
        }
    }

APK Certificate

About APK certificate

Verestro provides mechanism which ensures that authorized entities using Verestro SDKs.

To achieve that apk certificate needs to configured during onboarding.

Apk Certificate is binded to given client id, if customer uses many applications then many apk certificates digest should be provided and for each client id will be given by Verestro.

Calculate APK certificate digest

You can sign your application using self managed key, or let Google Play sign using Google Play managed keys:

If you update key, you must follow steps below again and provide key to representative uPaid person.

Please check your installation package and follow the outlined steps.

Using own APK Signing Key

When signing apk in android studio only, please follow the steps below:

1. Convert java keystore (eg. cert.jks) used to sign APK to p12 format using following command:

keytool -importkeystore -srckeystore cert.jks -destkeystore cert.p12 -srcstoretype jks -deststoretype pkcs12

2. Convert obtained p12 file (eg. cert.p12) to pem format using following command:

openssl pkcs12 -nokeys -in cert.p12 -out cert.pem


Using Google Play Signing Key

When signing application in Google Play console(whenever you uploaded own key, or used one that was automatically generated by Google), please follow steps below:

  1. Add .apk or .aab file in google play console.
  2. Select "Let Google create and manage my app signing key (recommended)" and press Continue.
    google app sign key.png

  3. In the application panel in the menu look for release management option.
  4. Select app signing section.

    app_signing.png

  5. Download the certificate from App signing certificate section.

    app sing cert.png

  6. Convert downloaded certificate from der to pem format using following command:

openssl x509 -inform der -in deployment_cert.der -out certificate.pem


Models

LimitedResourceInfo

Parameter Type Description
xRateLimitLimit Int? Limit of requests until resource will be locked
xRateLimitRemaining Int? Remaining amount of requests
retryAfter Int? Seconds until lock expires
xRateLimitReset Long? Lock expiration timestamp - epoch in seconds

External libraries

The SDK uses several external Apache 2.0 libraries:

MDC SDK Setup

Setup

Asynchronous. Offline. Mobile DC initialization method. Contains all necessary data to configure SDK.

Should be called at very beginning of application lifecycle. For example in Android Application::onCreate method.

Note: Please be aware to use this method before usage of any MobileDC methods or another Verestro product.

Input

Mobile DC different configuration options depending on SKD usage.

Configuration is provided by builder in facade method named setup.

All builder methods without optional keyword in method name are required.


Available configurations methods:


SDK Event Listeners - errors catching

The application should prevent throwing exceptions in MDC SDK Event Listeners described below as it could cause breaking process in SDK.

In case of error in application event listener implementation SDK runs this code in try-catch block.


MobileDcCoreConfiguration

Used when usage of uPaid product doesn't require Verestro backend system (f.e. UCP with External Wallet Server).


Method Parameter Description

Validation conditions

withApplicationContext Context Application context Not empty
withWalletSecurityEventListener

WalletSecurityEventListener

Global listener for security events

Not empty
withOptionalLogger EventsLogger Handler for secure logging of sdk events
withOptionalDeveloperOptions

DeveloperOptions

Additional options for developers


MobileDcApiConfiguration

Used when applicaton use Mobile DC API for user data management.


Method Parameter Description

Validation conditions

withApplicationContext Context Application context Not null

withMobileDcConnectionConfiguration

MobileDcConnectionConfiguration

Mobile DC API connection configuration delivered by uPaid

Not empty
withWalletSecurityEventListener

WalletSecurityEventListener

Global listener for security events

Not empty
withOptionalWalletPinConfiguration MobileDcWalletPinConfiguration Wallet Pin configuration in SDK
withOptionalLogger EventsLogger Handler for secure logging of sdk events
withOptionalDeveloperOptions DeveloperOptions Additional options for developers


MobileDcConnectionConfiguration

Parameter Type Description

Validation conditions

url String

Url for mobile DC environment in which SDK connect.
Depending on the deployment model the Wallet Server can be deployed on the Customer infrastructure or provided by uPaid.
Different for development and production environment.
For more details please contact uPaid representative.

Not empty
pinningCertificates List<String>

List of public key certificate in PEM associated with host server.
Certificate is used for certificate pinning during connection to Wallet Server.
Certificate is associated with the Wallet Server and like the url its value depends on the deployment model.


When used services hosted on uPaid side please contact uPaid representative.

Not empty
clientId String

Each customer has a unique client id it's different for development and production environment.

ClientId should be provided by uPaid representative.

Not empty


MobileDcWalletPinConfiguration

Parameter Type Description

Validation conditions

pinFailCount Int

Number of possible fails in offline pin verification

Greater then 0


WalletSecurityEventListener

Method name Parameters

Description

onSecurityIssueAppeared

EventSecurityIssueAppeared(tag: Int, code: Int, message:String)

Information about security issue. Due to security requirements this message isn’t readable for user

When using setup(MobileDcApiConfiguration) SDK reports event instantly to server (when internet is available). Could be also catched on application side and reported by client.

Some error codes could be properly handled in application Security processes overview


EventsLogger

Method name Parameters

Description

onEvent
onEvent(eventId: Int)

Callback to trace list of events that occured in SDK (those are secure aliases - event as Integer). You can collect 'em in ordered list and store to be accesible in case of errors/exceptions.


DeveloperOptions

Parameter Type

Description

allowDebug

Boolean

Determine AndroidManifest android:debuggable state in <application> scope.

When configured as true SDK verifies combination of SDK production(without -debug) version and android:debuggable=true.

enableAdditionalSecurityChecks Boolean

Enables additional security checks in application required during EMV Security Evaluation.

Enabling requires additional action on application side,  refer to Application Isolated Process to get more details.

Added in version 2.4.3.

enableCodeObfuscationCheck Boolean

Enable additional check if application obfuscates SDK facade classes.

Default value is false.


Sample

Initialization for MobileDcCoreConfiguration (without Wallet Server).

var eventsTrace = arrayListOf<Int>()//make use of this in case of error/failure/unexpected behaviour to retrace sdk internal processes


val mobileDcCoreConfiguration = MobileDcCoreConfiguration.create(
    MobileDcCoreConfigurationBuilder()
        .withApplicationContext(this)
        .withWalletSecurityEventListener(object : WalletSecurityEventListener {
            override fun onSecurityIssueAppeared(event: EventSecurityIssueAppeared) {
                //eg. show security screen or toast with details from event object
                //all data collected by SDK will be removed
                //Clearing application data in context of SDK is recommended
            }

        })
        .withOptionalLogger(object : EventsLogger {
            override fun onEvent(eventId: Int) {
                eventsTrace.add(eventId)
            }
        })
        .withOptionalDeveloperOptions(DeveloperOptions().apply {
            allowDebug = false
            enableAdditionalSecurityChecks = true
            enableCodeObfuscationCheck = true
        })
)

MobileDcApiKotlin.setup(mobileDcCoreConfiguration)

Initialization for MobileDcApiConfiguration.

class MyAppMobileDcConnectionConfig : MobileDcConnectionConfiguration {
    override val clientId: String = "clientId"
    override val url: String = "https://subdomain.domain.com/endpoint"
    override val pinningCertificates: List<String> = listOf(certificatePublicKeyInPemFormat)
}

class MyAppMobileDcWalletPinConfig : MobileDcWalletPinConfiguration {
    override val pinFailCount: Int = 3
}

var eventsTrace = arrayListOf<Int>()//make use of this in case of error/failure/unexpected behaviuour to retrace sdk internal processes

val mobileDcApiConfiguration = MobileDcApiConfiguration.create(
    MobileDcApiConfigurationBuilder()
        .withApplicationContext(this)
        .withMobileDcConnectionConfiguration(MyAppMobileDcConnectionConfig())
        .withOptionalWalletPinConfiguration(MyAppMobileDcWalletPinConfig())
        .withWalletSecurityEventListener(object : WalletSecurityEventListener {
            override fun onSecurityIssueAppeared(event: EventSecurityIssueAppeared) {
                //eg. show security screen or toast with details from event object
                //all data collected by SDK will be removed
                //Clearing application data in context of SDK is recommended
            }
        })
        .withOptionalLogger(object : EventsLogger {
            override fun onEvent(eventId: Int) {
                eventsTrace.add(eventId)
            }
        })
        .withOptionalDeveloperOptions(DeveloperOptions().apply {
            allowDebug = false
			enableAdditionalSecurityChecks = true
			enableCodeObfuscationCheck = true
        })
)

MobileDcApiKotlin.setup(mobileDcApiConfiguration)

Additional isolated process check, read more: Application Isolated Process

class App : Application() {

    override fun onCreate() {
        super.onCreate()
        if (isIsolatedProcess()) {
			return
        }

		//call all required methods
    }

}


Address domain

addAddress

Asynchronous. Online.

Adds new address with given parameters.

Input

AddAddress

Parameter Type Description Validation conditions
street CharArray?

Street

-
number CharArray?

Number

-
apartment CharArray?

Apartment

-
city

CharArray?

City

-
isBilling Boolean?

Is invoice address

-
isShipping Boolean?

Is Shipping address

-
zipCode CharArray?

Zip code

-
countryId Int?

Country identifier

-
vatNo CharArray?

Vat number

-
companyName CharArray?

Company name

-
firstName CharArray?

First name

-
lastName CharArray?

Last name

-
province CharArray?

Province

-
district CharArray?

District

-
additional CharArray?

(Optional) Additional field

-

Output

Success with Long value as addressId / failure callback.

Sample

fun addAdress(addAddress: AddAddress) {
    mobileDcApi
        .addressesService
        .addAddress(addAddress, { addressId ->
            // Address added
        }, {
            // Something went wrong
            // Check exceptions described in Error handling chapter
        })
}


getAll

Asynchronous. Online.

Gets all addresses for the current user.

Input

No input parameters.


Output

Success callback with list of user addresses.

Parameter Type Description
addresses List <Address>

List of user addresses


Address

Parameter Type Description
id Int Id of the address
street CharArray?

Street

number CharArray?

Number

apartment CharArray?

Apartment

city

CharArray?

City

isBilling Boolean?

Is invoice address

isShipping Boolean?

Is Shipping address

zipCode CharArray?

Zip code

country Country?

Country

vatNo CharArray?

Vat number

companyName CharArray?

Company name

firstName CharArray?

First name

lastName CharArray?

Last name

province CharArray?

Province

district CharArray?

District

additional CharArray?

Additional field


Country

Parameter

Type

Description

id

Int

Id of the country

code

CharArray?

Country code

currency

CharArray?

Currency code

currencyNumeric

CharArray?

Numeric currency code

prefix

CharArray?

Prefix telephone number for a given country

regexp

CharArray?

The phone number validation rule for a given country

name

CharArray?

The currency's name

currencyName

CharArray?

Country

language

CharArray?

Official language


Sample

fun getAll() {
    mobileDcApi
        .addressesService
        .getAll({
            // List of addresses
        }, { throwable ->
            // Something went wrong
            // Check exceptions described in Error handling chapter
        })
}


updateAddress

Asynchronous. Online.

Update address for the current id.

Input

Parameter Type Description
updateAddress UpdateAddress

An object containing address data to update


UpdateAddress

Parameter Type Description
addressId Long Id of the address
street CharArray? Street
number CharArray? Number
apartment CharArray? Apartment
city CharArray? City

isBilling

Boolean? Is invoice address
isShipping Boolean? Is shipping address
zipCode CharArray? Zip code
countryId Int? Country identifier
vatNo CharArray? Vat number
companyName CharArray? Company Name
firstName CharArray? First name
lastName CharArray? Last name
province CharArray? Province
district CharArray? District
additionalField CharArray? Additional filed


Output

Success / Failure callback.


Sample

private fun updateAddress(updateAddress: UpdateAddress) {

    mobileDcApi
        .addressesService
        .updateAddress(updateAddress, {
            //address updated successfully
        }, { throwable ->
            // Something went wrong, maybe user data was incorrect
            // Check exceptions described in Error handling chapter
        })
}


deleteAddress

Method for delete user address with given address id.


Input

Parameter Type Description
addressId Long (Required) Unique address id


Output

Success callback/ Failure callback.


Sample

fun deleteAddress(addressId: Long) {
    mobileDcApi
        .addressesService
        .deleteAddress(addressId, {
            //Success, address deleted
        }, {
            //Something went wrong
            //Check exceptions described in Error handling chapter
        })
}


User domain

addUser

Asynchronous. Online.

Creates new user wallet account with given parameters.

Input

NewUser model is required, but most of it's fields are optional. Fields requirement depends on product integration process.

Parameter
Type
Description
Validation coditions
newUser
NewUser
An object containing user data (Required)

NewUser object contains following fields:

Parameter
Type
Description

Validation conditions

phone CharArray?

User's phone number

Phone with country prefix. For pl: 48500500500
email CharArray? User's email address Email format if any value passed
firstName CharArray? User's first name
lastName CharArray? User's last name
walletPin CharArray? User's wallet pin 4 to 8 digits if passed
password CharArray? User's password Password should be composed of at least 8 characters and include at least 3 out of the following 4 categories: upper-case letter, lower-case letter, special character and digit
acceptedMarketing Boolean True if user accepted marketing agreement, false otherwise

-

invitationCode CharArray? Invitation code used in a specific server configuration (Conditional/Optional) - depends on specific server configuration
nip String? Taxpayer identification number Not empty if passed


Output

Success / failure callback.


Sample

fun addUser(newUser: NewUser) {
    mobileDcApi
        .userService
        .addUser(newUser, {
            //new user is added successfully
        }, { throwable ->
            // Something went wrong, maybe user data was incorrect
            // Check exceptions described in Error handling chapter
        })
}


addUser (deprecated)

Asynchronous. Online.

Creates new user wallet account with given parameters.


Input

Most of fields are optional. Fields requirement depends on product integration process.

Parameter Type Description

Validation conditions

phone CharArray?

User's phone number

Phone with country prefix. For pl: 48500500500
email CharArray? User's email address Email format if any value passed
firstName CharArray? User's first name
lastName CharArray? User's last name
walletPin CharArray? User's wallet pin 4 to 8 digits if passed
password CharArray? User's password Password should be composed of at least 8 characters and include at least 3 out of the following 4 categories: upper-case letter, lower-case letter, special character and digit
acceptedMarketing Boolean True if user accepted marketing agreement, false otherwise

-


Output

Success / failure callback.


addUserWithIban

Asynchronous. Online.

Creates new user wallet account if not exist with IBAN in Mobile DC backend.

When user already exist calling this method will be also finished with success.


Input

Parameter Type Description

Validation conditions

signedAccountInfo String

Signed AccountInfo per RFC 7519 generated on Client server side

Instruction how to sign data with JWT can be found in Data signing and encryption chapter

Not empty


AccountInfo

Parameter Type Description

Validation conditions

userId String

External user id given by the client

Not empty
iban String Bank Account Number Not empty
countryCode String

The country of the financial account

Expressed as a 3-letter (alpha-3 country code as defined in ISO 3166-1

Not empty


Output

Success callback. Called when new user is created or already exist with passed input data.

Parameter Type Description
ibanId String

Hash (sha256) of provided IBAN


Failure callback.


Sample

class SignedAccountInfo {
    fun generate() {
        val claims = JWTClaimsSet.Builder()
            .claim("userId", "externalUserId")
            .claim("iban", "IN15HIND23467433866365")
            .claim("countryCode", "IND")
            .build()

        val signedAccountInfo = JwtGenerator.generate(claims, certificates, privateKey)
        // ...
    }
}


private fun addUserWithIban() {

    val signedAccountInfo: String = getSignedAccountInfo()

    mobileDcApi
        .userService
        .addUserWithIban(signedAccountInfo, { ibanId ->
            //user already exist or was added with selected iban
        }, {
            //failure, check exceptions, maybe signedAccountInfo is wrong?
        })
}


updateUser

Asynchronous. Online.

Update user wallet account with given parameters.

Most of it's fields are optional. Fields requirement depends on product integration process.


Input

Parameter Type Description Validation coditions
updateUser UpdateUser An object containing user data to update (Required)


UpdateUser model:

Parameter Type Description
firstName CharArray? User's first name
lastName CharArray? User's last name
acceptedMarketing Boolean? True if user accepted marketing agreement, false otherwise
acceptedRegulations Boolean? Accepted regulations agreement
acceptedMarketingReceiving Boolean? Accepted marketing consent


Output

Success / failure callback.


Sample

fun updateUser(updateUser: UpdateUser) {
    mobileDcApi
        .userService
        .updateUser(updateUser, {
            //user updated successfully
        }, { throwable ->
            // Something went wrong, maybe user data was incorrect
            // Check exceptions described in Error handling chapter
        })
}


getUser

Asynchronous. Online.

Get data of current user.


Input

No input parameters.


Output

Success callback with User model.


Parameter Type Description
user User

User data


User contains following fields.

Parameter Type Description
userId Long

Id of registered user

firstName CharArray? First name of the user (required depending on server configuration)
lastName CharArray? Last name of the user (required depending on server configuration)
phone CharArray? Phone with country prefix. For pl: 48500500500 (required depending on server configuration)
email CharArray?

Email of the user (required depending on server configuration)

birthDate CharArray?

Birth date in format yyyy-MM-dd

gender CharArray? Gender: [M, F]
acceptTos CharArray? Date when user accepted regulations in format yyyy-MM-dd hh:mm:ss
acceptMarketing CharArray? Date when user accepted marketing info in format yyyy-MM-dd hh:mm:ss
isLocked Boolean? True if user is locked, false otherwise
deactivated Boolean? True if user is deactivated, false otherwise
status CharArray? User status: [ACTIVE, LOCKED, DEACTIVATED]
verified Boolean? True if user is verified, false otherwise
kyc CharArray? User’s KYC verification status, one of: [SUCCESS, REJECTED, IN_PROGRESS]
created CharArray? Date of creation user in DB
failCount Int? Number of failed authentication attempts
hasSetPassword Boolean? True if user has password set, false otherwise
lastPasswordChange CharArray? Last password change in format yyyy-MM-dd
lockTo CharArray? Time for which user is locked in format Y-m-d H:i:s
lastActivity CharArray? Data of user last activity in format yyyy-MM-dd hh:mm:ss
country Country Country object
acceptMarketingReceiving CharArray? Date when user accepted marketing consent in format yyyy-MM-dd hh:mm:ss


Country contains following fields.

Field Type Description
id Long

Country identifier

code CharArray Country code in accordance with the ISO 3166-2 standard
prefix CharArray Prefix telephone number for a given country
name CharArray

Country name


Failure callback.

Sample

fun getUser() {
    mobileDcApi.userService
        .getUser({ user ->
            // Getting user went successfully
			showUser(user)
        }, { throwable ->
            // Something went wrong
            // Check exceptions described in error handling chapter
        })
}


finalizeUserRegistration

Asynchronous. Online.

Activate user account by finalizing registration process with SMS code sent to the phone number provided during new user wallet account creation.


Input

Parameter Type Description

Validation conditions

otp CharArray One time password (sent via SMS as a result of successful new user wallet account creation) Not empty


Output

Success / failure callback.


Sample

fun finalizeUserRegistration(otp: CharArray) {
    mobileDcApi
        .userService
        .finalizeUserRegistration(otp, { 
           // User wallet account was successfully activated
        }, { throwable ->
            // Something went wrong. 
            // Check exceptions described in error handling chapter
        })
}


authenticateByPin

Asynchronous. Offline.

Authenticates user locally after providing correct pin.

Provide method to verify user without connection into Mobile DC.


Input

Parameter Type Description

Validation conditions

pin CharArray

Wallet Pin created during user registration process associated with user account. (see: addUser (deprecated))

Not empty.


Output

Success / failure callback.


Sample

fun authenticateByPin(mobileDcApi: MobileDcApiKotlin, pin: CharArray) {
    //Wallet Pin created during user registration process associated with user account
    mobileDcApi
        .userService
        .authenticateByPin(pin, {
            //user is verified
        }, { throwable ->
            // Something went wrong, maybe pin is incorrect? 
            // Check exceptions described in Error handling chapter
        })
}


isBiometricAuthenticationEnabled

Asynchronous. Offline.

Method that check if biometric authentication is enabled.

Note: Authentication could be disabled by system when Android Keystore state changed (eg. User disabled screen lock or add new authentication method).

State of biometrics should be checked before every biometrics authentication usage.

Input

No input parameters

Output

Success callback with status of authentication or failure callback.

Sample

fun isBiometricAuthenticationEnabled() {
    mobileDcApi
            .userService
            .isBiometricAuthenticationEnabled({ isBiometricEnabled ->
                if (isBiometricEnabled) {
                    // Biometric authentication is enabled, process startBiometricAuthentication method
                } else {
                    // Biometric authentication is disabled, use enableBiometricAuthentication
                }
            }, { throwable ->
                // Something went wrong
                // Check exceptions
            })
}

enableBiometricAuthentication

Asynchronous. Online.

Method for enabling device level authentication and updating biometric public key.

To perform this method device must have set PIN, pattern or password. To check these use KeyguardManager.


Input

Parameter Type Description Validation conditions
userName CharArray Current username Not empty
password CharArray Current password Not empty
biometricAuthType BiometricAuthType (BIOMETRIC_ONLY, BIOMETRIC_WITH_ALTERNATIVE) Type of biometrics to enable during device pairing process. Not null


Output

Success / failure callback.


Sample

//KeyguardManager example
keyguardManager = context.getSystemService(KEYGUARD_SERVICE)

fun isDeviceSecure(): Boolean {
    return keyguardManager.isKeyguardSecure
}
//if isDeviceSecure return true device is safe and enableBiometricAuthentication method can be performed

fun enableBiometricAuthentication(userName: CharArray, password: CharArray, biometricAuthType : BiometricAuthType) {
    mobileDcApi.userService
        		.enableBiometricAuthentication(userName, password, biometricAuthType,
					{
            			// Biometric authentication is enabled. Read startBiometricAuthentication description to authenticate user.
        			},
 					{ throwable ->
            			// Something went wrong
            			// Check exceptions described in Error handling chapter
        			}
				)
}


disableBiometricAuthentication

Asynchronous. Offline.

Disable possibility to use biometric authentication.


Input

No input parameters.


Output

Success / failure callback.


Sample

fun disableBiometricAuthentication() {
    mobileDcApi
        .userService
        .disableBiometricAuthentication({
            //Biometric authentication cannot be no longer used. Use enableBiometricAuthentication to enable it again
        }, {
            //Something went wrong
            //Check exceptions described in Error handling chapter            
        })
}

enableBiometricAuthenticationWithWalletPin

Asynchronous. Online.

Method for enabling device level authentication and updating biometric public key with Wallet Pin.

To perform this method device must have set PIN, pattern or password. To check these use KeyguardManager.

Input

Parameter Type Description Validation conditions
walletPin CharArray Current walletPin Not empty
biometricAuthType BiometricAuthType (BIOMETRIC_ONLY, BIOMETRIC_WITH_ALTERNATIVE) Type of biometrics to enable during device pairing process. Not null


Output

Success / failure callback.


Sample

//KeyguardManager example
keyguardManager = context.getSystemService(KEYGUARD_SERVICE)

fun isDeviceSecure(): Boolean {
    return keyguardManager.isKeyguardSecure
}
//if isDeviceSecure return true device is safe and enableBiometricAuthenticationWithWalletPin method can be performed

fun enableBiometricAuthenticationWithWalletPin(walletPin: CharArray, biometricAuthType : BiometricAuthType) {
    mobileDcApi.userService
        		.enableBiometricAuthenticationWithWalletPin(walletPin, biometricAuthType,
					{
            			// Biometric authentication is enabled. Read startBiometricAuthentication description to authenticate user.
        			},
 					{ throwable ->
            			// Something went wrong
            			// Check exceptions described in Error handling chapter
        			}
				)
}


startBiometricAuthentication

Asynchronous. Offline.

Create CryptoObject for biometric authentication.

Depends on usage of androidx/android support library an different CryptoObject can be provided by Android SDK.


Input

Parameter Type Description Validation conditions
cryptoObjectType CryptoObjectType

Enum that defines different types of CryptoObject

BIOMETRIC_PROMPT_ANDROIDX - androidx/biometric/BiometricPrompt/CryptoObject,

FINGERPRINT_MANAGER_COMPAT_ANDROIDX - androidx/core/hardware/fingerprint/FingerprintManagerCompat/CryptoObject,

FINGERPRINT_MANAGER - android/hardware/fingerprint/FingerprintManager/CryptoObject,

BIOMETRIC_PROMPT - android/hardware/biometrics/BiometricPrompt/CryptoObject

Not empty

Output


Success callback.


Parameter Type Description
result

BiometricAuthenticationData

Object containing CryptoObject kept as Object. 


BiometricAuthenticationData contains following field:

Parameter Type Description
cryptoObject Object Wrapper class for crypto objects supported biometric authentication.


Failure callback.


Sample 

startBiometricAuthentication sample: 

  mobileDcApi
            .userService
            .startBiometricAuthentication(CryptoObjectType.BIOMETRIC_PROMPT_ANDROIDX)
            {
             	// Creating Object for biometric authentication is done
            }, {
				// Something went wrong maybe: private key is not created or not authenticated
				// Check exceptions 
            }

BiometricAuthenticationData should be used as parameter in authenticateWithBiometric but application must cast cryptoObject parameter to CryptoObject.

Cast to CryptoObject sample :

fun wrapToBiometricAuthenticationResult(biometricAuthenticationData: BiometricAuthenticationData): BiometricAuthenticationResult {
   
	val cryptoObject = biometricAuthenticationData.cryptoObject as CryptoObject //Casting to androidx/support version of CryptoObject

    return BiometricAuthenticationResult(
        cryptoObject.signature,
        cryptoObject.cipher,
		cryptoObject.mac
	)
}

Complete flow of authentication with biometric methods:

Create your own custom view, which require to authenticate with biometric.

customViewForBiometricAuthentication = BiometricPrompt


fun startAuthentication(){
	mobileDcApi
            .userService
            .startBiometricAuthentication(CryptoObjectType.BIOMETRIC_PROMPT_ANDROIDX)
            { biometricAuthenticationData ->
             	verifyAuthentication(wrapToBiometricAuthenticationResult(biometricAuthenticationData))
            }, {
				// Something went wrong maybe: private key is not created or not authenticated
				// Check exceptions 
            }
}

fun verifyAuthentication(biometricAuthenticationResult:BiometricAuthenticationResult){
	 mobileDcApi
            .userService
            .authenticateWithBiometric(biometricAuthenticationResult)
        {
            // success authentication is done
        },
        { throwable ->
            // Something went wrong maybe private key is not authenticated?
            // Check exceptions
             
        }
    )
}


 val biometricPrompt: BiometricPrompt = BiometricPrompt(activityFragment, executor,
    object : BiometricPrompt.AuthenticationCallback() {
        override fun onAuthenticationError(
            errorCode: Int,
            errString: CharSequence
        ) {
            super.onAuthenticationError(errorCode, errString)
            Toast.makeText(context,"Authentication error", Toast.LENGTH_SHORT).show()
        }

        override fun onAuthenticationSucceeded(
            result: BiometricPrompt.AuthenticationResult
        ) {
            super.onAuthenticationSucceeded(result)
            Toast.makeText(
                context,
                "Authentication succeeded!", Toast.LENGTH_SHORT).show()

            startAuthentication()
        }


        override fun onAuthenticationFailed() {
            super.onAuthenticationFailed()
            Toast.makeText(
                context, "Authentication failed", Toast.LENGTH_SHORT).show()
        }
    })


authenticateWithBiometric

Asynchronous. Offline.

Starts system biometric authentication.

After invoke system waits for a biometric authentication.


Method can throw BiometricVerificationException.


Input

Parameter Type Description Validation conditions
biometricAuthenticationResult
BiometricAuthenticationResult

Class wrapper for biometric authentication result (Signature, Cipher, Mac) created in startBiometricAuthentication

Not empty


Output

Success callback.

Parameter Type Description
result
AuthorizationResult
Object containing verification details. 


AuthorizationResult contains following fields:

Parameter Type Description
timestamp Long? Internal information for SDK.
signedTimestamp ByteArray? Internal information for SDK
errorMessage String? Internal information for SDK


Failure callback.


Sample 

fun authenticateWithBiometrics(biometricAuthenticationResult: BiometricAuthenticationResult) {
    mobileDcApi
        .userService
        .authenticateWithBiometric(biometricAuthenticationResult, { authorizationResult ->
            // authentication with biometric is finished with success, use authorizationResult to loginBySignature
        }, { throwable ->
            // Something went wrong, was authentication passed?
            // Check exceptions
        })
}


loginByTrustedIdentity

Asynchronous. Online.

Authenticates user in Mobile DC backend after providing trusted identity.

Creates / refreshes user session.

Input

Parameter Type Description

Validation conditions

trustedIdentity String

Trusted identity generated by client

Not empty


TrustedIdentity

Parameter Type Description

Validation conditions

userId String

External user id given by the client

Not empty


Output

Success / failure callback.


Sample

Sample code for trustedIdentity generation (see also Data signing and encryption chapter):

class TrustedIdentity {
    fun generate() {
        val claims = JWTClaimsSet.Builder()
            .claim("userId", "externalUserId")
            .build();

        val trustedIdentity = JwtGenerator.generate(claims, certificates, privateKey);
        // ...
    }
}


Usage of trustedIdentity in application:

fun loginByTrustedIdentity(mobileDcApi: MobileDcApiKotlin, trustedIdentity: String) {
    //where trustedIdentity should be generated by server and passed to mobile application
    mobileDcApi
        .userService
        .loginByTrustedIdentity(trustedIdentity, {
            //user is logged
        }, { throwable ->
            // Something went wrong, maybe trustedIdentity is wrong? 
            // Check exceptions described in Error handling chapter
        })
}


loginByPin

Asynchronous. Online.

Authenticates user in Mobile DC backend after providing correct pin.

Creates / refreshes user session.


Input

Parameter Type Description

Validation conditions

pin CharArray

Wallet Pin created during user registration process associated with user account. (see: addUser)

Not empty.


Output

Success / failure callback.


Sample

fun loginByPin(mobileDcApi: MobileDcApiKotlin, pin: CharArray) {
    //Wallet Pin created during user registration process associated with user account
    mobileDcApi
        .userService
        .loginByPin(pin, {
            //user is logged
        }, { throwable ->
            // Something went wrong, maybe pin is incorrect? 
            // Check exceptions described in Error handling chapter
        })
}


loginBySignature

Asynchronous. Online.

Authenticates user in Mobile DC backend after local biometric authentication (startBiometricAuthentication and authenticateWithBiometric methods).

Creates / refreshes user session.

Input

AuthorizationResult provided in success callback from authenticateWithBiometric method.


Output

Success / failure callback.


Sample

fun loginBySignature(authorizationResult: AuthorizationResult) {
    mobileDcApi
            .userService
            .loginBySignature(authorizationResult, {
                // User is authenticated
            }, { throwable ->
                // Something went wrong
                // Check exceptions
            })
}


changeWalletPin

Asynchronous. Online.

Changes user's wallet PIN with given parameters.

Input


Parameter

Type

Description

Validation conditions

walletPin CharArray

Current wallet PIN.

Has 4 or 8 digits.
newWalletPin CharArray New wallet PIN. Has 4 or 8 digits.

Output


Success / failure callback.

Sample

fun changeWalletPin(walletPin:CharArray, newWalletPin:CharArray) {
    mobileDcApi
        .userService
        .changeWalletPin(walletPin, newWalletPin, {
            //user's Wallet PIN is changed
        }, { throwable ->
            // Something went wrong, maybe current PIN is wrong? 
            // Check exceptions described in Error handling chapter
        })
}


resetWalletPin

Asynchronous. Online.

Resets wallet pin with given parameters.


Input

Parameter Type Description

Validation conditions

userLoginType

UserType

User identifier type. One of: [PHONE, EMAIL]

Not empty
userLogin CharArray User identifier. Depends on user identifier type (EMAIL or PHONE) Depends on user identifier type. For a phone number  it's phone number with country prefix. For pl: 48500500500. For email it's a valid email
newWalletPin CharArray New user wallet pin Only numbers with 4 to 8 digits
password CharArray

Current user password

The password should be composed of at least 8 characters and include at least 3 out of the following 4 categories: upper-case letter, lower-case letter, special character and digit


Output

Success / failure callback.


Sample

fun resetWalletPin(userLogin: CharArray, loginType: UserType, newPin: CharArray, password: CharArray) {
    mobileDcApi
        .userService
        .resetWalletPin(userLogin, loginType, newPin, password, {
            //user's pin is changed
        }, { throwable ->
            // Something went wrong, maybe password is wrong? 
            // Check exceptions described in Error handling chapter
        })
}

changePassword

Asynchronous. Online.

Changes user's password with given parameters.


Input

Parameter Type Description

Validation conditions

password CharArray

Current user password

The password should be composed of at least 8 characters and include at least 3 out of the following 4 categories: upper-case letter, lower-case letter, special character and digit
newPassword CharArray New user password The password should be composed of at least 8 characters and include at least 3 out of the following 4 categories: upper-case letter, lower-case letter, special character and digit


Output

Success / failure callback.


Sample

fun changePassword(password:CharArray, newPassword:CharArray) {
    mobileDcApi
        .userService
        .changePassword(password, newPassword, {
            //user's password is changed
        }, { throwable ->
            // Something went wrong, maybe current password is wrong? 
            // Check exceptions described in Error handling chapter
        })
}


initializeResetUserPassword (deprecated)

Asynchronous. Online.

Reset user's password with given parameters.

Input

Parameter Type Description

Validation conditions

userLoginType UserType

 User identifier type. One of: [PHONE, EMAIL, INTERNAL_ID, EXTERNAL_ID]

 Not empty
userLogin CharArray User identifier. Depends on user identifier type Not empty, valid email address or phone with country prefix. For pl: 48500500500


Output

Success callback with key and optionally with LimitedResourceInfo.

Parameter Type Description
key CharArray (Required) Initialization key that will be required for finalize reser user password process
limitedResourceInfo LimitedRedourceInfo? Additional paremeter which shows information about rate of APIs limits.


Failure callback.

Sample

fun initializeResetUserPassword(userLoginType: UserType, userLogin: CharArray) {
    mobileDcApi
        .userService
        .initializeResetUserPassword(userLoginType, userLogin, { response ->
            val key = response // key is necessary to call the finalizeResetUserPassword method. 
        }, { throwable ->
            // Something went wrong. 
            // Check exceptions described in Error handling chapter
        })
}

initializeResetUserPassword

Asynchronous. Online.

Reset user's password with given parameters.


Input

Parameter Type Description

Validation conditions

initializeResetUserPassword InitializeResetUserPassword An object containing user login type and user login

 Not empty



InitializeResetUserPassword model:

Parameter Type Description
userLoginType UserType

User identifier type. One of: [PHONE, EMAIL, INTERNAL_ID, EXTERNAL_ID]

userLogin CharArray User identifier. Depends on user identifier type


Output

Success callback with key.


Parameter Type Description
key CharArray (Required) Initialization key that will be required for finalize reser user password process
limitedResourceInfo LimitedResourceInfo? Additional paremeter which shows information about rate limited APIs.


Failure callback.

Sample

fun initializeResetUserPassword(initializeResetUserPassword: InitializeResetUserPassword) {
    mobileDcApi
        .userService
        .initializeResetUserPassword(initializeResetUserPassword, { response ->
            val key = response.key // key is necessary to call the finalizeResetUserPassword method. 
			val limitedResourceInfo = response.limitedResourceInfo // limitedResourceInfo contains information about 
            // rate limited APIs, all parameters are nullable
        }, { throwable ->
            // Something went wrong. 
            // Check exceptions described in Error handling chapter
        })
}


finalizeResetUserPassword

Asynchronous. Online.

Set new user password with given parameters.


Input

Parameter Type Description

Validation conditions

userLoginType UserType

 User identifier type. One of: [PHONE, EMAIL, INTERNAL_ID, EXTERNAL_ID]

 Not empty
userLogin CharArray User identifier. Depends on user identifier type Not empty, valid email address or phone with country prefix. For pl: 48500500500
key CharArray Key from initialize reset user password method Not empty
otp CharArray One time password (sent via email during initialize password reset process) Not empty
newPassword CharArray New user password The password should be composed of at least 8 characters and include at least 3 out of the following 4 categories: upper-case letter, lower-case letter, special character and digit


Output

Success / failure callback.


Sample

fun finalizeResetUserPassword(userLoginType: UserType, userLogin: CharArray, 
	key: CharArray, otp: CharArray, newPassword: CharArray) {
    mobileDcApi
        .userService
        .finalizeResetUserPassword(userLoginType, userLogin, key, otp, newPassword, { 
           // The OTP has been sent
        }, { throwable ->
            // Something went wrong. 
            // Check exceptions described in Error handling chapter
        })
}


initializeEmailUpdate

Asynchronous. Online.

Change the user's email address to a new one.
After confirming the change of the email, the one-time password ( OTP) will be sent to this address.


Input

Parameter Type Description

Validation conditions

email CharArray

New email (an OTP will be sent to that address)

Email format


Output

Success callback with key.

Parameter Type Description
key CharArray Initialization key that will be required for finalize reset user password process


Failure callback.

Sample

fun initializeEmailUpdate(email: CharArray) {
    mobileDcApi
        .userService
        .initializeEmailUpdate(email, { response ->
            val key = response // key is necessary to call the finalizeChangeEmail method.
        }, { throwable ->
            // Something went wrong.
            // Check exceptions described in Error handling chapter
        })
}


finalizeEmailUpdate

Asynchronous. Online.

Set new user email.


Input

Parameter Type Description

Validation conditions

key CharArray Key from initialize change email method Not empty
otp CharArray One time password (sent via email during initialize change email process) Not empty


Output

Success / failure callback.


Sample

fun finalizeEmailUpdate(key: CharArray, otp: CharArray) {
    mobileDcApi
        .userService
        .finalizeEmailUpdate( key, otp, { 
           // The user's email has been changed
        }, { throwable ->
            // Something went wrong. 
            // Check exceptions described in Error handling chapter
        })
}


resendOtp

Asynchronous. Online.

Method for resend OTP.

Input


Parameter Type Description

Validation conditions

userLoginType UserType User identifier type. One of: [PHONE, EMAIL, INTERNAL_ID, EXTERNAL_ID] Not empty
userLogin User identifier. Depends on user identifier type User identifier. Depends on user identifier type Not empty, valid email address or phone with country prefix. For pl: 48500500500


Output

Success / failure callback.


Sample

fun resendOtp(userLoginType: UserType, userLogin: CharArray) {
    mobileDcApi
        .userService
        .resendOtp( userLoginType, userLogin, { 
           // OTP has been sent
        }, { throwable ->
            // Something went wrong. 
            // Check exceptions described in Error handling chapter
        })
}

logout

Asynchronous. Offline.

Cancels user session.

Input

No input parameters.


Output

Success / failure callback.


Sample

fun logout() {
    mobileDcApi
        .userService
        .logout({
            //User session has been canceled. Refresh user session to restore it.
        }, {
            //Something went wrong
            //Check exceptions described in Error handling chapter            
        })
}


deleteUser

Asynchronous. Online.

Delete data of current user and reset SDK state when success. The user can be hard or soft deleted depending on project’s configuration.
Hard - method used to delete user with deleting data connected to the user (eg. card).
Soft - method used to delete user without deleting data connected to the user (eg. card)

Usage of this method causes clearing all data related to selected user.

Input

No input parameters.


Output

Success/failure callback.


Sample

fun deleteUser() {
    mobileDcApi
        .userService
        .deleteUser({
            //user is deleted, all data related to user, device cards etc is cleared. SDK is restarted.
        }, { throwable ->
            // Something went wrong
            // Check exceptions described in Error handling chapter
        })
}


Cards domain

addCard

Asynchronous. Online.

Adds new payment card with given parameters.

Input

Parameter Type Description
addCard AddCard Card information data.


AddCard

Parameter Type Description Validation conditions
cardNumber CharArray

Card number

Field cannot be empty, it must contain only digits, a length of exactly 16 digits and the checksum of the digits must be valid
expirationDate CharArray Card expiration date Field may not be empty and  must have a format MM/YY
description CharArray

Card description

Not empty
cardHolder

CardHolder

Card holder data Not empty
isDefault Boolean? Is default card for user -
currency CharArray? Currency of card  (ISO 4217, three letter code) -
visualId CharArray? Visual identifier -


CardHolder

Parameter Type Description Validation conditions
firstName CharArray

First name of card holder

Not empty
lastName CharArray Last name of card holder Not empty


Output

Success callback with cardId.

Parameter Type

Description

cardId Long Id of added card


Sample

fun addCard(addCard: AddCard){
    mobileDcApi
        .cardsService
        .addCard(addCard, { cardId ->
            // Card added
        }, { throwable ->
            // Something went wrong, maybe any field is wrong? 
            // Check exceptions described in Error handling chapter
        })
}


addCard (deprecated)

Asynchronous. Online.

Adds new payment card with given parameters.


Input

Parameter Type Description Validation conditions
cardNumber CharArray Card number Field cannot be empty, it must contain only digits, a length of exactly 16 digits and the checksum of the digits must be valid
expirationDate CharArray Card expiration date Field may not be empty and  must have a format MM/YY
description CharArray

Card description

Not empty
firstName

CharArray

Card holder first name Not empty
lastName CharArray Card holder last name Not empty


Output

Success callback with cardId.

Parameter Type

Description

cardId Long Id of added card


Sample

fun addCard(cardNumber:CharArray, expirationDate:CharArray, description:CharArray, 
	firstName:CharArray, lastName:CharArray){
    	mobileDcApi
        	.cardsService
        	.addCard(cardNumber, expirationDate, description, firstName, lastName, { cardId ->
           	 // Card added
        	}, { throwable ->
          	  // Something went wrong, maybe any field is wrong? 
           	 // Check exceptions described in Error handling chapter
       	 })
}


getAll

Asynchronous. Online.

Provides user cards from Mobile DC backend.


Input

No input parameters.


Output

Success callback with list of user cards.

Parameter Type Description
cards List <Card>

List of user cards


Card

Field Type Description
cardId Long

Card main identifier. Also used as paymentInstrumentId

lastFourDigits String Last four digits of user card
expirationDate String Card expiration date
isVerified Boolean

Flag informing about card verification

cardHolder CardHolder? Card holder details
visualPath String? Path to visual of card
description String? Card description
cardType CardType (MASTERCARD, VISA, OTHER, UNKNOWN) Type of card
isDefault Boolean Indicates if card is default user’s card
source String? From which source card has been added
currency String? Currency code (ISO 4217, three letter code)
visualId String? Visual id
externalId String? Card external id
isLocked Boolean Flag which informs if card is locked


CardHolder object:

Field Type Description
firstName String Card holder first name
lastName String Card holder last name


Failure callback.


Sample

fun getCards() {
    mobileDcApi
        .cardsService
        .getAll({ cards ->
            showCardList(cards)
        }, {
            // Something went wrong
            // Check exceptions described in Error handling chapter
        })
}


deleteCard

Asynchronous. Online.

Delete card with given card id.


Input

Parameter Type Description Validation conditions
cardId Long Id of deleting card Field cannot be empty.


Output

Success / failure callback.


Sample

fun deleteCard(cardId: Long) {
    mobileDcApi
        .cardsService
        .deleteCard(cardId, {
            //Success
        }, {
            //Something went wrong
            //Check exceptions described in Error handling chapter
        })
}


initialize3ds

Asynchronous. Online.

Card verification- initialize 3D Secure. Provides the data needed for the 3D Secure verification process.


Input

Parameter Type Description Validation conditions
cardId Long Id of added card Not empty


Output

Success callback with Initialize3dsResult.


Parameter Type

Description

initialize3dsResult Initialize3dsResult Contains necessary data for 3DS verification


Initialize3dsResult

Field Type Description
paymentId CharArray Internal transaction id
pageContent CharArray Content of webpage to be shown in browser created in application

Sample

fun initialize3ds(mobileDcApi: MobileDcApiKotlin, cardId: Long) {
        mobileDcApi
                .cardsService
                .initialize3ds(cardId, { result ->
                    val paymentId = result.paymentId
                    val pageContent = result.pageContent

                    // Check is pageContent not null
                    if (pageContent != null) {
                        // Necessary convert from CharArray to ByteArray
                        val pageContentToByteArray = pageContent.toByteArray()
                        openWebView(paymentId, pageContentToByteArray)
                    } else {
                        // Card verification error
                    }
                }, { throwable ->
                    // Something went wrong, maybe cardId is invalid?
                    // Check exceptions described in Error handling chapter
                })

    }

    fun openWebView(paymentId: CharArray, pageContent: ByteArray) {
        //Bind your webView
        val myWebView = findViewById<WebView>(R.id.myWebView)

        //JavaScript is disabled in a WebView by default. You can enable it through the WebSettings
        //attached to your WebView. You can retrieve WebSettings with getSettings(), then enable JavaScript 
        //with setJavaScriptEnabled().
        val webSettings: WebSettings = myWebView.getSettings()
        webSettings.javaScriptEnabled = true

        //Necessary bind this class to the JavaScript that runs in your WebView with addJavascriptInterface() 
        //and name the interface Android.
        myWebView.addJavascriptInterface(WebAppInterface(), "Android")

        // Decode pageContent from initialize3ds response
        val viewPageContent = String(Base64.decode(pageContent, Base64.DEFAULT))
        // Load page in vebWiew
        myWebView.loadData(viewPageContent, "text/html; charset=UTF-8", "utf-8")
    }

//To bind a new interface between your JavaScript and Android code, call addJavascriptInterface(),
//passing it a class instance to bind to your JavaScript and an interface name that your JavaScript 
//can call to access the class, like below example

    class WebAppInterface {
        // Get the pares parameter from the web page
        @JavascriptInterface
       	fun setData(pares: String?) {
            // onPares interface method provides the pares parameter after interaction with webView. 
            //Parameter pares is needed to perform finalize3ds
            // Necessary convert from String to CharArray
            val paresToCharArray = pares?.toCharArray()
            // close webView
            // Then you need to properly handle the parameter pares to be able to call finalize3ds
            //with the parameter pares and paymentId.
        }
    }

finalize3ds

Asynchronous. Online.

Card verification - finalize 3D Secure. Verifies the payment card by the 3D Secure.


Input

Parameter Type Description Validation conditions
cardId Long Id of added card Not empty
cvc CharArray Card verification code  Field cannot be empty, it must contain only digits, a length of exactly 3 digits
pares CharArray Received after successful interaction with webView
Not empty
paymentId CharArray Received after a valid query to Initialize3ds
Not empty


Output

Success callback with Finalize3dsResult.


Parameter Type

Description

finalize3dsResult Finalize3dsResult Contains data on the needed to carry out the amount verification and the verification value of the cardholder authentication


Finalize3dsResult

Field Type Description
amountValidation Boolean Inform if random quotation should be used to complete card verification
cavv CharArray Cardholder authentication verification value

Sample

fun finalize3ds(mobileDcApi: MobileDcApiKotlin, cardId: Long, cvc: CharArray, pares: CharArray, 
	paymentId: CharArray) {
    	mobileDcApi
        	    .cardsService
            	.finalize3ds(cardId, cvc, pares, paymentId, { result ->
                	val amountValidation = result.amountValidation
                	val cavv = result.cavv
           		 }, { throwable ->
            	    // Something went wrong, maybe any field is invalid?
                	// Check exceptions described in Error handling chapter
            })
}


initialize3DSv2

Asynchronous. Online.

Card verification - initialize 3D Secure. Provides the data needed for the 3D Secure verification process.


Input

Parameter Type Description Validation conditions
initialize3DSv2 Initialize3DSv2 An object containing data for secure verification process.

Not empty


Initialize3DSv2

Parameter Type Description Validation conditaions
cardId Long Id of the card Not empty
challengeUrl String

Callback url to handle redirect during Challenge (status CHALLENGE_REQUIRED from response).
Check sample implementation below.

Not empty
browserDetails BrowserDetails Object with properties described below Not empty


BrowserDetails

Parameter Type Description Validation conditions
timezoneOffset String Timezone offset - numeric Not empty
userAgent String User Agent Not empty
acceptHeader String Accept Header Not empty
screenWidth String Screen Width - numeric Not empty
screenHeight String Screen Height Not empty
language String Language - IETF BCP 47 Not empty
browserIp String Browser IP Not empty
screenColorDepth String Screen Color Depth - numeric Not empty


Output

Success callback with Initialize3DSv2Result

Parameter Type

Description

initialize3DSv2Result Initialize3DSv2Result Contains necessary data for 3DS verification


Initialize3DSv2Result

Field Type Description
status String

Status returned of operation. Status could be SUCCESS or CHALLENGE_REQUIRED.
For SUCCESS the Card is already verified and no more action is required.
For CHALLENGE_REQUIRED application should show WebView with content from challengeHtmlFromBase64.

authenticationId String Card authentication id, used in finalize3DSv2 method.
acsUrl String? ACS (Access Control Server) url. Required for CHALLENGE_REQUIRED.
challengeHtmlFormBase64 String? 64BASED html code provided ACQ/ASC. This should be displayed to Application User. Required for CHALLENGE_REQUIRED.


Sample

fun initialize3DSv2(mobileDcApi : MobileDcApiKotlin){
    mobileDcApi
        .cardsService
        .initialize3DSv2(initialize3DSv2, { initialize3DSv2Result ->
            when (initialize3DSv2Result.status) {
                "SUCCESS" -> {
                    //3DS success, no more action is required
                }

                "CHALLENGE_REQUIRED" -> {
                    showWebView(initialize3DSv2Result.challengeHtmlFormBase64, challengeUrl)
                }

                else -> //failure
            }
        }, { throwable ->
        	// Something went wrong
            // Check exceptions described in Error handling chapter
        })
}


//WebView implementation

fun showWebView(challengeHtmlFormBase64: String, challengeUrl : String) {

    val viewPageContent = String(Base64.decode(challengeHtmlFormBase64, Base64.DEFAULT))
    val webViewUrlDetectionClient = WebViewUrlDetectionClient(challengeUrl)

    with(webView) {
        webViewClient = webViewUrlDetectionClient
		settings.javaScriptEnabled = true
		visibility = View.VISIBLE
        loadData(
            viewPageContent,
            "text/html; charset=UTF-8",
            "utf-8"
        )
    }
}


//sample WebViewClient implementation for handing redirect on challangeUrl
class WebViewUrlDetectionClient(private val challengeUrl: String): WebViewClient() {
    override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {
        super.onPageStarted(view, url, favicon)
        if (url.equals(challengeUrl, true)) {
            //call finalize3DSv2(cardId, initialize3DSv2Result.authenticationId)
        }
    }
}

finalize3DSv2

Asynchronous. Online.

Card verification - finalize 3D Secure. Verifies the payment card by the 3D Secure.

Input

Parameter Type Description Validation conditions
finalize3DSv2 Finalize3DSv2 An object containing data for secure finalization process. Not empty


Finalize3DSv2

Parameter Type Description Validation conditions
cardId Long Id of the card. Not empty
authenticationId String Identifier of verification process from Initialize3DSv2Result Not empty


Output

Success callback/ Failure callback.

Sample

fun finalize3DS(mobileDcApi : MobileDcApiKotlin) {

    val finalize3DSv2Input = Finalize3DSv2(cardId, authenticationId)

    mobileDcApi
        .cardsService
        .finalize3DSv2(
            finalize3DSv2Input, {
                //3DS finished with success
            }, { throwable ->
            	// Something went wrong
                // Check exceptions described in Error handling chapter
            }
        )
}


updateCard

Method for updating payment card data.

Input

Parameter Type Description
updateCard UpdateCard An object containing card data to update


UpdateCard

Parameter Type Description
cardId Long Unique card id
description CharArray? Card description
currency CharArray? Card currency (ISO 4217, three letter code format)
isDefault Boolean? Is this card default
visualId CharArray? Card visual identifier
firstName CharArray? Card holder first name - send only when lastName is not blank
lastName CharArray? Card holder last name - send only when firstName is not blank

Output

Success callback/ Failure callback.

Sample

fun updateCard(cardId: Long, description: CharArray?, isDefault: Boolean?, firstName: CharArray?, lastName: CharArray?){
	val updateCard = UpdateCard(cardId).apply {
		this.description = description
		this.firstName = firstName
		this.lastName = lastName
		this.isDefault = isDefault
	}

    mobileDcApi
        .cardsService
        .updateCard(updateCard) {
            // Card updated
        }, { throwable ->
            // Something went wrong, maybe any field is wrong? 
            // Check exceptions described in Error handling chapter
        })
}



verifyCard

Asynchronous. Online.

Card verification - verify card after 3ds.

Input

Parameter Type Description
verifyCard VerifyCard An object containing card data to verify.


VerifyCard

Parameter Type Description
cardId Long Unique card id
amount CharArray? If finalize3ds returns amountValidation set to false should be null otherwise value is amount freezed on the user account during card verification (value between 100 and 200 pennies).


Output

Success callback/ Failure callback.


Sample

fun verifyCard(cardId: Long, amount: CharArray?, amountValidation: Boolean) {
    val verifyCard: VerifyCard = VerifyCard(cardId).apply {
        this.amount = if (amountValidation) amount else null
    }
    mobileDcApi
        .cardsService
        .verifyCard(verifyCard, {
            //handle success
        }, { throwable ->
            //handle failure
        })
}


Device domain

pairByPassword

Asynchronous. Online.

Pairs device using given password and user identifier.

Input

Parameter Type Description

Validation conditions

userLoginType UserType

User identifier type. One of: [PHONE, EMAIL, INTERNAL_ID, EXTERNAL_ID]

Not empty
userLogin CharArray User identifier. Depends on user identifier type

Email or Phone with country prefix

userPassword CharArray User password Password should be composed of at least 8 characters and include at least 3 out of the following 4 categories: upper-case letter, lower-case letter, special character and digit
fcmToken CharArray Token for push notifications Not empty
biometricAuthType
BiometricAuthType?

Optional. One of: [BIOMETRIC_ONLY, BIOMETRIC_WITH_ALTERNATIVE].

BIOMETRIC_ONLY - enable only biometric authentication

BIOMETRIC_WITH_ALTERNATIVE - enable device level authentication

If not set any of above don't be enable.



Output

Success / failure callback.


Sample

fun pairByPassword(
    email: CharArray, //user email
    password: CharArray, //user password
    fcmToken: CharArray  // saved FCM token from Firebase service
) {

    mobileDcApi
        .deviceService
        .pairByPassword(UserType.EMAIL, email, password, fcmToken,
            {
                //device is paired, now you can use this device to manage Mobile DC resources
            },
            { throwable ->
                // Something went wrong, maybe any field is wrong?
                // Check exceptions described in Error handling chapter
            }
        )
}


pairByTrustedIdentity

Asynchronous. Online.

Binds device to user in Mobile DC backend with Trusted Identity genetated by client server.


Input

Parameter Type Description

Validation conditions

trustedIdentity String

JSON Web Token containing registration data

Not empty
fcmRegistrationToken CharArray

FCM Cloud messaging registration token

Not empty


TrustedIdentity

Parameter Type Description

Validation conditions

userId String

External user id given by the client

Not empty


Output

Success / failure callback.

Sample

Sample code for trustedIdentity generation (see also Data signing and encryption chapter):

class TrustedIdentity {
    fun generate() {
        val claims = JWTClaimsSet.Builder()
            .claim("userId", "externalUserId")
            .build();

        val trustedIdentity = JwtGenerator.generate(claims, certificates, privateKey);
        // ...
    }
}


Usage of trustedIdentity in application:

fun pairDeviceByTrustedIdentity(
    mobileDcApi: MobileDcApiKotlin,
    trustedIdentity: String
) {

    val fcmToken = getFcmRegistartionToken() // get saved FCM token from FirebaseMessagingService, or from 
		//FirebaseInsanceId::getToken()

	mobileDcApi
        .deviceService
        .pairByTrustedIdentity(
            trustedIdentity,
            fcmToken, {
                //device is paired, now you can use this device to manage Mobile DC resources
            }, { throwable ->
                //some error occured, check exception
            })
}


pairByExternalCredentials

Asynchronous. Online.

Binds device to user in Mobile DC backend using username and password.


Input

Parameter Type Description

Validation conditions

username String

User identifier

Not empty
password CharArray User password Not empty
fcmRegistrationToken CharArray

FCM Cloud messaging registration token

Not empty

biometricAuthType BiometricAuthType?

Optional. One of: [BIOMETRIC_ONLY, BIOMETRIC_WITH_ALTERNATIVE].

BIOMETRIC_ONLY - enable only biometric authentication

BIOMETRIC_WITH_ALTERNATIVE - enable device level authentication

If not set any of above don't be enable.


Output

Success / failure callback.


Sample

fun pairByExternalCredentials() {

    val username: CharArray = getCharArrayFromInput() //get username provided by user
    val password: CharArray = getCharArrayFromInput() //get password provided by user
    val fcmToken = getFcmToken() // get saved FCM token from Firebase service

    mobileDcApi
        .deviceService
        .pairByExternalCredentials(
            username,
            password,
            fcmToken, {
                //device is paired, now you can use this device to manage Mobile DC resources
            }, { throwable ->
                //some error occured, check exception
            })
}


isDevicePaired

Asynchronous. Offline.

Method allow to check is Device already paired with MDC Backend.


Input

No input parameters.


Output

Success / failure callback.


Sample

fun isDevicePaired() {
    mobileDcApi
        .deviceService
        .isDevicePaired()
        {
           // return is device paired state
		},
		{throwable ->  
           // some error occurred, check exception
        }
}


unPairDevice

Asynchronous. Online.

Removes all data collected by SDK and binding between user and device in Mobile DC backend.

Pairing device to user can be made by <<pairBy...>> methods.

Input

No input parameters.


Output

Success / failure callback.


Sample

fun unPairDevice() {
    
	mobileDcApi
        .deviceService
        .unPairDevice({
            //device is unPaired, SDK cannot be not longer used
            //application can remove all data in context of sDKDefaultBackoffStrategy
            //for use SDK again call pairBy.. method
        }, { throwable ->
            //some error occured, check exception
        })
}


Cloud messaging domain

getSource

Asynchronous. Offline.

Checks Verestro Backend service source of push content.

Application should check senderId in RemoteMessage object (RemoteMessage::from method) before passing data to this method.


Input

Parameter Type Description

Validation conditions

pushData Map<String, String>

Data received from notification service in RemoteMessage object

Not empty


Output

Success callback with source of push.

Parameter Type Description
source String

Source of push content, where push data should be passed. Possible values: UCP


Failure callback.


Sample

//FirebaseMessagingService class from Firebase

override fun onMessageReceived(remoteMessage: RemoteMessage) {
    super.onMessageReceived(remoteMessage)

    val senderId: String? = remoteMessage.from
    val pushData = remoteMessage.data

	//check push source only when push source is uPaid sender Id

    if (isUpaidSenderId(senderId)) {

		//checking push source and passing to proper uPaid module

        mobileDcApi
            .cloudMessagingService
            .getSource(pushData, { source ->
                when (source) {
                    "UCP" -> processUcpPush(pushData)
                }
            }, {
                //some error
            })

    } else {
        //proceed push from another source
    }
}


private fun processUcpPush(pushData: Map<String, String>) {
    ucpApi
        .cloudMessagingService
        .process(pushData, {
            //push processed in UCP
        }, {
            //some error
        })
}


updateFcmRegistrationToken

Asynchronous. Online.

Updates FCM Cloud Messaging registation token.

Method should be called when application receive new registration token from FCM service.

When updated application should still receive push notifications from Verestro Backend.

Application should always retry update FCM Registration token if method failed.


Input

Parameter Type Description

Validation conditions

fcmToken String

Registration token received from FCM service

Not empty


Output

Success / failure callback.


Sample

//application should listen for FCM token changes in FirebaseMessagingService::onNewToken method

private fun updateFcmToken(newFcmToken: String) {
    mobileDcApi
        .deviceService
        .isDevicePaired({ isPaired ->
            //token update is required only if device is already paired
            if (isPaired) {
                mobileDcApi
                    .cloudMessagingService
                    .updateFcmRegistrationToken(newFcmToken, {
                        //token updated
                    }, {
                        //some error, always retry action until success
                        //when internet or server connection is not reachable try again later
                    })
            }
        }, {
            //some error
        })

TransactionsHistory domain

getTransactionsHistory

Asynchronous. Online.

Provides transaction history from Mobile DC backend with selected transactions filters.


Input

Parameter Type Description Validation conditions
filters TransactionsFilters? Filters for transactions history. Leave null to get all user's transactions with limit equals 10
nextPage TransactionsNextPage?

Indicates starting point of downloaded transaction history

Pass null for first request or pass object from getTransactionHistory result



TransactionsFilters

Parameter Type Description Validation conditions
cardId String? Selected card id or null
ibanId String? Selected iban id or null
paymentTokenId String?

Selected paymentTokenId or null

Field is available in PaymentInstrument object in UCP module


area String? Area of transaction, specific per project (e.g. "UCP"). Could be null in order to avoid filtering by area of transaction.
timestampFrom String? The date/time (in ISO 8601 extended format) indicating the timestamp from which transactions would be filtered (e.g. "2020-10-10T00:59:00.000000+02:00"). Could be null in order to avoid filtering by indicating the earliest date of transactions.
timestampTo String? The date/time (in ISO 8601 extended format) indicating the timestamp to which transactions would be filtered (e.g. "2020-10-10T00:59:00.000000+02:00"). Could be null in order to avoid filtering by indicating the latest date of transactions.
amountMinorMin Long?

The transaction minimum monetary amount (inclusive) in terms of the minor units of the currency.
For example, for EUR 2.35 client should pass 235, and for BHD -1.345 should pass 1345. Absolute value is taken into consideration.


amountMinorMax Long? The transaction maximum monetary amount (inclusive) in terms of the minor units of the currency.
For example, for EUR 2.35 client should pass 235, and for BHD -1.345 should pass 1345. Absolute value is taken into consideration.

amountType AmountType? Transaction amount type. One of POSITIVE, NEGATIVE
limit Int? Limit of transactions to get. When not changed default value is 10


TransactionsNextPage

Parameter Type Description Validation conditions
seekId String Seek id of next transaction
seekTimestamp String Seek timestamp of next transaction


Output

Success callback with list of transactions history.


Parameter Type Description
transactionHistory TransactionHistory An object containing list of TransactionDetails and TransactionNextPage to show transaction history


Parameter Type

Description

transactions List<TransactionDetails> List of transactions history
nextPage TransactionsNextPage? Object for getting next transactions history items


TransactionDetails

Field Type Description
id Long Internal transaction id
clientTransactionId String Client id of transaction
amountMinor Long The transaction monetary count in terms of the minor units of the currency
currency String Currency of the transaction amount. 3-digits ISO 4217 currency code
type String Transaction type. One of: PURCHASE, REFUND, PAYMENT, ATM_WITHDRAWAL, CASH_DISBURSEMENT, ATM_DEPOSIT, ATM_TRANSFER
status String Transaction status. One of: DECLINED, CLEARED, AUTHORIZED, REVERSED
timestamp String The date/time when the transaction occurred. In ISO8601 extended format
description String? Description of transaction
cardId Long? Card id of transaction
paymentTokenId String? Id of payment token
cardLastFourDigits String? Last four digits of card
merchantName String? The merchant name
merchantPostalCode String? The postal code of the merchant
transactionCountryCode String? The country in which the transaction was performed. Expressed as a 3-letter country code as defined in ISO 3166-1
comboCardAccountType String? Indicator if Credit or Debit was chosen for a tokenized combo card at the time of the transaction. One of: CREDIT, DEBIT
issuerResponseInformation String?

Additional information provided by the issuer for declined transaction. One of: INVALID_CARD_NUMBER, FORMAT_ERROR, MAX_AMOUNT_EXCEEDED,

EXPIRED_CARD, PIN_AUTHORIZATION_FAILED, TRANSACTION_NOT_PERMITTED, WITHDRAWL_AMOUNT_EXCEEDED, RESTRICTED_CARD,

WITHDRAWL_COUNT_EXCEEDED, PIN_TRIES_NUMBER_EXCEEDED, INCORRECT_PIN, DUPLICATE_TRANSMISSION

transactionChannel String?

Information about transaction channel. One of: CONTACTLESS, CLOUD, MONEYSEND

ibanId String? Id of iban as sha256Hex
mcc String? 4 digits merchant category code
mccCategory String? Category of merchant category code
originalAmountMinor Long? The transaction monetary amount in terms of the minor units of the original currency. For example, EUR 2.35 will return 235, and BHD -1.345 will return -1345. Negative amounts indicate a refund or payment
originalCurrency String?
3-character ISO 4217 original currency code of the transaction
exchangeRate Double?
Exchange rate of the original currency into the base currency
balanceMinorValueAfterTransaction Long?
Account balance value after transaction in terms of the minor units
commissionMinorValue Long?
Commission value in terms of the minor units
clearingTimestamp String?
The date/time when the transaction changed status on CLEARED. In ISO 8601 extended format
parentId Long?
Id of base transaction
attachmentStatus String?
Attachment status of transaction. One of: [EMPTY, INCORRECT, TO_APPROVE, APPROVED]
incorrectAttachmentStatusReason String?
Reason of INCORRECT attachment status. Required only for this status. One of: [ATTACHMENT_UNREADABLE, ATTACHMENT_INCORRECT, OTHER]


TransactionsNextPage


Parameter Type Description Validation conditions
seekId String Seek id of next transaction
seekTimestamp String Seek timestamp of next transaction


Sample

//sample filters
val lastFiveTransactionForCard = TransactionsFilters()
lastFiveTransactionForCard.cardId = "1"
lastFiveTransactionForCard.limit = 5 //when not set default is 10

//another sample filters
val allTransactionsForUser: TransactionsFilters? = null

//another sample filters
val lastThreeTransactionsForUser = TransactionsFilters()
lastThreeTransactionsForUser.limit = 3


//indicates starting point of transaction history
//can be used while loading more history or for paging
var nextPage: TransactionsNextPage? = null


fun getTransactionsHistory(filters: TransactionsFilters?) {
    mobileDcApi
        .transactionsHistoryService
        .getTransactionsHistory(filters, nextPage, { transactionsHistory ->
                val transactions = transactionsHistory.transactions
                showTransactions(transactions)

                //save nextPage for getting next items
                nextPage = transactionsHistory.nextPage
            }, {
                //something went wrong, check exception
            })
}


getTransactionDetails

Asynchronous. Online.

Provides transaction details from Mobile DC backend for selected transactionId.


Input

Parameter Type Description Validation conditions
getTransactionDetails GetTransactionDetails Contains id for requested transactionId transactionId greater than 0 and not null


GetTransactionDetails

Parameter Type Description Validation conditions
transactionId Long Selected id of transaction Greater than 0 and not null


Output

Success callback with transaction details.



Parameter Type Description
getTransactionDetailsResult GetTransactionDetailsResult An object containing details for requested transaction


GetTransactionDetailsResult

Field Type Description
id Long Internal transaction id
clientTransactionId String Client id of transaction
amountMinor Long The transaction monetary count in terms of the minor units of the currency
currency String Currency of the transaction amount. 3-digits ISO 4217 currency code
type String Transaction type. One of: PURCHASE, REFUND, PAYMENT, ATM_WITHDRAWAL, CASH_DISBURSEMENT, ATM_DEPOSIT, ATM_TRANSFER
status String Transaction status. One of: DECLINED, CLEARED, AUTHORIZED, REVERSED
timestamp String The date/time when the transaction occurred. In ISO8601 extended format
description String? Description of transaction
cardId Long? Card id of transaction
paymentTokenId String? Id of payment token
cardLastFourDigits String? Last four digits of card
merchantName String? The merchant name
merchantPostalCode String? The postal code of the merchant
transactionCountryCode String? The country in which the transaction was performed. Expressed as a 3-letter country code as defined in ISO 3166-1
comboCardAccountType String? Indicator if Credit or Debit was chosen for a tokenized combo card at the time of the transaction. One of: CREDIT, DEBIT
issuerResponseInformation String?

Additional information provided by the issuer for declined transaction. One of: INVALID_CARD_NUMBER, FORMAT_ERROR, MAX_AMOUNT_EXCEEDED,

EXPIRED_CARD, PIN_AUTHORIZATION_FAILED, TRANSACTION_NOT_PERMITTED, WITHDRAWL_AMOUNT_EXCEEDED, RESTRICTED_CARD,

WITHDRAWL_COUNT_EXCEEDED, PIN_TRIES_NUMBER_EXCEEDED, INCORRECT_PIN, DUPLICATE_TRANSMISSION

transactionChannel String?

Information about transaction channel. One of: CONTACTLESS, CLOUD, MONEYSEND

ibanId String? Id of iban as sha256Hex
mcc String? 4 digits merchant category code
mccCategory String? Category of merchant category code
originalAmountMinor Long? The transaction monetary amount in terms of the minor units of the original currency. For example, EUR 2.35 will return 235, and BHD -1.345 will return -1345. Negative amounts indicate a refund or payment
originalCurrency String?
3-character ISO 4217 original currency code of the transaction
exchangeRate Double?
Exchange rate of the original currency into the base currency
balanceMinorValueAfterTransaction Long?
Account balance value after transaction in terms of the minor units
commissionMinorValue Long?
Commission value in terms of the minor units
clearingTimestamp String?
The date/time when the transaction changed status on CLEARED. In ISO 8601 extended format
parentId Long?
Id of base transaction
attachmentStatus String?
Attachment status of transaction. One of: [EMPTY, INCORRECT, TO_APPROVE, APPROVED]
incorrectAttachmentStatusReason String?
Reason of INCORRECT attachment status. Required only for this status. One of: [ATTACHMENT_UNREADABLE, ATTACHMENT_INCORRECT, OTHER]
attachments
List<TransactionDetailsAttachment>
Transaction attachments list


TransactionDetailsAttachment

Parameter Type Description
id String Attachment id
name String File name
mimeType String Mime type
link String Url address valid by default 10 minutes. If link expires then API to generate link should be used. Mostly in this case minio will return 403 Forbidden
linkExpirationDate String Url expiration date for given link in ISO 8601 extended format. Given link will be valid only short period of time


Sample

//sample entry data
val getTransactionDetails = GetTransactionDetails(1210L)

fun getTransactionDetails(getTransactionDetails: GetTransactionDetails) {
    mobileDcApi
        .transactionsHistoryService
		.getTransactionDetails(getTransactionDetails, { getTransactionDetailsResult ->
                //succes
            }, {
                //something went wrong, check exception
            })
}


storeAttachment

Asynchronous. Online.

Stores attachment file in Mobile DC backend for selected transactionId.


Input

Parameter Type Description
transactionAttachment TransactionAttachment Contains all data required to save attachment


TransactionAttachment

Parameter Type Description Validation conditions
transactionId Long Selected id of transaction not null and greater or equal 0
attachmentInputStream InputStream Stream of file data not null
mimeType String MIME type of file. For example image/jpeg image/png Is not empty
fileName String? Name of file. If null or blank then it is generated randomly with unique name. File extension is optional.


Output

Success callback.

Sample


//sample entry data
val inputStream = contentResolver.openInputStream(uri)
val mimeType = contentResolver.getType(uri)

val transactionAttachment = TransactionAttachment(
    transactionId = 10023L,
    attachment = inputStream,
    mimeType = "image/jpeg"
)


//transaction attachment with optional file name
val transactionAttachment = TransactionAttachment(
    transactionId = 10023L,
    attachment = inputStream,
    mimeType = "image/png"
	fileName = "picture.png"
)


val transactionAttachment = TransactionAttachment(
    transactionId = 10023L,
    attachment = inputStream,
    mimeType = "image/png"
	fileName = "1636362847509"
)


fun storeAttachment(transactionAttachment: TransactionAttachment) {
    mobileDcApi
        .transactionsHistoryService
		.storeAttachment(transactionAttachment, {
                //succes
            }, {
                //something went wrong, check exception
            })
}


generateAttachmentLink

Asynchronous. Online.

Provides new link to load attachment when existing one fails with 403 HTTP status.


Input

Parameter Type Description

generateAttachmentLink

GenerateAttachmentLink

Contains transactionId and attachmentId


GenerateAttachmentLink

Parameter Type Description Validation conditions
transactionId Long Selected id of transaction not null and greater or equal 0
attachmentId String Selected attachment ID is not empty


Output

Success callback with new attachment link and expiration date.

Parameter Type Description
generateAttachmentLinkResult GenerateAttachmentLinkResult An object containing new link and link expiry date


GenerateAttachmentLinkResult

Field Type Description
link String Url address
linkExpirationDate String Url expiration date for given link in ISO 8601 extended format. Given link will be valid only short period of time

Sample

//sample entry data
val generateAttachmentLink = GenerateAttachmentLink(1210L, "2145")

fun generateAttachmentLink(generateAttachmentLink: GenerateAttachmentLink) {
    mobileDcApi
        .transactionsHistoryService
		.generateAttachmentLink(generateAttachmentLink, { generateAttachmentLinkResult ->
                //succes
            }, {
                //something went wrong, check exception
            })
}


//sample usage when loading link from getTransactionDetails returns 403 HTTP status
fun getTransactionDetails() {
	mobileDcApi
		.transactionHistoryService
		.getTransactionDetails(GetTransactionDetails(transactionId), { getTransactionDetailsResult ->
			loadAttachmentsImages(getTransactionDetailsResult)
		}, {
			//something went wrong, check exception
		}
	)
}


private fun loadAttachmentsImages(getTransactionDetailsResult: GetTransactionDetailsResult) {
	val attachments: List<TransactionDetailsAttachment> = getTransactionDetailsResult.attachments
	attachments.forEach { transactionDetailAttachment ->
		loadImage(getTransactionDetailsResult.id, transactionDetailAttachment)
	}
}


private fun loadImage(attachment: TransactionDetailsAttachment, transactionId: Long) {
    //downloading file may differ in your project. This is only example in synchronised code
    val request = Request.Builder().url(attachment.link).build()
    val response = OkHttpClient().newCall(request).execute()
    val httpCode = response.code()
    when (httpCode) {
        403 -> {
            refreshAttachment(transactionId, attachment.id)
        }
        200 -> {
            //convert stream to bitmap and load into image view
        }
        else -> {
            //check other status
        }
    }
}

private fun refreshAttachment(transactionId: Long, attachmentId: String) {
    mobileDcApi
        .transactionsHistoryService
        .generateAttachmentLink(
            GenerateAttachmentLink(transactionId, attachmentId), { generateAttachmentLinkResult ->
				//sample with Glide library usage
				Glide.with(context).asBitmap()
					.load(generateAttachmentLinkResult.link)
					.into(nextImageView)
      	}, {
           //something went wrong, check exception
        })
}


deleteAttachment

Asynchronous. Online.

Delete attachment associated with provided transaction.


Input

Parameter Type Description Validation conditions
deleteAttachment DeleteAttachment

Plain object of DeleteAttachment

Not empty

DeleteAttachment object contains following fields.

Parameter Type Description Validation conditions
transactionId Long

Identifier of selected transaction. Id can be taken from GetTransactionDetailsResult object, check getTransactionDetails method

Not empty
attachmentId String Identifier of selected attachment. Id can be taken from TransactionDetailsAttachment, check getTransactionDetails method
Not empty

Output

Success callback/ Failure callback.

Sample

val transactionDetailsResult: GetTransactionDetailsResult = GetTransactionDetails(1L)
val deleteAttachment: DeleteAttachment = DeleteAttachment(transactionDetailsResult.id, 
	transactionDetailsResult.transactionDetailsAttachment.id)

private fun deleteAttachment(deleteAttachment) {

    mobileDcApi.transactionService
        .deleteAttachment(deleteAttachment, {
                //Deletion of attachment went succesfully
            }, { throwable ->
                //Something went wrong, check exception with documentation
            })
}

updateSingleTransactionData

Asynchronous. Online.

Updates single transaction data in Mobile DC backend by transactionId.

Input

Parameter Type Description Validation conditions

updateSingleTransactionData

UpdateSingleTransactionData

Transaction data to be updated Not empty

UpdateSingleTransactionData

Parameter Type Description Validation conditions

transactionId

Long

Transaction ID Not empty

description

String?

Description of transaction

Output

Success callback/ Failure callback.

Sample

fun updateSingleTransactionData(updateSingleTransactionData: UpdateSingleTransactionData) {
    mobileDcApi
        .transactionsHistoryService
        .updateSingleTransactionData(updateSingleTransactionData, {
            //Transaction updated successfully
        }, {
            //Something went wrong, check exception with documentation
        })
}

DOCUMENT CHANGELOG

Version 1.0.1

Version 2.0.0

Version 2.1.0

Version 2.1.1

Version 2.2.0

Version 2.3.1

Version 2.4.0

Version 2.5.0

Version 2.6.0

Version 2.6.1

Version 2.7.0

Version 2.8.0

Version 2.9.0

Version 2.9.3

Version 2.10.0

Version 2.10.1

Version 2.11.2

Version 2.11.3

Version 2.11.5

Version 2.11.6

Version 2.11.8

Version 2.11.10

Version 2.11.12

Version 2.12.0

Version 2.12.1

Version 2.13.2

Version 2.13.3

Version 2.13.5

Version 2.13.6

Version 2.13.7