Tap to Pay on Pocket
Initiate and accept contactless payments from your POS application via the SDK.
Intent sequence
The code samples in this document use kotlin.
Click one of the intent endpoints in the sequence below to jump to the relevant section.
- TaP request: Initializes the TaP application
- POS response: Sends initialization results
- TaP: Start or refund transaction
- POS: Send sale or refund results
- TaP: Send last transaction results
- POS: Receive last transaction results
- TaP: Request a split bill and set gratuity information
- POS: Send split bill and gratuity information
Setting up the SDK
First, generate an API key in the Developer Portal by following this guide.
Then add the dependency to your project:
repositories {
mavenCentral()
}
dependencies {
implementation 'tech.dojo.pos:tap-to-pay-on-pocket:1.0.0'
}
Finally, initialise the SDK within your custom Application’s onCreate, using the API key from earlier and the software house ID provided to you by Dojo:
class ExamplePosApp : Application() {
override fun onCreate() {
super.onCreate()
initSdk()
}
private fun initSdk() {
DojoTapToPayOnPocket.initSdk(
context = this,
config = TapToPayOnPocket.Config(
apiKey = "[YOUR API KEY]",
softwareHouseId = "[YOUR SOFTWARE HOUSE ID]",
)
)
}
}
Customising the SDK
TapToPayOnPocket.Config provides sensible defaults but allows you control the behaviour of the SDK should the need arise.
data class Config(
val apiKey: String,
val softwareHouseId: String,
val resellerId: String = softwareHouseId,
val apiEnvironment: DojoApiEnvironment = DojoApiEnvironment.PRODUCTION,
val appEnvironment: TapAppEnvironment = TapAppEnvironment.PRODUCTION,
val foregroundReconciliation: ForegroundReconciliationConfig = ForegroundReconciliationConfig(
val enabled: Boolean = true,
val windowMs: Long = 5_000,
val pollIntervalMs: Long = 1_000,
val networkConfig: ApiCallConfig = ApiCallConfig(
val connectTimeoutMs: Int = 10_000,
val readTimeoutMs: Int = 10_000,
val maxAttempts: Int = 3,
val firstRetryDelayMs: Long = 500,
val secondRetryDelayMs: Long = 1_000,
),
),
val processLifecycle: ProcessLifecycle = ProcessLifecycleOwnerAdapter(),
)
Reseller IDs
resellerId can be used to identify the reseller who sells software on behalf of the EPOS company. This value will be unique and provided by Dojo to each reseller.
In sandbox, use your assigned software-house-id and reseller-id if you have them; otherwise use the literal values softwareHouse1 and reseller1. Production integrations always use values assigned by Dojo.
Environments
By default, the SDK targets the production environments. For development, you may be testing against a staging version of the TAP app. This version of TAP has a different package name. As the SDK uses explicit Intents, when initialising you can pass appEnvironment.
appEnvironment controls the target Pocket environment. This should only be changed when developing internally against Dojo's staging environment.
apiEnvironment controls the Dojo API environment and should not be changed as PRODUCTION supports both sandbox and production API keys.
Foreground reconciliation
By default, the SDK uses the Dojo API as a fallback when the POS app does not receive a response from the TAP app. This is triggered when focus is returned to the POS app without the SDK receiving a reply it expects. This can be disabled if you prefer to manually handle this. The timings can also be configured if the default values are not suitable for your app.
Process lifecycle observation
The SDK uses Android Jetpack Startup library in order to listen to the process lifecycle. We recommend keeping this library enabled, however if you have disabled this then you must provide an alternative implemention through the processLifecycle property.
Multi-process
We do not recommend using the SDK across multiple processes. By default, the SDK and its components will run in the default process. If you customise the manifest properties to run within a different process, the SDK will enforce all invocations to be within that same process. You must guard against trying to initialise the SDK or observing responses from alternative processes for correctness. Failure to comply will result in the SDK returning errors and the integration not working as expected.
R8/ProGuard
If you are using R8, any shrinking or obfuscation rules required by this SDK will be included automatically.
Responses
All responses from TAP are emitted via the DojoTapToPayOnPocket.responses Flow. Responses can be returned to the SDK whilst your app is in the background and therefore collection shouldn't directly make UI-modifications. We recommend subscribing to responses only once at the process-level to guarantee delivery. These can be persisted, observed or multicast to fit within your architecture.
For easier migrations from Intents to the SDK, though the Responses contain properties now, Responses also expose a Bundle. This is backwards compatible with the Intent/Bundles returned through Intent-integration.
If the SDK is expecting a response but does not receive one, will emit MissingResponse along with the request type and any known metadata, such as Payment Intent & Terminal Session IDs (when known), allowing you to reconcile.
Initialize

Flow diagram: Tap Init Flow
graph TD
Start["val intent = Intent('com.dojo.action.INIT')"] --> Provisions[Device Provisions]
Provisions -->|Device has never been activated| Activation[Device Activation Flow<br/>Completed within Dojo Pay App]
Provisions --> Complete
Activation --> Complete
Complete[INIT_COMPLETE<br/>Check OnActivityResult]
Complete --> ResultFalse[INIT_RESULT false]
Complete --> ResultTrue[INIT_RESULT true]
style ResultFalse fill:#f96,stroke:#333
style ResultTrue fill:#3f3,stroke:#333
style Provisions fill:#d1f2eb,stroke:#333
style Complete fill:#b8c2f2,stroke:#333
Before defining any sale, refund, or split bill and gratuity logic, the first step is to initialize and provision TaP.
Request message
Begin the initialization and provisioning process:
DojoTapToPayOnPocket.initDojo()
TaP provisioning may take up to two minutes to complete.
Prerequisites
- The device must not be in developer mode, or connected via Android Debug Bridge (ADB) to a client.
- The device system images must not be modified (no custom bootloader or SU binary).
- The bootloader must be locked.
- The device must be NFC-enabled.
Should these checks fail, TaP will not be able to provision.
TaP Action
Initialization is currently a UI-interactive process in TaP, requiring user input to enter the activation code and complete the device setup procedure. In future releases, this third party driven initialization will become a silent background process in TaP, with no UI interaction required. Any required setup data would be passed as a payload within the intent message.
Response
TaP will return its response to DojoTapToPayOnPocket.responses as both properties and a Bundle within TapToPayOnPocket.Response.DojoInit:
- An
INIT_COMPLETEresponse is returned to indicate the status of the initialization. - The
INIT_RESULTandINIT_RESULT_DETAILextra fields reflect the initialization status.INIT_RESULTreturns a boolean value oftrueif it is successful andfalseif it is not.- The
INIT_RESULT_DETAILvalue will be eitherOKif initialization completes successfully orCOMPLETEDif it was already initialised before the call was made.
- If there are any problems an error code will be provided as a string.
com.dojo.extra.TERMINAL_IDcontains the unique identifier (known as a TID) of the current Pocket device. This is only returned from26.07.15onwards.
This message returns TaP initialization status information to the POS:
val pendingIntent = IntentCompat.getParcelableExtra(requestIntent, "com.dojo.extra.PENDING_INTENT", PendingIntent::class.java)
val response = Intent("com.dojo.action.INIT_COMPLETE").apply {
putExtra("com.dojo.extra.INIT_RESULT", isInitSuccess)
putExtra("com.dojo.extra.INIT_RESULT_DETAIL", "OK")
putExtra("com.dojo.extra.TERMINAL_ID", "58804222")
}
with (requireActivity()) {
pendingIntent?.send(this, Activity.RESULT_OK, response)
finish()
}
Required POS Action
Within TapToPayOnPocket.Response.DojoInit:
- Properties
- Bundle
The POS should check the isSuccess property to determine whether the TaP initialization succeeded or failed. When false, further information on the failure will be available in the detail property.
localPosClient.responses.collect { response ->
when (response) {
is Response.DojoInit -> {
val initResult = response.isSuccess
val initResultDetail = response.detail
}
}
}
The POS should parse this message to determine whether the TaP initialization succeeded or failed by parsing the INIT_RESULT boolean. Further information on the failure status will be available in the INIT_RESULT_DETAIL string.
localPosClient.responses.collect { response ->
when (response) {
is Response.DojoInit -> {
val initResult = response.bundle.getBoolean("com.dojo.extra.INIT_RESULT", false)
val initResultDetail = response.bundle.getString("com.dojo.extra.INIT_RESULT_DETAIL")
}
}
}
Error codes include:
E1- a payment session failed to start.A10- a provisioning error occurred.T1- a timeout caused the provisioning to be cancelled.NO_TID- terminal ID not found after initialising. Recommended action: retry.
The POS app should respond to the messages using one of the following approaches:
- No action required in the event of a successful device initialization.
- Re-trying the initialization.
- Notifying the user of a technical fault after multiple retries.
Sale
Request message
This message is to be used by the POS to request TaP to begin a contactless transaction.
scope.launch {
val result = DojoTapToPayOnPocket.sale(
amountInPennies,
reference = "Order #1234" // Optional
)
}
Prerequisites
TaP must have been previously provisioned using INIT in order for this request to succeed.
TaP Action
On receiving the request, TaP will begin a transaction, display the contactless acceptance screen, and wait for the presentation of a contactless EMV card.
Response
The user should present a card to the device for contactless payment. TaP will then process the transaction, contact the acquiring bank for authorization, then show the result to the user.
Should the transaction fail, the reason will be displayed to the user (for example, card declined or card expired). These status codes will be returned to the POS in the response message.
This message returns transaction status and payment data to the POS.
Sender example (TaP):
val pendingIntent = IntentCompat.getParcelableExtra(requestIntent, "com.dojo.extra.PENDING_INTENT", PendingIntent::class.java)
val response = Intent("com.dojo.action.TX_COMPLETE").apply {
putExtra("com.dojo.extra.SALE_STATUS", "OK")
putExtra("com.dojo.extra.TRANSACTION_RESULT", "AUTHORISED") // enum: AUTHORISED, DECLINED, CANCELLED, FAILED
// ...
}
pendingIntent?.send(requireActivity(), Activity.RESULT_OK, response)
// finish() is called upon the user pressing the Done button
Expected POS Action
TaP will return its response to DojoTapToPayOnPocket.responses as both properties and a Bundle within TapToPayOnPocket.Response.Sale.
- Properties
- Bundle
The POS should check the transactionResult property to determine whether the transaction succeeded or failed. Additional properties exist for further details.
localPosClient.responses.collect { response ->
when (response) {
is Response.Sale -> {
val saleStatus = response.saleStatus
val transactionResult = response.transactionResult
val baseAmount = response.baseAmount
val gratuityAmount = response.gratuityAmount
val transactionId = response.transactionId
val authCode = response.authCode
val paymentMethod = response.paymentMethod
val cvm = response.cardholderVerificationMethod
val cardScheme = response.cardScheme
val cardApplicationLabel = response.cardApplicationLabel
val cardApplicationId = response.cardApplicationId
val cardPan = response.cardPan
val dateTime = response.dateTime
val paymentIntentId = response.paymentIntentId
val terminalSessionId = response.terminalSessionId
}
}
}
| Property | Value | Type |
|---|---|---|
saleStatus | NOT_PROVISIONED / OK | String |
baseAmount | Base transaction amount | Integer |
gratuityAmount | Gratuity transaction amount | Integer |
transactionResult | AUTHORISED/CANCELLED/DECLINED/FAILED/UNKNOWN | Enum |
authCode | Tx Authorization Code | String |
paymentMethod | MANUAL_ENTRY/KEYED/SWIPE/CHIP/CONTACTLESS/UNKNOWN | Enum |
cardholderVerificationMethod | PIN/SIGNATURE/DEVICE/NONE/UNKNOWN | Enum |
cardScheme | Mastercard/Visa/Amex/Discover | String |
applicationLabel | EMV application label | String |
applicationId | EMV application ID | String |
cardPan | Card Primary Account Number | String |
dateTime | Time of the reversal | String |
transactionId | TaP transaction ID | String |
paymentIntentId | Dojo API payment intent ID | String |
terminalSessionId | Dojo API terminal session ID | String |
The POS should parse the Bundle to determine whether the transaction succeeded or failed by parsing the TRANSACTION_RESULT string along with the fields listed below.
localPosClient.responses.collect { response ->
when (response) {
is Response.Sale -> {
val saleStatus = response.bundle.getString("com.dojo.extra.SALE_STATUS")
val transactionResult = response.bundle.getString("com.dojo.extra.TRANSACTION_RESULT")
val baseAmount = response.bundle.getInt("com.dojo.extra.BASE_AMOUNT")
val gratuityAmount = response.bundle.getInt("com.dojo.extra.GRATUITY_AMOUNT")
val transactionId = response.bundle.getString("com.dojo.extra.TRANSACTION_ID")
val authCode = response.bundle.getString("com.dojo.extra.AUTH_CODE")
val paymentMethod = response.bundle.getString("com.dojo.extra.PAYMENT_METHOD")
val cvm = response.bundle.getString("com.dojo.extra.CARDHOLDER_VERIFICATION_METHOD")
val cardScheme = response.bundle.getString("com.dojo.extra.CARD_SCHEME")
val cardApplicationLabel = response.bundle.getString("com.dojo.extra.CARD_APPLICATION_LABEL")
val cardApplicationId = response.bundle.getString("com.dojo.extra.CARD_APPLICATION_ID")
val cardPan = response.bundle.getString("com.dojo.extra.CARD_PAN")
val dateTime = response.bundle.getString("com.dojo.extra.DATE_TIME")
val paymentIntentId = response.bundle.getString("com.dojo.extra.PAYMENT_INTENT_ID")
val terminalSessionId = response.bundle.getString("com.dojo.extra.TERMINAL_SESSION_ID")
}
}
}
| Key (literal string) | Value | Type |
|---|---|---|
com.dojo.extra.SALE_STATUS | OK | String |
com.dojo.extra.BASE_AMOUNT | Base transaction amount | Integer |
com.dojo.extra.GRATUITY_AMOUNT | Gratuity transaction amount | Integer |
com.dojo.extra.TRANSACTION_RESULT | AUTHORISED/CANCELLED/DECLINED/FAILED/UNKNOWN | String |
com.dojo.extra.AUTH_CODE | Tx Authorization Code | String |
com.dojo.extra.PAYMENT_METHOD | MANUAL_ENTRY/KEYED/SWIPE/CHIP/CONTACTLESS/UNKNOWN | String |
com.dojo.extra.CARDHOLDER_VERIFICATION_METHOD | PIN/SIGNATURE/DEVICE/NONE/UNKNOWN | String |
com.dojo.extra.CARD_SCHEME | Mastercard/Visa/Amex/Discover | String |
com.dojo.extra.CARD_APPLICATION_LABEL | EMV application label | String |
com.dojo.extra.CARD_APPLICATION_ID | EMV application ID | String |
com.dojo.extra.CARD_PAN | Card Primary Account Number | String |
com.dojo.extra.DATE_TIME | Time of the reversal | String |
com.dojo.extra.TRANSACTION_ID | TaP transaction ID | String |
com.dojo.extra.PAYMENT_INTENT_ID | Dojo API payment intent ID | String |
com.dojo.extra.TERMINAL_SESSION_ID | Dojo API terminal session ID | String |
Refund
Request message
This message is to be used by the POS to request TaP to begin a contactless refund transaction.
scope.launch {
val result = DojoTapToPayOnPocket.refund(
amountInPennies,
)
}
Prerequisites
TaP must have been previously provisioned using INIT in order for this request to succeed.
TaP Action
On receiving the request, TaP will begin a transaction, display the contactless acceptance screen, and wait for the presentation of a contactless EMV card.
The user should present a card to the device for contactless payment. TaP will then process the refund transaction, contacting the acquiring bank for authorization and show the result to the user.
Response
This message returns transaction status and payment data to the POS.
Should the transaction fail, the reason will be displayed to the user (for example, card declined or card expired). These status codes will be returned to the POS in the response message.
Sender example (TaP):
val pendingIntent = IntentCompat.getParcelableExtra(requestIntent, "com.dojo.extra.PENDING_INTENT", PendingIntent::class.java)
val response = Intent("com.dojo.action.TX_COMPLETE").apply {
putExtra("com.dojo.extra.SALE_STATUS", refundStatus)
putExtra("com.dojo.extra.TRANSACTION_RESULT", transactionResult)
// ...
}
pendingIntent?.send(requireActivity(), Activity.RESULT_OK, response)
// finish() is called upon the user pressing the Done button
Expected POS Action
TaP will return its response to DojoTapToPayOnPocket.responses as a Bundle within TapToPayOnPocket.Response.Refund.
- Properties
- Bundle
The POS should check the transactionResult property to determine whether the refund succeeded or failed. Additional properties exist for further details.
localPosClient.responses.collect { response ->
when (response) {
is Response.Refund -> {
val refundStatus = response.refundStatus
val transactionResult = response.transactionResult
val baseAmount = response.baseAmount
val transactionId = response.transactionId
val authCode = response.authCode
val paymentMethod = response.paymentMethod
val cvm = response.cardholderVerificationMethod
val cardScheme = response.cardScheme
val cardPan = response.cardPan
val dateTime = response.dateTime
val terminalSessionId = response.terminalSessionId
}
}
}
| Property | Value | Type |
|---|---|---|
refundStatus | OK | String |
baseAmount | Base transaction amount | Integer |
transactionResult | AUTHORISED/CANCELLED/DECLINED/FAILED/UNKNOWN | Enum |
authCode | Tx Authorization Code | String |
paymentMethod | MANUAL_ENTRY/KEYED/SWIPE/CHIP/CONTACTLESS/UNKNOWN | Enum |
cardholderVerificationMethod | PIN/SIGNATURE/DEVICE/NONE/UNKNOWN | Enum |
cardScheme | Mastercard/Visa/Amex/Discover | String |
applicationLabel | EMV application label | String |
applicationId | EMV application ID | String |
cardPan | Card Primary Account Number | String |
dateTime | Time of the reversal | String |
transactionId | TaP transaction ID | String |
terminalSessionId | Dojo API terminal session ID | String |
The POS should parse the Bundle to determine whether the refund succeeded or failed:
localPosClient.responses.collect { response ->
when (response) {
is Response.Refund -> {
val refundStatus = response.bundle.getString("com.dojo.extra.SALE_STATUS")
val transactionResult = response.bundle.getString("com.dojo.extra.TRANSACTION_RESULT")
val baseAmount = response.bundle.getInt("com.dojo.extra.BASE_AMOUNT")
val transactionId = response.bundle.getString("com.dojo.extra.TRANSACTION_ID")
val authCode = response.bundle.getString("com.dojo.extra.AUTH_CODE")
val paymentMethod = response.bundle.getString("com.dojo.extra.PAYMENT_METHOD")
val cvm = response.bundle.getString("com.dojo.extra.CARDHOLDER_VERIFICATION_METHOD")
val cardScheme = response.bundle.getString("com.dojo.extra.CARD_SCHEME")
val cardPan = response.bundle.getString("com.dojo.extra.CARD_PAN")
val dateTime = response.bundle.getString("com.dojo.extra.DATE_TIME")
val terminalSessionId = response.bundle.getString("com.dojo.extra.TERMINAL_SESSION_ID")
}
}
}
| Key (literal string) | Value | Type |
|---|---|---|
com.dojo.extra.SALE_STATUS | OK | String |
com.dojo.extra.BASE_AMOUNT | Base transaction amount | Integer |
com.dojo.extra.TRANSACTION_RESULT | AUTHORISED/CANCELLED/DECLINED/FAILED/UNKNOWN | String |
com.dojo.extra.AUTH_CODE | Tx Authorization Code | String |
com.dojo.extra.PAYMENT_METHOD | MANUAL_ENTRY/KEYED/SWIPE/CHIP/CONTACTLESS/UNKNOWN | String |
com.dojo.extra.CARDHOLDER_VERIFICATION_METHOD | PIN/SIGNATURE/DEVICE/NONE/UNKNOWN | String |
com.dojo.extra.CARD_SCHEME | Mastercard/Visa/Amex/Discover | String |
com.dojo.extra.CARD_APPLICATION_LABEL | EMV application label | String |
com.dojo.extra.CARD_APPLICATION_ID | EMV application ID | String |
com.dojo.extra.CARD_PAN | Card Primary Account Number | String |
com.dojo.extra.DATE_TIME | Time of the reversal | String |
com.dojo.extra.TRANSACTION_ID | TaP transaction ID | String |
Last transaction details
We recommend reconciling through reconcileSale and reconcileRefund. This functionality remains for parity with Intent-based integrations.
Request message
This message is used by the POS to request details of the last executed transaction. It should be utilized in scenarios where the POS fails to receive a response from the preceding transaction. Example situations include:
- The TaP app failed to send the response due to an internal failure.
- The POS app failed during processing the response.
- The device restarted before the POS could process the response.
val result = DojoTapToPayOnPocket.lastTx()
Prerequisites
TaP must have been previously provisioned using INIT for this request to succeed.
TaP Action
Upon receiving this message, TaP will return the available details from the last completed transaction, regardless of the transaction outcome (authorized, declined, or failed).
Response
TaP will return its response to DojoTapToPayOnPocket.responses as a Bundle within TapToPayOnPocket.Response.LastTx.
Fields default to empty strings where data was not successfully retrieved, for example, where card data could not be fetched successfully. The payload contains the following data:
val pendingIntent = IntentCompat.getParcelableExtra(requestIntent, "com.dojo.extra.PENDING_INTENT", PendingIntent::class.java)
val response = Intent("com.dojo.action.LAST_TX_COMPLETE").apply {
putExtra("com.dojo.extra.SPLIT_BILL", isSplitBill)
// ...
}
with(requireActivity()) {
pendingIntent?.send(this, Activity.RESULT_OK, response)
finish()
}
Expected POS action
- Properties
- Bundle
The property splitBill indicates whether the last transaction was split between two or more customers. See the Split bills section for more info.
localPosClient.responses.collect { response ->
when (response) {
is Response.LastTx.Sale -> {
// Handle just like a Sale response
// e.g. val transactionResult = response.transactionResult
}
is Response.LastTx.Sale -> {
// Handle just like a SplitSale response
// e.g. val paymentsMade = response.paymentsMade
}
}
}
The field SPLIT_BILL indicates whether the last transaction was split between two or more customers. See the Split bills section for more info.
localPosClient.responses.collect { response ->
when (response) {
is Response.LastTx -> {
val isSplitBill= response.bundle.getBoolean("com.dojo.extra.SPLIT_BILL")
if (isSplitBill == true) {
// Handle just like a SplitSale response
// e.g. val paymentsMade = response.bundle.getInt("com.dojo.extra.PAYMENTS_MADE")
} else {
// Handle just like a Sale response
// e.g. val txStatus = response.bundle.getString("com.dojo.extra.TX_STATUS")
}
}
}
}
Split bills
At the payment stage, the user can split a bill into constituent transactions and then recombine those into a single response.
- Properties
- Bundle
A SplitSale response will be returned instead of Sale:
localPosClient.responses.collect { response ->
when (response) {
is Response.SplitSale -> {
val status = response.status
val paymentsMade = response.paymentsMade
val totalBaseAmount = response.totalBaseAmount
val totalPaidAmount = response.totalPaidAmount
val totalGratuityAmount = response.totalGratuityAmount
val splitTransactions = response.splitTransactions
}
}
}
| Property | Value | Type |
|---|---|---|
paymentsMade | Number of payments made | Integer |
totalBaseAmount | Total amount to be paid in pennies | Integer |
totalPaidAmount | Total amount paid in pennies | Integer |
totalGratuityAmount | Total gratuity amount paid in pennies | Integer |
splitTransactions | List of payment splits | List(SplitTransaction) |
The details of each transaction can be found in SplitTransaction.
localPosClient.responses.collect { response ->
when (response) {
is Response.SplitSale -> {
response.splitTransactions.forEach { tx->
val status = tx.status
val baseAmount = tx.baseAmount
val gratuityAmount = tx.gratuityAmount
val transactionResult = tx.transactionResult
val transactionId = tx.transactionId
val authCode = tx.authCode
val paymentMethod = tx.paymentMethod
val cvm = tx.cardholderVerificationMethod
val cardScheme = tx.cardScheme
val cardApplicationLabel = tx.cardApplicationLabel
val cardApplicationId = tx.cardApplicationId
val cardPan = tx.cardPan
val dateTime = tx.dateTime
}
}
}
}
| Property | Value | Type |
|---|---|---|
txStatus | OK | String |
baseAmount | Base transaction amount | Integer |
gratuityAmount | Gratuity transaction amount | Integer |
transactionResult | AUTHORISED/CANCELLED/DECLINED/FAILED/UNKNOWN | Enum |
authCode | Tx Authorisation Code | String |
paymentMethod | MANUAL_ENTRY/KEYED/SWIPE/CHIP/CONTACTLESS/UNKNOWN | Enum |
cardholderVerificationMethod | PIN/SIGNATURE/DEVICE/NONE/UNKNOWN | Enum |
cardScheme | Mastercard/Visa/Amex/Discover | String |
cardApplicationLabel | EMV application label | String |
cardApplicationId | EMV application ID | String |
transactionId | TaP transaction ID | String |
These are the response schema associated with a bundled collection, as a whole:
localPosClient.responses.collect { response ->
when (response) {
is Response.SplitSale -> {
val paymentsMade = response.bundle.getInt("com.dojo.extra.PAYMENTS_MADE")
val totalBaseAmount = response.bundle.getInt("com.dojo.extra.TOTAL_BASE_AMOUNT")
val totalPaidAmount = response.bundle.getInt("com.dojo.extra.TOTAL_PAID_AMOUNT")
val totalGratuityAmount = response.bundle.getInt("com.dojo.extra.TOTAL_GRATUITY_AMOUNT")
val splitTransactionKeys = response. bundle.getStringArrayList("com.dojo.extra.PAYMENT_KEYS")
}
}
}
| Key (literal string) | Value | Type |
|---|---|---|
com.dojo.extra.PAYMENTS_MADE | Number of payments made | Integer |
com.dojo.extra.TOTAL_BASE_AMOUNT | Total amount to be paid in pennies | Integer |
com.dojo.extra.TOTAL_PAID_AMOUNT | Total amount paid in pennies | Integer |
com.dojo.extra.TOTAL_GRATUITY_AMOUNT | Total gratuity amount paid in pennies | Integer |
com.dojo.extra.PAYMENT_KEYS | List of payment keys | List(String) |
The value passed for PAYMENT_KEYS will be a list of strings. These keys are
associated with individual transactions inside the split bill bundle.
The details of each transaction can then be extracted as a bundle from the intent response using that key. You can extract individual transaction information from a split bill bundle:
localPosClient.responses.collect { response ->
when (response) {
is Response.SplitSale -> {
response.splitTransactions.forEach { tx->
val status = tx.bundle.getString("com.dojo.extra.TX_STATUS")
val baseAmount = tx.bundle.getInt("com.dojo.extra.BASE_AMOUNT")
val gratuityAmount = tx.bundle.getInt("com.dojo.extra.GRATUITY_AMOUNT")
val transactionResult = tx.bundle.getString("com.dojo.extra.TRANSACTION_RESULT")
val transactionId = tx.bundle.getString("com.dojo.extra.TRANSACTION_ID")
val authCode = tx.bundle.getString("com.dojo.extra.AUTH_CODE")
val paymentMethod = tx.bundle.getString("com.dojo.extra.PAYMENT_METHOD")
val cvm = tx.bundle.getString("com.dojo.extra.CARDHOLDER_VERIFICATION_METHOD")
val cardScheme = tx.bundle.getString("com.dojo.extra.CARD_SCHEME")
val cardApplicationLabel = tx.bundle.getString("com.dojo.extra.CARD_APPLICATION_LABEL")
val cardApplicationId = tx.bundle.getString("com.dojo.extra.CARD_APPLICATION_ID")
val cardPan = tx.bundle.getString("com.dojo.extra.CARD_PAN")
val dateTime = tx.bundle.getString("com.dojo.extra.DATE_TIME")
}
}
}
}
These response schema are associated with individual transactions extracted from a bundle:
| Key (literal string) | Value | Type |
|---|---|---|
com.dojo.extra.TX_STATUS | NOT_PROVISIONED | OK |
com.dojo.extra.BASE_AMOUNT | Base transaction amount | Integer |
com.dojo.extra.GRATUITY_AMOUNT | Gratuity transaction amount | Integer |
com.dojo.extra.TRANSACTION_RESULT | AUTHORISED / DECLINED / FAILED | String |
com.dojo.extra.AUTH_CODE | Tx Authorisation Code | String |
com.dojo.extra.PAYMENT_METHOD | MANUAL_ENTRY/KEYED/SWIPE/CHIP/CONTACTLESS/UNKNOWN | String |
| `com.dojo.extra.CARDHOLDER_VERIFICATION_METHOD | PIN/SIGNATURE/DEVICE/NONE/UNKNOWN | String |
com.dojo.extra.CARD_SCHEME | Mastercard/Visa/Amex/Discover | String |
com.dojo.extra.CARD_APPLICATION_LABEL | EMV application label | String |
com.dojo.extra.CARD_APPLICATION_ID | EMV application ID | String |
com.dojo.extra.TRANSACTION_ID | TaP transaction ID | String |