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. First version digit tracks compatibility-breaking changes in SDK public APIs. It is mandatory to update the application code and to use SDK when this is incremented. Second version digit tracks new, not compatibility-breaking changes in the public API of SDK. It is optional to update the application code when this digit is incremented. The third version digit tracks internal changes in SDK. No updates in the application code are necessary to update to the version, which has this number incremented. Changes not breaking compatibility: Adding a new optional interface to SDK setup. Adding a new method to any domain. Adding new ENUM value to input or output. Adding a new field in the input or output model. 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 "" password "" } 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. 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. Recommended solution when using Verestro SDK below: //AndroidManifest.xml //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: 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 size from the table above is referred to release version; size depends on configured proguard (module provides consumer progurd rules); 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: Cards. User. Device. CloudMessaging. TransactionsHistory. 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: MobileDcApiJava for projects which use Java programming language. MobileDcApiKotlin for projects which use Kotlin programming language. 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: Asynchronous - Operation could take more time and method is called on thread different than main. The result of execution is provided in callback (described below). Synchronous - Result of operation is provided as method return type. Method type: Online - Operation requires internet connection. Offline - Operation can be called without internet access. 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 Success callback - Depends on used programming language and facade type  Multiple facade types.   s  onSuccess or success callback inform about operation success. Success callback with data - Callback with additional result object. Failure callback - Informs about failure. Contains information about exception ( Error handling. ). Exception can contains additional details. Sample usage: //java sample cardsService.getAll( new SuccessDataCallback>() { @Override public void onSuccess(List 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: Searching for harmful binaries: SDK analyses device in search for commonly known binaries indicating that device is rooted. Additionally in this step there are checked some binaries connected to hooking tools. Checking system partitions permissions: SDK validates if some paths(commonly connected with root access), along with some common system directories are writtable on specific partition. Validating installed packages : SDK analyses installed application on device in search for apps  known to be connected with root access, apps requiring root, and root cloak apps. Android 11 introduced some changes reducing visibility of other packages installed on device. To keep checking harmful application there is added additional android permission:  QUERY_ALL_PACKAGES Checking rom settings: Analyses device rom properties, to search for flags set on rooted devices. Checking su existance: Checks is  su  directory accessible in some common paths. 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: provide Root CA and DN of the public key certificate for the private key which already has and use this private key for signing data. DN cannot change during certificate renewals and all intermediate certificates should be placed in JWT generate csr where  CN=Signature-${uniqueClientName} . Csr will be signed by uPaid. Client needs to use private key for signing from key pair used to generate csr. 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, 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 s et) 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 period s (.). 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: APK or Bundle  signing key (aka "upload key"). Google Play signing key (optional, may be enabled and configured in Google Play Console). 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: Add .apk or .aab file in google play console. Select "Let Google create and manage my app signing key (recommended)" and press Continue. In the application panel in the menu look for release management option. Select app signing section. Download the certificate from App signing certificate section. Convert downloaded certificate from der to pem format using following command: openssl x509 -inform der -in deployment_cert.der -out certificate.pem Recommended MPA data protection mechanisms Code obfuscation: Code obfuscation is basic, and one of the most efficient application protection mechanism. Obfuscating code saves your app from static code analysis, exploring your code in search of vulnerabilities, that can be used by hooking software. There are many tools used for obfuscation nowadays, the most popular are proguard and its successor - R8. If you are using Kotlin in your project, R8 is a better option for you. It is also important to keep app architecture supporting obfuscation, using obfuscation tools is as simple as your architecture is adjusted to it. Disable logs & turning off debugging: It is very important to remember turning off logging data and disable debugging in your production application. Data printed in logs in development process should never be available in release application. It is recommended to manage printing it from one place, to not 'forget' removing every single of them. Input data validation: Input data should be validated on every level of app structure, it reduces risk of processing some unwanted, or even harmful data. It is recommended to clean sensitive data that is no longer useful, we advise to not use string to keep it. String is immutable, data stored in it can later be accessed by dumping application memory. We recommend using  char[] , and overwriting it when it is no longer useful. Prevent taking screenshot: We recommend adding a mechanism that prevents taking screenshots, and recording your application. It protects you from harmful applications getting users inputted data. Prevent copy/paste : Input taking sensitive data such as user password should not have the ability to copying and pasting in it. Storing it in clipboard expose it for copying, or modifying by harmful applications, even if it was initially encrypted it is plaintext when the user copies it. Prevent screen overlay: It is recommended to protect MPA from applications that have the possibility to overlay it. Not securing it may result with recording user data. Checking the installer: MPA should implement a mechanism that will check installer of application. It should check if the application is downloaded from Google Play, preventing it from possibility of tampering installation binary. Checksum mechanism: Implementing checking checksum mechanism is a very efficient way to check if your application was not tampered. It should compare checksum of your application, prepared after generating app with data send by your app after installing it on device. It bases on the fact that every generated application have different checksum, comparing it can ensure you that your server is communicating with the app released by you. Removal redundant permissions: It is important to keep in your app only used permissions. You should not give your application access to components, that it not requires. Network security configuration: MPA should use network security configuration application customize their network security settings(for example protection application from usage of cleartext traffic) in declarative configuration file without modifying app code. 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: com.nimbusds:nimbus-jose-jwt commons-codec:commons-codec com.fasterxml.jackson.core:jackson-core com.fasterxml.jackson.core:jackson-annotations com.fasterxml.jackson.core:jackson-databind com.fasterxml.jackson.module:jackson-module-kotlin io.insert-koin:koin-android io.reactivex.rxjava2:rxjava io.reactivex.rxjava2:rxandroid com.squareup.retrofit2:adapter-rxjava2 com.squareup.retrofit2:retrofit com.squareup.retrofit2:converter com.squareup.okhttp3:logging com.squareup.okhttp3:okhttp 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 : setup(MobileDcCoreConfiguration) setup(MobileDcApiConfiguration) 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 withMobileDcConnection Configuration MobileDcConnection Configuration Mobile DC API connection configuration delivered by uPaid Not empty withWalletSecurityEventListener WalletSecurityEventListener Global listener for security events Not empty withOptionalWalletPin Configuration MobileDcWalletPin Configuration Wallet Pin configuration in SDK withOptionalLogger EventsLogger Handler for secure logging of sdk events withOptionalDeveloperOptions DeveloperOptions Additional options for developers withOptionalCloudMessaging Configuration MobileDcCloudMessaging Configuration Interface for providing cloud messaging configuration like actual registration token 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 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 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 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 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. MobileDcCloudMessagingConfiguration Parameter Type Description cloudMessagingRegistrationToken CloudMessagingRegistrationProvider Provides information abour Cloud Messaging registrationtoken like FCM Method Parameters Description getRegistrationToken - Gets actual FCM registration token from application. Used to device registration in RNS and SSE service. CloudMessagingRegistrationToken Parameter Type Description type CloudMessagingType Mandatory. One of: [FCM]. FCM - Firebase Cloud Messaging token String Registaration token for push notifications Sample Initialization for MobileDcCoreConfiguration (without Wallet Server). var eventsTrace = arrayListOf()//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 = listOf(certificatePublicKeyInPemFormat) } class MyAppMobileDcWalletPinConfig : MobileDcWalletPinConfiguration { override val pinFailCount: Int = 3 } var eventsTrace = arrayListOf()//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 }) .withOptionalCloudMessagingConfiguration( object : MobileDcCloudMessagingConfiguration { override val cloudMessagingRegistrationTokenProvider = object : MobileDcCloudMessagingInfoProvider { override fun getRegistrationToken(): CloudMessagingRegistrationToken? { return CloudMessagingRegistrationToken( CloudMessagingType.FCM, getFCMToken() //implement blocking get FCM token ) } } }) ) 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
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 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 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 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(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 CharArry 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 (deprecated in 2.14.3) Asynchronous. Online. Pairs device using given password and user identifier. Deprecated, use pairByPassword(PairByPassword) 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 } ) } pairByPassword Asynchronous. Online. Pairs device using given password and user identifier. Input Parameter Type Description Validation conditions pairByPassword PairByPassword An object containing user information to pair device. Not empty PairByPassword 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 cloudMessagingRegistrationToken CloudMessagingRegistrationToken An object containing cloud messaging registration token information. 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. externalDeviceId String? External device id CloudMessagingRegistrationToken Parameter Type Description Validation conditions type CloudMessagingType Mandatory. One of: [FCM]. FCM - Firebase Cloud Messaging Not empty token String Token for push notifications Not empty Output Success / failure callback. Sample val cloudMessagingRegistrationToken: CloudMessagingRegistrationToken = CloudMessagingRegistrationToken( type: CloudMessagingType, //messaging token type token: String // saved cloud messaging token ) val pairByPassword: PairByPassword = PairByPassword( userLoginType: UserType, //user identifier type userLogin: CharArray, //user identifier password: CharArray, //user password cloudMessagingRegistrationToken: CloudMessagingRegistrationToken, //cloud messaging registration token information biometricAuthType: BiometricAuthType?, //Optional biometric authentication type externalDeviceId: String? //Optional external device id ) fun pairByPassword(pairByPassword: PairByPassword) { mobileDcApi .deviceService .pairByPassword(pairByPassword, { //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 (deprecared in 2.14.3) Asynchronous. Online. Binds device to user in Mobile DC backend with Trusted Identity genetated by client server. Deprecated, use pairByTrustedIdentity(PairByTrustedIdentity). 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 }) } pairByTrustedIdentity Asynchronous. Online. Binds device to user in Mobile DC backend with Trusted Identity genetated by client server. Input Parameter Type Description Validation conditions pairByTrustedIdentity PairByTrustedIdentity An object containing user information to pair device. Not empty PairByTrustedIdentity Parameter Type Description Validation conditions trustedIdentity String JSON Web Token containing registration data Not empty cloudMessagingRegistrationToken CloudMessagingRegistrationToken An object containing cloud messaging registration token information. Not empty externalDeviceId String External device id TrustedIdentity Parameter Type Description Validation conditions userId String External user id given by the client Not empty CloudMessagingRegistrationToken Parameter Type Description Validation conditions type CloudMessagingType Mandatory. One of: [FCM]. FCM - Firebase Cloud Messaging Not empty token String Token for push notifications 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: val cloudMessagingRegistrationToken: CloudMessagingRegistrationToken = CloudMessagingRegistrationToken( type: CloudMessagingType, //messaging token type token: String // saved cloud messaging token ) val pairByTrustedIdentity: PairByTrustedIdentity = PairByTrustedIdentity( trustedIdentity: String, //JSON Web Token containing registration data cloudMessagingRegistrationToken: CloudMessagingRegistrationToken, //cloud messaging registration token information externalDeviceId: String? //Optional external device id ) fun pairByTrustedIdentity(pairByTrustedIdentity: PairByTrustedIdentity) { mobileDcApi .deviceService .pairByTrustedIdentity(pairByTrustedIdentity, { //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 } ) } pairByExternalCredentials (deprecated in 2.14.3) Asynchronous. Online. Binds device to user in Mobile DC backend using username and password. Deprecated, use pairByTrustedIdentity(PairByExternalCredentials). 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 }) } pairByExternalCredentials Asynchronous. Online. Binds device to user in Mobile DC backend using username and password. Input Parameter Type Description Validation conditions pairByExternalCredentials PairByExternalCredentials An object containing user information to pair device. Not empty PairByExternalCredentials Parameter Type Description Validation conditions username String User identifier Not empty password CharArray User password Not empty cloudMessagingRegistrationToken CloudMessagingRegistrationToken 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. deviceExternalId String External device id CloudMessagingRegistrationToken Parameter Type Description Validation conditions type CloudMessagingType Mandatory. One of: [FCM]. FCM - Firebase Cloud Messaging Not empty token String Token for push notifications Not empty Output Success / failure callback. Sample val cloudMessagingRegistrationToken: CloudMessagingRegistrationToken = CloudMessagingRegistrationToken( type: CloudMessagingType, //messaging token type token: String //saved cloud messaging token ) val pairByExternalCredentials: PairByExternalCredentials = PairByExternalCredentials( userName: CharrArray, //username provided by user password: CharrArray, //password provided by user cloudMessagingRegistratinoToken: CloudMessagingRegistrationToken, //cloud messaging registration token information biometricAuthType: BiometricAuthType?, //Optional biometric authentication type externalDevice: String? //Optional external device id ) fun pairByExternalCredentials(pairByExternalCredentials: PairByExternalCredentials) { mobileDcApi .deviceService .pairByExternalCredentials(pairByExternalCredentials, { //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 } ) } 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 <> 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 process Asynchronous. Offline. Processes data sent by backend (push notification data). Application should check Verestro senderId in RemoteMessage object (RemoteMessage::from method) to verify sender. Method can throw InvalidPushException in case of invalid push content passed to it. Input Parameter Type Description Validation conditions pushData Map Data received from notification service in RemoteMessage object Not empty Output Success/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 Verestro sender Id if (isVerestroSenderId(senderId)) { mobileDcApi .cloudMessagingService .process(pushData, { //push sent to SDK }, { //some error }) } else { //proceed push from another source } } getSource (Deprecated in 2.14.3) 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. Deprecated in 2.14.3, no longer required to use. Input Parameter Type Description Validation conditions pushData Map 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) { ucpApi .cloudMessagingService .process(pushData, { //push processed in UCP }, { //some error }) } updateRegistrationToken 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 cloudMessagingRegistrationToken CloudMessagingRegistrationToken An object containing user information to update registration token. Not empty CloudMessagingRegistrationToken Parameter Type Description Validation conditions type CloudMessagingType Mandatory. One of: [FCM]. FCM - Firebase Cloud Messaging Not empty token String Registration token Not empty Output Success / failure callback. Sample //application should listen for FCM token changes in FirebaseMessagingService::onNewToken method val cloudMessagingRegistrationToken: CloudMessagingRegistrationToken = CloudMessagingRegistrationToken( type: CloudMessagingType, //messaging token type token: String //saved cloud messaging token ) fun updateRegistrationToken(cloudMessagingRegistrationToken: CloudMessagingRegistrationToken) { mobileDcApi .deviceService .isDevicePaired({ isPaired -> //token update is required only if device is already paired if (isPaired) { mobileDcApi .cloudMessagingService .updateRegistrationToken(cloudMessagingRegistrationToken, { //token updated }, { //some error, always retry action until success //when internet or server connection is not reachable try again later }) } }, { //some error }) } updateFcmRegistrationToken (deprecated in 2.14.3) Asynchronous. Online. Updates Cloud Messaging registation token for selected token type (FCM). 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. Deprecated in 2.14.3, use updateRegistrationToken. 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 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 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 = 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 transa ction. 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 Created. Version 2.0.0 Changed approach to SDK setup. Removed methods used to fingerprint authentication. Added NetworkConnection exception and CoreSdkException. Added new reason codes to existing exceptions. New methods in user domain: addUser, loginByTrustedIdentity, changePassword. New methods in device domain: pairByPassword, pairByExternalCredentials, unPairDevice. New methods in cards domain: getAll. New domains: ibans, transactionsHistory. Version 2.1.0 Added new methods in User domain (authenticateByPin, loginByPin, changeWalletPin, resetWalletPin, initializeResetUserPassword, finilizeResetUserPassword). Added new methods in Cards domain (addCard, initialize3ds, finalize3ds, deleteCard). Version 2.1.1 Added information about SDK size. Added information about SDK ingetration on lower Android API level. Version 2.2.0 Improved Mobile DC SDK startup time. Version 2.3.1 Added new methods in user domain (isBiometricAuthenticationEnabled, enableBiometricAuthentication, startBiometricAuthentication, authenticateByBiometric, loginBySignature). Fixed security reports sending. Consumer proguard rules update. Version 2.4.0 Added optional log handler to MobileDcCoreConfigurationBuilder. Added disableBiometricAuthentication method. Added BiometricTypeAuth paramter to pairing methods. Version 2.5.0 Added getUser method. Version 2.6.0 Added addUser method. Version 2.6.1 Disabled sending native checksum in pairDevice process. Version 2.7.0 Added addresses service to facade. Version 2.8.0 Added addresses service to facade. Fixed checksum sending. Added apk certificate description. Added updateUser method to User domain. Version 2.9.0 Security issue codes are more precisely and give us more information about issue. Marked addAddress as deprecated. Added new one addAddress method which returning addressId of added address. Version 2.9.3 Device un-pairing device with  unPaidDevice is now avaliable for not logged in users. Un-pair process ( unPaidDevice method) requires application restart if UCP SDK is used and card was already digitized for another user. Login methods now clearing SDK data when device is removed from server When any login method fails with  BackendException  and  CANT_FIND_DEVICE reason application should proceed with device pairing again. Version 2.10.0 Added new method for adding address with NewAddress model. Previous method is deprecated now. Added new method in Cards service: updateCard. Added new methods in Addresses servive: updateAddress, deleteAddres. Version 2.10.1 Removed false-positive security rules. Improved security reports sent to Wallet Server. Version 2.11.2 Added DeveloperOptions configuration in setup. Added logout method. Version 2.11.3 Updated security libraries. Version 2.11.5 Added new optional to DeveloperOptions, introducing new security checks. Added method verifyCard to verify card after 3DS. Card domain. Extended TransactionsFilters in getTransactionHistory. Transaction history domain.  Added new method to addCard with AddCard model. The old method was marked as deprecated. Card domain. Added new response parameter to getAll method. Card domain.  Added new request parameter to updateCard method. Card domain. Added new permission:  QUERY_ALL_PACKAGES  for security checks. Version 2.11.6 Minor fixes in user session. Version 2.11.8 Added new method for initializing reset user password with InitializeResetUserPassword model. Previous method is deprecated now. Version 2.11.10 Added new chapter Firebase Cloud Messaging configuration. Updated Security processes overview with Error codes handling in application. Introduced new approach to handling security issue. To provide better experience new status was added CoreSdkException with reason SECURITY_EVENT_OCCURRED. Error could be provided in every SDK methods if security issue was detected. Change doesn't impact on onSecurityIssue callback. Version 2.11.12 Added more protections for Android Keystore issues related to access by retrying and adding multi-thread synchronization. Version 2.12.0 IMPORTANT Updated security tools after EMV Security Evaluation. Please refer to  setup.  and  Application Isolated Process . added new security checks which which requires additional action on application side, added new fields in DeveloperOptions object - allowDebug and enableAdditionalSecurityChecks. Updated Gradle and R8 tools. Added new methods related to transaction history and attachment in TransactionsHistoryService: getTransactionDetails, storeAttachment, generateAttachmentLink, deleteAttachment. Added new fields related to MCC (mcc, mccCategory) in methods getTransactionHistory and getTransactionDetails. Version 2.12.1 Fixed aggressive security process check from MDC SDK 2.12.0. Version 2.13.2 Updated documentation for Application Isolated Process with Magisk information. Updated  recommended configuration  and documentation for  extractNativeLibs  flag configuration, native libs should be in uncompressed form. Read more in Basic configuration section. Isolated security process mechanism improvements (related to  enableAdditionalSecurityChecks  configuration flag). Update Kotlin version to Kotlin version to 1.5.31 and Koin to 2.1.6. Updated Jackson dependency to 2.13.2 (with jackson-databind 1.13.2.2 security patch). Added new methods: initialize3DSv2 in Cards domain, finalize3DSv2 in Cards domain, deleteUser in User domain. Added new field "nip" in AddUser model. Added logs for all facade methods  (available in SDK debug version). Version 2.13.3 IMPORTANT  Removed security check for disabling permission QUERY_ALL_PACKAGES i application AndroidManifest file. Read more in Basic configuration : Android permission chapter. Version 2.13.5 Added new value in additional DeveloperOptions, responsible for verification SDK code obfuscation. Added information about using SDK on Android API 31+ in  Basic Configuration chapter. Wraped in try-catch block callbacks from setup method to prevent process breaking in SDK. Version 2.13.6 Added new returned fields to methods: getTransactionsHistory and getTransactionDetails. Version 2.14.5 Important!  Introduced Play Integrity API instead Safetynet Attestation API - could require additional configuration. Read more in  Security processes overview  chapter . Enabling r equires Google API console changes. Important! Added optional configuration method - MobileDcCloudMessagingConfiguration. Interface allows to register not-paired devices in SSE service provided by Verestro. Significally optimizes RNS message delivery, usage is strongly recommended. Added method  updateSingleTransactionData  in transactions history service. Added new methods for device pairing - old methods became deprecated. Added new fileld optional to new pair device methods - externalDeviceId. Introduced RefreshSession mechanism for user HTTP token management - extends a duration of session and allows to use SDK methods.