# Process a Refund or Cancellation

This guide explains how to initiate a refund or cancel an existing payment transaction using the Tap on Phone application. Both operations require the original transaction ID and use a similar Intent structure to standard purchases.

## Understanding Refunds vs. Cancellations

While both operations return funds to the customer, they have different use cases and restrictions:

* **Cancellation**: Reverses a transaction. The transaction must be valid, approved, and not already refunded or cancelled. The user logged into the app must have administrator access.  
* **Refund**: Returns funds to the customer after the transaction is fully processed. The transaction must be valid, approved, and not already refunded or cancelled. The user logged into your application must have administrator access to perform a refund.

## Prerequisites

Before you process a refund or cancellation, ensure you have:

* An initialized Tap on Phone application.  
* The `userId`, `userToken`, and `merchantId` associated with the current session.  
* The `transactionId` (from the Tap on Phone system) of the original approved payment.  
* Configured your backend to handle Single Sign-On (SSO) `refund` authorization requests (see [Backend Integration: Handling SSO Requests](/en/get-tap-on-phone/first-steps/backend-integration-handling-sso-requests)).

## Step 1: Register the Activity Result Launcher

Register an Activity Result callback to handle the outcome of the refund or cancellation process.

```
val modificationResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
    val data = result.data

    if (result.resultCode == Activity.RESULT_OK && data != null) {
        val status = data.getStringExtra("status") ?: "None"

        if (status == "APPROVED") {
            println("Transaction successfully modified (Refunded/Canceled).")
            // Extract receipt data for the refund/cancellation
        } else {
            val declineCause = data.getStringExtra("declineCause") ?: "Unknown"
            println("Modification declined: $declineCause")
        }
    } else if (result.resultCode == Activity.RESULT_CANCELED) {
        val errorCode = data?.getStringExtra("errorCode") ?: "None"
        val errorMessage = data?.getStringExtra("errorMessage") ?: "User Canceled"
        println("Operation failed or was canceled: $errorMessage ($errorCode)")
    }
}
```

## Step 2: Prepare the SSO Metadata

Because refunds are sensitive operations, the Tap on Phone backend validates them against your backend using SSO. You must pass your Client ID in the `operationMetadata` field so the platform can route the authorization request properly.

```
// Format your Client ID as a JSON string
val operationMetadata = "{\"ClientID\\":\"your-client-id-here\"}"
```

## Step 3: Construct and Launch the Intent

Create an explicit intent targeting the `POSActivity` in the Tap on Phone application.

You must specify the `transactionType` (either `REFUND` or `CANCEL`) and provide the identifier of the transaction you wish to modify in the `originalTransaction` field.

```
private fun performRefundOrCancel(originalTransactionId: Int, isRefund: Boolean) {
    val intent = Intent().apply {
        setClassName(
            "com.dejamobile.cbp.sps.app",
            "com.dejamobile.cbp.sps.app.POSActivity"
        )

        // Session Identifiers
        putExtra("userId", userId)
        putExtra("userToken", userToken)
        putExtra("merchantId", merchantId)

        // Specify the type: "REFUND" or "CANCEL"
        val type = if (isRefund) "REFUND" else "CANCEL"
        putExtra("transactionType", type)

        // Pass the ID of the transaction to modify
        putExtra("originalTransaction", originalTransactionId)

        // Required for SSO authorization
        putExtra("operationMetadata", operationMetadata)
    }

    // Launch the intent
    modificationResultLauncher.launch(intent)
}
```

## Step 4: Handle the Result

Once you launch the intent, the Tap on Phone application takes over. For a refund, the merchant may be prompted to present the original payment card.

When the operation concludes, your `modificationResultLauncher` callback executes. Inspect the `status` field to verify the refund or cancellation was approved, and update your internal order records accordingly.

## Next Steps

* Learn how to extract and parse the receipt data returned by these operations in [Handle Transaction Results](/en/get-tap-on-phone/transaction-guides/handle-transaction-results).