Unreferenced Refund

An unreferenced refund is a card-present credit that is not tied to any original sale. Instead of pointing at a previous payment, you start a brand new transaction and the customer presents their card at the terminal to receive the money back.

Use this when you need to return funds but don't have, or don't want to use, the original payment's gatewayPaymentId. If you do have the original payment, prefer a Referenced Refund, which links the credit back to the initial sale for cleaner reconciliation. Because there is no original transaction to validate against, unreferenced refunds are subject to additional fraud screening and can be declined more often.

Make an unreferenced refund

Call the makeUnreferencedRefund function on the TeyaCommonTransactionsApi instance. It reuses the same state machine as makePayment, so it returns a PaymentStateSubscription rather than the RefundResultSubscription used by referenced refunds.

Kotlin

val refundSubscription = teyaIntegration.makeUnreferencedRefund(
    transactionId = UUID.randomUUID().toString(), // or pass whatever identifier you already have for this refund
    amount = amountToRefund, // The amount to refund, in the smallest unit of the currency (e.g., cents).
    currency = "GBP" // The ISO 4217 currency code (e.g., "GBP", "EUR").
)

The terminal always asks for the manager PIN before processing an unreferenced refund. If the wrong PIN is entered, the refund reaches a final ProcessingFailed state.

Subscribe to the refund status

Since makeUnreferencedRefund returns a PaymentStateSubscription, you track its progress exactly like a payment. Subscribe a PaymentStateChangeListener and read the same PaymentStateDetails described in Make Payment, moving through PaymentState values such as InProgress, Successful and ProcessingFailed. As with payments on All-in-One, inProgressState is always null.

Kotlin

val listener = object : PaymentStateSubscription.PaymentStateChangeListener {
    override fun onPaymentStateChanged(state: PaymentStateSubscription.PaymentStateDetails) {
        println("new state = $state, is it a final state = ${state.isFinal}")
    }
}
refundSubscription.subscribe(listener)

If the OS kills your app before the final state is delivered, you can still receive it through MissedResponseListener.onMissedUnreferencedRefundResponse. See Missed Responses.

Transaction type

The PaymentStateSubscription exposes a transactionType property so you can tell, at runtime, whether it tracks a payment or a refund.

public enum class TransactionType {
    Payment, // Money charged to the customer.
    Refund,  // Money returned to the customer.
}

For an unreferenced refund, refundSubscription.transactionType is TransactionType.Refund. The id of the created refund is available on PaymentStateDetails.gatewayRefundId once it reaches the Successful state.

Payment app version

Unreferenced refunds require a Teya payment app that recognises the new request. An older payment app answers with a version mismatch, which the SDK reports as a final CommunicationFailed state.

Availability

Contact us at partnersupport@teya.com to have unreferenced refunds enabled for your account. Until the feature is activated, the refund reaches a failed state whose reason is PaymentStateReason.FeatureNotActivatedUnreferencedRefunds. You can read state.reason on the latest PaymentStateDetails.