# Make payment

Great! If you've reached this point, it means you have successfully set up and initialized the SDK. Now you can start making payments.

To make a payment, call the `makePayment` function on the `TeyaCommonTransactionsApi` instance:

```tabs
    tab:
      title: Kotlin
      content:
        ```kotlin
        val paymentSubscription = teyaIntegration.makePayment(
            transactionId = UUID.randomUUID().toString(), // or pass whatever identifier you already have for the payment you're about to make
            amount = amountToPay, // the total amount to be paid including the tip, in the smallest unit of the currency (e.g., cents).
            currency = "GBP", // The ISO 4217 currency code (e.g., "GBP", "EUR").
            tip = null // An optional tip amount, in the smallest unit of the currency.
        )
        ```
    tab:
      title: Java
      content:
        ```java
        PaymentStateSubscription paymentSubscription = teyaIntegration.makePayment(
                UUID.randomUUID().toString(), // transactionId: or pass whatever identifier you already have for the payment you're about to make
                amountToPay, // amount: the total amount to be paid including the tip, in the smallest unit of the currency (e.g., cents).
                "GBP", // currency: The ISO 4217 currency code (e.g., "GBP", "EUR").
                null // tip: An optional tip amount, in the smallest unit of the currency.
        );
        ```
```

## Subscribe to Payment updates

`makePayment` call returns a `PaymentStateSubscription` which allows you to add and remove listeners for status updates of the payment.

```tabs
    tab:
      title: Kotlin
      content:
        ```kotlin
        val listener = object : PaymentStateSubscription.PaymentStateChangeListener {
            override fun onPaymentStateChanged(state: PaymentStateSubscription.PaymentStateDetails) {
                println("new state = $state, is it a final state = $state.isFinal")
            }
        }
        paymentSubscription.subscribe(listener)
        ```
    tab:
      title: Java
      content:
        ```java
        PaymentStateSubscription.PaymentStateChangeListener listener = state -> {
            System.out.println("new state = " + state + ", is it a final state = " + state.isFinal());
        };
        
        paymentSubscription.subscribe(listener);
        ```
```

The `PaymentStateDetails` object includes the following parameters:

```kotlin
data class PaymentStateDetails(
    val eposTransactionId: String,
    val amount: Int,
    val tip: Int?,
    val currency: String,
    val state: PaymentState,
    val inProgressState: InProgressState?,
    val gatewayPaymentId: GatewayPaymentId? = null,
    val reason: PaymentStateReason? = null,
    val debugErrorMessage: String? = null,
    val metadata: Metadata? = null,
    val transactionTimestamp: Long? = null,
    val wasUnsubscribed: Boolean = false
)
```

```admonition
icon: fas fa-exclamation-triangle
content: To enable future refunds and receipt printing, make sure to store the `gatewayPaymentId`. You'll need access to it later, as it's used to identify the transaction during the refund and printing process.
```

## Adding a Tip

You can add a tip either through our SDK on **ePOS** or directly on the **card machine**. See the documentation below for more details.

### Adding a Tip on ePOS

As shown above, you can add a tip to `makePayment`.

```tabs
    tab:
      title: Kotlin
      content:
        ```kotlin
        val paymentSubscription = teyaIntegration.makePayment(
            transactionId = UUID.randomUUID().toString(),
            amount = amountToPay,
            currency = "GBP",
            tip = 30 // An optional tip amount, in the smallest unit of the currency.
        )
        ```
    tab:
      title: Java
      content:
        ```java
        PaymentStateSubscription paymentSubscription = teyaIntegration.makePayment(
                UUID.randomUUID().toString(), // transactionId
                amountToPay, // amount
                "GBP", // currency
                30 // An optional tip amount, in the smallest unit of the currency.
        );
        ```
```

The tip parameter allows you to specify an optional tip amount, in the smallest unit of the currency (e.g., pence for GBP, cents for EUR/USD). When you provide a tip, it is treated as included within the total amount you pass.

For example, if you set:
```kotlin
amount = 100
tip = 20
```

In other words, the tip is not added on top of the amount - it is included within it. For example, if the total is **£1.00**, **£0.20** will go toward the tip and **£0.80** will be the purchased goods amount.

```admonition
icon: fas fa-exclamation-triangle
content: Please note that the tip cannot exceed the total transaction amount.
```

### Adding a tip on Card Machine

If you don't provide a tip amount in the `makePayment` function and tipping is enabled on the **card machine**, the tip can be selected directly on the card machine.

If you want to enable tipping on the card machine, you also need to pass true for tipping in the setup function:

```tabs
    tab:
      title: Kotlin
      content:
        ```kotlin
        val teyaIntegration = teyaAllInOneSDK.setupTransactionsApi(
            skipApprovedScreen = false,
            allowPaymentAppTips = true, // Enable tipping on the payment app
            showReceiptOptionsOnPaymentApp = false
        )
        ```
    tab:
      title: Java
      content:
        ```java
        TeyaCommonTransactionsApi teyaIntegration = teyaAllInOneSDK.setupTransactionsApi(
                false, // skipApprovedScreen
                true, // allowPaymentAppTips: Enable tipping on the payment app
                false // showReceiptOptionsOnPaymentApp
        );
        ```
```

When a tip is selected this way, the `amount` and `tip` properties in the `PaymentStateDetails` object will be updated accordingly. These updates occur once the payment status changes to `Successful`, allowing you to see the final tip amount selected on the card machine.

```kotlin
public data class PaymentStateDetails(
    val eposTransactionId: String,
    val amount: Int,           // Total amount including tip; updated after a Successful payment with a terminal-side tip
    val tip: Int?,             // Tip amount; updated after a Successful payment with a terminal-side tip
    // ...
)
```
