Android SDK
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 dependenciesimplementation '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:
- Kotlin example app – Available in Jetpack Compose and XML-based implementations.
- Java example app – Available in XML-based implementation.
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:
- Initialisation of the SDK
- Fetching possible payment methods
- Fetching and displaying payment method details
- Validation of the provided data
- Encryption and transfer of payment data
- 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 |
|---|---|
|
|
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 |
|---|---|
|
|
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 |
|---|---|
|
|
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 |
|---|---|
|
|
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 |
|---|---|
|
|
Alternatively, adapt the code sample by supplying both the account on file and the corresponding payment product:
| Java | Kotlin |
|---|---|
|
|
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 |
|---|---|
|
|
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 |
|---|---|
|
|
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 |
|---|---|
|
|
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
- PaymentContext
- BasicPaymentProduct
- AccountOnFile
- PaymentProduct
- PaymentProductField
- PaymentRequest
- CreditCardTokenRequest
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 |
|---|---|
|
|
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 |
|---|---|
|
|
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 |
|---|---|
|
|
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 |
|---|---|
|
|
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 |
|---|---|
|
|
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 |
|---|---|
|
|
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 |
|---|---|
|
|
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 |
|---|---|
|
|
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 |
|---|---|
|
|
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 |
|---|---|
|
|
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 |
|---|---|
|
|
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 |
|---|---|
|
|
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 |
|---|---|
|
|
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 |
|---|---|
|
|
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:
- Use the sdk.encryptPaymentRequest to encrypt the payment information provided in the PaymentRequest.
- The sdk.encryptPaymentRequest returns the EncryptedRequest containing the encrypted customer data.
- Retrieve the encrypted customer input from the EncryptedRequest.
- Send the encrypted customer input to your server.
- Send the encrypted data from your server using the CreatePayment request. Provide the encrypted data in the encryptedCustomerInput field.
- 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 |
|---|---|
|
|
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 |
|---|---|
|
|
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 |
|---|---|
|
|
Logging is disabled by default. If the loggingEnabled parameter is not supplied, it automatically defaults to false.