Refund a Payment
This guide details how to implement refund operations using the RefundRepository. Refunds allow you to return funds to a customer’s card, either linked to a previous transaction or as a standalone operation.
Before performing any refund, ensure you have initialized the TPV.
Refund Methods
The RefundRepository supports three distinct refund workflows:
1. Standard Refund (By ID)
Use this method when you have the original transaction identifier (operationId) and want to refund a specific amount against it. This is the most common scenario.
Function: makeRefund
Parameters:
operationId: The unique identifier of the original sale.amount: TheMoneyobject representing the amount to refund.proprietaryExtraData(Optional): Third-party data.language(Optional): Language for the service UI.
Example:
suspend fun refundTransaction(originalId: String, amount: Money) {
val result = refundRepository.makeRefund(
operationId = originalId,
amount = amount
)
handleRefundResult(result)
}2. Refund with Card Reading
Use this method when you have the original operationId but want to force the customer to present their card again (e.g., for security or compliance reasons).
Function: makeRefundReadingCard
Parameters: Same as Standard Refund.
Example:
suspend fun refundWithCardCheck(originalId: String, amount: Money) {
val result = refundRepository.makeRefundReadingCard(
operationId = originalId,
amount = amount
)
handleRefundResult(result)
}3. Refund Without Original
Use this method to issue a refund without linking it to a previous transaction. This functionality typically requires specific configuration (noOriginal flag) to be enabled on the TPV.
Function: makeRefundWithoutOriginal
Parameters:
amount: TheMoneyobject representing the amount to refund.proprietaryExtraData(Optional): Third-party data.language(Optional): Language for the service UI.
Example:
suspend fun adhocRefund(amount: Money) {
val result = refundRepository.makeRefundWithoutOriginal(
amount = amount
)
handleRefundResult(result)
}Interpreting the RefundResult
When the repository call is successful (RepositoryResult.Success), it returns a RefundResult sealed interface. You must handle the following states:
1. Accepted (RefundResult.Accepted)
The refund was authorized by the host.
- Data: Contains a
Transactionobject with details of the refund operation. - Action: Print the refund receipt and confirm success to the user.
2. Denied (RefundResult.Denied)
The refund was rejected.
- Data: Contains a
Transactionobject, potentially with a rejection reason. - Action: Inform the user the refund was declined.
3. Exceeded Amount (RefundResult.ExceededAmount)
Specific error indicating the requested refund amount is greater than the original transaction amount (or the remaining refundable balance).
- Action: Show an error indicating the amount is too high.
Example Handling Logic
fun handleRefundResult(result: RepositoryResult<RefundResult>) {
when (result) {
is RepositoryResult.Success -> {
when (val refundOutcome = result.data) {
is RefundResult.Accepted -> {
println("✅ Refund Approved: ${refundOutcome.data.operationInfo.authorizationNumber}")
}
is RefundResult.Denied -> {
println("❌ Refund Denied")
}
is RefundResult.ExceededAmount -> {
println("⚠️ Error: Refund amount exceeds original transaction")
}
}
}
is RepositoryResult.ConnectionError -> println("❌ Connection Error")
is RepositoryResult.Cancelled -> println("⚠️ Cancelled by user")
is RepositoryResult.ProtocolError -> println("❌ Protocol Error: ${result.type}")
}
}Next Steps
- Create a Pre-Authorized Payment: Learn about reserving funds on a card.