> 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/advance-flows.md).

# Advance Flows

## Cancel Transaction <a href="#id5" id="id5"></a>

The POS should use the [TransactionManager.abort() ](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanager#abort)method to cancel the transaction in progress. The corresponding [PaymentCompletedEvent.getStatus()](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentcompletedevent#getstatus) will return [StatusCode.ABORTED](https://docs.verifone.com/psdk-api-latest/android-java/index/statuscode) to indicate that it was aborted. If the event does not have this status, then it’s possible that calling abort did not happen in time, and the POS should either reverse the transaction using the [TransactionManager.processVoid()](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanager#processvoid-payment) method, or simply accept the completed result.

## Inline Tipping with Tip Options <a href="#id6" id="id6"></a>

The merchant would like the customer to select a tip from a pre-configured menu, determining how much gratuity should be added to the purchase. This menu can be presented before the card is presented, or after, depending on the POS’ preference.

{% @plantuml/diagram content="    @startuml

```
hide footbox

participant POS order 10
participant POI order 20
actor Customer order 30
|||
group If card presentation is desired first
    POS ->> POI : Start pre-auth payment 
    POI <-> Customer : Perform payment
    ...
    POS <<-- POI : Payment completed event
end
|||
POS ->> POI : Present user options
POI -> Customer : Display tip options
POI <- Customer : Select option
POS <<-- POI : User input event with the selected option
POS -> POS : Update payment amount with selected option.
alt If pre-auth was performed
    POS ->> POI : Start pre-auth completion payment
else Else if payment has not yet been done
    POS ->> POI : Start payment
end
POI <-> Customer : Perform payment
...
POS <<-- POI : Payment completed event
|||
@enduml
```

" %}

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

```java
@Override // Overridden from the CommerceListenerAdapter
public void handleUserInputEvent(UserInputEvent event) {
    if (UserInputEvent.RECEIVED_TYPE.equals(event.getType())) {
        Values valueFromCustomer = event.getValues();
        if (event.getInputType() == InputType.MENU_OPTIONS) {
            if (event.getStatus() == StatusCode.SUCCESS) {
                int selectedIndex = valueFromCustomer.getSelectedIndices()[0];
                // Use selected index to determine which button they selected.
                // In this example, index 0 is 20%, 1 is 15%, etc.
            } // else handle error
        } // else handle other input response
    } // else handle input request from POI
}

final String header = "Please select a tip";
final String[] buttons = new String[] {
        "20%",
        "15%",
        "10%",
        "None"
};
mTransactionManager.presentUserOptions(header, buttons);
```

{% endcode %}
{% endtab %}

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

```kotlin
 // Overridden from the CommerceListenerAdapter
override fun handleUserInputEvent(event: UserInputEvent) {
    if (UserInputEvent.RECEIVED_TYPE.equals(event.getType())) {
        val valueFromCustomer = event.getValues()
        if (event.getInputType() == InputType.MENU_OPTIONS) {
            if (event.getStatus() == StatusCode.SUCCESS) {
                val selectedIndex = valueFromCustomer.getSelectedIndices()[0]
                // Use selected index to determine which button they selected.
                // In this example, index 0 is 20%, 1 is 15%, etc.
            } // else handle error
        } // else handle other input response
    } // else handle input request from POI
}

val header = "Please select a tip"
val buttons = arrayOf("20%", "15%", "10%", "None")
mTransactionManager.presentUserOptions(header, buttons)
```

{% endcode %}
{% endtab %}

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

```swift
// Overridden from the VFICommerceListenerAdapter
override func handle(_ event: VFIUserInputEvent?) {
    var valueFromCustomer = event?.getValues()
    if (VFIInputType.MENUOPTIONS == event?.getInputType()) {
        if (VFIStatusCodeSuccess == event?.getStatus()) {
            var selectedIndex = valueFromCustomer?.getSelectedIndices()[0]
            // Use selected index to determine which button they selected.
            // In this example, index 0 is 20%, 1 is 15%, etc.
        } // else handle error
    } // else handle other input response
}

let header = "Please select a tip"
let buttons = ["20%", "15%", "10%", "None"]
sdk.getTransactionManager()?.presentUserOptions(header, buttonLabels: buttons)
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}

<pre class="language-csharp" data-line-numbers data-full-width="true"><code class="lang-csharp"><strong> private readonly EventHandler&#x3C;UserInputEvent> user_input_event_handler_;
</strong>
private void HandleEvent(UserInputEvent event)
{
    if (event.Type == UserInputEvent.RECEIVED_TYPE)
    {
        Values value_from_customer = event.ResponseValues;
        if (event.InputType == InputType.MENU_OPTIONS)
        {
            if (event.Status == StatusCode.SUCCESS)
            {
                int selected_index = value_from_customer.SelectedIndices[0];
                // Use selected index to determine which button they selected.
                // In this example, index 0 is 20%, 1 is 15%, etc.
            } // else handle error
        } // else handle other input response
    } // else handle input request from POI
}

// ...
// Link event handler after initialization is complete but before requesting input
user_input_event_handler_ = async (sender, args) =>
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
        () => HandleEvent(args));
};
payment_sdk_.TransactionManager.HandleUserInputEvent += user_input_event_handler_;

// ...
// Present the tip options.
string header = "Please select a tip";
string[] buttons = new string[] {"20%", "15%", "10%", "None"};
payment_sdk_.TransactionManager.PresentUserOptions(header, buttons);
</code></pre>

{% endtab %}

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

```cpp
// Overridden from the CommerceListenerAdapter
void handleUserInputEvent (
    const std::shared_ptr<verifone_sdk::UserInputEvent>& event) override {
    if (event->getType() == verifone_sdk::UserInputEvent::RECEIVED_TYPE) {
      auto values = event->getValues();
      if (event->getInputType() == InputType::MENU_OPTIONS) {
        if (event->getStatus() == StatusCode::SUCCESS) {
          auto selected_indices = event->getValues()->getSelectedIndices();
          // Use selected indices to determine which button they selected.
          // In this example, index 0 is 20%, 1 is 15%, etc.
        } // else handle error
      } // else handle other input response
    } // else handle input request from POI
}
// ...


std::vector<std::string> options = {"20%", "15%", "10%", "None"};
auto status = psdk->getTransactionManager()->presentUserOptions(
    "Please select a tip", options);
if (status->getStatus() == verifone_sdk::StatusCode::SUCCESS) {
  //operation initiated successfully
}
```

{% endcode %}
{% endtab %}

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

```aspnet
public void HandleUserInputEvent(UserInputEvent sdk_event)
{
    if (sdk_event.Type == UserInputEvent.RECEIVED_TYPE)
    {
        Values value_from_customer = sdk_event.Values;
        if (sdk_event.InputType == VerifoneSdk.InputType.MENU_OPTIONS)
        {
            if (sdk_event.Status == 0)
            {
                int selected_index = value_from_customer.SelectedIndices[0];
                // Use selected index to determine which button they selected.
                // In this example, index 0 is 20%, 1 is 15%, etc.
            } // else handle error
        } // else handle other input response
    } // else handle input request from POI
}

// ...
// Present the tip options.
string header = "Please select a tip";
string[] buttons = new string[] {"20%", "15%", "10%", "None"};
payment_sdk_.TransactionManager.PresentUserOptions(header, buttons);
```

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

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

* [TransactionManager.presentUserOptions(…)](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanager#presentuseroptions-string-arrayliststring)
* [UserInputEvent.RECEIVED\_TYPE](https://docs.verifone.com/psdk-api-latest/android-java/index/userinputevent)
* [UserInputEvent.getValues()](https://docs.verifone.com/psdk-api-latest/android-java/index/userinputevent#getvalues)
* [UserInputEvent.Values](https://docs.verifone.com/psdk-api-latest/android-java/index/userinputevent)
  {% endhint %}

## Handling Requests for User Input from the Payment Application

There will be times when the POI requires input from the cashier. In these cases, the [CommerceListener](https://docs.verifone.com/psdk-api-latest/android-java/index/commercelistener2) will receive an event of type [UserInputEvent.REQUEST\_TYPE.](https://app.gitbook.com/s/yzyMJNwlQJZoQOIC8vZ8/api/moduleindex-2/_user_input_event_8hpp) The event contains a RequestParameters object, which contains all of the different values and type of request that should be displayed to the cashier. Any time the response is required by the request, the listener must display this information to the cashier for the current flow to proceed. The receiving application must construct a new [Values](https://docs.verifone.com/psdk-api-latest/android-java/index/values) object, populating it with the data received from the cashier, then attach it to the response object from [UserInputEvent.generateUserInputEventResponse()](https://docs.verifone.com/psdk-api-latest/android-java/index/userinputevent#generateuserinputeventresponse), and send it back to the payment application using [TransactionManager.sendEventResponse(response)](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanager#sendeventresponse-commerceresponse).

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

```
actor Cashier order 10
participant POS order 20
participant POI order 30
|||
POS ->> POI : Login
...
POS <<- POI : Request User Input
POS -> POS : Create dialog based on the Request Parameters
Cashier <<- POS : Present dialog
Cashier -> POS : Provide input
POS -> POS : Put input into the Values object
POS -> POS : Attach the values to the response
POS ->> POI : Send event response back to POI. The POI continues the flow.
...
|||
@enduml" %}
```

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

```java
@Override // Overridden from the CommerceListenerAdapter
public void handleUserInputEvent(UserInputEvent event) {
    if (UserInputEvent.REQUEST_TYPE.equals(event.getType())) {
        RequestParameters requestParameters =
                        event.getRequestParameters();
        UserInputEventResponse response = event.generateUserInputEventResponse();
        // Based on requestParameters.getInputType(), present the appropriate dialog.
        // Keep track of the response, it is needed once the input is collected.
    }
}

// Send back the response once the input is collected.
Values responseValues = response.getResponseValues();
// Set the appropriate value on the values object based on the input type.
response.setValues(responseValues);
mTransactionManager.sendInputResponse(response);
```

{% endcode %}
{% endtab %}

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

```kotlin
 // Overridden from the CommerceListenerAdapter
override fun handleUserInputEvent(event: UserInputEvent) {
    if (UserInputEvent.REQUEST_TYPE.equals(event.getType())) {
        val requestParameters = event.getRequestParameters()
        val response = event.generateUserInputEventResponse()
        // Based on requestParameters.getInputType(), present the appropriate dialog.
        // Keep track of the response, it is needed once the input is collected.
    }
}

// Send back the response once the input is collected.
val responseValues = response.getResponseValues()
// Set the appropriate value on the values object based on the input type.
response.setValues(responseValues)
mTransactionManager.sendInputResponse(response)
```

{% endcode %}
{% endtab %}

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

```swift
// Overridden from the VFICommerceListenerAdapter
override func handle(_ event: VFIUserInputEvent?) {
    if (VFIUserInputEventREQUESTTYPE == event?.getType()) {
        var requestParameters: VFIRequestParameters? = event?.getRequestParameters()
        var response: VFIUserInputEventResponse? = event?.generateResponse()
        // Based on requestParameters.getInputType(), present the appropriate dialog.
        // Keep track of the response, it is needed once the input is collected.
    }
}

// Send back the response once the input is collected.
let responseValues = response?.getValues()
// Set the appropriate value on the values object based on the input type.
response?.setValues(responseValues)
sdk.getTransactionManager()?.sendInputResponse(response)
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}

<pre class="language-csharp" data-line-numbers data-full-width="true"><code class="lang-csharp"><strong> private readonly EventHandler&#x3C;UserInputEvent> user_input_event_handler_;
</strong>
private void HandleUserInputvent(UserInputEvent event)
{
    if (event.Type.Value == UserInputEvent.REQUEST_TYPE)
    {
        var request_parameters = event.RequestParameters;
        var response = event.GenerateUserInputEventResponse();
        // Based on requestParameters.getInputType(), present the appropriate dialog.
        // Keep track of the response, it is needed once the input is collected.
    }
}

// ...
// Link event handler after initialization is complete but before requesting input
user_input_event_handler_ = async (sender, args) =>
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
        () => HandleEvent(args));
};
payment_sdk_.TransactionManager.HandleUserInputEvent += user_input_event_handler_;

// ...
// Send back the response once the input is collected.
var responseValues = response.ResponseValues;
// Set the appropriate value on the values object based on the input type.
response.ResponseValues(responseValues);
transaction_manager_.SendInputResponse(response);
</code></pre>

{% endtab %}

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

```cpp
// Overridden from the CommerceListenerAdapter
void handleUserInputEvent (
        const std::shared_ptr<verifone_sdk::UserInputEvent>& event) override {
    if (event->getType() == verifone_sdk::UserInputEvent::REQUEST_TYPE
        && event_->getStatus() == verifone_sdk::StatusCode::SUCCESS) {
      auto request_parameters = event->getRequestParameters();
      auto response = event->generateUserInputEventReponse();
      // Based on requestParameters.getInputType(), present the appropriate dialog.
      // Keep track of the response, it is needed once the input is collected.
    }
}
// ...

// Send back the response once the input is collected.
auto responseValues = response->getResponseValues();
// Set the appropriate value on the values object based on the input type.
response->setResponeValues(responseValues);
psdk->getTransactionManager()->sendInputResponse(response);
```

{% endcode %}
{% endtab %}

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

```aspnet
public void HandleUserInputEvent(UserInputEvent sdk_event)
{
    if (sdk_event.Type == UserInputEvent.REQUEST_TYPE)
    {
        var request_parameters = sdk_event.RequestParameters;
        var response = sdk_event.GenerateUserInputEventResponse();
        // Based on requestParameters.getInputType(), present the appropriate dialog.
        // Keep track of the response, it is needed once the input is collected.
    }
}



// ...
// Send back the response once the input is collected.
var responseValues = response.ResponseValues;
// Set the appropriate value on the values object based on the input type.
response.ResponseValues(responseValues);
payment_sdk_.TransactionManager.SendInputResponse(response);
```

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

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

* [UserInputEvent.REQUEST\_TYPE](https://app.gitbook.com/s/yzyMJNwlQJZoQOIC8vZ8/api/moduleindex-2/_user_input_event_8hpp)
* [UserInputEvent.generateUserInputEventResponse()](https://docs.verifone.com/psdk-api-latest/android-java/index/userinputevent#generateuserinputeventresponse)
* [UserInputEvent.getRequestParameters()](https://docs.verifone.com/psdk-api-latest/android-java/index/userinputevent#getrequestparameters)
* [UserInputEvent.RequestParameters.getInputType()](https://docs.verifone.com/psdk-api-latest/android-java/index/userinputevent#getrequestparameters)
* [TransactionManager.sendEventResponse(response)](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanager#sendeventresponse-commerceresponse)
  {% endhint %}

## Manually Keying in Card Information <a href="#id8" id="id8"></a>

This section describes the procedure for the merchant to manually key in the card information when making a payment. This is required when the card reader is unable to read the card information due to a device malfunction in reading the chip or magnetic strip. In these cases, the [Payment.setRequestedCardPresentationMethods()](https://docs.verifone.com/psdk-api-latest/android-java/index/payment#setrequestedcardpresentationmethods-arraylistpresentationmethod) must be called with the parameter [PresentationMethod.KEYED.](https://docs.verifone.com/psdk-api-latest/android-java/index/presentationmethod) The card information will then be keyed into the terminal.

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

```java
// Please note that creating Payment also creates AmountTotals
Payment payment = Payment.create();
ArrayList<PresentationMethod> presentationMethods = new ArrayList<PresentationMethod>();
presentationMethods.add(PresentationMethod.KEYED);
payment.setRequestedPaymentType(PaymentType.CREDIT);
payment.getRequestedAmounts.setSubtotal(ConversionUtility.parseAmount(8.00)
                           .setTax(ConversionUtility.parseAmount(1.00))
                           .setGratuity(ConversionUtility.parseAmount(1.00))
                           .setTotal(ConversionUtility.parseAmount(10.00));
payment.setTransactionType(TransactionType.PAYMENT);
payment.setRequestedCardPresentationMethods(presentationMethods);
```

{% endcode %}
{% endtab %}

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

```kotlin
 // Please note that creating Payment also creates AmountTotals
val payment = Payment.create()
payment.setRequestedCardPresentationMethods({PresentationMethod.KEYED})
// Configure amounts and other payment properties before starting.
transactionManager.startPayment(payment)
// Listener receives the PaymentCompletedEvent.
```

{% endcode %}
{% endtab %}

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

```swift
var payment = VFIPayment.create()
payment?.setRequestedCardPresentationMethods([
NSNumber(value: VFIPresentationMethod.KEYED.rawValue)])
// Configure amounts and other payment properties before starting.
sdk.getTransactionManager()?.start(payment)
// Listener receives the PaymentCompletedEvent.
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}

<pre class="language-csharp" data-line-numbers data-full-width="true"><code class="lang-csharp"><strong> var payment = new Payment
</strong>{
    RequestedCardPresentationMethods = new List&#x3C;PresentationMethod> { PresentationMethod.KEYED }
    // Configure amounts and other payment properties before starting.
};
transactionManager.StartPayment(payment);
// Listener receives the PaymentCompletedEvent.
</code></pre>

{% endtab %}

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

```cpp
auto payment = verifone_sdk::Payment::create();
payment->setRequestedCardPresentationMethods({verifone_sdk::PresentationMethod::KEYED});
// Configure amounts and other payment properties before starting.
transaction_manager->startPayment(payment);
// Listener receives the PaymentCompletedEvent.
```

{% endcode %}
{% endtab %}

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

```aspnet
var payment = Payment.Create();
payment.RequestedCardPresentationMethods = new List<PresentationMethod> { PresentationMethod.KEYED };
payment_sdk_.TransactionManager.StartPayment(payment);
// Listener receives the PaymentCompletedEvent.
```

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

## Handling External Changes to the Basket/Amount

It is possible for external apps to request changes to the basket and/or amount during four triggers:

<table data-full-width="true"><thead><tr><th width="195">Listener Event</th><th width="546">CP ID</th><th>CP Trigger Class</th></tr></thead><tbody><tr><td><a href="/spaces/yzyMJNwlQJZoQOIC8vZ8/pages/rc25KbD58mrGETtfNtFa">BasketAdjustedEvent</a></td><td>CP_SYSTEM_REQUESTS_BASKET_ADJUSTMENT</td><td><a href="/spaces/yzyMJNwlQJZoQOIC8vZ8/pages/3w62sd0ONzyoduyi9FqR">BasketAdjustmentRequest</a></td></tr><tr><td><a href="/spaces/yzyMJNwlQJZoQOIC8vZ8/pages/igQUBoZUg1DlBzft594l">LoyaltyReceivedEvent</a></td><td>CP_SYSTEM_REQUESTS_LOYALTY</td><td><a href="/spaces/yzyMJNwlQJZoQOIC8vZ8/pages/HryfG2ZzzfxlxZ4VIBnS">LoyaltyRequest</a></td></tr><tr><td><a href="/spaces/yzyMJNwlQJZoQOIC8vZ8/pages/F3rjjyDWwIKPfcKf2GLQ">AmountAdjustedEvent</a></td><td>CP_SYSTEM_REQUESTS_AMOUNT_ADJUSTMENT</td><td><a href="/spaces/yzyMJNwlQJZoQOIC8vZ8/pages/X3deEBBRQwlmByiLHHno">AmountAdjustmentRequest</a></td></tr><tr><td>None</td><td>CP_SYSTEM_REQUESTS_PAYMENT_AMOUNT_ADJUSTMENT</td><td><a href="/spaces/yzyMJNwlQJZoQOIC8vZ8/pages/nnlSt5CAFrW2yivjM5B6">PaymentAmountAdjustmentRequest</a></td></tr></tbody></table>

The first 3 require “adjudication”, that is, the POS can decide to accept or reject any of the modifications performed during these triggers. This can be done either automatically or by presenting an appropriate UI to the cashier, depending on the preference of the POS.

To accept or reject the modifications, get a Response object using the generateResponse() method, then set the accepted modifications on the response object. Any modifications not set on the response will be rejected. Send back the response using [TransactionManager.sendEventResponse(response).](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanager#sendeventresponse-commerceresponse)

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

```
actor Cashier as cashier order 10
participant POS as pos order 20
participant "Payment App" as pay order 30
participant "CP App" as cp order 40
|||
cashier <--> pos: Possibly select payment type\nor somehow indicate the basket is ready
pos ->> pay: Finalize basket
pay <<->> cp: Resolve Basket Adjustment
group If CP Apps make any changes
    pos <<- pay: Basket Adjusted Event
    cashier <-> pos: Optionally allow cashier to decide
    pos -> pos: Apply changes and/or\nexplicitly leave out items
    pos ->> pay : Send event response.
    |||
end
pos <<- pay: Basket Event with type BasketAction.FINALIZED
cashier <--> pos: Possibly select payment type\nor somehow indicate payment is ready,\nor skip straight to start payment
pos ->> pay: Start payment
pay <<->> cp: Resolve Loyalty Adjustment
group If CP Apps make any changes
    pos <<- pay: Loyalty Adjusted Event
    cashier <-> pos: Optionally allow cashier to decide
    pos -> pos: Apply changes and/or\nexplicitly leave out items
    pos ->> pay : Send event response.
    |||
end
pay <<->> cp: Resolve Amount Adjustment
group If CP Apps make any changes
    pos <<- pay: Loyalty Adjusted Event
    cashier <-> pos: Optionally allow cashier to decide
    pos -> pos: Apply changes and/or\nexplicitly leave out items
    pos ->> pay : Send event response.
    |||
end
pay <<->> cp: Resolve Payment Amount Adjustment
pos <<- pay: Payment Completed Event
|||
@enduml" %}
```

{% hint style="info" %}
**Note:** The CP\_SYSTEM\_REQUESTS\_PAYMENT\_AMOUNT\_ADJUSTMENT, is included in the payment response, since it cannot be rejected by the POS.
{% endhint %}

### **BasketAdjustedEvent**

Sent when a CP App decides that the cart is eligible for a specific deal or interacts with the customer to collect a donation amount. The CP App adds the offer(s) or donation(s) which are then sent back to the POS after the Payment App collects them from all of the CP Apps.

Use [BasketAdjustedEvent.getAdjustments() ](https://docs.verifone.com/psdk-api-latest/android-java/index/basketadjustedevent#getadjustments)to retrieve the adjustments requested by the CP App(s). Iterate through the [Offer(s)](https://docs.verifone.com/psdk-api-latest/android-java/index/offer) and Donation(s) in the [BasketAdjustment](https://docs.verifone.com/psdk-api-latest/android-java/index/basketadjustment), either removing them from the current object or adding them to a separate new [BasketAdjustment](https://docs.verifone.com/psdk-api-latest/android-java/index/basketadjustment). In either case, get the appropriate BasketAdjustedEvent.Response from [BasketAdjustedEvent.generateBasketAdjustedResponse(),](https://docs.verifone.com/psdk-api-latest/android-java/index/basketadjustedevent#generatebasketadjustedeventresponse) and [BasketAdjustedEvent.Response.setFinalAdjustments(…](https://docs.verifone.com/psdk-api-latest/android-java/index/basketadjustedeventresponse#setfinaladjustments-basketadjustment-amounttotals)) to identify the accepted adjustments and the new total amount for the payment.

If no adjustments are accepted, simply send back the BasketAdjustedEvent.Response without setting the final adjustments.

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

```java
@Override // Overridden from the CommerceListenerAdapter
public void handlBasketAdjustedEvent(
        BasketAdjustedEvent event) {
    if (BasketAdjustedEvent.TYPE.equals(event.getType())) {
        BasketAdjustment adjustments = event.getAdjustments();
        // Keep this response object to fill in with the accepted adjustments.
        BasketAdjustedEventResponse response =
              event.generateBasketEventResponse();
        // Either decide directly which adjustments are accepted, or allow
        // the cashier to review and decide.
    }
}

// Sometime later, send back the response after selecting the accepted adjustments.
response.setFinalAdjustments(adjustments, amountTotals);
transactionManager.sendEventResponse(
    BasketAdjustedEventResponse.asCommerceResponse(response));
```

{% endcode %}
{% endtab %}

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

```kotlin
 // Overridden from the CommerceListenerAdapter
override fun handleBasketAdjustedEvent(event: BasketAdjustedEvent) {
    if (BasketAdjustedEvent.TYPE.equals(event.getType())) {
        val adjustments = event.getAdjustments()
        // Keep this response object to fill in with the accepted adjustments.
        val response = basketAdjustedEvent.generateBasketEventResponse()
        // Either decide directly which adjustments are accepted, or allow
        // the cashier to review and decide.
    }
}

// Sometime later, send back the response after selecting the accepted adjustments.
response.setFinalAdjustments(adjustments, amountTotals)
transactionManager.sendEventResponse(
    BasketAdjustedEventResponse.asCommerceResponse(response))
```

{% endcode %}
{% endtab %}

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

```swift
// Overridden from the VFICommerceListenerAdapter
override func handle(_ event: VFIBasketAdjustedEvent?) {
    if (VFIBasketAdjustedEventTYPE == event?.getType()) {
        adjustments = event?.getAdjustments()
        // Keep this response object to fill in with the accepted adjustments.
        response = event?.generateResponse()
        // Either decide directly which adjustments are accepted, or allow
        // the cashier to review and decide.
    }
}

// Sometime later, send back the response after selecting the accepted adjustments.
response?.setFinalAdjustments(adjustments, amountTotals: amountTotals)
transactionManager?.sendEventResponse(
    VFIBasketAdjustedEventResponse.asCommerceResponse(response))
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}

<pre class="language-csharp" data-line-numbers data-full-width="true"><code class="lang-csharp"><strong> private void HandleBasketAdjustedvent(BasketAdjustedEvent event)
</strong>{
    if (event.Type.Value == BasketAdjustedEvent.TYPE)
    {
        var adjustments = event.Adjustment;
        var response = event.GenerateBasketAdjustedEventResponse();
        // Based on requestParameters.getInputType(), present the appropriate dialog.
        // Keep track of the response, it is needed once the input is collected.
    }
}

// Sometime later, send back the response after selecting the accepted adjustments.
response.SetFinalAdjustments(adjustments, amount_totals);
CommerceResponse commerceResponse = response as CommerceResponse;
payment_sdk_.TransactionManager.SendEventResponse(commerceResponse);
</code></pre>

{% endtab %}

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

```cpp
void handleBasketAdjustedEvents(
    const std::shared_ptr<verifone_sdk::BasketAdjustedEvents>& event) override {
  if (event->getType() == BasketAdjustedEvents::TYPE) {
    auto basket_adjustments = event->getAdjustments();
    auto response = event->generateBasketAdjustedEventResponse();
    // Based on requestParameters.getInputType(), present the appropriate dialog.
    // Keep track of the response, it is needed once the input is collected.
  }
}

// Sometime later, send back the response after selecting the accepted adjustments.
response->setFinalAdjustments(adjustments, amount_totals);
psdk->getTransactionManager()->sendEventResponse(
    std::dynamic_pointer_cast<verifone_sdk::CommerceResponse>(response));
```

{% endcode %}
{% endtab %}

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

```aspnet
private void HandleBasketAdjustedvent(BasketAdjustedEvent sdk_event)
{
    if (sdk_event.Type == BasketAdjustedEvent.EVENT_TYPE)
    {
        var adjustments = sdk_event.Adjustments;
        var response = sdk_event.GenerateBasketAdjustedEventResponse();
        // Based on requestParameters.getInputType(), present the appropriate dialog.
        // Keep track of the response, it is needed once the input is collected.
    }
}

// Sometime later, send back the response after selecting the accepted adjustments.
response.SetFinalAdjustments(adjustments, amount_totals);
CommerceResponse commerceResponse = BasketAdjustedEventResponse.AsCommerceResponse(response);
mw.Dispatcher.Invoke(() => { mw.payment_sdk_.TransactionManager.SendEventResponse(commerceResponse); });
```

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

### **LoyaltyReceivedEvent**

This is sent when a CP App collects loyalty information about the customer, and finds that they are eligible for a reward of some kind. The CP App adds the [Offer](https://docs.verifone.com/psdk-api-latest/android-java/index/offer) that they are eligible for, which is communicated back to the POS to decide if it can be applied to the current order or not.

Use [LoyaltyReceivedEvent.getLoyaltyAdjustments() ](https://docs.verifone.com/psdk-api-latest/android-java/index/loyaltyreceivedevent#getloyaltyadjustments)to get each adjustment grouped by CP App, or use [LoyaltyReceivedEvent.getLoyaltyOffersList() ](https://docs.verifone.com/psdk-api-latest/android-java/index/loyaltyreceivedevent#getloyaltyofferslist)to get all of the adjustments aggregated in a single list, without regard to the CP App. Get the appropriate [LoyaltyReceivedEvent.Response](https://docs.verifone.com/psdk-api-latest/android-java/index/loyaltyreceivedeventresponse) from [LoyaltyReceivedEvent.generateLoyaltyReceivedEventResponse() ](https://docs.verifone.com/psdk-api-latest/android-java/index/loyaltyreceivedevent#generateloyaltyreceivedeventresponse)and [LoyaltyReceivedEvent.Response.setLoyaltyOffers(offers)](https://docs.verifone.com/psdk-api-latest/android-java/index/loyaltyreceivedeventresponse#setloyaltyoffers-arraylistoffer) to identify the accepted offers.

Update the final amount using [Payment.setRequestedAmountTotals()](https://docs.verifone.com/psdk-api-latest/android-java/index/payment#setrequestedamounts-amounttotals) on either the original payment object or the one returned from LoyaltyReceivedEvent.Response.getResponsePayment(). If using a payment object other than the one returned from the response, set this payment on the response using [LoyaltyReceivedEvent.Response.updatePayment(payment).](https://docs.verifone.com/psdk-api-latest/android-java/index/loyaltyreceivedeventresponse#updatepayment-payment)

Finally, it is optional to use [LoyaltyReceivedEvent.Response.selectLoyaltyIdentifier(identifier)](https://docs.verifone.com/psdk-api-latest/android-java/index/loyaltyreceivedeventresponse#selectloyaltyidentifier-loyaltyidentifier) to select which loyalty ought to be associated with the current [Transaction](https://docs.verifone.com/psdk-api-latest/android-java/index/transaction). This can allow the system to auto-populate the email address and/or phone number if receiving a receipt using either of these, or for some other prompts that may require this information from the user.

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

```java
@Override // Overridden from the CommerceListenerAdapter
public void handlLoyaltyReceivedEvent(
        LoyaltyReceivedEvent event) {
    if (LoyaltyReceivedEvent.TYPE.equals(event.getType())) {
        // Offers per loyalty app
        LoyaltyAdjustment[] loyaltyAdjustments = event.getLoyaltyAdjustments();
        // Aggregated offers
        ArrayList<Offer> offers = event.getLoyaltyOffersList();
        // Keep this response object to fill in with the accepted adjustments.
        LoyaltyReceivedEventResponse response = event.generateResponse();
        // Either decide directly which offers are accepted, or allow
        // the cashier to review and decide.
    }
}

// Sometime later, send back the response after selecting the accepted offers.
response.setLoyaltyOffers(offers);
Payment payment = response.getResponsePayment();
// update amount totals to changedAmountTotals based on accepted offers
payment.setRequestedAmountTotals(changedAmountTotals);
transactionManager.sendEventResponse(
        LoyaltyReceivedEventResponse.asCommerceResponse(response));
```

{% endcode %}
{% endtab %}

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

```kotlin
 // Overridden from the CommerceListenerAdapter
override fun handleLoyaltyReceivedEvent(event: LoyaltyReceivedEvent) {
    if (LoyaltyReceivedEvent.TYPE.equals(event.getType())) {
        // Offers per loyalty app
        val loyaltyAdjustments = event.getLoyaltyAdjustments()
        // Aggregated offers
        val offers = event.getLoyaltyOffersList()
        // Keep this response object to fill in with the accepted adjustments.
        val response = event.generateLoyaltyReceivedEventResponse()
        // Either decide directly which offers are accepted, or allow
        // the cashier to review and decide.
    }
}

// Sometime later, send back the response after selecting the accepted offers.
response.setLoyaltyOffers(offers)
val payment = response.getResponsePayment()
// update amount totals to changedAmountTotals based on accepted offers
payment.setRequestedAmountTotals(changedAmountTotals)
transactionManager.sendEventResponse(
        LoyaltyReceivedEventResponse.asCommerceResponse(response))
```

{% endcode %}
{% endtab %}

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

```swift
var loyaltyAdjustments: [VFILoyaltyAdjustment]?
var offers: [VFIOffer]?
var response: VFILoyaltyReceivedEventResponse?
var payment: VFIPayment?
var transactionManager: VFITransactionManager?

// Overridden from the VFICommerceListenerAdapter
override func handle(_ event: VFILoyaltyReceivedEvent?) {
    if (VFILoyaltyReceivedEventTYPE == event?.getType()) {
    // Offers per loyalty app
    loyaltyAdjustments = event?.getLoyaltyAdjustments()
    // Aggregated offers
    offers = event?.getLoyaltyOffersList()
    // Keep this response object to fill in with the accepted adjustments.
    response = event?.generateResponse()
    // Either decide directly which offers are accepted, or allow
    // the cashier to review and decide.
}

// Sometime later, send back the response after selecting the accepted offers.
response?.setLoyaltyOffers(offers)
payment = response?.getResponsePayment()
// update amount totals to changedAmountTotals based on accepted offers
payment.setRequestedAmountTotals(changedAmountTotals)
transactionManager?.sendEventResponse(
    VFILoyaltyReceivedEventResponse.asCommerceResponse(response))
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}

<pre class="language-csharp" data-line-numbers data-full-width="true"><code class="lang-csharp"><strong> private readonly EventHandler&#x3C;LoyaltyReceivedEvent> loyalty_event_handler_;
</strong>
private void HandleEvent(LoyaltyReceivedEvent event)
{
    if (event.Type.Value == LoyaltyReceivedEvent.EVENT_TYPE)
    {
        // Offers per loyalty app
        Array&#x3C;LoyaltyAdjustments> loyalty_adjustments = event.GetLoyaltyAdjustments();
        // Aggregated offers
        ArrayList&#x3C;Offer> offers = event.GetLoyaltyOffers();
        // Keep this response object to fill in with the accepted adjustments.
        LoyaltyReceivedEventResponse response = event.GenerateLoyaltyReceivedEventResponse();
        // Either decide directly which offers are accepted, or allow
        // the cashier to review and decide.
    }
}

// ...
// Link event handler after initialization is complete
loyalty_event_handler_ = async (sender, args) =>
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
        () => HandleEvent(args));
};
payment_sdk_.TransactionManager.HandleLoyaltyReceivedEvent += loyalty_event_handler_;

// ...
// Send back the response after selecting the accepted offers.
response.SetLoyaltyOffers(offers);
Payment payment = response.ResponsePayment();
// update amount totals to changed_amount_totals based on accepted offers
payment.RequestedAmounts(changed_amount_totals);
CommerceResponse commerceResponse = response as CommerceResponse;
payment_sdk_.TransactionManager.SendEventResponse(commerceResponse);
</code></pre>

{% endtab %}

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

```cpp
// Overridden from the CommerceListenerAdapter
void handleLoyaltyReceivedEvent(
    const std::shared_ptr<verifone_sdk::LoyaltyReceivedEvent>& event) override {
  if (event->getType() == LoyaltyReceivedEvent::TYPE) {
    // Offers per loyalty app
    auto loyalty_adjustments = event->getLoyaltyAdjustments();
    // Aggregated offers
    auto offers = event->getLoyaltyOffersList();
    // Keep this response object to fill in with the accepted adjustments.
    auto response = event->generateLoyaltyReceivedEventResponse();
    // Either decide directly which offers are accepted, or allow
    // the cashier to review and decide.
  }
}

// Sometime later, send back the response after selecting the accepted offers.
response->setLoyaltyOffers(offers);
auto payment = response->getResponsePayment();
payment->setRequestedAmountTotals(changed_amount_totals);
psdk->getTransactionManager()->sendEventResponse(
    std::dynamic_pointer_cast<verifone_sdk::CommerceResponse>(response));
```

{% endcode %}
{% endtab %}

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

```aspnet
public void HandleLoyaltyReceivedEvent(LoyaltyReceivedEvent sdk_event)
{
    if (sdk_event.Type == LoyaltyReceivedEvent.EVENT_TYPE)
    {
        // Offers per loyalty app
        IList<VerifoneSdk.LoyaltyAdjustment> loyalty_adjustments = sdk_event.LoyaltyAdjustments;
        // Aggregated offers
        IList<Offer> offers = sdk_event.LoyaltyOffersList;
        // Keep this response object to fill in with the accepted adjustments.
        LoyaltyReceivedEventResponse response = sdk_event.GenerateLoyaltyReceivedEventResponse();
        // Either decide directly which offers are accepted, or allow
        // the cashier to review and decide.
    }
}

// ...
// Send back the response after selecting the accepted offers.
response.SetLoyaltyOffers(offers);
response.LoyaltyOffers = offers;
Payment payment = response.ResponsePayment;
// update amount totals to changed_amount_totals based on accepted offers
payment.RequestedAmounts = changed_amount_totals;
CommerceResponse commerceResponse = LoyaltyReceivedEventResponse.AsCommerceResponse(response);
mw.Dispatcher.Invoke(() => { mw.payment_sdk_.TransactionManager.SendEventResponse(commerceResponse); });
```

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

{% hint style="info" %}
Use [LoyaltyReceivedEvent.getLoyaltyAdjustments() ](https://docs.verifone.com/psdk-api-latest/android-java/index/loyaltyreceivedevent#getloyaltyadjustments)to get more information about the customer, including the [LoyaltyIdentifier](https://docs.verifone.com/psdk-api-latest/android-java/index/loyaltyidentifier) information that is being used for the specific loyalty program. This information can streamline further interactions with the customer.
{% endhint %}

### **AmountAdjustedEvent**

This is sent to allow CP Apps to change the amount, generally based on the payment type such as the card bin range, or based on some interaction with the customer. These can increase or decrease the overall amount, depending on the value in the [AmountAdjustment](https://docs.verifone.com/psdk-api-latest/android-java/index/amountadjustment), and it can be either determined by a percentage AmountAdjustment.getAdjustmentPercentage() or by a fixed amount AmountAdjustment.getAdjustmentValue(), depending on which is set.

Use [AmountAdjustedEvent.getAdjustments()](https://docs.verifone.com/psdk-api-latest/android-java/index/amountadjustedevent#getadjustments) to get the proposed changes, and [AmountAdjustedEvent.generateAmountAdjustedEventResponse()](https://docs.verifone.com/psdk-api-latest/android-java/index/amountadjustedevent#generateamountadjustedeventresponse) to get the [AmountAdjustedEvent.Response.](https://docs.verifone.com/psdk-api-latest/android-java/index/amountadjustedeventresponse) Iterate through the [AmountAdjustment](https://docs.verifone.com/psdk-api-latest/android-java/index/amountadjustment)(s), and add the accepted adjustment(s) to the response using [AmountAdjustedEvent.Response.setAdjustments(adjustments).](https://docs.verifone.com/psdk-api-latest/android-java/index/amountadjustedeventresponse#setadjustments-arraylistamountadjustment)

Update the final amount using Payment.setRequestedAmountTotals(updatedTotals) on either the original payment object or the one returned from [AmountAdjustedEvent.Response.getPayment()](https://docs.verifone.com/psdk-api-latest/android-java/index/amountadjustedeventresponse#getpayment). If using a payment object other than the one returned from the response, set this payment on the response using [AmountAdjustedEvent.Response.updatePayment(payment).](https://docs.verifone.com/psdk-api-latest/android-java/index/amountadjustedeventresponse#updatepayment-payment)

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

```java
@Override // Overridden from the CommerceListenerAdapter
public void handlAmountAdjustedEvent(
        AmountAdjustedEvent event) {
    if (AmountAdjustedEvent.TYPE.equals(event.getType())) {
        // Offers per loyalty app
        AmountAdjustment[] amountAdjustments = event.getAdjustments();
        // Keep this response object to fill in with the accepted adjustments.
        AmountAdjustedEventResponse response =
                event.generateAmountAdjustedEventResponse();
        // Either decide directly which offers are accepted, or allow
        // the cashier to review and decide.
    }
}

// Sometime later, send back the response after selecting the accepted offers.
response.setAdjustments(amountAdjustments);
Payment payment = response.getPayment();
payment.setRequestedAmountTotals(changedAmountTotals);
transactionManager.sendEventResponse(
        AmountAdjustedEventResponse.asCommerceResponse(response));
```

{% endcode %}
{% endtab %}

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

```kotlin
 // Overridden from the CommerceListenerAdapter
override fun handleAmountAdjustedEvent(event: AmountAdjustedEvent) {
    if (AmountAdjustedEvent.TYPE.equals(event.getType())) {
        // Offers per loyalty app
        val amountAdjustments = event.getAdjustments()
        // Keep this response object to fill in with the accepted adjustments.
        val response = event.generateAmountAdjustedEventResponse()
        // Either decide directly which offers are accepted, or allow
        // the cashier to review and decide.
    }
}

// Sometime later, send back the response after selecting the accepted offers.
response.setAdjustments(amountAdjustments)
val payment = response.getPayment()
payment.setRequestedAmountTotals(changedAmountTotals)
transactionManager.sendEventResponse(
        AmountAdjustedEventResponse.asCommerceResponse(response))
```

{% endcode %}
{% endtab %}

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

```swift
var amountAdjustments: [VFIAmountAdjustment]?
var response: VFIAmountAdjustedEventResponse?
var payment: VFIPayment?
var transactionManager: VFITransactionManager?
var changedAmountTotals: VFIAmountTotals?

// Overridden from the VFICommerceListenerAdapter
override func handle(_ event: VFIAmountAdjustedEvent?) {
    if (event?.getType() == VFIAmountAdjustedEventTYPE) {
        // Offers per loyalty app
        amountAdjustments = event?.getAdjustments()
        // Keep this response object to fill in with the accepted adjustments.
        response = event?.generateResponse()
        // Either decide directly which offers are accepted, or allow
        // the cashier to review and decide.
    }
}

// Sometime later, send back the response after selecting the accepted offers.
response.setAdjustments(amountAdjustments)
payment = response.getPayment()
payment?.setRequestedAmounts(changedAmountTotals)
transactionManager?.sendEventResponse(
    VFIAmountAdjustedEventResponse.asCommerceResponse(response))
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}

<pre class="language-csharp" data-line-numbers data-full-width="true"><code class="lang-csharp"><strong> private void HandleAmountAdjustedEvent(AmountAdjustedEvent event)
</strong>{
    if (event.Type.Value == AmountAdjustedEvent.EVENT_TYPE)
    {
        // Offers per loyalty app
        Array&#x3C;LoyaltyAdjustments> amount_adjustments = event.GetAdjustments();
        // Keep this response object to fill in with the accepted adjustments.
        AmountAdjustedEventResponse response =
                event.GenerateAmountAdjustedEventResponse();
        // Either decide directly which offers are accepted, or allow
        // the cashier to review and decide.
    }
}

// Sometime later, send back the response after selecting the accepted offers.
response.SetAdjustments(amount_adjustments);
response.Payment.RequestedAmounts(changed_amount_totals);
CommerceResponse commerceResponse = response as CommerceResponse;
payment_sdk_.TransactionManager.SendEventResponse(commerceResponse);
</code></pre>

{% endtab %}

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

```cpp
// Overridden from the CommerceListenerAdapter
void handleAmountAdjustedEvent(
    -const std::shared_ptr<verifone_sdk::AmountAdjustedEvent>& event) override {
  if (event->getType() == AmountAdjustedEvent::TYPE) {
    // Offers per loyalty app
    auto amount_adjustments = event->getAdjustments();
    // Keep this response object to fill in with the accepted adjustments.
    auto response = event->generateAmountAdjustedEventRepsonse;
    // Either decide directly which offers are accepted, or allow
    // the cashier to review and decide.
  }
}
  ...

// Sometime later, send back the response after selecting the accepted offers.
response->setAdjustments(amount_adjustments);
auto payment = response->getPayment();
payment->setRequestedAmountTotals(changed_amount_totals);
psdk->getTransactionManager()->sendEventResponse(std::dynamic_pointer_cast
    <verifone_sdk::CommerceResponse>(response));
```

{% endcode %}
{% endtab %}

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

```aspnet
private void HandleAmountAdjustedEvent(AmountAdjustedEvent sdk_event)
{
    if (sdk_event.Type == AmountAdjustedEvent.EVENT_TYPE)
    {
        // Offers per loyalty app
        IList<AmountAdjustment> amount_adjustments = sdk_event.Adjustments;
        // Keep this response object to fill in with the accepted adjustments.
        AmountAdjustedEventResponse response =
                sdk_event.GenerateAmountAdjustedEventResponse();
        // Either decide directly which offers are accepted, or allow
        // the cashier to review and decide.
    }
}

// Sometime later, send back the response after selecting the accepted offers.
response.Adjustments(amount_adjustments);
response.Payment.RequestedAmounts = changed_amount_totals;
CommerceResponse commerceResponse = AmountAdjustedEventResponse.AsCommerceResponse(response);
mw.Dispatcher.Invoke(() => { mw.payment_sdk_.TransactionManager.SendEventResponse(commerceResponse); });
```

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

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

* [Create a Commerce Listener](/psdk-latest/psdk-user-guide-and-training/psdk-user-guide/pos_guide.md#create-a-commerce-listener)
* [Finishing a Basket](/psdk-latest/psdk-user-guide-and-training/psdk-user-guide/general_basket_flow.md#finishing-a-basket)
* [BasketManager.finalizeBasket()](https://docs.verifone.com/psdk-api-latest/android-java/index/basketmanager#finalizebasket)
* [TransactionManager.startPayment(payment)](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanager#startpayment-payment)
* [TransactionManager.sendEventResponse(response)](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanager#sendeventresponse-commerceresponse)
* [BasketAdjustedEvent](https://docs.verifone.com/psdk-api-latest/android-java/index/basketadjustedevent)
* [BasketAdjustment](https://docs.verifone.com/psdk-api-latest/android-java/index/basketadjustment)
* [BasketAdjustedEvent.Response](https://docs.verifone.com/psdk-api-latest/android-java/index/basketadjustedeventresponse)
* [LoyaltyReceivedEvent](https://docs.verifone.com/psdk-api-latest/android-java/index/loyaltyreceivedevent)
* [LoyaltyAdjustment](https://docs.verifone.com/psdk-api-latest/android-java/index/loyaltyadjustment)
* [Offer](https://docs.verifone.com/psdk-api-latest/android-java/index/offer)
* [LoyaltyReceivedEvent.Response](https://docs.verifone.com/psdk-api-latest/android-java/index/loyaltyreceivedeventresponse)
* [AmountAdjustedEvent](https://docs.verifone.com/psdk-api-latest/android-java/index/amountadjustedeventresponse)
* [AmountAdjustment](https://docs.verifone.com/psdk-api-latest/android-java/index/amountadjustment)
* [AmountAdjustedEvent.Response](https://docs.verifone.com/psdk-api-latest/android-java/index/amountadjustedeventresponse)
* CP Triggers
  {% endhint %}

***

{% 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/advance-flows.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.
