> For the complete documentation index, see [llms.txt](https://docs.verifone.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.verifone.com/psdk-latest/psdk-user-guide-and-training/psdk-user-guide/payment_functions/semi-integrated-payments/void-reversal.md).

# Void / Reversal

A void is used to remove a payment from the batch before it is settled, stopping the funds from transferring to the merchant from the customer. This generally results in fewer fees for the merchant, and is a better choice than refunds when possible. This can appear the same as a refund to the cashier, while the difference between the call is handled “behind the scenes.”

After the batch is settled, or if the POS does not keep track of the settled state, use refunds to return the funds to the customer (see [perform-refund](/psdk-latest/psdk-user-guide-and-training/psdk-user-guide/payment_functions/semi-integrated-payments/refund.md)).

Note

* The payment that is to be voided is referred to as the “original payment”.
* Void and reversal are the same from the perspective of the SDK.

{% @plantuml/diagram content="    @startuml
hide footbox

```
participant POS order 20
participant POI order 30
|||
POS ->> POI: Start session
POS <<- POI: Session started
POS ->> POI: Process Void
POS <<- POI: PaymentCompletedEvent
POS -> POS: Handle Void event
POS ->> POI: End session
POS <<- POI: Session ended
|||
@enduml" %}
```

### Starting a Void <a href="#starting-a-void" id="starting-a-void"></a>

Voids are performed using the original completed payment. The payment object can be the object as received in the PaymentCompletedEvent or can be a new Payment object using the App Specific Data from the original completed payment.

{% tabs fullWidth="false" %}
{% tab title="Java" %}
{% code lineNumbers="true" fullWidth="true" %}

```java
// A session must be open

// Construct a Payment with the AppSpecificData from the original
// completed payment.
Payment payment = Payment.create();
payment.setAppSpecificData(completedAppSpecificData);
transactionManager.processVoid(payment);
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code lineNumbers="true" %}

```kotlin
 // A session must be open

// Construct a Payment with the AppSpecificData from the original
// completed payment.
val payment = Payment.create()
payment.setAppSpecificData(completedAppSpecificData)
transactionManager.processVoid(payment)
```

{% endcode %}
{% endtab %}

{% tab title="Swift" %}
{% code lineNumbers="true" %}

```swift
// A session must be open

// Construct a Payment with the AppSpecificData from the original
// completed payment.
var payment = VFIPayment.create()
payment?.setAppSpecificData(completedAppSpecificData)
sdk.getTransactionManager()?.processVoid(payment)
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}

<pre class="language-csharp" data-line-numbers data-full-width="true"><code class="lang-csharp"><strong> // A session must be open
</strong>
// Construct a Payment with the AppSpecificData from the original
// completed payment.
Payment payment = new Payment { AppSpecificData = completed_app_specific_data };
psdk.TransactionManager.processVoid(payment);
</code></pre>

{% endtab %}

{% tab title="C++" %}
{% code lineNumbers="true" %}

```cpp
// A session must be open

// Construct a Payment with the AppSpecificData from the original
// completed payment.
auto payment = Payment::create();
payment->setAppSpecificData(completed_app_specific_data);
transaction_manager->processVoid(payment);
```

{% endcode %}
{% endtab %}

{% tab title=".NET" %}
{% code lineNumbers="true" %}

```aspnet
// A session must be open

// Construct a Payment with the AppSpecificData from the original
// completed payment.
Payment payment = Payment.Create();
AppSpecificData = completed_app_specific_data;
psdk.TransactionManager.processVoid(payment);
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Handling the Void Event <a href="#handling-the-void-event" id="handling-the-void-event"></a>

The [CommerceListener](https://docs.verifone.com/psdk-api-latest/android-java/index/commercelistener2) receives a [PaymentCompletedEvent](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentcompletedevent) with type [TransactionEvent.TRANSACTION\_ENDED ](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionevent)once the Void is complete. Retrieve the new Payment object from the event ([PaymentCompletedEvent.getPayment()](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentcompletedevent#getpayment)), then examine the the auth result of the payment ([Payment.getAuthResult()](https://docs.verifone.com/psdk-api-latest/android-java/index/payment#getauthresult)) to see if it is [AuthorizationResult.VOIDED, AuthorizationResult.VOID\_DECLINED, AuthorizationResult.USER\_CANCELLED, or AuthorizationResult.CANCELLED\_EXTERNALLY.](https://docs.verifone.com/psdk-api-latest/android-java/index/authorizationresult) The payment IDs such as [Payment.getReferencePaymentId()](https://docs.verifone.com/psdk-api-latest/android-java/index/payment#getreferencepaymentid) and [Payment.getReferenceLocalPaymentId()](https://docs.verifone.com/psdk-api-latest/android-java/index/payment#getreferencelocalpaymentid) will match the corresponding values of the original payment, i.e., the new Void payment’s Reference Payment ID will match the original payment’s Payment ID, and the new Void payment’s Reference Local Payment ID will match the original payment’s Local Payment ID.

As with all events, the status will be non-zero for failures, and zero for success.

{% tabs fullWidth="false" %}
{% tab title="Java" %}
{% code lineNumbers="true" fullWidth="true" %}

```java
@Override // Overridden from the CommerceListenerAdapter
public void handlePaymentCompletedEvent(PaymentCompletedEvent event) {
    if (TransactionEvent.TRANSACTION_ENDED.equals(event.getType())) {
        if (event.getStatus() == StatusCode.SUCCESS) {
            Payment payment = event.getPayment();
            AuthorizationResult authorizationResult = payment.getAuthResult();
            // Confirm the authorization result is VOIDED instead
            // of VOID_DECLINED or some other result.
        }
        // Else handle failure by examining the status code and message.
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code lineNumbers="true" %}

```kotlin
 // Overridden from the CommerceListenerAdapter
override fun handlePaymentCompletedEvent(
        event: PaymentCompletedEvent) {
    if (TransactionEvent.TRANSACTION_ENDED.equals(event.getType())) {
        if (event.getStatus() == StatusCode.SUCCESS) {
            val payment = event.getPayment()
            val authorizationResult = payment.getAuthResult()
            // Confirm the authorization result is VOIDED instead
            // of VOID_DECLINED or some other result.
        }
        // Else handle failure by examining the status code and message.
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="Swift" %}
{% code lineNumbers="true" %}

```swift
// Overridden from the VFICommerceListenerAdapter
override func handle(_ event: VFIPaymentCompletedEvent?) {
    if (event?.getType() == VFITransactionEventTRANSACTIONENDED) {
        if (event?.getStatus() == VFIStatusCodeSuccess) {
            let payment = event?.getPayment()
            let authorizationResult = payment?.getAuthResult()
            // Confirm the authorization result is
            // VFIAuthorizationResultVOIDED instead of
            // VFIAuthorizationResultVOIDDECLINED or some other result.
        }
        // Else handle failure by examining the status code and message.
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}

<pre class="language-csharp" data-line-numbers data-full-width="true"><code class="lang-csharp"><strong> private void HandlePaymentCompletedEvent(PaymentCompletedEvent event)
</strong>{
    if (event.Type.Value == TransactionEvent.TRANSACTION_ENDED)
    {
        if (event.Status == 0)
        {
            Payment payment = event.Payment;
            AuthorizationResult authorization_result = payment.AuthResult;
            // Confirm the authorization result is VOIDED instead
            // of VOID_DECLINED or some other result.
        }
        // Else handle failure by examining the status code and message.
    }
}
</code></pre>

{% endtab %}

{% tab title="C++" %}
{% code lineNumbers="true" %}

```cpp
// Overridden from the CommerceListenerAdapter
void handlePaymentCompletedEvent(
    const std::shared_ptr<verifone_sdk::PaymentCompletedEvent>& event) override {
    if (event->getType() == TransactionEvent::TRANSACTION_ENDED) {
      if (event->getStatus() == StatusCode::SUCCESS) {
          auto payment = event->getPayment();
          auto auth_result = payment->getAuthResult();
          // Confirm the authorization result is VOIDED instead
          // of VOID_DECLINED or some other result.
      }
      // Else handle failure by examining the status code and message.
    }
}
```

{% endcode %}
{% endtab %}

{% tab title=".NET" %}
{% code lineNumbers="true" %}

```aspnet
private void HandlePaymentCompletedEvent(PaymentCompletedEvent sdk_event)
{
    if (sdk_event.Type == TransactionEvent.TRANSACTION_ENDED)
    {
        if (sdk_event.Status == 0)
        {
            Payment payment = sdk_event.Payment;
            AuthorizationResult authorization_result = payment.AuthResult.Value;
            // Confirm the authorization result is VOIDED instead
            // of VOID_DECLINED or some other result.
        }
        // Else handle failure by examining the status code and message.
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="info" %}
**See also**

* [TransactionManager.processVoid(Transaction)](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanager#processvoid-payment)
* [TransactionEvent.TRANSACTION\_ENDED](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionevent)
* [PaymentCompletedEvent](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentcompletedevent)
* [Transaction.getPayments()](https://docs.verifone.com/psdk-api-latest/android-java/index/transaction#getpayments)
* [Payment.getAuthResult()](https://docs.verifone.com/psdk-api-latest/android-java/index/payment#getauthresult)
* [Create a Commerce Listener](/psdk-latest/psdk-user-guide-and-training/psdk-user-guide/pos_guide.md#create-a-commerce-listener)
* [start-session](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanager#startsession2-transaction)
  {% endhint %}

### Void during a Sale <a href="#void-during-a-sale" id="void-during-a-sale"></a>

It is possible to void payments in the middle of a session that is performing a sale.

{% @plantuml/diagram content="@startuml
hide footbox

```
    participant POS order 20
    participant POI order 30
    |||
    POS ->> POI: Start session
    POS <<- POI: Session started
    POS <<->> POI: Process payments
    ...
    POS -> POS: Select payment to Void
    POS ->> POI: Process Void
    POS <<- POI: PaymentCompletedEvent
    POS -> POS: Handle Void event
    POS <<->> POI: Continue processing payments
    ...
    POS ->> POI: End session
    POS <<- POI: Session ended
    |||
    @enduml" %}
```

{% tabs fullWidth="false" %}
{% tab title="Java" %}
{% code overflow="wrap" lineNumbers="true" fullWidth="true" %}

```java
Transaction transaction = transactionManager.getTransaction();
// In this example, voiding the second payment for the current order.
Payment payment = transaction.getPayments().get(1);
transactionManager.processVoid(payment);
// Once the event is received for the void, continue processing the current order.
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code overflow="wrap" lineNumbers="true" %}

```kotlin
 val transaction = transactionManager.getTransaction()
// In this example, voiding the second payment for the current order.
val payment = transaction.getPayments().get(1)
payment.setTransactionType(TransactionType.VOID_TYPE)
transactionManager.processVoid(payment)
// Once the event is received for the void, continue processing the current order.
```

{% endcode %}
{% endtab %}

{% tab title="Swift" %}
{% code overflow="wrap" lineNumbers="true" %}

```swift
var transaction = sdk.getTransactionManager()?.getTransaction()
// In this example, voiding the second payment for the current order.
var payment = transaction?.getPayments()[1]
payment?.setTransactionType(transactionType: VFITransactionType.VOIDTYPE)
sdk.getTransactionManager()?.processVoid(payment)
// Once the event is received for the void, continue processing the current order.
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}

<pre class="language-csharp" data-overflow="wrap" data-line-numbers data-full-width="true"><code class="lang-csharp"><strong> Transaction transaction = transactionManager.Transaction;
</strong>// In this example, voiding the second payment for the current order.
Payment payment = transaction.Payments[1];
transactionManager.ProcessVoid(payment);
// Once the event is received for the void, continue processing the current order.
</code></pre>

{% endtab %}

{% tab title="C++" %}
{% code overflow="wrap" lineNumbers="true" %}

```cpp
auto transaction_manager = psdk->getTransactionManager();
auto transaction = transaction_manager->getTransaction();
// In this example, voiding the second payment for the current order.
transaction_manager->processVoid(transaction->getPayments().at(1));
// Once the event is received for the void, continue processing the current order.
```

{% endcode %}
{% endtab %}

{% tab title=".NET" %}
{% code overflow="wrap" lineNumbers="true" %}

```aspnet
Transaction transaction = payment_sdk_.TransactionManager.Transaction;
// In this example, voiding the second payment for the current order.
Payment payment = transaction.Payments[1];
payment_sdk_.TransactionManager.ProcessVoid(payment);
// Once the event is received for the void, continue processing the current order.
```

{% endcode %}
{% endtab %}
{% endtabs %}

***

{% columns %}
{% column width="25%" %}

<figure><img src="/files/9ezXRridnCaI1awLr3X9" alt="" width="150"><figcaption></figcaption></figure>
{% endcolumn %}

{% column width="25%" %}

{% endcolumn %}

{% column width="16.66666666666666%" %}
**Version:**\
**Date:**
{% endcolumn %}

{% column width="33.333333333333336%" %} <code class="expression">space.vars.psdk\_version</code>\ <code class="expression">space.vars.psdk\_date</code>
{% endcolumn %}
{% endcolumns %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.verifone.com/psdk-latest/psdk-user-guide-and-training/psdk-user-guide/payment_functions/semi-integrated-payments/void-reversal.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
