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.
Click the following link to download all the code for this codelab:
For this codelab we will use Android studio Giraffe, SDK 33 and Gradle 7.5
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.
Take a moment to explore the project structure and run the app.
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.
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 | Intent | Purpose |
Financial | com.worldline.payment.action.PROCESS_TRANSACTION | Process a financial transaction |
Management | com.worldline.payment.action.PROCESS_MANAGEMENT | Trigger payment solution managed actions |
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 | ||||||
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 | float | Mandatory | ||||||
Response:
Extra | Description | Type | Purpose |
WPI_RESPONSE | The response contains JSON structured data processed for the requested service type | 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. |
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 in the currency. For example, 11.91€ must be sent as 1191 and the currency as EUR | Integer | |||
cashbackAmount | |||||
paymentSolutionReference | A previous transaction reference used for subsequent transactions like a Reversal. This value is defined by the payment application and contains all necessary data to perform subsequent transactions. This value can differ based on the payment application and can only be used on the same device. | String | |||
reference | Reference to be send to the payment solution for reconciliation | String | |||
productRecords | Product catalogue for energy solution based use-cases. This records needs the format that the issuer can understand. Most often used for petrol use-cases. | Array | |||
receiptFormat | To override the default receipt format | Array | |||
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 |
actionCode | Specific action to be performed by the business application | String |
remark | Terminal / transaction specific message for detailed error descriptions. Text provided by payment app in English | String |
timestamp | Date and time of the transaction, indicated by the acquirer. | 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. Example: | Integer |
brandName | Brand name of used payment card, like MasterCard, VISA, AMEX and so on. | String |
customerLanguage | Language used on all screens towards the cardholder and when formatting the receipt. Language code will be returned for english > en | String |
applicationIdentifier | Payment card application identifier dependent on the used card e.g. for MasterCard A00000041010 | String |
applicationLabel | Payment card application label, depending on the used card e.g. MasterCard DEBIT | String |
formattedReceipt | Merchant and cardholder receipt are contained in this field. Both receipts are available as text preformatted. Check the subsequent chapter below for an example. The receipt wide is defined by the payment application (often 32 characters) and depends on the printer capabilities or configuration. | Object |
paymentSolutionReference | Transaction specific and unique identification. This value is defined by the payment application and contains all necessary data to perform subsequent transactions. This value can differ based on the payment application and can only be used on the same device. | String |
dccUsed | Whether DCC was used or not for the transaction. This field is present as soon as DCC is activated for this payment solution. | Boolean |
tipAmount | The tip amount that was entered by the cardholder during the transaction with the payment solution. This field is present as soon as TIP is activated for this payment solution. | Integer |
reference | Reference to be send to the payment app for reconciliation. The reference will be the same value as in the response. | String |
softwareVersion | Payment Solution software version | String |
terminalIdentifier | The terminal identifier configured for the payment solution | String |
supportedLanguages | List of language that are supported | String |
cardholderDefaultLanguage | The configured cardholder default language | String |
merchantLanguage | The configured merchant default language | String |
countryCode | The country code of the terminal ISO 3166-1 (alpha-2 code) | String |
defaultCurrency | The default currency that is configured for the payment solution. | String |
supportedCurrency | All currencies that are supported by the payment solution. | String |
shopInfo | The shop information of the terminal. Usually these are the first three lines of each receipt. | Array |
acquirerProtocol | The used acquirer protocol by the payment solution, usually this is the official acronym like CTAP. | String |
supportedTicketFormats | The supported ticket formats by the payment solution | String |
paymentInformation | Detailed payment solution information per brand & acquirer | Array |
paymentSolutionSupportedServiceTypes | Payment Solution supported service types. This includes all service types of WPI. | Array |
entryMode | The technology that was used to read the card | String |
isoTrack1 | ISO track 1 data | String |
isoTrack2 | ISO track 2 data (due to PCI regulatory payment card PAN data are always masked) | String |
isoTrack3 | ISO track 3 data | String |
token | The token of the card PAN / UID (in case of NFC non payment related card) that was read. The token should be an unique value, generated by the payment solution and can be reproduced on the same device. This token is used to identify the customer. | String |
pan | PAN of the card (due to PCI regulatory payment card PAN data are always masked) | String |
mediaType | Media type of NFC non payment card. e.g. MIFARE Ultralight | String |
mediaUniqueIdentifier | UID of NFC based non payment card | String |
waitForNextAction | Whether the payment solution keeps the card in read mode for a subsequent transaction or not | Boolean |
nextActionWaitTime | The time how long the card is kept in read mode, in milliseconds | Integer |
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.
@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.5.0'
}
To finish sync your project with Gradle files.
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.
@Serializable
public data class SaleTransactionResponse(
val result: String?,
val authorizedAmount: Long? = null,
val currency: String? = null,
)
We can now create the SaleActivity
in the package com.worldline.wpi_codelab
, this activity 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.
The SaleActivity
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", 1)
launcher.launch(intent)
}
The SaleActivity
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
}
To finish this step, just add to your main activity the laucher
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 subjectof 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 button listener:
if(radioOne.isChecked){
executeSaleTransaction(1999)
}
if(radioTwo.isChecked){
executeSaleTransaction(12000)
}
if(radioThree.isChecked){
executeSaleTransaction(5000)
}
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.