The Worldline Payment Interface (WPI) is an Android intent-based interface that enables easy and fast integration with payment apps. It is designed to allow additional business applications to execute payments on any Worldline offered SmartPOS device. A SmartPOS device is a payment device that runs Android And also smartphones using Tap On Mobile..

All Worldline Payment Solutions support WPI, which means that business applications that use this interface can run everywhere without any change of code. This makes it easy for developers to build payment apps that are compatible with a wide range of payment devices and payment protocols.

The WPI interface is built on top of the Android Intent mechanism, which allows different parts of an app to communicate with each other in a structured way. By using intents to trigger payment-related actions, the WPI interface simplifies the payment integration process and makes it easier for developers to build business applications on top of Payment Solutions.

What You'll Learn

Get the code

Click the following link to download all the code for this codelab:

Download Zip

Check out the sample app

For this codelab we will use Android studio Narwhal Feature Drop, SDK 36 and Gradle 8.14.3Important Please verify that you have a payment application running on your device.

The code you just downloaded contains code for all codelabs available. To complete this codelab, open the samplecode project inside Android Studio.

The codelabs repo contains starter code for all codelabs in the pathway. For this codelab, use the wpiCodelab project.

The project is built with two app folders:

We recommend that you start with the code in the start folder and follow the codelab step-by-step at your own pace.

During the codelab, you'll be presented with snippets of code that you'll need to add to the project. In some places, you'll also need to remove code that is explicitly mentioned in comments on the code snippets.

Getting familiar with the code and running the sample app

Take a moment to explore the project structure and run the app.

Project structure

When you run the app from the ‘start' folder , you'll see that this is a very simple application with only a text field to enter an amount and a button to proceed to the payment.

Project structure

For this codelab we will see how to implement a payment but the WPI provides a set of intents that developers can use to build apps that work with the interface. The following table lists each intent, along with its purpose:

Type

Display Action / Background Action

Intent

Purpose

Financial

Display Action

com.worldline.payment.action.PROCESS_TRANSACTION

Process a financial transaction

Management

Display Action

com.worldline.payment.action.PROCESS_MANAGEMENT

Trigger payment solution managed actions

Information

Background Action

com.worldline.payment.action.PROCESS_INFORMATION

Background management of payment solution info

Learn more about Android Messenger Service

Extras

An extra in Android intents is a way to pass additional data or parameters to another component in order to provide more context or information for the requested action. In WPI we have extras for request and response. The request extras needs to be provided by the Business Application that is using the interface and the response extra is provided by the Payment Solution.

Request:

Extra

Description

Type

Condition

WPI_SERVICE_TYPE

Specify the subtype of action to be executed

String

Mandatory for all service types except WPI_SVC_LAST_TRANSACTION

WPI_REQUEST

The request contains JSON structured data mandatory for given service type, in some specific cases this field is not given or empty

String

Mandatory for Financial, Optional for Management

WPI_VERSION

Used WPI version

String

Mandatory

WPI_SESSION_ID

Used as an identifier of a WPI exchange (a request/response) between a client application and a payment application. Is used to recover the status of the exchange in case of an unexpected failure. Is provided by the client and is part of the response. The session id must be unique, must be part of the response, must not be reused for subsequent requests (except for the last transaction request as it is used to do the recovery). Any business application should store the WPI_SESSION_ID before sending the intent. Due to this the business application can do a recovery with the last transaction function to check the outcome of the previous transaction in case that the business application has crashed.

String

Mandatory

Response:

Extra

Description

Type

Condition

WPI_SERVICE_TYPE

Specify the subtype of action that was executed

String

Mandatory for all service types except WPI_SVC_LAST_TRANSACTION

WPI_RESPONSE

The response contains JSON structured data processed for the requested service type

String

Mandatory for all service types except WPI_SVC_LAST_TRANSACTION

WPI_VERSION

Used WPI version

String

Mandatory

WPI_SESSION_ID

Identifier of a WPI exchange provided by the client.

String

Mandatory

Service type

Purpose

WPI_SVC_PAYMENT

Used to perform a simple sale transaction also known as purchase

WPI_SVC_CANCEL_PAYMENT

Used to reverse a previous transaction

WPI_SVC_REFUND

Used to refund a previous transaction

WPI_SVC_PRE_AUTHORIZATION

Used to perform a reservation

WPI_SVC_CANCEL_PRE_AUTHORIZATION

Used to cancel a previous reservation

WPI_SVC_UPDATE_PRE_AUTHORIZATION

Used to increment a previous reservation

WPI_SVC_CANCEL_UPDATE_PRE_AUTHORIZATION

Used to cancel the previous incrementation of a reservation

WPI_SVC_PAYMENT_COMPLETION

Used to purchase a reservation / incremented reservation

WPI_SVC_CANCEL_PAYMENT_COMPLETION

Used to cancel the purchased reservation

WPI_SVC_DEFERRED_PAYMENT_AUTHORIZATION

Used to execute a deferred payment authorization (energy solution use-case)

WPI_SVC_DEFERRED_PAYMENT_COMPLETION

Used to execute a deferred payment completion of a previous authorization(energy solution use-case)

WPI_SVC_PAYMENT_WITH_PRODUCT_DELIVERY

Used to execute a transaction with product delivery (vending use-case)

WPI_SVC_PRODUCT_DELIVERY

Used to inform the payment solution that the product was delivered (vending use-case)

WPI_SVC_PAYMENT_INSTRUMENT_RECOGNITION

Used to do a payment card of non payment card recognition request without performing a real transaction (token)

Service type

Purpose

WPI_SVC_PAYMENT_MENU

Used to open the payment solution menu

WPI_SVC_DAY_END

Used to upload the transactions (online and offline) to perform the final settlement.

WPI_SVC_PAYMENT_PARAMETERIZATION

Used to fetch the latest payment solution configuration from the payment solution related configuration system.

WPI_SVC_ACQUIRER_PARAMETERIZATION

Used to fetch the latest acquirer parameters from the acquirer

WPI_SVC_REPEAT_RECEIPT

Used to repeat the receipt printing

WPI_SVC_ABORT

Used to abort an ongoing transaction

WPI_SVC_LAST_TRANSACTION

Used to return the last transaction result

WPI_SVC_PAYMENT_INFORMATION

Used to retrieve the payment solution information especially which service types are supported.

Data Dictionary

Payment Request Data:

Field Name

Description

Type

currency

Currency of the amount. Alpha code value defined in ISO 4217 (e.g. EUR)

String

requestedAmount

Total payment amount as minor unit. The fractional digits are evaluated based on the currency. For example, 11.91€ must be sent as 1191 and the currency as EUR

Integer

tipAmount

Tip amount to be added to the transaction

Integer

cashbackAmount

Cashback amount to be added to the transaction

Integer

reference

Reference to be sent to the payment solution for reconciliation

String

customerLanguage

Language to be used for the cardholder (ISO 639-1 alpha-2 code)

String

useManualPanKeyEntry

Whether manual card data entry is activated

Boolean

receiptFormat

Receipt format(s) to override the default (see 4.1.1 Receipt Format)

Array

receiptDelegation

Whether receipt delegation is supported

Boolean

receiptWidth

Width of the receipt in characters

Integer

recognitionTimeout

Defines the timeout before an error will be returned in milliseconds

Integer

recognitionOptions

Card recognition options

Array

Response Data:

Field Name

Description

Type

result

Result of the transaction (success or failure)

String

errorCondition

Specific error reason (see table below)

String

reference

Reference to be sent to the payment app for reconciliation.

String

remark

Terminal/transaction specific message for detailed error descriptions.

String

actionCode

Specific action to be performed by the business application

String

timestamp

Date and time of the transaction, indicated by the acquirer. ISO 8601 format

String

currency

Currency code of the transaction. Alpha code value defined in ISO 4217 e.g. EUR

String

authorizedAmount

Amount of the transaction. The fraction is taken from the currency code.

Integer

customerLanguage

Language used on all screens towards the cardholder and when formatting the receipt.

String

brandName

Brand name of used payment card, like MasterCard, VISA, AMEX and so on.

String

applicationIdentifier

Payment card application identifier dependent on the used card

String

applicationLabel

Payment card application label, depending on the used card

String

receipt

Merchant and cardholder receipt. See section 5.2.5 Receipt.

Object

paymentSolutionReference

Transaction specific and unique identification.

String

acquirerIdentifier

Acquirer identifier

String

merchantIdentifier

Merchant identifier

String

terminalIdentifier

Terminal identifier configured for the payment solution

String

authorizationCode

Authorization code

String

cashbackAmount

Cashback amount

Integer

tipAmount

Tip amount entered by the cardholder or provided in the request

Integer

dccUsed

Whether DCC was used or not for the transaction

Boolean

dccOffered

Whether DCC selection was shown towards the cardholder

Boolean

dccAmount

DCC amount

Integer

dccCurrency

DCC currency

String

dccExchangeRate

DCC exchange rate

String

entryMode

The technology that was used to read the card (see 4.2.7 Supported Technologies)

String

authorizationMode

Authorization mode (see 4.2.10 Authorization Mode)

String

pan

PAN of the card

String

cardholderVerificationMethod

Cardholder verification method (see 4.2.13 Cardholder Verification Method)

String

cardDataInput

Card data input (see 4.2.12 Card Data Input)

String

Important: If your app targets Android 11 (API level 30) or higher, you must declare the external intents your app queries in your AndroidManifest.xml using the queries element. Without this, your app will not be able to discover or interact with payment solutions using WPI intents.

Add the following to your AndroidManifest.xml (outside the tag):

<queries>
    <intent>
        <action android:name="com.worldline.payment.action.PROCESS_INFORMATION" />
    </intent>
    <intent>
        <action android:name="com.worldline.payment.action.PROCESS_TRANSACTION" />
    </intent>
    <intent>
        <action android:name="com.worldline.payment.action.PROCESS_MANAGEMENT" />
    </intent>
</queries>

This ensures your app can query and interact with payment solutions using the WPI interface on Android 11+.

Creation of the request

Create a new data class SaleTransactionRequest in the package com.worldline.wpi_codelab.model.request. This class takes 2 parameters: the currency and the amount as these are the only mandatory parameters for a sale transaction.

@Serializable
public data class SaleTransactionRequest(
    val currency: String,
    val requestedAmount: Long,
)

To use the Serialization you need to add the following code in your gradle.app:

plugins {
    id("kotlinx-serialization")
}

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0")
}

To finish sync your project with Gradle files.

Creation of the response

Create a second data class SaleTransactionResponse in the package com.worldline.wpi_codelab.model.response. This class takes 3 parameters: the result the currency and the amount. We can serialiaze more fields of the response based on the table of response data but, for this codelab we will only use these 3 fields.

@Serializable
data class SaleTransactionResponse(
    val result: String?,
    val authorizedAmount: Long? = null,
    val currency: String? = null,
)

In the MainActivity we will execute the transaction and handle the response. To do so we will use a registerForActivityResult.

To have more information about how to get a result from an activity you can click here.

executeSaleTransaction

The first method will be executeSaleTransaction and it will execute the registerForActivityResult:

private fun executeSaleTransaction(amount: Long) {
    val saleTransaction = SaleTransactionRequest("eur", amount)
    val saleTransactionJson: String = Json.encodeToString(saleTransaction)

    val intent = Intent("com.worldline.payment.action.PROCESS_TRANSACTION")
    // These extras are mandatory whether the intent comes from the payment
    // application or a 3rd party application.
    intent.putExtra("WPI_SERVICE_TYPE", "WPI_SVC_PAYMENT")
    intent.putExtra("WPI_REQUEST", saleTransactionJson)
    intent.putExtra("WPI_VERSION", "2.1")
    // Session value is always up to the third party application
    // Random unique identifier of the current communication session
    // Can be used to restore the state of the transaction in multipart communication (e.g. product delivery)
    intent.putExtra("WPI_SESSION_ID", UUID.randomUUID().toString())
    
    launcher.launch(intent)
}

handleTransactionResponse

The second method will be handleTransactionResponse:

//allows ignoring fields we don't need in the response
private val json = Json { ignoreUnknownKeys = true }

private fun handleTransactionResponse(intent: Intent) {
    val rawJsonResponse = intent.getStringExtra("WPI_RESPONSE")
    if (rawJsonResponse != null) {
        Log.d("Transaction response", rawJsonResponse)
        val transactionResponse = json.decodeFromString<SaleTransactionResponse>(rawJsonResponse)
        val paymentMessage = "${transactionResponse.result}: ${(transactionResponse.authorizedAmount?.toDouble()?.div(100))} ${transactionResponse.currency}"
        Toast.makeText(this, paymentMessage, Toast.LENGTH_SHORT).show()
    }
    // Handle response
}

launcher

To finish this step, just add to your main activity the launcher that will handle the result of the activity when you perform a payment:

private val launcher = registerForActivityResult(
    ActivityResultContracts.StartActivityForResult()
) { result ->
    result.data?.let { handleTransactionResponse(it) }
}

Now that everything is set up, we will make the payment start by pressing the button.

As the amount formating is not the subject of this codelab, we use a simple solution with radio buttons and pre-defined amount.

To finish on this codelab, just add the executeSaleTransaction function in the onSubmit of your SaleTransactionScreen Composable:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
        SaleTransactionScreen { amount ->
            executeSaleTransaction(amount)
        }
    }
}

Here we check which radio is checked and we lauch executeSaleTransaction with the selected amount.

You can now run the app on a terminal and proceed to your first payment.

Congratulations, you've successfully completed this codelab and learned how to proceed to a payment with the WPI!

You learned about how to create a request, a response, and how to use the Worldline Payment Interface.

What's next? Check out the others possible transactions in the documentation and try to handle them.