Refund a Payment

A referenced refund uses the original payment’s reference so the refund is directly linked to the initial sale, ensuring accurate reconciliation and audit tracking.

If you don't have, or don't want to use, the original payment's reference, use an Unreferenced Refund instead, but be aware that it can fail more often, so use it only as a last resort.

Note
It is recommended that your ePOS application provides a controlled way to issue refunds (e.g., manager PIN or role-based permissions) to prevent unauthorized refunds.

Prerequisites

  • You must have initialized the SDK and obtained a valid TeyaCommonTransactionsApi instance. See Getting Started.
  • Store the gatewayPaymentId from a successful payment state. See Make Payment.
The `gatewayPaymentId` is provided in `TeyaPaymentStateDetails` when a payment reaches a final successful state. Persist it in your app to support refunds later.

Make a referenced refund

Call refundPayment on your TeyaCommonTransactionsApi instance, passing the original gatewayPaymentId, the amount to refund, and the currency.

import Foundation
import TeyaUnifiedEposSDK

let amountToRefund: Int32 = 100 // minor units (e.g., cents)
let currency = "GBP"          // ISO 4217

let refundSubscription = teyaPosLinkSDK.transactionsApi.refundPayment(
    paymentId: originalSuccessfulPaymentId, 
    amount: amountToRefund,
    currency: currency
)
Partial refunds

You must always specify the amount because partial refunds are supported. For example, if the original payment was £2.99, you may refund £1.00.
The refund amount cannot exceed the original captured amount or the remaining refundable balance.

Listen for refund result

Subscribe to the refund result using TeyaRefundResultListener. You’ll receive a single callback once the refund completes (either successful or failed).

Create a small Swift wrapper for convenience:

private class RefundResultListener: TeyaRefundResultListener {
    private let onResult: (TeyaRefundResultDetails) -> Void

    init(onResult: @escaping (TeyaRefundResultDetails) -> Void) {
        self.onResult = onResult
    }

    func onRefundResult(refundResult: TeyaRefundResultDetails) {
        onResult(refundResult)
    }
}

Subscribe to the refund result:

refundSubscription.subscribe(listener_: RefundResultListener { refundResult in
    // Inspect refundResult and update your UI
    print("Refund result: \(refundResult)")
})

TeyaRefundResultDetails contains a refund id (if successful), a debugErrorMessage (optionally) and the result which can be:

Name
SUCCESS
INVALID_AMOUNT_OR_PAYMENT_ID
AMOUNT_EXCEEDS_ALLOWED
DECLINED
NETWORK_ERROR
CANCELLED
FAILED
The SDK currently does not provide a built-in UI for refunds. We recommend showing your own progress indicator and final status based on the refund callback.