Handle Transaction Results
After the Tap on Phone application finishes processing a payment, refund, or cancellation, it returns control to your application. It passes the transaction outcome through the Android Activity Result API.
This guide explains how to parse the result code, determine the final status of the transaction, and extract the detailed receipt data.
Step 1: Check the Activity Result Code
When your registered Activity Result callback triggers, you must first inspect the resultCode. This code tells you if the Tap on Phone application completed its process.
RESULT_OK: The transaction process completed successfully, and the Tap on Phone app generated a receipt. Note: This does not mean the payment was approved; it only means the process finished without a fatal system error.RESULT_CANCELED: The process aborted before a receipt could be generated. This happens if the user manually cancels the operation (for example, by pressing the back button) or if an error occurs before the transaction goes online (such as a card reading failure or network timeout).
val resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
val data = result.data
if (result.resultCode == Activity.RESULT_OK && data != null) {
// The process finished and generated a receipt. Proceed to Step 2.
} else if (result.resultCode == Activity.RESULT_CANCELED) {
// The process was canceled or failed. Proceed to Step 4.
}
}Step 2: Determine the Transaction Status
When you receive RESULT_OK, you must evaluate the status extra to determine the actual financial outcome of the transaction:
-
APPROVED: The transaction was successful. -
DECLINED: The transaction was rejected. CheckdeclineCauseanddeclineErrorfor details.
// ... inside your RESULT_OK block
val status = data.getStringExtra("status") ?: "None"
if (status == "APPROVED") {
println("The transaction was approved.")
// Fulfill the order and save the receipt data
} else if (status == "DECLINED") {
val declineCause = data.getStringExtra("declineCause") ?: "Unknown reason"
println("The transaction was declined: $declineCause")
// Prompt the user to try a different payment method
}The Tap on Phone app also returns an authorized boolean extra. This is a convenience field derived directly from the status field (true when APPROVED, false when DECLINED).
Step 3: Extract Receipt Data
For every completed transaction (RESULT_OK), the intent data contains detailed information about the payment. You use these fields to update your backend, print physical receipts, or send digital receipts to the customer.
Extract the data using standard Android intent getters:
// Basic Identifiers
val transactionId = data.getIntExtra("transactionId", -1)
val uuid = data.getStringExtra("uuid") ?: "" // Unique receipt ID
// Financial Details
val amount = data.getLongExtra("amount", 0) // Amount in cents
val currency = data.getStringExtra("currency") ?: "" // ISO 4217 code (e.g., "EUR")
val date = data.getStringExtra("date") ?: ""
// Card & EMV Details
val scheme = data.getStringExtra("scheme") ?: "" // e.g., "Visa", "Mastercard"
val pan = data.getStringExtra("pan") ?: "" // Masked PAN (e.g., "************1234")
val aid = data.getStringExtra("aid") ?: "" // Selected EMV Application ID
val applicationLabel = data.getStringExtra("applicationLabel") ?: ""
val authCode = data.getStringExtra("authCode") ?: "" // EMV Authorization CodeThe Formatted Receipt String
If you want to display or print a receipt without manually formatting each field, the Tap on Phone application provides a pre-formatted string.
Extract the formatedString extra. This string contains a complete, ready-to-print receipt layout that includes the merchant name, location, masked PAN, date, and authorization codes.
val fullReceiptString = data.getStringExtra("formatedString") ?: "No receipt available"
println(fullReceiptString)Step 4: Handle Cancellations and Errors
When you receive RESULT_CANCELED, you must check if it was a simple user cancellation or a system error.
If an error caused the cancellation, the Tap on Phone app includes error details in the intent extras. If the intent does not contain these extras, you can assume the user manually canceled the process.
// ... inside your RESULT_CANCELED block
if (data != null && data.hasExtra("errorCode")) {
val errorCode = data.getStringExtra("errorCode") ?: "Unknown"
val errorName = data.getStringExtra("errorName") ?: "Unknown"
val errorMessage = data.getStringExtra("errorMessage") ?: "Unknown"
println("Transaction failed with error [$errorCode]: $errorName - $errorMessage")
// Display the error message to the merchant
} else {
println("The merchant canceled the transaction.")
}Next Steps
- For an exhaustive list of all available data fields returned in the intent, consult the Response Parameters reference.
- Learn how to query the status of a past transaction using its UUID in Querying Past Transactions.