> 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/connect-to-a-terminal.md).

# Connect to a Terminal

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

{% column width="24.999999999999986%" %}

{% endcolumn %}

{% column %}
✅ Connection Logic

✅ Configuration

✅ Exception Handling
{% endcolumn %}
{% endcolumns %}

{% stepper %}
{% step %}

## Introduction

This code lab describes steps for connecting to the payment application while developing PSDK based POS application.

#### What you should already know

* The device you will be using for integration.
* testing changes during demo
* Setting up the device and development environment for developing PSDK application

#### 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
  {% endstep %}

{% step %}

## Connect Payment Application/Terminal

This section covers the steps to establish connection to the payment application.

#### **Initialize Payment SDK object**

The first step of initialization is to create a payment SDK object.

```java
// To be done once per application launch
PaymentSdk paymentSdk = PaymentSdk.create(context)
```

#### **Define Commerce Listener class**

Define a commerce listener class. Override the class from **CommerceListenerAdapter** class. This class offers various callbacks to notify the progress of the transaction.Since we are implementing the initialization sequence, override method handleStatus() to get notified with the connection details

Below sample code shows which function to override in the CommerceListenerAdapter for getting the connection status.

```java
private inner class PSDKListener : CommerceListenerAdapter() {
    // This callback has to be overridden to handle connection notifications
    override fun handleStatus(status: Status) {
        when (status.type) {
            Status.STATUS_INITIALIZED -> {
                when (status.status) {
                    StatusCode.SUCCESS -> {
                        // Initialization was successful.
                        // If information needs to be shown to POS Operator, text in status.message can be shown
                    }
                    StatusCode.CONFIGURATION_REQUIRED -> {
                        // If this status is returned it means additional parameters possibly IP address of the Payment Terminal needs to be provided.
                    }
                    else -> {
                        // If any other failure is returned please follow the steps mentioned in exception handling section.
                    }
                }
            }
        }
    }
}
```

#### **Create an instance of PSDKListener**

Create an instance of PSDKListener class which you have derived from CommerceListenerAdapter() to register with PaymentSdk object. This commerce listener object would be the single point of contact for receiving information from the payment application.

```java
// Create a CommerceListener object
private val listener: PSDKListener = CommerceListener()
```

{% hint style="success" %}
**Best Practice:** Use [`CommerceListenerAdapter`](https://app.gitbook.com/s/yzyMJNwlQJZoQOIC8vZ8/api/moduleindex-4/_commerce_listener_adapter_8java) instead of implementing [`CommerceListener2`](https://docs.verifone.com/psdk-api-latest/android-java/index/commercelistener2) directly. The adapter provides default implementations, so you only need to override the methods you care about.
{% endhint %}

#### **Connect to Payment Application**

By this time you would have already created a PaymentPSDK and CommerceListener object. Now its time to connect to payment application. This connection step varies based on the integration mode.

**OnDevice**

To establish connection with the payment application we need to use [**initialize(CommerceListener)**](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdkbase#initialize) API from instance of paymentSDK object. If there is any persistent information about the connection configuration, PSDK will use that information to connect to the payment solution

Below is a sample code in java on how to call the initialize API once the paymentSDK object is created

```java
// Connecting to Payment Solution
paymentSdk.initialize(listener);
```

In case of **OnDevice** integration, PSDK will identify that the application is running on a Verifone terminal, and will automatically attempt to connect over local loopback (127.0.0.1). This will disable network scanning and device connection recovery since its getting connected locally.

> Note: This step of calling initialize() has to be done for OffDevice integration also.

**OffDevice**

If it is an OffDevice integration, along with initialize() API call as mentioned above, you also need to perform these additional steps. On the calling initialize(), PSDK will identify that you are not running on a Verifone terminal, and respond back with [StatusCode.CONFIGURATION\_REQUIRED](https://docs.verifone.com/psdk-api-latest/android-java/index/statuscode) , At this point it might be good to bring up a screen to accept the IP Address of the Verifone device to which you want to connect.

This process applies to all Verifone terminals including connecting to an Android terminal.

Once you get the IP Address, call the API [**initializeFromValues**](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdkbase#initializefromvalues) and pass the IP Address of Verifone terminal

```java
val config = HashMap<String, String>()
// Setting up the terminal IP address.
config[PsdkDeviceInformation.DEVICE_CONNECTION_TYPE_KEY] = "tcpip"
config[PsdkDeviceInformation.DEVICE_ADDRESS_KEY] = "ipAddress"
// Connecting to Payment Solution
paymentSdk.initializeFromValues(listener, config);
```

*This will also enable network scanning and device connection recovery by default since you are not connecting locally*. After PSDK has successfully connected to the terminal all connection information is persisted. All subsequent attempts for connecting to the payment solution can call [**initialize(CommerceListener2)**](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdkbase#getcommercelistener) API. PSDK will use the persisted information to re-establish a connection to the terminal. *Persisted information is maintained across application restarts and device reboots*.

Once [**initialize()**](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdkbase#getcommercelistener) or [**initializeFromValues()**](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdkbase#initializefromvalues) API is called, PSDK will return the status of the API call as part of the **handleStatus** callback in the [CommerceListener2](https://docs.verifone.com/psdk-api-latest/android-java/index/commercelistener2)

The Status Type should be [Status.STATUS\_INITIALIZED](https://docs.verifone.com/psdk-api-latest/android-java/index/status)

If the connection was successful the event.status in the handlestatus callback will be StatusCode.SUCCESS and the **Transaction Manager State** would become [TransactionManagerState.NOT\_LOGGED\_IN](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanagerstate) or if the connection failed the event.status will indicate reason for failure and **Transaction Manager State** would be [TransactionManagerState.UNKNOWN](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanagerstate)
{% endstep %}

{% step %}

## Advance Configuration

As part of the **initializeFromValues()** API call, we can pass the below parameters to configure the POS. Configuration parameters can be found in [PsdkInitializationConstants](https://docs.verifone.com/psdk-api-latest/android-java/index/psdkinitializationconstants), [PosInformation](https://docs.verifone.com/psdk-api-latest/android-java/index/posinformation), [PsdkDeviceInformation](https://docs.verifone.com/psdk-api-latest/android-java/index/psdkdeviceinformation) and [TransactionManager](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanager) classes.

#### Configuration done per integration

**Server Mode** - Wait for a connection request from the terminal.

* TransactionManager.DEVICE\_LISTEN\_KEY with value TransactionManager.ENABLED\_VALUE works only for **GPA engage** integrations at the moment.
* *usecase*: When you want a single POS system to handle multiple terminals across the network.
* **Note**: *The listening timeout is 2 seconds in this mode, so it is the POS systems responsibility to call the **initialize()** api when needed* **Slim Integrated Mode** - If the POS is handling the host interactions.
* TransactionManager.DEVICE\_HOST\_AUTHENTICATION\_KEY with value TransactionManager.DEVICE\_HOST\_AUTHENTICATION\_ENABLED works only for **AGPA** integrations at the moment. **Network Configuration** - Please refer [Configuration](https://docs.verifone.com/psdk-api-latest/android-java/index/psdkinitializationconstants) for more details.
* ***PsdkInitializationConstants.NETWORK\_CONFIGURATION\_KEY*** with values ***PsdkInitializationConstants.NETWORK\_CONFIGURATION\_DYNAMIC\_VALUE*** or ***PsdkInitializationConstants.NETWORK\_CONFIGURATION\_STATIC\_VALUE***

**Message Encryption** (This is applicable only for PSDK SCA integration)-

* ***TransactionManager.DEVICE\_ENCRYPTION\_KEY*** with values

  ```java
    -***TransactionManager.ENABLED_VALUE***  // For Encryption only setup
    - ***TransactionManager.ENABLED_FALLBACK_VALUE*** // If Encryption fails we can fallback to plaintext communication
  ```

**Configuration done per device**

**VHQ Device ID** - The Device ID used in VHQ Server to identify the terminal. - ***TransactionManager.VHQ\_DEVICE\_ID\_KEY*** works only for **SCA GSC** integrations at the moment. - *usecase*: Performing Terminal Out Of Box setup from POS. **POS ID** - Set a unique ID for the POS system so that terminal can differentiate between POS systems when there are multiple connection instances.

```java
* ***TransactionManager.DEVICE_ID_KEY*** with value <Unique POS id>.
```

**Terminal Serial Number** \* ***PsdkDeviceInformation.DEVICE\_SERIAL\_NUMBER\_KEY*** with value ***PsdkDeviceInformation.ACCEPT\_ANY\_DEVICE\_VALUE*** for connecting to any device or specify a serial number to connect to a specific terminal.

{% code overflow="wrap" lineNumbers="true" %}

```java
private fun getInitializationParams(): HashMap<String, String> {
    val config = HashMap<String, String>()
    val slimMode = false
    val serverMode = false
    val encryption = false
    val stubMode = false
    val networkScanOnIPChange = false
    val encryptionWithFallback = false
    val deviceId = ""
    val ipAddress = ""


    if (deviceId.isNotEmpty()) {
        //this will work only with SCA GSC solutions
        config[TransactionManager.VHQ_DEVICE_ID_KEY] = deviceId
    }
    if (slimMode) {
        // this is only for PSDK Android slim integrations
        // where host module is handled by POS
        config[TransactionManager.DEVICE_HOST_AUTHENTICATION_KEY] =
            TransactionManager.DEVICE_HOST_AUTHENTICATION_ENABLED
    }
    if (encryption) {
        // this will work only with SCA solutions
        config[TransactionManager.DEVICE_ENCRYPTION_KEY] = TransactionManager.ENABLED_VALUE
    }
    if (encryptionWithFallback) {
        // this will work only with SCA solutions
        config[TransactionManager.DEVICE_ENCRYPTION_KEY] =
            TransactionManager.ENABLED_FALLBACK_VALUE
    }
    if (serverMode) {
        // this will work only with AGPA/GPA solutions
        config[TransactionManager.DEVICE_LISTEN_KEY] = TransactionManager.ENABLED_VALUE
    }

    if (Patterns.IP_ADDRESS.matcher(ipAddress).matches() || serverMode) {
        config[PsdkDeviceInformation.DEVICE_CONNECTION_TYPE_KEY] = "tcpip"
        config[PsdkDeviceInformation.DEVICE_SERIAL_NUMBER_KEY] =
            PsdkDeviceInformation.ACCEPT_ANY_DEVICE_VALUE
        if (!serverMode) {
            config[PsdkDeviceInformation.DEVICE_ADDRESS_KEY] = ipAddress
        }
    }
    config[PosInformation.DEVICE_ID_KEY] = "PSDK_EMULATOR"
    // this is needed only for off device solutions
    // which does not want the auto scan feature provided by PSDK
    // incase of IP address change, PSDK will scan the subnet to identify the terminal if value
    // is set to dynamic
    if (networkScanOnIPChange) {
        config[PsdkInitializationConstants.NETWORK_CONFIGURATION_KEY] =
            PsdkInitializationConstants.NETWORK_CONFIGURATION_DYNAMIC_VALUE
    } else { 
        config[PsdkInitializationConstants.NETWORK_CONFIGURATION_KEY] =
            PsdkInitializationConstants.NETWORK_CONFIGURATION_STATIC_VALUE
    }

    return config
}
```

{% endcode %}

If you have set the VHQ Device ID during initialization (SCA GSC), can can check the status of it as part of the **handleStatus**

{% code overflow="wrap" lineNumbers="true" %}

```java
private inner class PSDKListener : CommerceListenerAdapter() {

    override fun handleStatus(responseStatus: Status) {
        eventReceived(responseStatus.status, responseStatus.type, responseStatus.message)
        when (responseStatus.type) {
            Status.STATUS_INITIALIZED -> {
                when (responseStatus.status) {
                    StatusCode.SUCCESS -> {
                        // Initialization was successful.
                        // If information needs to be shown to POS Operator, text in status.message can be shown.


                        // deviceInformation will work be available for AGPA/GPA solutions at this point, for SCA we will get
                        // device information after a successful login
                        logDeviceInformation(paymentSdk.deviceInformation)
                    }
                    StatusCode.CONFIGURATION_REQUIRED -> {
                        // Need to set IP address or some other initialization parameter and
                        // call initializeFromValues() api
                        System.out.println(TAG, "CONFIGURATION_REQUIRED")
                    }
                    StatusCode.DEVICE_CONNECTION_FAILED,
                    StatusCode.DEVICE_ERROR,
                    StatusCode.DEVICE_REJECTED_PAIRING -> {
                        // Call teardown() API and initiate re-connect logic.
                        paymentSdk.tearDown()
                    }
                    else -> {
                        System.out.println(TAG, "INIT Failed : " + responseStatus.status)
                    }
                }
            }

            Status.STATUS_TEARDOWN -> {
                // This event was fired for teardown. Update state to unknown.
                when (responseStatus.status) {
                    StatusCode.SUCCESS -> {
                        // if under reconnect sequence, call initialize() as background task
                        // or
                        // show UI to operator to get confirmation for calling initialize() API.
                    }
                }
            }

            Status.STATUS_SETUP_COMPLETE -> {
                // This event was fired for setup complete.
            }

            Status.STATUS_ERROR -> {
                // This event was fired for error scenario.
            }
        }

    }
}
```

{% endcode %}
{% endstep %}

{% step %}

## Connect a new terminal or reset existing connection

If you have already connected to a terminal, and now you want to connect to a new terminal, then the old terminal must be forgotten first. Follow the procedure below to forget the current terminal and connect to a new terminal:

Example: In the situation where a previously connected device is being replaced, if the logical ID of the new device as assigned by VHQ is different from the original logical ID, or if the original device did not have a logical ID, then the old device information must be wiped out of persistent storage and initialized with a configuration which contains the new information.

* Use [PaymentSdk.getDeviceInformation() ](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdkbase#getdeviceinformation)to get the current terminal's information record.
* Call [**paymentSdk.UseDevice(PsdkDeviceInformation, false)**](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdkbase#usedevice-psdkdeviceinformation-boolean) API by passing the device information object retrieved in step 1.
* This will erase the persisted information of the current terminal.
* Once the persisted information is erased , we can call the [**initializeFromValues()**](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdkbase#initializefromvalues) API with new connection details.

```java
// Sample to handle connection to new device
// Forgetting information about connection. 
{ 
    PsdkDeviceInformation current = mPaymentSdk.getDeviceInformation() 
    if (!current) { 
       // there is no known last device return 
   } 
   // Forget current device 
   mPaymentSdk.UseDevice(current, false) 
}
```

{% endstep %}

{% step %}

## Connect to multiple terminals with AGPA

PSDK can communicate with multiple terminals, below are the steps for connecting to multiple terminals.

* POS software is expected to instantiate a separate instance of PSDK for each terminal by passing an instance id to the [*createWithInstanceId*](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdk) API
* Once an instance id has been set, the POS is expected to remember this id and use it when initializing psdk in the future to retrieve the saved terminal information.
* A unique listener should be set in each PSDK instance, in-order to receive event notifications. If you want to set the same listener for all the PSDK instances, one suggestion is for you to introduce an id property in your [CommerceListener](https://docs.verifone.com/psdk-api-latest/android-java/index/commercelistener2) implementation, and use that to identify the events received. Please refer below API usage

paymentSDK.createWithInstanceId(Context context, String instanceId)
{% endstep %}

{% step %}

## Connection Recovery/Maintenance

When the connection between the POS and Payment terminal is lost, PSDK tries to re-establish the connection using an in-built mechanism for 2 seconds, if PSDK is not able to re-establish connection automatically it invokes the required callback as part of the CommerceListener2 object which was registered.

Example,

* If the connection is lost during a transaction, **handlePaymentCompletedEvent** will be invoked with **StatusCode.DEVICE\_CONNECTION\_LOST** (-5).
* If the connection is lost when POS is idle , **handleNotificationEvent** might be invoked with **StatusCode.DEVICE\_CONNECTION\_LOST** (-5).

Recommendation is to check and handle the disconnect status in all relevant callbacks.

Once you receive the connection lost event.

* invoke [**teardown()**](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdkbase#teardown) API to reset the connection handling in PSDK.
* wait for [**STATUS\_TEARDOWN**](https://docs.verifone.com/psdk-api-latest/android-java/index/status) in handleStatus callback.
* invoke [**initialize()**](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdkbase#getcommercelistener) API via operator interaction or background task.
* wait for [**STATUS\_INITIALIZED**](https://docs.verifone.com/psdk-api-latest/android-java/index/status) Status with **StatusCode.SUCCESS** (0) to confirm connection is re-established.

Below code sample shows how to handle a disconnect and automatically try and reconnect back to the terminal or payment application

private inner class PSDKListener : CommerceListenerAdapter() { // Disconnect function which can be called in the CommerceListener2 callbacks. internal fun handleDisconnect(statusCode: Int, type: String, message: String?) { when (statusCode) { StatusCode.DEVICE\_CONNECTION\_LOST -> { teardown() } } }

{% code overflow="wrap" lineNumbers="true" %}

```java
    // Sample callback
    override fun handleNotificationEvent(event: NotificationEvent) {
        handleDisconnect(event.status, event.type, event.message)
    }

    // If handling auto-reconnect
    override fun handleStatus(status: Status) {
        when (status.type) {
            Status.STATUS_TEARDOWN -> {
                // This event was fired for teardown. Update state to unknown.
                when (status.status) {
                    StatusCode.SUCCESS -> {
                        // Create conditional code for re-connect sequence
                        // if under reconnect, call initialize() as background task
                        // or
                        // show UI to operator to get confirmation for calling initialize() API.
                    }
                }
            }
        }
    }
```

{% endcode %}

}

#### Connection Status

Once [**initialize()**](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdkbase#getcommercelistener) or [**initializeFromValues()**](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdkbase#initializefromvalues) API is called, PSDK will return the status of the API call as part of the **handleStatus** callback in the [CommerceListener2](https://docs.verifone.com/psdk-api-latest/android-java/index/commercelistener2)

The Status Type should be Status.STATUS\_INITIALIZED

If the connection was successful **Transaction Manager State** would become [TransactionManagerState.NOT\_LOGGED\_IN](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanagerstate) or if the connection failed **Transaction Manager State** would be [TransactionManagerState.UNKNOWN](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanagerstate).
{% endstep %}

{% step %}

## Merchant Information

After the connection is established, [TransactionManager](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanager) and [PsdkDeviceInformation](https://docs.verifone.com/psdk-api-latest/android-java/index/psdkdeviceinformation) would be created as part of the [PaymentSDK](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdk) instance. POS can use [PsdkDeviceInformation](https://docs.verifone.com/psdk-api-latest/android-java/index/psdkdeviceinformation) and [DeviceVitals](https://docs.verifone.com/psdk-api-latest/android-java/index/devicevitals) to access some fundamental details about the terminal solution it is paired with.

In [PsdkDeviceInformation](https://docs.verifone.com/psdk-api-latest/android-java/index/psdkdeviceinformation) , the Merchant details is available only for AGPA and GPA solutions

[DeviceVitals](https://docs.verifone.com/psdk-api-latest/android-java/index/devicevitals) is available only for AGPA and GPA solutions

The most relevant information from the above can be showing via the POS application for diagnostics purpose.

```java
fun logMerchantInformation(deviceInfo: PsdkDeviceInformation){
    val merchantList = deviceInfo.merchantConfig 
    val sb = StringBuilder()
    sb.apply {
        merchantList.forEach {
            append("\n")
            append((it?.merchantName ?: "Merchant"))
            append("\n")
            if (it?.acquirers?.size ?: 0 > 0) {
                it?.acquirers?.forEach { acquirer ->
                    append("Acquirer Name: " + (acquirer?.acquirerName ?: "Not Set")).append("\n")
                    append("Acquirer Id: " + (acquirer?.acquirerId ?: "Not Set")).append("\n")
                    append("Merchant Id :" + (acquirer?.merchantId ?: "Not Set")).append("\n")
                    append("Terminal Id :" + (acquirer?.acquirerPoiid ?: "Not Set")).append("\n")
                }
            }

            if (it?.currencies?.size ?: 0 > 0) {
                append("\n").append("Currencies\n")
                it?.currencies?.forEach { currency ->
                    append((currency)).append("\n")
                }
            }

            if (it?.alternativePaymentMethods?.size ?: 0 > 0) {
                append("\n").append("APM Details").append("\n")
                it?.alternativePaymentMethods?.forEach { apms ->
                    append((apms.displayName)).append("\n")
                }
            }

            append("\n")
            it?.config?.forEach { (key, value) ->
                append("$key\n ${value?:"NA"}").append("\n\n")
            }
        }
    }
}
```

{% hint style="info" %}
**Note**: the payment application details and logical device id will be available after login, please check login codelabs for details
{% endhint %}
{% endstep %}

{% step %}

## Exception Handling

This section is mainly for OffDevice integrations were POS is connected to Payment Solution over IP or other communication channels.

*Initialization failure is highly unlikely for OnDevice solutions, but if you do get an initialization failure, it is most likely because payment app is has not launched or is busy, suggestion is to re-try in initialization in the background till you get a success call, or you reach a predefined timeout please keep in mind that you need to wait for the previous initialize call to invoke handleStatus() callback with the result before trying again. Recommended timeout is 30 secs (if previous initialize call is not complete reset the counter and wait for next loop). If the connection is still not established, it is best to prompt the user to restart the device to check if it is recovered, if restart does not fix the issue, we might have to contact Help Desk for further assistance.*

#### Scenario

When [**initialize()**](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdkbase#getcommercelistener) or [**initializeFromValues()**](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdkbase#initializefromvalues) API gives us a negative **StatusCode** for **Status.STATUS\_INITIALIZED**.

This scenario mostly occurs if

* The POS is unable to connect over IP due to configuration/environment.
* The payment terminal is not listening for a connection as it has not completed its boot sequence.
* Payment terminal is not configured properly.
* There is a change in POID unexpectedly resulting in cache configuration mismatch error with status code (-33)

**Note:** ***There are other corner cases were this could happen***

*Solution*\*

Recommendation is to call [**teardown()**](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdkbase#teardown) API after the Initialization status is received under [**handleStatus**](https://docs.verifone.com/psdk-api-latest/android-java/index/commercelistener2#handlestatus-status) callback, then call [**initialize()**](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdkbase#getcommercelistener) **or** [**initializeFromValues()**](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdkbase#initializefromvalues) API with the right configuration.

If the [**initialize()**](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdkbase#getcommercelistener) call is taking too long, and you would like to abort the current [**initialize()**](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdkbase#getcommercelistener) call , please call [**teardown()**](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdkbase#teardown) to stop PSDK from continuing to try and establish connection with the terminal, wait for the [**handleStatus()**](https://docs.verifone.com/psdk-api-latest/android-java/index/commercelistener2#handlestatus-status) to return an event saying teardown was successful before calling the initialize api again.

{% code overflow="wrap" lineNumbers="true" %}

```java
private inner class PSDKListener : CommerceListenerAdapter() {
    fun handleDisconnect(status: Int, type: String, message: String?) {
        when (status) {
            StatusCode.DEVICE_CONNECTION_LOST,
            StatusCode.DEVICE_CONNECTION_FAILED,
            StatusCode.DEVICE_ERROR,
            StatusCode.DEVICE_REJECTED_PAIRING -> {
                Log.i(TAG, "Event Status : Device Connection Lost")
                paymentSdk.tearDown()

            }
        }
    }
    
    override fun handleNotificationEvent(event: NotificationEvent) {         
        handleDisconnect(event.status, event.type, event.message)
    }
    
    override fun handleStatus(response: Status) {
        when (response.type) {
            Status.STATUS_INITIALIZED -> {
                when (response.status) {
                    StatusCode.SUCCESS -> {
                        // Initialization was successful.
                        // If information needs to be shown to POS Operator, 
                        // text in status.message can be shown.
                    }
                    StatusCode.CONFIGURATION_REQUIRED -> {
                        // If this status is returned it means additional parameters 
                        //possibly IP address of the Payment Terminal needs to be provided.
                    }
                    StatusCode.DEVICE_NOT_FOUND, StatusCode.DEVICE_NOT_READY -> {
                        // Call initialize() API again to retry.
                    }
                    StatusCode.DEVICE_CONNECTION_FAILED,
                    StatusCode.DEVICE_CONNECTION_LOST,
                    StatusCode.DEVICE_ERROR -> {
                        // Call teardown() API and indicate re-connect logic.
                    }
                    else -> {
                        // Call teardown() API and indicate re-connect logic.
                    }
                    
                    StatusCode.CACHED_CONFIGURATION_MISMATCH -> {
                       // 1.Call teardown() API 
                       // 2. Call UseDevice() API to clear POS cache using API
                       // Please refer reset settings on clearing terminal configurations
                     
                       // 3.Call initialize() API when teardown is success.
                    }
                }
            }
            Status.STATUS_TEARDOWN -> {
                // This event was fired for teardown. Update state to unknown.
                when (response.status) {
                    StatusCode.SUCCESS -> {
                        // Create conditional code for re-connect sequence
                        // if under reconnect, call initialize() as background task
                        // or
                        // show UI to operator to get confirmation for calling initialize() API.
                    }
                }
            }
        }
    }
}
```

{% endcode %}

#### Error Codes and Suggested Actions

* **DEVICE\_NOT\_FOUND (-2)**
  * Action: Call `initialize` API after checking the connection and confirming the terminal is operational.
* **DEVICE\_NOT\_READY (-3)**
  * Action: Call `initialize` API after confirming the terminal is operational.
* **DEVICE\_CONNECTION\_FAILED (-4)**
  * Action: Call `tearDown` API followed by `initialize` API.
* **DEVICE\_CONNECTION\_LOST (-5)**
  * Action: Call `tearDown` API followed by `initialize` API.
* **DEVICE\_ERROR (-8)**
  * Action: Call `tearDown` API followed by `initialize` API.
* **DEVICE\_REJECTED\_PAIRING (-9)**
  * Action: Check device and network settings for invalid configuration.
* **CACHED\_CONFIGURATION\_MISMATCH (-33)**
  * Action: Clear the cache and retry the connection.
    {% 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/connect-to-a-terminal.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.
