> 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/reference-material/code-labs/reporting.md).

# Reporting

{% columns %}
{% column %} <i class="fa-clock">:clock:</i> 7 minutes reading time\ <i class="fa-calendar">:calendar:</i> Last updated: 10th October, 2025
{% endcolumn %}

{% column %}

{% endcolumn %}

{% column %}
✅ Query Transactions

✅ Receipt Reprinting

✅ X-report

✅ Z-report
{% endcolumn %}
{% endcolumns %}

{% stepper %}
{% step %}

## Introduction

This code lab describes the process of querying the transactions performed on the terminal.

### What you should already know

* The device you will be using for integration.
* Setting up the device and development environment for developing PSDK application
* Performing payments using PSDK.

### What you'll need

* Any Verifone device with necessary software loaded.
* Watch the PSDK Getting started code labs for more details on devices and software.
* Internet connectivity
* Few transactions which are already completed.

### Check Terminal Capabilities

The [ReportManager ](https://docs.verifone.com/psdk-api-latest/android-java/index/reportmanager)provides the APIs for reports as well as searching for transactions using a [TransactionQuery](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionquery). Not all regions and host integrations support all of the APIs, so it is critical to check the capability before calling the APIs, or handling the matching error event properly

The [ReportManager.isCapable(String) ](https://docs.verifone.com/psdk-api-latest/android-java/index/reportmanager#iscapable-string)method allows the calling application to check if the current Payment App or Payment Host are able to perform a specific operation. This call is one of the few that returns synchronously, below are the various capabilities which can be checked.

[TransactionQuery.TRANSACTION\_QUERY\_FILTER\_FIELDS\_CAPABILITY ](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionquery)[TransactionQuery.TRANSACTION\_QUERY\_PAYMENT\_ID\_BOUNDS\_CAPABILITY ](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionquery)[TransactionQuery.TRANSACTION\_QUERY\_BY\_PAYMENT\_CAPABILITY](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionquery)
{% endstep %}

{% step %}

## Query Transactions

### Query Last Transaction

Class [**TransactionQuery** ](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionquery)allows the payment terminal transaction status to be queried. The most recent transaction can always be queried, but the capability checks are extremely important for other types of queries, as the support for these queries will vary between regions and hosts. To obtain the last transaction result, create a [**TransactionQuery** ](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionquery)object, use [**TransactionQuery.setQueryingLastTransaction(true)**](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionquery#setqueryinglasttransaction-boolean) to mark it as recovering the information about the most recent payment, and then examine the information returned in the [**TransactionQueryEvent**](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionqueryevent).

The following text demonstrates the call of the [queryTransactions ](https://docs.verifone.com/psdk-api-latest/android-java/index/reportmanager#querytransactions-transactionquery)API to access the last transaction information.

```
// Create Transaction Query
{
TransactionQuery transactionQuery = TransactionQuery.create();
transactionQuery.setQueryingLastTransaction(true);
Status result = paymentSdk.getTransactionManager().getReportManager().queryTransactions(transactionQuery);
}

// In the commerce listener class below callback needs to be handled for getting the reponse.
@Override
public void handleTransactionQueryEvent(TransactionQueryEvent transactionQueryEvent) {
if (transactionQueryEvent.foundPayments()) {
    ArrayList<Payment> payments = transactionQueryEvent.getPayments();
    for (Payment p : payments) { 
    // get required information from the payment object
    }
}
```

}

### Query Specific transaction(s)

The transaction details of all the performed transactions can be obtained by having a uniqueID for each of the performed transaction, which can used to access the transaction details.

#### Query transaction(s) based on LocalPaymentId

You can use [setLocalPaymentId("UniqueID") ](https://docs.verifone.com/psdk-api-latest/android-java/index/payment#setlocalpaymentid-string)on the Payment object while starting the sale transaction which can be retrieved during [queryTransactions(query)](https://docs.verifone.com/psdk-api-latest/android-java/index/reportmanager#querytransactions-transactionquery), the ID which was passed to the [`setLocalPaymentId()`](https://docs.verifone.com/psdk-api-latest/android-java/index/payment#setlocalpaymentid-string) should be unique so that it can be retrieved and compared using [paymentObject.getLocalPaymentId()](https://docs.verifone.com/psdk-api-latest/android-java/index/payment#getlocalpaymentid).

```
//1.Create payment object and set LocalPaymentId
Payment payment = Payment.create();
payment.setLocalPaymentId("UniqueID");
paymentViewModel.mTransactionManager.startPayment(payment);

//2.Create Transaction Query to search for the already set LocalPaymentId on the payment Object
{
    TransactionQuery transactionQuery = TransactionQuery.create();
    ArrayList<Payment> payments = new ArrayList<>();
    Payment payment = Payment.create();
    payment.setLocalPaymentId("UniqueID");
    payments.add(payment);

    transactionQuery.setPayments(payments);
    transactionQuery.setAllPos(true);  // Sets the query to retrieve transactions for all POS systems connected to the Payment Application
    Status result = paymentSdk.getTransactionManager().getReportManager().queryTransactions(transactionQuery);
}

//3. In the commerce listener class below callback needs to be handled for getting the reponse.
@Override
public void handleTransactionQueryEvent(TransactionQueryEvent transactionQueryEvent) {
    if (transactionQueryEvent.foundPayments()) {
        ArrayList<Payment> payments = transactionQueryEvent.getPayments();
        for (Payment p : payments) { 
            // get required information from the payment object comparing the LocalPaymentId
            if("UniqueID". equals(p.getLocalPaymentId.toString())
            {
            //Perform some operation..
            }
        }
    }
}
```

#### Query transaction(s) based on date range

You can query the transactions based on the date and time range using [TransactionQuery](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionquery).

```
TransactionQuery transactionQuery = TransactionQuery.create();

//Set the start EPOC time, Date and time (GMT): Sunday, June 25, 2023 1:32:46 PM
transactionQuery.setStartTime(Long.valueOf(1687699966));

// Set the End EPOC time, Date and time GMT: Tuesday, June 27, 2023 5:22:31 PM
transactionQuery.setEndTime(Long.valueOf(1687886551));
//Query for transactions
Status result = paymentViewModel.mTransactionManager.getReportManager().queryTransactions(transactionQuery);
//In the commerce listener class below callback needs to be handled for getting the transactions
@Override
    public void handleTransactionQueryEvent(TransactionQueryEvent transactionQueryEvent) {
        if (transactionQueryEvent.foundPayments()) {
            ArrayList<Payment> payments = transactionQueryEvent.getPayments();
                for (Payment p : payments) { 
                // List the transactions from start time to End time

            }
        }
    }
```

### Query offline transaction(s) - Pending Store and Forward (SAF) Transactions

To query pending Store and Forward (SAF) transactions, the transaction query must be marked as offline via [TransactionQuery.setOffline(bool)](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionquery#setoffline-boolean). This setting solicits the reporting of all transactions which were ever offline, not just those that are currently offline. It is typically useful to specify a starting time for which the offline transactions are reported via [TransactionQuery.setStartTime(...)](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionquery#setstarttime-long). A command is also available to specify the ending time for the report via [TransactionQuery.setEndTime(...)](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionquery#setendtime-long), however this is rarely used, in order to report transactions up until the present

You can the query to check on transactions that were processed offline, returning their current status using below API's

```
TransactionQuery transactionQuery = TransactionQuery.create();
transactionQuery.setOffline(true);
transactionQuery.setStartTime(1589302704000);
//Query for transactions
Status result = paymentViewModel.mTransactionManager.getReportManager().queryTransactions(transactionQuery);
//In the commerce listener class below callback needs to be handled for getting the transactions
@Override
public void handleTransactionQueryEvent(TransactionQueryEvent transactionQueryEvent) {
    if (transactionQueryEvent.foundPayments()) {
        ArrayList<Payment> payments = transactionQueryEvent.getPayments();
            for (Payment p : payments) { 
            // List the Offline transactions
            }
    }
}
```

### Query offline transaction(s) based on range of paymentId's (SCA)

This is used only for terminals using SCA as payment solution
{% endstep %}

{% step %}

## Receipts Re-printing

This is a convenient method to reprint the receipt of a transaction. Before printing a receipt, its important to check the state of the [TransactionManager](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanager). This can be done using the [getState()](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanager#getstate) method.

You can reprint the receipts using the [reprintReceipt ](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanager#reprintreceipt-payment-receipttype-deliverymethod-string)method of the [TransactionManager](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanager) class. This method requires the following parameters:

* The receipt content
* The content type
* The receipt type (see [ReceiptType](https://docs.verifone.com/psdk-api-latest/android-java/index/payment_sdk_receipttype))
* The delivery method (see [DeliveryMethod](https://docs.verifone.com/psdk-api-latest/android-java/index/deliverymethod))
* A string for additional information

  ```
  // Reprint a customer receipt for an earlier transaction if the TransactionManager is in a valid state
  public Status reprintReceipt(Payment payment, ReceiptType receiptType, DeliveryMethod receiptDeliveryMethod, String deliveryAddress) {
    if (paymentSdk.getTransactionManager().getState() == TransactionManagerState.LOGGED_IN ||
        paymentSdk.getTransactionManager().getState() == TransactionManagerState.SESSION_OPEN) {
        
      // Create a payment object and set app-specific data for receipt reprinting
      Payment paymentObject = Payment.create();
      paymentObject.setAppSpecificData(mPaymentObject.getAppSpecificData());

      // Reprint the receipt; ensure address is specified for EMAIL delivery
      paymentSdk.getTransactionManager().reprintReceipt(paymentObject, ReceiptType.CUSTOMER, DeliveryMethod.PRINT, "test");
    }
  }
  ```

After printing the receipt, you can use the [`handleCommerceEvent()`](https://docs.verifone.com/psdk-api-latest/android-java/index/commercelistener2#handlecommerceevent-commerceevent) method to handle the response. This method checks the status of the event and performs actions based on whether the printing was successful or not. See [CommerceEvent ](https://docs.verifone.com/psdk-api-latest/android-java/index/commerceevent)and [TransactionEvent](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionevent).

```
//callback event for print API
@Override
public void handleCommerceEvent(CommerceEvent commerceEvent) {
    if(commerceEvent.getType()==TransactionEvent.RECEIPT_REPRINTED){
        if(commerceEvent.getStatus()==StatusCode.SUCCESS)
            //reprint successful

        else
            //reprint failure
            // commerceEvent.getMessage() will have the message for failure.
    }
}
```

{% endstep %}

{% step %}

## Generate X Report

**For specific customers in Australia direct to host solutions using AGPA**

An ‘X’ Report is an ‘End of Shift’ report which will give the Merchant a total of all their takings up to the end of a shift.

[ReportManager.getTotalsForGroup](https://docs.verifone.com/psdk-api-latest/android-java/index/reportmanager#gettotalsforgroup-string) is used to generate both the X-Report.

public Status [getActiveTotals()](https://docs.verifone.com/psdk-api-latest/android-java/index/reportmanager#getactivetotals)

Provides the transactions totals realised since the beginning of the current reconciliation period until the reception of this request. This is also called a pre-settlement report. Fires a [ReconciliationEvent ](https://docs.verifone.com/psdk-api-latest/android-java/index/reconciliationevent)with type [`ReconciliationEvent.ACTIVE_TOTALS_TYPE`](https://docs.verifone.com/psdk-api-latest/android-java/index/reconciliationevent) to the listener. The current reconciliation period is never closed by this message, please use [closePeriod()](https://docs.verifone.com/psdk-api-latest/android-java/index/reportmanager#closeperiod), [closePeriodAndReconcile()](https://docs.verifone.com/psdk-api-latest/android-java/index/reportmanager#closeperiodandreconcile-arraylistinteger), or [closePeriodAndReconcile(int\[\])](https://docs.verifone.com/psdk-api-latest/android-java/index/reportmanager#closeperiodandreconcile-arraylistinteger) to close the period.

```
//To generate X report
//TransactionManager state must be in valid state, here it is Logged in or in session open
if( paymentSdk.getTransactionManager().getState()==TransactionManagerState.LOGGED_IN||
    paymentSdk.getTransactionManager().getState()==TransactionManagerState.SESSION_OPEN)
{
    //check if the terminal has the capability to provide back the report when calling getActiveTotals().
    if (paymentSdk.getTransactionManager().getReportManager().isCapable(ReportManager.GET_ACTIVE_TOTALS_CAPABILITY)) {
     Status result = paymentSdk.getTransactionManager().getReportManager().getActiveTotals();
        String s = "getActiveTotals:  " + result.getStatus() + " : " + result.getMessage();
    }
}
```

After generating the X-report, you can use the [`handleReconciliationEvent()`](https://docs.verifone.com/psdk-api-latest/android-java/index/commercelistener2#handlereconciliationevent-reconciliationevent) method to handle the response. This method checks the status of the event and performs actions based on whether the reporting was successful or not. See [ReconciliationEvent](https://docs.verifone.com/psdk-api-latest/android-java/index/reconciliationevent).

```
@Override 
public void handleReconciliationEvent(ReconciliationEvent reconciliationEvent) { 
    try { 
        switch (reconciliationEvent.getType()) { 
            case ReconciliationEvent.TYPE: 
                // Handle TYPE event 
                break; 
            case ReconciliationEvent.ACTIVE_TOTALS_TYPE: 
                // Handle ACTIVE_TOTALS_TYPE event 
                break; 
            case ReconciliationEvent.GROUP_TOTALS_TYPE: 
                // Handle GROUP_TOTALS_TYPE event 
                break; 
            default: 
                // Handle other event types if needed 
                break; 
        } 
    } catch (Exception e) { 
        e.printStackTrace();
        // Handle the exception appropriately, such as logging or rethrowing 
    } 
}
```

{% endstep %}

{% step %}

## Generate Z Report

**For specific customers in australia direct to host solutions using AGPA**

A ‘Z’ Report is an ‘End of Day’ report which will give the Merchant a total of all their taking for that particular day. The Z report is an end-of-shift overview of the sales, returns, voids, discards, and other register activity that took place during a register shift, from open to close. This report is generated at the end of the day after the reconciliation is done.

After [ReportManager.closePeriod()](https://docs.verifone.com/psdk-api-latest/android-java/index/reportmanager#closeperiod) is called to close the shift, generate the Z- report.

```
//To generate Z report
//check if the terminal has the capability to provide back the report when calling getTotalsForGroup().
if (paymentSdk.getTransactionManager().getReportManager().isCapable(ReportManager.GET_GROUP_TOTALS_CAPABILITY)) {
    Status result = PaymentSdk.getTransactionManager().getReportManager().getTotalsForGroup(null);
}
```

After generating the Z-report, you can use the [`handleReconciliationEvent()`](https://docs.verifone.com/psdk-api-latest/android-java/index/commercelistener2#handlereconciliationevent-reconciliationevent) method to handle the response. This method checks the status of the event and performs actions based on whether the reporting was successful or not. See [ReconciliationEvent](https://docs.verifone.com/psdk-api-latest/android-java/index/reconciliationevent).

```
@Override 
public void handleReconciliationEvent(ReconciliationEvent reconciliationEvent) { 
    try { 
        switch (reconciliationEvent.getType()) { 
            case ReconciliationEvent.TYPE: 
                // Handle TYPE event 
                break; 
            case ReconciliationEvent.ACTIVE_TOTALS_TYPE: 
                // Handle ACTIVE_TOTALS_TYPE event 
                break; 
            case ReconciliationEvent.GROUP_TOTALS_TYPE: 
                // Handle GROUP_TOTALS_TYPE event 
                break; 
            default: 
                // Handle other event types if needed 
                break; 
        } 
    } catch (Exception e) { 
        e.printStackTrace(); 
        // Handle the exception appropriately, such as logging or rethrowing 
    } 
}
```

{% endstep %}
{% endstepper %}


---

# 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/reference-material/code-labs/reporting.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.
