Error Handling

Last updated: 2026-03-13

Result Codes

SoftPOS returns a standard Android result code to your Activity Result callback:

Result CodeValueMeaning
RESULT_OK-1The operation completed. Check isSuccess in the response extras to determine whether the transaction succeeded or failed.
RESULT_CANCELED0The operation was cancelled or aborted before completion. Check the error / Error extra for the reason.

Error Codes

The error extra (string) indicates the specific error condition. Always check both "error" and "Error" (capital E) key variants for compatibility:

kotlin
val error = data?.getStringExtra("error") ?: data?.getStringExtra("Error")
ValueDescription
NoneNo error.
AbortedThe operation was aborted.
BusyThe system is busy. Retry after a short delay.
InProgressAn operation is already in progress.
FailedThe operation failed.
ResponseNotReceivedNo response was received from the payment network.
NotAllowedThe operation is not allowed in the current state.
RefusalThe transaction was refused.
WrongPINThe cardholder entered an incorrect PIN.
CardReadFailedThe card could not be read. Ask the cardholder to try again.
CancelThe operation was explicitly cancelled.

Denial Reasons

The denialReason extra (string) provides additional context when a transaction is denied:

ValueDescription
NoneNo denial reason.
TechnicalErrorA technical error occurred.
CardReadErrorThe card could not be read correctly.
ValidationErrorRequest validation failed.
InputDataErrorInvalid input data was provided.
ConfigurationErrorTerminal configuration error.
CardDataErrorInvalid card data.
TransactionAuthorizationErrorAuthorization was denied by the card issuer.
GatewayResponseErrorAn error was received from the payment gateway.
MacGenerationFailedMAC generation failed.
CancelledByCardholderThe cardholder cancelled the transaction.
MacValidationFailedMAC validation failed.

Transaction Status

The status extra (string) reflects the final state of the transaction:

ValueDescription
NoneNo status (default).
ValidCardDetailsCard details were successfully validated.
ApprovedThe transaction was approved.
DeclinedThe transaction was declined.
VoiceReferralA voice referral is required to complete the transaction.
MustGoOnlineThe terminal must go online to complete the transaction.
MessageSequenceErrorA message sequence error occurred.

Error Handling Example

kotlin
private fun handleTransactionError(
    denialReason: String?,
    error: String?,
    status: String?
) {
    when {
        error != null && error != "None" -> {
            when (error) {
                "Aborted" -> showError("Transaction was aborted")
                "Busy" -> showError("System is busy, please try again")
                "CardReadFailed" -> showError("Failed to read card, please try again")
                "WrongPIN" -> showError("Incorrect PIN entered")
                else -> showError("Transaction error: $error")
            }
        }
        denialReason != null && denialReason != "None" -> {
            when (denialReason) {
                "CancelledByCardholder" -> showError("Transaction cancelled by cardholder")
                "TechnicalError" -> showError("A technical error occurred")
                "GatewayResponseError" -> showError("Gateway communication error")
                else -> showError("Transaction denied: $denialReason")
            }
        }
        status == "Declined" -> showError("Transaction was declined")
        else -> showError("Transaction failed")
    }
}

Common Issues

ActivityNotFoundException

Problem: The app crashes when launching a SoftPOS Intent.

Solution: Always verify SoftPOS is installed before launching:

kotlin
if (intent.resolveActivity(packageManager) != null) {
    resultLauncher.launch(intent)
} else {
    showError("WestPay SoftPOS is not installed")
}

Error Extra Not Found

Problem: The error message is not retrieved from a cancelled result.

Solution: Check both key variants:

kotlin
val error = data?.getStringExtra("error") ?: data?.getStringExtra("Error")

Amount Format Rejected

Problem: The transaction amount is not accepted by SoftPOS.

Solution: Use a comma as the decimal separator, not a period:

kotlin
val amount = "100,50"  // correct
val amount = "100.50"  // incorrect — will not be accepted

Date Format Issues

Problem: Transaction history query returns no results or fails.

Solution: Use the yyyy-MM-dd format for date extras:

kotlin
val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
val startDate = dateFormat.format(date)