> 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/standard-payments.md).

# Standard Payments

{% columns %}
{% column width="41.66666666666667%" %} <i class="fa-clock">:clock:</i> 14 minutes reading time\ <i class="fa-calendar">:calendar:</i> Last updated: 23rd November, 2023
{% endcolumn %}

{% column width="24.999999999999986%" %}

{% endcolumn %}

{% column %}
✅ Sale

✅ Refund

✅ Void

✅ Pre-Auth
{% endcolumn %}
{% endcolumns %}

{% stepper %}
{% step %}

### Introduction

This code lab describes steps to perform a sale transaction using **Semi Integrated Payments** — the standard PSDK integration mode where the SDK manages the complete payment flow and returns only the final result to the POS. For direct POS control over each step of the transaction, see the [Fully Integrated (FI) Payments](/psdk-latest/reference-material/code-labs/fi-payments.md) code lab.

#### What you should already know

* The device you will be using for integration.
* Setting up the device and test environment for performing transactions.
* Initialization and Login with PSDK on the POS 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 %}

### Sale

A sale transaction can be performed only within a session this can be validated by the POS application by checking the **TransactionManagerState** state is [TransactionManagerState.SESSION\_OPEN](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanagerstate)

Multiple payments can occur within a single session, but a session should be ended before a new cart/order is started.

This section covers the entire process of a sale transaction. Below sample code shows how to perform payment ...

```java
    //Start a session to be able to perform a sale transaction
    if (paymentSdk.transactionManager.state == TransactionManagerState.LOGGED_IN) {
            transactionManager.startSession(null)
        }
    // handling start session response in the CommerceListenerAdapter
    override fun handleTransactionEvent(event: TransactionEvent) {
            when (event.type) {
                CommerceEvent.SESSION_STARTED -> {
                    if (event.status == StatusCode.SUCCESS) {
                        // "Session Start Success"
                        // Session is open, you can proceed with the payment
                    } else {
                        // "Session Start Failed", event.message() will have the reason for failure
                    }
                }
            }
        }
    // when Session is open, you can proceed with the payment
    if (paymentSDK.transactionManager.state == TransactionManagerState.SESSION_OPEN) {
        //Configure amounts and other payment properties before starting.
        //Creating a Payment also creates an empty AmountTotals object in the requested amounts.
        Payment payment = Payment.create();
        AmountTotals amountTotals = AmountTotals.create(true);

        //To set the subtotal which is mandatory field
        amountTotals .setSubtotal(ConversionUtility.parseAmount(8.00));
        //To set the general tax amount which is optional
        amountTotals .setTax(ConversionUtility.parseAmount(1.00)); 
        //To set the amount that is being paid as a tip or gratuity which is optional field
        amountTotals .setGratuity(ConversionUtility.parseAmount(1.00));
        //To set the grand total, which is (subtotal + tax(es) + gratuity + any other amounts)
        amountTotals .setTotal(ConversionUtility.parseAmount(10.00));

        //It is required to set the amount to load, for the customer to make a payment
        payment.setRequestedAmounts(amountTotals);

        //To use a specific payment type, you can set the PaymentType as per requirement
        payment.setRequestedPaymentType(PaymentType.CREDIT);

        //The Presentation method is another optional field which the POS/ECR can use to control the card which is presented during the payment.
        ArrayList<PresentationMethod> presentationMethods = new ArrayList<PresentationMethod>();
        //Below mentioned are the various card presentation methods that can be used during a payment
        //Using an EMV chip
        presentationMethods.add(PresentationMethod.CHIP); 
        //Using Magnetic Stripe card
        presentationMethods.add(PresentationMethod.MAG_STRIPE);
        //Using a contactless card for tap
        presentationMethods.add(PresentationMethod.CTLS_CARD); 
        //For Manual entry of the card 
        presentationMethods.add(PresentationMethod.KEYED);  
        //Set the requested card presentation method to any of the above mentioned options
        payment.setRequestedCardPresentationMethods(presentationMethods); 

        //Set the order type (optional) to fulfill this payment if you have added PresentationMethod.KEYED in setRequestedCardPresentationMethods()
        //Below are the commonly used order types which can be set during payment.

        //OrderType.MOTO - Order type as Mail Order Telephone Order
        //OrderType.MAIL - Order type as Mail
        //OrderType.PHONE - Order type as Phone
        payment.setOrderType(OrderType orderType) 

        //During the payment request, you can also set the following fields which are optional
        //Set local payment ID for managing the payment events. This enables a PaymentCompletedEvent to be matched using your custom unique identifier.
        // This field currently works only with AGPA 
        payment.setLocalPaymentId(String paymentId) 

        //Set the InvoiceID for the transaction 
        //For SCA solutions please use 6 digit representation for the Invoice.
        payment.setInvoice(String invoice) 

        //Set SaleNote value for transaction, this can be used to query the transactions at a later point.
        // This only works for AGPA solutions.
        payment.setSaleNote(String saleNote) 

        //Set CustomerNote value for transaction, this can be used to query the transactions at a later point.
       // This only works for AGPA solutions.
        payment.setCustomerNote(String customerNote)

        //Start a payment for the current transaction
        Status s = transactionManager.startPayment(payment);

    }
    
```

Notifications generated during a sale Transactions

* There are notifications which are generated during a sale transaction which can help cashier to know the progress of the sale transaction.
* Below are the few important notification events received during the sale transaction. These notifications are applicable only for AGPA. For SCA solutions, notifications will be of type **NotificationType.other.**`event.getMessage()` will have the message that can be displayed to the operator. There are various notifications:
  * **NotificationType.WAITING\_FOR\_CARD -** Triggered when there is a request for card input.
  * **NotificationType.CARD\_PRESENTED -** Triggered when the card is presented for payment.
  * **NotificationType.HOST\_STARTING -** Triggered when the communication with the host has started and is now in progress.
  * **NotificationType.HOST\_RESPONSE\_RECEIVED -** Triggered when the host response is received.
  * **NotificationType.TRANSACTION\_OUTCOME -** Triggered when the transaction is completed.
* The notifications generated can be handled in the listener [**handleNotificationEvent(NotificationEvent event)**](https://docs.verifone.com/psdk-api-latest/android-java/index/commercelistener2#handlenotificationevent-notificationevent) which can be used to notify the user/cashier for the events.
* Please refer below code snippet for handling notifications

  ```java
  @Override // Overridden from the CommerceListenerAdapter
  public void handleNotificationEvent(NotificationEvent event) {
      // TransactionManagerState.PAYMENT_PROCESSING indicates the notification is sent during a transaction
      // event.getNotificationType contains the current stage in the transaction flow. 
      event.getNotificationType();

      //getStatus() is used to get the status for this particular event. 
      //A status means success, any other status is a failure. 
      //If event.getStatus() == StatusCode.SUCCESS, then it indicates that the transaction is progressing as expected
      event.getStatus(); 

      //To get the user-readable message of the status of the sale transaction.
      event.getMessage(); 

  }
  ```

Once the payment has been initiated, the payment application handles everything, including consumer UI, card reader interaction, and host authorization.We just need to wait for the TransactionEvent.TRANSACTION\_PAYMENT\_COMPLETED event and check the authorization result in the response to find the transaction outcome in handlePaymentCompletedEvent callback.

Below is the code snippet to handle the payment response in [**handlePaymentCompletedEvent**](https://docs.verifone.com/psdk-api-latest/android-java/index/commercelistener2#handlepaymentcompletedevent-paymentcompletedevent):

```java
@Override // Overridden from the CommerceListenerAdapter
public void handlePaymentCompletedEvent(PaymentCompletedEvent event) 
{
    if (TransactionEvent.TRANSACTION_PAYMENT_COMPLETED.equals(event.getType())) {
        if (event.getStatus() == StatusCode.SUCCESS) {
            Payment payment = event.getPayment();

            //AuthorizationResult is used to determine the final result of the payment, if it was approved, 
            //canceled or failed. getAuthResult() gets the result of transaction authorization.
            AuthorizationResult authorizationResult = payment.getAuthResult();

            //To get the ways by which the cardholder is verified.
             payment.getAuthorizationMethod(); 

            //Below are the few authorization methods which are commonly used during payment
            //AuthorizationMethod.PIN - when user enters the PIN
            //AuthorizationMethod.SIGNATURE - when user signs either digitally or physically.
            //AuthorizationMethod.NONE - when user is not required to perform any additional actions.

            //To get the payment type used to complete this payment
            payment.getPaymentType();
            //PaymentType.CREDIT - when user requires a credit transaction
            //PaymentType.DEBIT - when user requires a debit transaction

            //To get the descriptive text accompanying the authorization code from the host.
            //This is usually present when the transaction has failed authorization, providing the reason for the failure.
            payment.getAuthResponseText();

            //AppSpecificData provided in this Payment response can be used for linked transactions.
            appSpecificData = event.Payment.AppSpecificData;

            //Receipt can be retreived from Payment.getReceipts()
            //Use Receipt.getAsHtml() to get a printable HTML string and Receipt.getAsPlainText() to get the plain text variant of the receipt
            for (HashMap.Entry<ReceiptType, Receipt> entry : receipts.entrySet()) {
                Receipt receipt = entry.getValue(); 
                if (receipt != null) {
                    if (entry.getKey() == ReceiptType.MERCHANT) {
                        String merchantReceipt = receipt.getAsHtml(); 
                    }
                    if (entry.getKey() == ReceiptType.CUSTOMER) {
                        String CustomerReceipt = receipt.getAsHtml(); 
                    }
                }
            }

            //CardInformation contains the information of the card that was used in the transaction
            CardInformation cardInfo = paymentCompletedEvent.getPayment().getCardInformation(); 
            if (cardInfo != null) {
            //Some of the important fields are listed below
                //To get card presentation method
                cardInfo.getPresentationMethod(); 
                 //To get the card brand details
                cardInfo.getPaymentBrand();
                //To get the account type 
                cardInfo.getAccountType(); 
                //Present only with EMV cards, this is the relevant EMV Tags necessary for record keeping. 
                The key is the tag, e.g. “9F26”, and the value is a string encoding of the EMV value.
                for (HashMap.Entry<String,String> entry : cardInfo.getEmvTags().entrySet()) {
                    entry.getKey().append(": ").append(entry.getValue());
                } 
            }

            //If the authorization method is signature and the signature was captured on the device
            Image image = payment.getSignature();
            image.getFormat(); //get signature format
            image.getData(); //get signature data

            //Below are the parameters which can be extracted and used further to query the transaction when required. 
            //These parameters value will be available if the values are set while making payment.

            //To get the local payment id set during payment
            payment.getLocalPaymentId();

            //To get the ID of the invoice set during payment
            payment.getInvoice();

            //To get Reference/Customer Note set during payment
            payment.getCustomerNote();

            //To get Reference/Sale Note set during payment
            payment.getSaleNote();

            //To get the acquirer terminal id
            payment.getTerminalId();

        } else {

        // Handle failure by examining the status code and message.
        }
    }
}
```

#### EndSession

When the payment is completed, end the session by calling [TransactionManager.endSession()](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanager#endsession) and handle status in listener callback [handletransactionevent()](https://docs.verifone.com/psdk-api-latest/android-java/index/commercelistener2#handletransactionevent-transactionevent)

```java
    if (paymentSDK.transactionManager.state == TransactionManagerState.SESSION_OPEN) {
      //Ends the open session 
      Status status = paymentSDK.transactionManager.endSession();
    }

    //handling end session response 
    @Override
    public void handleTransactionEvent(TransactionEvent event) {
     switch (event.getType()) {
                case CommerceEvent.SESSION_ENDED -> {
                    if (event.getStatus() == StatusCode.SUCCESS) {
                        // "Session End Success"
                        // Session is closed
                    } else {
                        // "Session End Failed"
                    }
                }
        }
    }
```

{% endstep %}

{% step %}

### Refund

A refund returns the funds from the merchant to the customer. There are mainly two important types of refunds - linked and unlinked. Only one refund is performed at a time, though multiple refunds may be performed within the same session.

#### Linked Refund

A **linked refund** has reference information to the original payment. To link a refund, either set the App Specific Data from the original payment on a new Payment object i.e., [**Payment.getAppSpecificData()**](https://docs.verifone.com/psdk-api-latest/android-java/index/payment#getappspecificdata) , or less commonly, send the original Payment object directly.

[**getAppSpecificData**](https://docs.verifone.com/psdk-api-latest/android-java/index/payment#getappspecificdata) stores the information necessary to perform other operations on this payment at a later time, such as, completing a pre-auth or refunding a specific payment.

[**setAppSpecificData**](https://docs.verifone.com/psdk-api-latest/android-java/index/payment#setappspecificdata-string) sets the data from a previous payment object to perform another operation on that payment or to look up a specific payment when querying transactions.

#### Unlinked Refund

An **unlinked refund** is a simple amount that is pushed from the merchant account into the customer’s account. Simply create a new Payment object for this type of refund and set the requested amount totals ([**Payment.setRequestedAmounts(totals)**](https://docs.verifone.com/psdk-api-latest/android-java/index/payment#setrequestedamounts-amounttotals)).

Every transaction is wrapped within a session so please ensure that the state is **TransactionManagerState.SESSION\_OPEN**.

This section covers the entire process of a refund transaction. Below sample code shows how to perform **Refund**

```java
 //start a session to be able to perform a refund, refer sale transaction code snippet for details
    if (paymentSDK.transactionManager.state == TransactionManagerState.SESSION_OPEN) {
        // Session is open, you can proceed with the refund

        Payment payment = Payment.create();
        //For an unlinked refund it is required to set the requested amount to be refunded
        AmountTotals requestedAmounts = payment.setRequestedAmounts(totals); // Totals being the amount from the original sale transaction.
        //For a linked refund set the app specific data 
        payment.setAppSpecificData(getAppSpecificData());
        //Once you choose to perform either a linked refund or unlinked refund, process the refund for the specific payment,
        // use processRefund method which returns the status object, indicating if the refund command was issued properly.
        Status s = transactionManager.processRefund(payment);
    }
```

Once the refund is initiated, notificationevent will be sent to the ECR to indicate the progress of the transaction. The CommerceListener receives a **PaymentCompletedEvent** with type **TransactionEvent.TRANSACTION\_PAYMENT\_COMPLETED** once the refund is complete. Below is the code snippet to handle the refund response in [**handlePaymentCompletedEvent**](https://docs.verifone.com/psdk-api-latest/android-java/index/commercelistener2#handlepaymentcompletedevent-paymentcompletedevent):

```java
@Override
public void handlePaymentCompletedEvent(PaymentCompletedEvent event) {
    if (TransactionEvent.TRANSACTION_ENDED.equals(event.getType())) {
        if (event.getStatus() == StatusCode.SUCCESS) {
            // AuthorizationResult is used to determine the final result of the payment, if it was approved, canceled, or failed.
            AuthorizationResult authorizationResult = payment.getAuthResult();
            // To get the ways by which the payment is authorized
            PaymentMethod authorizationMethod = payment.getAuthorizationMethod();
            // To get the payment type used to complete this payment
            PaymentType paymentType = payment.getPaymentType();
            // To get the descriptive text accompanying the authorization code from the payment processor.
            // This is usually present when the transaction has failed authorization, providing the reason for the failure. This is optional.
            String authResponseText = payment.getAuthResponseText();
            // Additional fields can also be retrieved. Please refer to the payment codelabs for more details.
        }
    }
```

Once you handle the [**handlePaymentCompletedEvent**](https://docs.verifone.com/psdk-api-latest/android-java/index/commercelistener2#handlepaymentcompletedevent-paymentcompletedevent), you can end the session. Please refer to the sale transaction code snippets on how to end the session.
{% endstep %}

{% step %}

### Void

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 code lab describes steps for correctly implementing a void transaction feature.

#### **1. Retrieving App Specific Data**

The first step to implement void functionality is to get the App Specific Data of a successful sale transaction.

#### **2. Process Void**

Next, you can create a new payment object and set the appSpecific data value that we obtained from original sale transaction.

```java
    //check if session is open
    boolean isSessionOpen = paymentSdk.getTransactionManager().getState() == TransactionManagerState.SESSION_OPEN;
    if(isSessionOpen){
        Payment payment = Payment.create();
        payment.setAppSpecificData(appSpecificData);//from completed sale transaction
        paymentSdk.getTransactionManager().processVoid(payment);
    }
```

#### **3. Handling the Void Event**

To make sure the void transaction was successful, you can check its status at the same handlePaymentCompletedEvent callback again:

```java
    @Override 
    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.
            }
        }
    }
    //End the session after void is complete.Please refer to the sale transaction code snippets on how to end the session.
```

{% endstep %}

{% step %}

### Pre-Auth

Pre-authorization is a feature that places a hold on your customer’s card for a specified amount based on the expected sales amount.

#### Pre Auth Top Up

If the final amount of the transaction is exceeded the pre-authorization amount, then a top-up can be done. A top-up transaction increments the pre-authorized amount and requests the authorization of the incremented amount. A merchant may process one or more top-up transactions.

#### Pre Auth Completion

The Pre-authorization Completion feature retrieves funds that have been locked and prepare them for settlement into the merchant’s account. This code lab describes steps for correctly implementing a pre auth transaction from beginning to end.

#### Starting a Pre Auth Transaction

This section covers the steps to start a pre auth transaction on your terminal

**1. Pre-Authorisation Transaction**

A pre-auth transaction is done in the same way as a sale transaction. But for initialising pre-authorization, you have to set TransactionType to **TransactionType.PRE\_AUTHORIZATION**. Please note that the following code must be called after session has started.

```java
    // Check if the session is open
    // Create the payment and set the transaction type to pre-authorization.
    boolean isSessionOpen = paymentSDK.getTransactionManager().getState() == TransactionManagerState.SESSION_OPEN;
    if (isSessionOpen) {
        Payment payment = Payment.create();
        payment.setTransactionType(TransactionType.PRE_AUTHORIZATION);
        // Configure amounts and other payment properties before starting. 
        AmountTotals amountTotals = AmountTotals.create(true);
        amountTotals.setTotal(Decimal.valueOf(BigDecimal.valueOf(280)));//assuming the sale amount to be 280, for example.
        payment.setRequestedAmounts(amountTotals);

        transactionManager.startPayment(payment);
        // Listener receives the PaymentCompletedEvent.
    }
```

**2.Pre- Auth Top Up**

Pre Auth Top up comes handy when we want to update the amount of hold on customer's card with a different amount, based on a new service being added, or a previous service being cancelled. If the Initial Pre - Auth amount is 100, and the customer wants to add a service which costs 50 units of currency, then the pre-auth top-up amount should be 150 (100+50). Similarly, if the customer's card is blocked for 200 USD, for example, and he/she wants to cancel a service that was previously paid for, (priced at 30 USD, eg), we can use Pre-Auth Top Up with Amount 200-30 =170 USD.

```java
    // Check if the session is open
    // Create the payment object
    if (isSessionOpen) {
        Payment payment = Payment.create();
        // For pre-auth operations of increment, decrement, extend, preauth,set the transaction type to pre-authorization update and configure the requested amounts
        payment.setTransactionType(TransactionType.PRE_AUTHORIZATION_UPDATE);
        AmountTotals amountTotals = AmountTotals.create(true);
        amountTotals.setTotal(Decimal.valueOf(BigDecimal.valueOf(150)));//assuming the required top up amount is 150
        payment.setRequestedAmounts(amountTotals);
        // Set the AppSpecificData from the approved pre-authorization here to link the two.
        payment.setAppSpecificData(appSpecificdataFromPreAuth);
        // Configure the other payment properties before starting.
        paymentSDK.getTransactionManager().startPayment(payment);
        // Listener receives the PaymentCompletedEvent.
    }
```

**3.Pre- Auth Completion**

After configuring the Transaction.PRE\_AUTHORIZATION\_COMPLETION\_TYPE on the transaction object, either pass the original Payment object from the pre-auth or configure a new payment object with the app-specific data from the original pre-auth. This call completes the entire pre-auth transaction.

```java
    //As was done in Pre Auth init, check if the session is open
    //Create the payment object and set the transaction type to pre-authorization completion.
    if (isSessionOpen) {
        Payment payment = Payment.create();
        payment.setTransactionType(TransactionType.PRE_AUTHORIZATION_COMPLETION);
        // Set the AppSpecificData from the approved pre-authorization here to link the two.
        payment.setAppSpecificData(appSpecificDataFromPreAuth);
        // Configure amounts and other payment properties before starting.
        paymentSDK.getTransactionManager().startPayment(payment);
        // Listener receives the PaymentCompletedEvent.
    } else {
        //start session
    }
```

**4.Pre- Auth Cancellation**

```java
    //Check if the session is open
    //Create the payment object
    //Set AppSpecificData from the approved pre-authorization here to link the two.
    if(isSessionOpen){
        Payment payment = Payment.create();
        payment.setAppSpecificData(dataFromPreAuth);
        // Configure amounts and other payment properties before starting.
        paymentSDK.getTransactionManager().processVoid(payment);
        // Listener receives the PaymentCompletedEvent.
    }
```

For partial void, we can simply set the amount that we want to void.

**5. handlePaymentCompletedEvent**

**Allowed Operations**

After pre auth initialisation, we may check which operations are allowed on that payment by calling **getAllowedPaymentOperations** on the payment object inside the **handlePaymentCompletedEvent** callback. If our desired operation is found on the list of allowed operations, we may proceed with the transaction.

**Pre Auth History**

You may wish to show all transactions that the user may have done. It can be done in the following way:

```java
     @Override
     public void handlePaymentCompletedEvent(PaymentCompletedEvent event) {
    if (event.getType() == TransactionEvent.TRANSACTION_PAYMENT_COMPLETED) {
        //determines whether the transactions have been authorised or declined. Refer this in case of Pre Auth Init, Top up and complete transactions
        if (event.getPayment().getAuthResult() == AuthorizationResult.AUTHORIZED) {
        //transaction authorized
        } else  {
        //transaction not authorized
        }

    } else if (event.getType() == TransactionEvent.TRANSACTION_ENDED) {
        //determines whether the void transactions have been successful or declined
        if (event.getPayment().getAuthResult() == AuthorizationResult.VOIDED) {
        //handle a successful void transaction
        } else if (event.getPayment().getAuthResult() == AuthorizationResult.VOID_DECLINED) {
        //handle a failed void transaction
        }
    }

       //To get allowed operations in a particular transaction 
        ArrayList<PaymentOperation> allowedOperations = event.getPayment().getAllowedPaymentOperations();
        if (allowedOperations != null) {
            for (PaymentOperation i : allowedOperations) {
                String operationName = i.name();
                //according to allowed operations, you may proceed with the next step.
                //here is a list of operations that may appear here
                /*CREATED,
                        PRE_AUTHORIZATION_INCREASE_AMOUNT,
                        PRE_AUTHORIZATION_COMPLETION,
                        VOID_TYPE,
                        PARTIAL_VOID,
                        PRE_AUTHORIZATION_EXTEND,
                        GRATUITY_ADJUSTMENT,
                        DELAYED_CHARGE;
                        */
        }
    } else {
        //no operations are allowed further on this payment transaction
    }

            //To get the entire operation history performed
             ArrayList<PaymentOperationHistory> operationHistory = payment.getOperationsHistory();
            if (operationHistory != null) {
                for (PaymentOperationHistory i : operationHistory) {
                    String amount = i.getAmount().toBigDecimal().toString();
                    //can display different values to the customer like amount, authorization status, timestamp etc, for each transaction, shown below

                i.getAmount();//amount
                i.getPaymentOperation().name();//name
                i.getAuthorized();//boolean value
                i.getTimestamp();//timestamp
                }
            } else {
                //no history found on this payment transaction
            }
}
```

Please end the session after the pre-auth operations are complete. Please refer sale transaction code snippet how to end the session.
{% 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/standard-payments.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.
