payone
Sign up

Use our native Android SDK written in Kotlin to build secure and fully native payment flows inside your Android app.

Our native SDK helps you communicate with the Client API. It offers:

  • Convenient wrappers for API responses.
  • Handling of all the details concerning the encryption of payment details.
  • Caching of payment product logos and images to offer additional information about payment products.
  • User-friendly formatting of payment data, such as card numbers and expiry dates.
  • Input validation.
  • Checks to determine to which issuer a card number is associated.

Our example app simulates the user interface for the whole payment flow based on the interaction between the app and our platform. Find the source code of the SDK and the example app on GitHub, including installation instructions.

To understand how to use this SDK, look at the following documentation:

  • Mobile/Client Integration – Familiarise yourself with various concepts.
  • Client API Reference – The SDK wraps the Client API and (among other things) exposes the responses of the web service calls as objects. Understanding the Client API will help you understand these SDK objects as well.
  • The SDK on GitHub – The SDK contains a working example application, which can help you understand how to best use it.
  • This current document will help you understand the global flow when creating payment pages using the SDK.

Why use the Android SDK

Our Android SDK helps you integrate payments into Android applications faster and with less effort. It handles many technical details for you, so you do not have to work directly with the Client API for common tasks. The main advantages of using the SDK are:

  • Less code to write and maintain – The SDK includes ready-made functionality, which reduces development time and ongoing maintenance.
  • Simple and secure authentication – The SDK takes care of authentication and security-related logic, making setup faster and safer.
  • More stable integration over time – Most platform changes are handled within the SDK, minimising the impact on your application code.
  • Faster setup and easier support – Using the SDK creates more standardised integrations, making onboarding quicker and support more efficient.

If you require tight dependency control, minimal features, or a lightweight setup, the SDK may add code and functionality you do not need. In these cases, working directly with the API is simpler and more efficient.

SDK integration

To create payments, you first need to integrate the SDK with your project. You can find all the versions of the SDK in our repository. We have prepared the requirements and installation instructions for the SDK below.

Requirements

The minimum supported library versions are the following:

  • Java 17+
  • Android 6+ (API level 23)

Installation

Add a dependency to the SDK in your app's build.gradle file, where x.y.z is the version number:

dependencies {
// other dependencies
implementation 'com.worldline-solutions:sdk-client-android:x.y.z'
}

Example apps

We have provided an example application in both Kotlin and Java that you can use as a basis for your own implementation. If you like how it looks and feels, you do not need to make any changes at all. You can get the example apps below:

After you successfully integrate the SDK with your project, you can proceed to integrate it with the entire payment system. The complete payment process consists of these steps:

  1. Initialisation of the SDK
  2. Fetching possible payment methods
  3. Fetching and displaying payment method details
  4. Validation of the provided data
  5. Encryption and transfer of payment data
  6. Finalising transaction

1. Initialise SDK


Firstly, you need to create an OnlinePaymentSdk object enabling communication between the Server API and the client. Your app must have its own server, acting as an intermediary between our Client and Server API.

Since the customer initiates the payment in your app, your Client application asks your Server application to create a Session. When a Server application receives a request, it can create a Session via CreateSession from the Server SDK.

Try our API Explorer to send a CreateSession request.

After configuring and connecting your application to the Server API, you receive a response containing information about the created Session. A typical response looks like this:

{
"assetUrl": "https://assets.test.cdn.v-psp.com/s2s/515c2c0bd13d5dd4bd42",
"clientApiUrl": "https://payment.preprod.direct.worldline-solutions.com/",
"clientSessionId": "68a4b0b183a34016b4b694b97938f75b",
"customerId": "cf7d7aafd42e4a1cb9e4b0624a5041b1"
}

Now pass clientSessionId, customerId, clientApiUrl and assetUrl to the Client application. Once the application receives a response from the Server application with the Session data information, create a local OnlinePaymentSdk object on the Client application side.

Each Session has a fixed 3-hour lifespan. If it expires, you need to create a new Session.

Java Kotlin

    // Create session data
SessionData sessionData = new SessionData(
    "47e9dc332ca24273818be2a46072e006", // client session id
"9991-0d93d6a0e18443bd871c89ec6d38a873", // customer id
    "https://clientapi.com", // client API URL
    "https://assets.com" // asset URL
);

// Create SDK configuration
SdkConfiguration sdkConfiguration = new SdkConfiguration( //optional
    false, // states if the environment is production, this property is used to determine the Google Pay environment
    "Android Example Application/v2.0.4", // your application identifier
    "AndroidSDK/v4.0.0", // SDK identifier, optional
    true // if true, requests and responses will be logged to the console; not supplying this parameter means it is false; should be false in production
);

// Initialise SDK
OnlinePaymentSdk sdk = new OnlinePaymentSdk(
    sessionData,
    getApplicationContext(), // this will get your Java application context
    sdkConfiguration
);

// Create session data
 val sessionData = SessionData(
    clientSessionId = "47e9dc332ca24273818be2a46072e006", // client session id
    customerId = "9991-0d93d6a0e18443bd871c89ec6d38a873", // customer id
    clientApiUrl = "https://clientapi.com", // client API URL
    assetUrl = "https://assets.com" // asset URL
 )

 // Create SDK configuration
 val sdkConfiguration = SdkConfiguration(
    environmentIsProduction = false, // states if the environment is production, this property is used to determine the Google Pay environment
    appIdentifier = "Android Example Application/v2.0.4", // your application identifier
    sdkIdentifier = "AndroidSDK/v4.0.0", // SDK identifier
    loggingEnabled = true // if true, requests and responses will be logged to the console; not supplying this parameter means it is false; should be false in production
 )

 // Initialise SDK
 val sdk = OnlinePaymentSdk(
    sessionData = sessionData,
    context = getApplication<application>().applicationContext, // application context
    configuration = sdkConfiguration //optional
 )

After creating OnlinePaymentSdk, you will also need to configure your PaymentContext object, as shown below. It contains information like currency, country, amount, etc.

Java Kotlin

AmountOfMoney amountOfMoney = new AmountOfMoney(
    1298L, // in cents as a Long
    "EUR" //three-letter currency code as defined in ISO 4217
);
 
PaymentContext paymentContext = new PaymentContext(
    amountOfMoney,
    "NL", // two-letter country code as defined in ISO 3166-1 alpha-2
    false // true, if it is a recurring payment
);

val amountOfMoney = AmountOfMoney(
    1298L, // in cents as a Long
    "EUR" //three-letter currency code as defined in ISO 4217
)
 
val paymentContext = PaymentContext(
    amountOfMoney,
    "NL", // two-letter country code as defined in ISO 3166-1 alpha-2
    false // true, if it is a recurring payment
)

Different payment methods are available for different PaymentContext objects. If you change any variable, you must start the process again. Only the Session can remain the same if the same customer made the payment.

2. Fetch possible payment methods

The next step is to get and display the possible payment options. Since payment items are instances of BasicPaymentProduct, your app can use these items to create a screen that lists them. Just fetch and display the BasicPaymentProduct and AccountOnFile lists to let your customer select one.

Use our convenient Kotlin example app and Java example app as a basis for your own implementation.

Java Kotlin

// sync call - blocks the main thread
 try {
 BasicPaymentProducts basicPaymentProducts = sdk.getBasicPaymentProductsSync(paymentContext);
    // Display the contents of basicPaymentProducts to your customer.
 } catch (ResponseException e) {
    // Handle HTTP/API errors (usually 4xx)
 } catch (CommunicationException e) {
   // Handle communication errors (network connection failed, timeout, malformed URL, etc.)
 } catch (Exception e) {
   // Handle any other unhandled exception
 }

// *** Listener-based async call ****
session.getBasicPaymentProducts(
    paymentContext, // PaymentContext
    new BasicPaymentProductsResponseListener() {
        @Override
        public void onSuccess(@NonNull BasicPaymentProducts basicPaymentProducts) {
           // Display the contents of basicPaymentProducts to your customer
        }

        @Override
        public void onApiError(ErrorResponse errorResponse) {
            // Handle API failure of retrieving the available Payment Products
        }

        @Override
        public void onException(Throwable throwable) {
            // Handle failure of retrieving the available Payment Products
        }
    }
);

try {
     BasicPaymentProducts basicPaymentProducts = sdk.getBasicPaymentProducts(paymentContext);
     // Display the contents of basicPaymentProducts to your customer.
 } catch (ResponseException e) {
     // Handle the exception thrown by the API. Usually, these are 4xx exceptions.
 } catch (CommunicationException e) {
    // Handle communication errors (network connection failed, timeout, malformed URL, etc.)
 } catch (Exception e) {
    // Handle any other unhandled exception
 }

Remember that each session call can throw errors. Wrap your code into the try/catch block to avoid this.

Since Kotlin methods are asynchronous (using coroutines), you can use synchronous overloads with Sync suffixes in Java. However, be aware that they will block the main thread.

For async calls in Java, you can use the listener-based approach (as shown in the example above). You can use the same approach for other calls as well.

3. Fetch and display payment method details

For certain payment products, customers can opt for our platform to store their credentials for recurring payments. We refer to the stored data as an account on file (Card On File) or a token. You can reuse this account on file/token for subsequent payments if your customers chose the same payment method.

The list of available payment products that the SDK receives from the Client API also contains the accounts on file for each payment product. Your application can present this list to the user.

Depending on the method the customer chooses, consider cases of different data flows:

If the customer chooses a native form of payment, you need to use the SDK of the payment provider. You will need to handle the response only in the last step to inform the customer of their payment status. Read more about native payments in this dedicated chapter.

For payments with a third-party payment provider, you receive data with the redirection address in the payment properties. Redirect your customers in their browser to the third-party payment portal to continue the payment process. After the successful payment, your app needs to handle the redirection to the Client app.

The standard payment process is a card payment. Once the customer selects the desired payment product, retrieve the enriched PaymentProduct detailing what information the customer needs to provide to authorise the payment. Then, display the required information fields to your customer.

Java Kotlin

// sync call
try {
    PaymentProduct paymentProduct = sdk.getPaymentProductSync(paymentProductId, paymentContext);
    // Display the fields to your customer.
} catch (e: ResponseException) {
    // Handle the exception thrown by the API. Usually, these are 4xx exceptions.
} catch (e: CommunicationException) {
    // Handle the communication exception - it can happen when the API call could not be established.
} catch (e: Exception) {
    // Handle any other unhandled exception.
}

try {
    val paymentProduct = sdk.getPaymentProduct(paymentProductId, paymentContext)
    // Display the fields to your customer.
} catch (e: ResponseException) {
    // Handle the exception thrown by the API. Usually, these are 4xx exceptions.
} catch (e: CommunicationException) {
    // Handle the communication exception - it can happen when the API call could not be established.
} catch (e: Exception) {
    // Handle any other unhandled exception.
}

If your customer selects an account on file, you can fill in the provided masked information in the respective input fields. The prefilled data on behalf of the customer is in line with applicable regulations. Depending on the individual use case, your customer may still have to provide some card data (i.e., CVC).

Use our Kotlin example app and Java example app for inspiration to create your screen.

4. Validate provided data

After your customer enters their payment information, your application needs to validate the received data. But, before validation, you will first need to save the customer's input for the required information fields in a PaymentRequest instance. This class has a tokenize property used to indicate whether the app should store the customer's credentials for recurring payments.

Java Kotlin

// payment request with paymentProduct, accountOnFile, tokenize status
PaymentRequest paymentRequest = new PaymentRequest(paymentProduct, null, false);

var paymentRequest = PaymentRequest(paymentProduct)

Alternatively, adapt the code sample by supplying both the account on file and the corresponding payment product:

Java Kotlin

PaymentRequest paymentRequest = new PaymentRequest(paymentProduct, accountOnFile, true);

var paymentRequest = PaymentRequest(paymentProduct, true)

Once you configure a payment request, supply the values for the payment product fields. Use the identifiers of the fields, such as "cardNumber", "cvv", and "expiryDate", to set the field values for the payment request:

Java Kotlin

// set a value to the specific field 
paymentRequest.field("cardNumber).setValue("12451254457545")

// or 
paymentRequest.setValue("cvv","123");
paymentRequest.setValue("expiryDate","1225");

// set a value to the specific field
paymentRequest.field("cardNumber").setValue("12451254457545")

// or
paymentRequest.setValue("cvv","123")
paymentRequest.setValue("expiryDate","1225")

Now you need to validate the received data using the available list of validators. Do that by performing validation on the PaymentRequest, which will validate both the field values and the whole payment request.

Java Kotlin

// validate all fields in the payment request
// validate() returns ValidationResult object with isValid status and errors
ValidationResult validationResult = paymentRequest.validate();

// check if the payment request is valid - result will return isValid: true and errors: []
if (validationResult.isValid()) {
    // payment request is valid
} else {
    // payment request has errors
    List errors = validationResult.getErrors();
    
    for (ValidationErrorMessage error : errors) {
        //show errors
    }
}

// validate all fields in the payment request
// validate() returns ValidationResult object with isValid status and errors
val validationResult = paymentRequest.validate()

// check if the payment request is valid - result will return isValid: true and errors: []
if (validationResult.isValid) {
    // payment request is valid
} else {
    // payment request has errors
    for (error in validationResult.errors) {
      //show errors
    }
}

Remember that the data entry interface must be fully transparent and understandable for your customers. So if there are validation errors, you should provide the customer with feedback about them. You receive error information during the validation of a payment field or the validation of the payment request, so you can use it to display appropriate error messages. Each validation error has a reference to the corresponding faulty field.

5. Encrypt and transfer payment data

After the PaymentRequest validation, you will have access to its encrypted version, EncryptedRequest. Send the encrypted customer data to your server as follows:

Java Kotlin

try {
     EncryptedRequest encryptedRequest = sdk.encryptPaymentRequestSync(paymentRequest);
     // Send the encryptedRequest.encryptedCustomerInput to your server and use it to create the payment with the Server SDK.
 } catch (EncryptionException e) {
     // Handle encryption failure (invalid payment data, encryption failed, etc.)
 } catch (ResponseException e) {
     // Handle HTTP/API errors (usually 4xx)
 } catch (CommunicationException e) {
     // Handle communication errors when fetching public key (network issues, timeout, etc.)
 } catch (Exception e) {
    // handle any other unhandled exception
 }

try {
     val encryptedRequest = sdk.encryptPaymentRequest(paymentRequest)
     // Send the encryptedRequest.encryptedCustomerInput to your server and use it to create the payment with the Server SDK.
 } catch (e: EncryptionException) {
     // Handle encryption failure (invalid payment data, encryption failed, etc.)
 } catch (e: ResponseException) {
     // Handle HTTP/API errors (usually 4xx)
 } catch (e: CommunicationException) {
    // Handle communication errors when fetching public key (network issues, timeout, etc.)
 } catch (e: Exception) {
    // Handle any other unhandled exception
 }

See a more detailed description of the encryption process in this dedicated chapter.

6. Finalise transaction

After encrypting the customer data, send the encrypted customer input string to your server and use it to make a CreatePayment request with the Server SDK. You can use the provided encryptedCustomerInput from the encrypted request for the encryptedCustomerInput field of the create payment request to finalise the payment.

The response of the CreatePayment request may require additional actions from the Client, specified in the MerchantAction object. In most cases, this involves redirecting the customer to an external party (i.e. for a 3-D Secure check). Once your customers complete this check, our platform processes the actual transaction. Read the Server SDK documentation for more information.

Finally, you have to pass the information back to your Client application to display the transaction result to your customers.

Find a full overview of the payment flow in the Mobile/Client Integration guide.

SDK objects

The Android SDK includes several objects. Choose the object of your interest from the list below to read more about it:

OnlinePaymentSdk

An instance of OnlinePaymentSdk is required for all interactions with the SDK. The following code snippet shows how to initialise OnlinePaymentSdk. You obtain session details by performing a Create Client Session call using the Server API.

Java Kotlin

// Create session data
SessionData sessionData = new SessionData(
    "47e9dc332ca24273818be2a46072e006", // client session id
"9991-0d93d6a0e18443bd871c89ec6d38a873", // customer id
    "https://clientapi.com", // client API URL
    "https://assets.com" // asset URL
);

// Create SDK configuration
SdkConfiguration sdkConfiguration = new SdkConfiguration( //optional
    false, // states if the environment is production, this property is used to determine the Google Pay environment
    "Android Example Application/v2.0.4", // your application identifier
    "AndroidSDK/v4.0.0", // SDK identifier, optional
    true // if true, requests and responses will be logged to the console; not supplying this parameter means it is false; should be false in production
);

// Initialise SDK
OnlinePaymentSdk sdk = new OnlinePaymentSdk(
    sessionData,
    getApplicationContext(), // this will get your Java application context
    sdkConfiguration
);

// Create session data
 val sessionData = SessionData(
    clientSessionId = "47e9dc332ca24273818be2a46072e006", // client session id
    customerId = "9991-0d93d6a0e18443bd871c89ec6d38a873", // customer id
    clientApiUrl = "https://clientapi.com", // client API URL
    assetUrl = "https://assets.com" // asset URL
 )

 // Create SDK configuration
 val sdkConfiguration = SdkConfiguration(
    environmentIsProduction = false, // states if the environment is production, this property is used to determine the Google Pay environment
    appIdentifier = "Android Example Application/v2.0.4", // your application identifier
    sdkIdentifier = "AndroidSDK/v4.0.0", // SDK identifier
    loggingEnabled = true // if true, requests and responses will be logged to the console; not supplying this parameter means it is false; should be false in production
 )

 // Initialise SDK
 val sdk = OnlinePaymentsSDK(
    sessionData = sessionData,
    context = getApplication<application>().applicationContext, // application context
    configuration = sdkConfiguration
 )

All methods the OnlinePaymentSdk provides are wrappers around the Client API. They create the request and convert the response to Java objects that may contain convenience functions.

PaymentContext

PaymentContext is an object that contains the context/settings of the upcoming payment. Some methods of the OnlinePaymentSdk instance require it as an argument. This object can contain the following details:

Java Kotlin

public class PaymentContext {
    private AmountOfMoney amountOfMoney; // contains the total amount and the ISO 4217 currency code
    private String countryCode; // ISO 3166-1 alpha-2 country code
    private boolean isRecurring; // Set `true` when payment is recurring. Default false.
}

data class PaymentContext(
    var amountOfMoney: AmountOfMoney? = null, // contains the total amount and the ISO 4217 currency code
    var countryCode: String? = null, // ISO 3166-1 alpha-2 country code
    var isRecurring: Boolean = false // Set `true` when payment is recurring. Default false.
) : Serializable { ... }

BasicPaymentProduct

The SDK offers two types of objects to represent information about payment products:

  • BasicPaymentProduct
  • PaymentProduct

The instances of BasicPaymentProduct contain only the information required to display a simple list of payment products or accounts on file for the customer to choose from.

The object PaymentProduct contains additional information on each payment product. An example would be the specific form fields that the customer must fill out. You typically use this object when creating a form that asks for a customer's payment details. Read the PaymentProduct section for more info.

Below is an example of how to get display names and assets for the Visa product.

Java Kotlin

BasicPaymentProducts basicPaymentProducts = sdk.getBasicPaymentProducts(paymentContext)

List<basicpaymentproduct> paymentProducts = basicPaymentProducts.getPaymentProducts();

String label = paymentProducts[0].getLabel();
String logoUrl = paymentProducts[0].getLogo();

val basicPaymentProducts = sdk.getBasicPaymentProducts(paymentContext)

val paymentProducts = basicPaymentProducts.paymentProducts

val label = paymentProducts[0].label
val logoUrl = paymentProducts[0].logo

AccountOnFile

An instance of AccountOnFile represents information about a stored card product for the current customer. You must provide the available AccountOnFile IDs for the current payment in the request body of the Server API's CreateSession call if you want to let a customer use a previously tokenised payment method.

If the customer wants to use an existing AccountOnFile for a payment, you should add the selected AccountOnFile to the PaymentRequest. The code snippet below shows how to retrieve the display data for an account on file. You can show this label and the logo of the corresponding payment product to the customer.

Java Kotlin

// All available accounts on file for the payment product
List<accountonfile> allAccountsOnFile = basicPaymentProduct.getAccountsOnFile();

// Get the specific account on file for the payment product
AccountOnFile accountOnFile = null;

for (AccountOnFile aof : basicPaymentProduct.getAccountsOnFile) {
    if (Objects.equals(aof.getId(), identifier)) { // 'identifier' is the ID of the AccountOnFile selected by the customer
        accountOnFile = aof;
        break;
    }
}

// Shows a mask-based formatted value for the obfuscated cardNumber.
String label = accountOnFile.getLabel();

// All available accounts on file for the payment product
val allAccountsOnFile = basicPaymentProduct.accountsOnFile

// Get the specific account on file for the payment product
val accountOnFile = basicPaymentProduct.accountsOnFile
    .firstOrNull { it.id == identifier } // 'identifier' is the ID of the AccountOnFile selected by the customer

// Shows a mask-based formatted value for the obfuscated card number
val label = accountOnFile?.label

PaymentProduct

BasicPaymentProduct only contains the basic payment product information that customers need to distinguish them. However, when they select a payment product or an account on file, they must provide additional information. The system needs mandatory info like the bank account number, credit card number, and expiry date to process the payment. The instances of BasicPaymentProduct do not contain any information about these fields.

So when you need detailed payment information, call the PaymentProduct object. This object contains several instances of PaymentProductField. Each PaymentProductField carries a piece of information required to process the payment (e.g. bank account number, credit card number).

Use the OnlinePaymentSdk instance to retrieve the instance of PaymentProduct, as shown in the code snippet below.

Java Kotlin

// Note that exception handling is omitted here. Check the code above for more info. 
PaymentProduct paymentProduct = sdk.getPaymentProductSync(
    "1", // id of the payment product you want to retrieve
    paymentContext, // PaymentContext
);

// Note that exception handling is omitted here. Check the code above for more info. 
val paymentProduct = sesssdkion.getPaymentProduct(
    "1", // id of the payment product you want to retrieve
    paymentContext, // PaymentContext
)

PaymentProductField

PaymentProductField instances represent individual payment product fields (e.g. bank account number, credit card number). Each field has the following:

  • An identifier
  • A type
  • A definition of restrictions that apply to the field's value
  • Built-in validation for input values
  • Information on how the field should be displayed to the customer

In the code example below, the system retrieves the field with the identifier "cvv" from a payment product. The system then checks the data restrictions to identify if it is a required field or an optional field. Finally, the system inspects whether the values the customer provided should be visible or hidden in the user interface.

Java Kotlin

PaymentProductField ccvField = paymentProduct.getField("cvv");

Boolean isRequired = ccvField.isRequired(); // state if value is required for this field
Boolean shouldObfuscate = ccvField.shouldObfuscate(); // state if field value should be obfuscated

val ccvField = paymentProduct.getField("cvv")

val isRequired = ccvField.isRequired()
val shouldObfuscate = ccvField.shouldObfuscate()

PaymentRequest

Once the customer selects a payment product and the system retrieves an instance of PaymentProduct, a payment request can be constructed. You must use the PaymentRequest class as a container for all the values the customer provides.

The PaymentRequest object has a list of PaymentRequestFields. Each field provides the methods to:

  • Set and retrieve values
  • Get the field label
  • Obtain masked values for display
  • Validate user input against the field’s restrictions

Once the PaymentRequest is created, supply it with the field values as follows:

Java Kotlin

boolean tokenize = true; // true or false 

// provide paymentProduct, accountOnFile, tokenize status
PaymentRequest paymentRequest = new PaymentRequest(paymentProduct, null, tokenize);

// or
PaymentRequest paymentRequest = new PaymentRequest(paymentProduct, accountOnFile, tokenize);

// tokenize status set to false by default
var paymentRequest = PaymentRequest(paymentProduct)

// with account on file
var paymentRequest = PaymentRequest(paymentProduct, accountOnFile)

When no AccountOnFile is selected for the specific PaymentRequest, all payment request fields (e.g. cardNumber) are writable, and you can set them normally.

But when the PaymentRequest has an AccountOnFile set, the SDK behaves differently. The system clears all previously unwritable field values from the PaymentRequest, and you can no longer manually set read-only fields. Calling setter will throw InvalidArgumentException, while calling paymentRequest.getField(readOnlyFieldId).getValue() will return undefined.

This behaviour ensures only editable values are submitted. You can still use the accountOnFile instance to display masked values to the customer.

Tokenise payment request

A PaymentRequest has a property tokenize. You can use it to indicate whether a payment request should be stored as an account on file for future payments. The code snippet below shows how to construct a payment request when you want to store it as an account on file.

Java Kotlin

// you can supply tokenize via the constructor
PaymentRequest paymentRequest = new PaymentRequest(paymentProduct, accountOnFile, true);

// you can supply tokenize via the constructor
var paymentRequest = PaymentRequest(paymentProduct, true)

By default, tokenize is set to false.

If the customer selects an account on file, you must supply both the account on file and the corresponding payment product when constructing the payment request. You can retrieve the instances of AccountOnFile from instances of BasicPaymentProduct and PaymentProduct.

Java Kotlin

PaymentRequest paymentRequest = new PaymentRequest(
    paymentProduct,
    accountOnFile,
    tokenizeStatus
); // when you do not pass an accountOnFile argument, it will be null

val paymentRequest = PaymentRequest(paymentProduct, accountOnFile)

Set field values for the payment request

Once you create a payment request, you can supply the values for the payment request fields as follows:

Java Kotlin

PaymentRequest paymentRequest = new PaymentRequest(paymentProduct, null, false);

paymentRequest.getField("cardNumber").setValue("12451254457545")
paymentRequest.getField("cvv").setValue("123")
paymentRequest.getField("expiryDate").setValue("1225")

var paymentRequest = PaymentRequest(paymentProduct)

paymentRequest.getField("cardNumber").setValue("12451254457545")
paymentRequest.getField("cvv").setValue("123")
paymentRequest.getField("expiryDate").setValue("1225")

The identifiers of the fields, such as "cardNumber" and "cvv", are used to set the field values using the payment request. In general, you can retrieve all available fields from the PaymentProduct instance.

Validate payment request

Once the PaymentRequest receives all the values, it can validate the payment request. The validation uses the DataRestrictions defined in the fields added to the PaymentRequest. The server will also provide a list of errors that occurred during validation.

If there are no errors, you can encrypt the payment request and send it to our platform via your server. If there are validation errors, you should provide the customer with feedback on these errors.

The validations return a ValidationErrorMessage list inside the ValidationResult object.

Java Kotlin

// validate all fields in the payment request
// validate() return ValidationResult object with isValid status and errors
ValidationResult validationResult = paymentRequest.validate();

// check if the payment request is valid - result will return isValid: true and errors: []
if (validationResult.isValid()) {
    // payment request is valid
} else {
    // payment request has errors
    List<validationerrormessage> errors = validationResult.getErrors();
    
    for (ValidationErrorMessage error : errors) {
        //show errors
    }
}

// validate all fields in the payment request
// validate() return ValidationResult object with isValid status and errors
val validationResult = paymentRequest.validate()

// check if the // check if the payment request is valid - result will return isValid: true and errors: []
if (validationResult.isValid) {
    // payment request is valid
} else {
    // payment request has errors
    for (error in validationResult.errors) {
      //show errors
    }
}

Encrypt payment request

The PaymentRequest is ready for encryption only after the following conditions have been met:

  • The PaymentProduct is set
  • The PaymentProductField values have been provided and validated
  • The selected AccountOnFile or tokenize properties have been set (optional)

After successfully encrypting the PaymentRequest, you will get access to its encrypted version. The EncryptedRequest contains the encrypted payment request fields and encoded client meta info.

Java Kotlin

try {
    EncryptedRequest encryptedRequest = sdk.encryptPaymentRequestSync(paymentRequest);
    // Send the encryptedRequest.encryptedCustomerInput to your server and use it to create the payment with the Server SDK.
} catch (EncryptionException e) {
    // Handle encryption failure (invalid payment data, encryption failed, etc.)
} catch (ResponseException e) {
    // Handle HTTP/API errors (usually 4xx)
} catch (CommunicationException e) {
    // Handle communication errors when fetching public key (network issues, timeout, etc.)
} catch (Exception e) {
    // Handle any other unhandled exception
}

try {
    val encryptedRequest = sdk.encryptPaymentRequest(paymentRequest)

    // Send the encryptedRequest.encryptedCustomerInput to your server and use it to create the payment with the Server SDK.
} catch (EncryptionException e) {
    // Handle encryption failure (invalid payment data, encryption failed, etc.)
} catch (ResponseException e) {
    // Handle HTTP/API errors (usually 4xx)
} catch (CommunicationException e) {
    // Handle communication errors when fetching public key (network issues, timeout, etc.)
} catch (Exception e) {
    // Handle any other unhandled exception
}

Although you can use your own encryption algorithms to encrypt a payment request, we advise you to use the encryption functionality offered by the SDK.

CreditCardTokenRequest

You can use the CreditCardTokenRequest class to create a CardTokenization request. It contains the essential credit card fields like: card number, cardholder name, expiry date, cvv, and payment product id.

Java Kotlin

CreditCardTokenRequest tokenRequest = new CreditCardTokenRequest();
tokenRequest.setCardNumber("1234567890123452");
tokenRequest.setCardHolderName("John Doe");
tokenRequest.setExpiryDate("1225");
tokenRequest.setSecurityCode("123");
tokenRequest.setPaymentProductId(1);

val tokenRequest = CreditCardTokenRequest()
tokenRequest.cardNumber = "1234567890123452"
tokenRequest.cardholderName = "John Doe"
tokenRequest.expiryDate = "1225"
tokenRequest.securityCode = "123"
tokenRequest.paymentProductId = 1

Note that no validation rules are applied for values set in the token request since it is detached from the instance of the payment product. You should use this class as a helper for encrypting data required to create a token using the Server SDK. However, if invalid data is provided, the CreateToken request will fail.

Java Kotlin

try {
    EncryptedRequest encryptedRequest = sdk.encryptTokenRequest(tokenRequest);
    // Send the encryptedRequest.encryptedCustomerInput to your server and use it to create the payment with the Server SDK.
} catch (EncryptionException e) {
    // Handle encryption failure (invalid payment data, encryption failed, etc.)
} catch (ResponseException e) {
    // Handle HTTP/API errors (usually 4xx)
} catch (CommunicationException e) {
    // Handle communication errors when fetching public key (network issues, timeout, etc.)
} catch (Exception e) {
    // Handle any other unhandled exception
}

try {
    val encryptedRequest = sdk.encryptTokenRequest(tokenRequest)
    // Send the encryptedRequest.encryptedCustomerInput to your server and use it to create the payment with the Server SDK.
} catch (EncryptionException e) {
    // Handle encryption failure (invalid payment data, encryption failed, etc.)
} catch (ResponseException e) {
    // Handle HTTP/API errors (usually 4xx)
} catch (CommunicationException e) {
    // Handle communication errors when fetching public key (network issues, timeout, etc.)
} catch (Exception e) {
    // Handle any other unhandled exception
}

Additional features

The SDK has a lot more to offer. Have a look at the following features, as they will help you build the perfect solution.

Encrypt sensitive data

One of the biggest assets of the SDK is its encryption tool. It offers great security when transferring sensitive data (i.e. card numbers, expiry date, CVC code). An entire encryption/transfer flow looks like this:

The SDK is here to simplify this process. Here is what you need to do:

  1. Use the sdk.encryptPaymentRequest to encrypt the payment information provided in the PaymentRequest.
  2. The sdk.encryptPaymentRequest returns the EncryptedRequest containing the encrypted customer data.
  3. Retrieve the encrypted customer input from the EncryptedRequest.
  4. Send the encrypted customer input to your server.
  5. Send the encrypted data from your server using the CreatePayment request. Provide the encrypted data in the encryptedCustomerInput field.
  6. Send the transaction result to the client application.

Do not store the encrypted data. Transfer it via the Server API directly to our platform right after the encryption.

Java Kotlin

// Note that exception handling is omitted here. Check the code above for more info. 
EncryptedRequest encryptedRequest = sdk.encryptPaymentRequest(paymentRequest);

// Note that exception handling is omitted here. Check the code above for more info. 
val encryptedRequest = sdk.encryptPaymentRequest(paymentRequest)

The SDK does all the heavy lifting, including:

  • Requesting a public key from the Client API
  • Performing the encryption
  • BASE-64 encoding the result into one string

You only need to ensure that the PaymentRequest object contains all the information entered by the user.

Validate data

Each PaymentProductField has appropriate DataRestrictions. The DataRestrictions object contains information about all mandatory fields and validates whether the values entered meet the correctness condition. Together with a list of abstract validators, it also has a property isRequired. This property informs whether given restrictions are required or not.

You can validate a particular input just as easily as through the PaymentRequest validation. In case of any errors, the Errors field will display a list of errors.

SDK contains the following validators:

  • Expiration Date: Checks whether the entered card expiration date is not earlier than the current date and whether it is not beyond the range of twenty-five years ahead.
  • Email Address: Checks the format of the email address the customer has provided.
  • Fixed List: Checks whether the entered value is on the list of possibilities.
  • IBAN: Validates the IBAN the customer has provided.
  • Length: Checks if the entered value is longer than the minimum value and if it is not longer than the maximum value.
  • Luhn: The checksum formula used to validate a variety of identification numbers, such as credit card numbers.
  • Range: Checks if the value is greater than the minimum value and if it is not greater than the maximum value.
  • Regex: Validates that the entered value matches the regular expression.
  • TermsAndConditions: The boolean validator for the terms and conditions accept field.

Each validator returns an appropriate error, indicating a field that does not meet the conditions, and a message you can easily translate. These validators are not directly available to you, but you can retrieve an instance of the PaymentProductField from the PaymentProduct instance and call the setValue() and validate() methods.

Apply IIN check

The first six digits of a payment card number are known as the Issuer Identification Number (IIN). You can check the payment product and network associated with the entered IIN as soon as the customer enters the first six digits of their card number. Use the sdk.getIinDetails call to retrieve that information and verify if you can accept that card type.

You can use an instance of OnlinePaymentSdk to check which payment product is associated with an IIN. You do that with the session.getIinDetails function. The result of this check is an instance of IinDetailsResponse. This class has the following:

  • A property status indicating the result of the check.
  • Property paymentProductId indicating which payment product is associated with the IIN.

You can use the returned paymentProductId to fetch the PaymentProduct and show the appropriate logo to the customer.

The IinDetailsResponse has a status property represented through the IinStatus enum. The IinStatus enum values are:

  • SUPPORTED indicates that the IIN is associated with a payment product supported by our platform.
  • UNKNOWN indicates that the IIN is not recognised.
  • NOT_ENOUGH_DIGITS indicates that fewer than six digits were provided, and that it is impossible to perform the IIN check.
  • EXISTING_BUT_NOT_ALLOWED indicates that the provided IIN is recognised, but that the corresponding product is not allowed for the current payment or merchant.
Java Kotlin

// The exception handling is omitted from this example. See the examples above.
sdk.getIinDetailsSync(
    "123456", // partial credit card number
    paymentContext // PaymentContext
);

// The exception handling is omitted from this example. See the examples above.
sdk.getIinDetails("123456", paymentContext)

Some cards are co-branded and can be processed as either a local card (with a local brand) or an international card (with an international brand). If you are not set up to process these local cards, the API call will not return that card type in its response. Otherwise, the IinDetailsResponse instance will have the information on co-brands.

Implement native payments

Our system supports native payments for mobile devices, specifically Google Pay for Android and Apple Pay for iOS. However, that does not mean they will be available on every device.

If the customer receives a payment product responsible for the native payment, the SDK automatically verifies whether the device can handle the payment. If the device does not meet the conditions, this payment is hidden. As the user of our product, this procedure means you do not have to worry about verifying the correctness of the operation.

For Android devices, you first verify whether the system meets the minimum version (6.0 - Marshmallow) criterion. Then, you use the PaymentClient to perform an IsReadToPayRequest to return a value depending on the result. The SDK will do that automatically and filter out unsupported payment products.

Refer to our Google Pay guide for more information.

Use logging

Logging allows you to inspect the requests and responses exchanged between your application and our platform. This is useful for development and debugging, but you should not enable it in production environments.

You can configure logging when initialising the OnlinePaymentSdk. To enable it, set the loggingEnabled field to true in the SdkConfiguration.

Java Kotlin

new SdkConfiguration(
        false, // states if the environment is production, this property is used to determine the Google Pay environment
        "Android Example Application/v2.0.4", // your application identifier
        "AndroidSDK/v4.0.0", // SDK identifier
        true // if true, requests and responses will be logged to the console; not supplying this parameter means it is false; should be false in production
    )

// Create SDK configuration
 val sdkConfiguration = SdkConfiguration(
    environmentIsProduction = false, // states if the environment is production, this property is used to determine the Google Pay environment
    appIdentifier = "Android Example Application/v2.0.4", // your application identifier
    sdkIdentifier = "AndroidSDK/v4.0.0", // SDK identifier
    loggingEnabled = true // if true, requests and responses will be logged to the console; not supplying this parameter means it is false; should be false in production
 )

Logging is disabled by default. If the loggingEnabled parameter is not supplied, it automatically defaults to false.

Was this page helpful?

Do you have any comments?

Thank you for your response.