---
updatedAt: 2025-09-18T11:22:43.000Z
agentTools:
  projectIndex: https://docs.portone.cloud/llms.txt
---

# Checkout: Android Connect

```kotlin MainActivity.kt
package com.android.portoneApp

import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.widget.Button
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import com.android.portonelibrary.PortOne
import com.android.portonelibrary.PortOneImpl
import com.android.portonelibrary.constants.*
import com.android.portonelibrary.dto.CheckoutConnectDto
import com.android.portonelibrary.networkCalls.ApiCallbackInterface
import com.android.portonelibrary.utils.LoggerUtil

class MainActivity : AppCompatActivity() {

    private lateinit var portOne: PortOne
    private lateinit var buttonPayout: Button

    @RequiresApi(Build.VERSION_CODES.O)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)


        portOne = PortOneImpl(
            context = this,
            environment = RequestBodies.environment,
            applicationId = BuildConfig.APPLICATION_ID
        )

        if (null != intent && null != intent.data) {
            val paymentStatus = intent.data.toString()
            portOne.updatePaymentStatus(paymentStatus)
        }


        buttonPayout.setOnClickListener {

            portOne.checkout(request = RequestBodies.getCheckoutRequest())

            portOne.checkoutUsingNewCard(
                paymentDetails = RequestBodies.getCardCheckoutRequest(),
                newCard = RequestBodies.newCardDetails,
                token = "JWT Token",
            )


            portOne.getPaymentMethods(
                portoneKey = RequestBodies.portoneKey,
                subMerchantKey = RequestBodies.subMerchantKey,
                currency = RequestBodies.currency,
                object :
                    ApiCallbackInterface<CheckoutConnectDto.PaymentMethodResponse> {
                    override fun onSucceed(response: CheckoutConnectDto.PaymentMethodResponse) {
                        LoggerUtil.info("Successful")
                    }

                    override fun onFailure(
                        errorCode: Int?,
                        status: String?,
                        errorMessage: String,
                        throwable: Throwable
                    ) {
                        LoggerUtil.info("Failed")
                    }
                })

            portOne.getOTP(phoneNo = "+9176767236767", object :
                ApiCallbackInterface<CheckoutConnectDto.OtpResponse> {
                override fun onSucceed(response: CheckoutConnectDto.OtpResponse) {
                    LoggerUtil.info("Successful")
                }

                override fun onFailure(
                    errorCode: Int?,
                    status: String?,
                    errorMessage: String,
                    throwable: Throwable
                ) {
                    LoggerUtil.info("Failed")
                }
            })

            portOne.getSavedCards(
                token = "",
                portoneKey = RequestBodies.portoneKey,
                phoneNo = "+xxxxxxxxxxxxxxxxx",
                otp = "520387",
                object :
                    ApiCallbackInterface<CheckoutConnectDto.SavedCardsResponse> {
                    override fun onSucceed(response: CheckoutConnectDto.SavedCardsResponse) {
                        LoggerUtil.info("Successful")
                    }

                    override fun onFailure(
                        errorCode: Int?,
                        status: String?,
                        errorMessage: String,
                        throwable: Throwable
                    ) {
                        LoggerUtil.info("Failed")
                    }
                })

            portOne.getBankList(
                channel = RequestBodies.paymentChannel,
                request = RequestBodies.getBankListRequest(),
                object : ApiCallbackInterface<CheckoutConnectDto.BankListResponse> {
                    override fun onSucceed(response: CheckoutConnectDto.BankListResponse) {
                        LoggerUtil.info("Successful")
                    }

                    override fun onFailure(
                        errorCode: Int?,
                        status: String?,
                        errorMessage: String,
                        throwable: Throwable
                    ) {
                        LoggerUtil.info("Failed")
                    }

                })

            portOne.checkout(request = RequestBodies.getCheckoutWithInstallationRequest())

            portOne.getDBTDetails(portoneKey = RequestBodies.portoneKey,
                object : ApiCallbackInterface<CheckoutConnectDto.DBTResponse> {
                    override fun onSucceed(response: CheckoutConnectDto.DBTResponse) {
                        LoggerUtil.info("Successful")
                    }

                    override fun onFailure(
                        errorCode: Int?,
                        status: String?,
                        errorMessage: String,
                        throwable: Throwable
                    ) {
                        LoggerUtil.info("Failed")
                    }

                })

            portOne.checkout(request = RequestBodies.getCheckoutWithDirectBankTransferRequest())

             portOne.addCustomer(
                token = "JWT Token",
                portOneKey = RequestBodies.portoneKey,
                subMerchantKey = RequestBodies.subMerchantKey,
                request = CheckoutConnectDto.AddCustomerRequest(
                    name = "Skia Salva",
                    phoneNo = RequestBodies.phoneNo,
                    "skia@something.com",
                    Utility.getRandomString(10)
                ),
                object : ApiCallbackInterface<CheckoutConnectDto.AddCustomerResponse> {
                    override fun onSucceed(response: CheckoutConnectDto.AddCustomerResponse) {
                        val gson = Gson()
                        val json = gson.toJson(response)
                        LoggerUtil.info("Successful")
                    }

                    override fun onFailure(
                        errorCode: Int?,
                        status: String?,
                        errorMessage: String,
                        throwable: Throwable
                    ) {
                        LoggerUtil.info("Failed")
                    }

                })

            portOne.getCustomer(
                token = "JWT Token",
                portOneKey = RequestBodies.portoneKey,
                customerUUID = RequestBodies.customerUUID,
                object : ApiCallbackInterface<CheckoutConnectDto.GetCustomerDataResponse> {
                    override fun onSucceed(response: CheckoutConnectDto.GetCustomerDataResponse) {
                        val gson = Gson()
                        val json = gson.toJson(response)
                        LoggerUtil.info("Successful")
                    }

                    override fun onFailure(
                        errorCode: Int?,
                        status: String?,
                        errorMessage: String,
                        throwable: Throwable
                    ) {
                        LoggerUtil.info("Failed")
                    }

                })

            portOne.addCardForCustomer(
                customerUUID = RequestBodies.customerUUID,
                token = "JWT Token",
                portoneKey = RequestBodies.portoneKey,
                subMerchantKey = RequestBodies.subMerchantKey,
                newCard = RequestBodies.OmiseCreditCard,
                object : ApiCallbackInterface<CheckoutConnectDto.AddCardsForCustomerResponse> {
                    override fun onSucceed(response: CheckoutConnectDto.AddCardsForCustomerResponse) {
                        LoggerUtil.info("Successful")
                    }

                    override fun onFailure(
                        errorCode: Int?,
                        status: String?,
                        errorMessage: String,
                        throwable: Throwable
                    ) {
                        LoggerUtil.info("Failed")
                    }

                })

            portOne.deleteCardForCustomer(
                customerUUID = RequestBodies.customerUUID,
                token = "JWT Token",
                portoneKey = RequestBodies.portoneKey,
                subMerchantKey = RequestBodies.subMerchantKey,
                request = CheckoutConnectDto.DeleteCardRequest(token = "xxxxxxxxxxxxxxxxx"),
                object : ApiCallbackInterface<CheckoutConnectDto.GenericResponse> {
                    override fun onSucceed(response: CheckoutConnectDto.GenericResponse) {
                        LoggerUtil.info("Successful")
                    }

                    override fun onFailure(
                        errorCode: Int?,
                        status: String?,
                        errorMessage: String,
                        throwable: Throwable
                    ) {
                        LoggerUtil.info("Failed")
                    }

                })

            portOne.listCardsForCustomer(
                customerUUID = RequestBodies.customerUUID,
                token = "JWT Token",
                portoneKey = RequestBodies.portoneKey,
                subMerchantKey = RequestBodies.subMerchantKey,
                object : ApiCallbackInterface<CheckoutConnectDto.ListCardsForCustomerResponse> {
                    override fun onSucceed(response: CheckoutConnectDto.ListCardsForCustomerResponse) {
                        LoggerUtil.info("Successful")
                    }

                    override fun onFailure(
                        errorCode: Int?,
                        status: String?,
                        errorMessage: String,
                        throwable: Throwable
                    ) {
                        LoggerUtil.info("Failed")
                    }

                })
              
             portOne.captureTransaction(
                orderReference = "2PMPrDODLQ1dEHOHibQp9ZgyaB2",
                portoneKey = RequestBodies.portoneKey,
                token = Utility.getJwtToken(),
                object : ApiCallbackInterface<CheckoutConnectDto.GenericResponse> {
                    override fun onSucceed(response: CheckoutConnectDto.GenericResponse) {
                        LoggerUtil.info("Successful")
                    }

                    override fun onFailure(
                        errorCode: Int?,
                        status: String?,
                        errorMessage: String,
                        throwable: Throwable
                    ) {
                        LoggerUtil.info("Failed")
                    }

                })
              
             portOne.getRoutesList(
                token = Utility.getJwtToken(),
                portoneKey = RequestBodies.portoneKey,
                object : ApiCallbackInterface<CheckoutConnectDto.RoutesListResponse> {
                    override fun onSucceed(response: CheckoutConnectDto.RoutesListResponse) {
                        val gson = Gson()
                        val json = gson.toJson(response)
                        LoggerUtil.info("Successful")
                    }

                    override fun onFailure(
                        errorCode: Int?,
                        status: String?,
                        errorMessage: String,
                        throwable: Throwable
                    ) {
                        LoggerUtil.info("Failed")
                    }

                })

        }

    }


    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if (resultCode == RESULT_CODE && data != null) {
            when (requestCode) {
                PAYOUT_REQUEST_CODE, PAYMENT_STATUS_REQUEST_CODE -> {
                    val paymentStatus: CheckoutConnectDto.UpdatedPaymentStatusResponse =
                        (data.getSerializableExtra(PAYMENT_STATUS)
                            ?: "Empty") as CheckoutConnectDto.UpdatedPaymentStatusResponse
                }

            }

        }
    }
}
```

```kotlin RequestBodies.kt
package com.android.portoneApp

import android.os.Build
import androidx.annotation.RequiresApi
import com.android.portonelibrary.constants.*
import com.android.portonelibrary.dto.CheckoutConnectDto
import java.time.Instant
import java.time.format.DateTimeFormatter

object RequestBodies {

    var paymentChannel = ""
    var paymentMethod = ""
    var portoneKey = ""
    var subMerchantKey = ""
    var currency = "VND"                                          // VND || THB || SGD || IDR || PHP
    var phoneNo = ""
    var transactionType = PURCHASE                               // PURCHASE || PREAUTH
    var environment = SANDBOX                                    // SANDBOX || LIVE

    val newCardDetails = CheckoutConnectDto.NewCard(
        cardNumber = "",
        cardType = "",
        cardholderName = "",
        serviceCode = "",
        expiryYear = "",
        expiryMonth = ""
    )


    fun getCardCheckoutRequest(): CheckoutConnectDto.CheckoutRequest {

        val paymentDetails = CheckoutConnectDto.CheckoutRequest(
            portoneKey = portoneKey,
            paymentChannel = paymentChannel,
            paymentMethod = paymentMethod,
            merchantOrderId = "order_id_001",
            amount = 0.00,
            currency = currency,
            successUrl = "",
            failureUrl = "",
            signatureHash = "signatureHash",
            billingDetails = CheckoutConnectDto.BillingDetails(billingPhone = phoneNo),
            redirectUrl = "portone://checkout",
            cardDetails = null,
            environment = environment,
            isRoutingEnabled = false,
            routingParams = CheckoutConnectDto.RoutingParams(type = "failover", routeRef = null),
            source = "mobile",
            transactionType = transactionType
        )
        return paymentDetails
    }

    fun getCheckoutRequest(): CheckoutConnectDto.CheckoutRequest {
        
        val billingAddress: CheckoutConnectDto.Address = CheckoutConnectDto.Address()
        billingAddress.city = currency
        billingAddress.countryCode = "VN"
        billingAddress.locale = "en"
        billingAddress.line_1 = "address"
        billingAddress.line_2 = "address_2"
        billingAddress.postal_code = "400202"
        billingAddress.state = "Mah"
        val shippingAddress: CheckoutConnectDto.Address = billingAddress

        val billingDetails: CheckoutConnectDto.BillingDetails = CheckoutConnectDto.BillingDetails()
        billingDetails.billingName = "Test mark"
        billingDetails.billingEmail = "markweins@gmail.com"
        billingDetails.billingPhone = phoneNo
        billingDetails.billingAddress = billingAddress

        val shippingDetails: CheckoutConnectDto.ShippingDetails = CheckoutConnectDto.ShippingDetails()
        shippingDetails.shippingName = "Test mark"
        shippingDetails.shippingEmail = "markweins@gmail.com"
        shippingDetails.shippingPhone = phoneNo
        shippingDetails.shippingAddress = shippingAddress

        val orderDetail: CheckoutConnectDto.OrderDetail = CheckoutConnectDto.OrderDetail()
        orderDetail.id = "knb"
        orderDetail.name = "kim nguyen bao"
        orderDetail.price = 1000.00
        orderDetail.quantity = 1
        val orderList = ArrayList<CheckoutConnectDto.OrderDetail>()
        orderList.add(orderDetail)

        val orderDetails = CheckoutConnectDto.CheckoutRequest()
        orderDetails.portoneKey = portoneKey
        orderDetails.paymentChannel = paymentChannel
        orderDetails.paymentMethod = paymentMethod
        orderDetails.merchantOrderId = "order_id_001"
        orderDetails.amount = 50010.00
        orderDetails.currency = currency
        orderDetails.signatureHash = ""
        orderDetails.billingDetails = billingDetails
        orderDetails.shippingDetails = shippingDetails
        orderDetails.orderDetails = orderList
        orderDetails.successUrl = ""
        orderDetails.failureUrl = ""
        orderDetails.redirectUrl = "portone://checkout"
        orderDetails.environment = environment
        orderDetails.source = "mobile"
        orderDetails.transactionType = transactionType

        return orderDetails
    }

    fun getCheckoutWithInstallationRequest(): CheckoutConnectDto.CheckoutRequest {
        
        val billingAddress: CheckoutConnectDto.Address = CheckoutConnectDto.Address()
        billingAddress.city = currency
        billingAddress.countryCode = "VN"
        billingAddress.locale = "en"
        billingAddress.line_1 = "address"
        billingAddress.line_2 = "address_2"
        billingAddress.postal_code = "400202"
        billingAddress.state = "Mah"
        val shippingAddress: CheckoutConnectDto.Address = billingAddress

        val billingDetails: CheckoutConnectDto.BillingDetails = CheckoutConnectDto.BillingDetails()
        billingDetails.billingName = "Test mark"
        billingDetails.billingEmail = "markweins@gmail.com"
        billingDetails.billingPhone = phoneNo
        billingDetails.billingAddress = billingAddress

        val shippingDetails: CheckoutConnectDto.ShippingDetails = CheckoutConnectDto.ShippingDetails()
        shippingDetails.shippingName = "Test mark"
        shippingDetails.shippingEmail = "markweins@gmail.com"
        shippingDetails.shippingPhone = phoneNo
        shippingDetails.shippingAddress = shippingAddress

        val orderDetail: CheckoutConnectDto.OrderDetail = CheckoutConnectDto.OrderDetail()
        orderDetail.id = "knb"
        orderDetail.name = "kim nguyen bao"
        orderDetail.price = 1000.00
        orderDetail.quantity = 1
        val orderList = ArrayList<CheckoutConnectDto.OrderDetail>()
        orderList.add(orderDetail)

        val installmentPeriod: CheckoutConnectDto.TermObject = CheckoutConnectDto.TermObject()
        installmentPeriod.month = 3

        val bankDetails: CheckoutConnectDto.BankDetails = CheckoutConnectDto.BankDetails()
        bankDetails.bankCode = "004"
        bankDetails.bankName = "Kasikorn Bank"
        bankDetails.isMerchantSponsored = false
        bankDetails.override_default = false
        bankDetails.installmentPeriod = installmentPeriod

        val orderDetails = CheckoutConnectDto.CheckoutRequest()
        orderDetails.portoneKey = portoneKey
        orderDetails.paymentChannel = paymentChannel
        orderDetails.paymentMethod = paymentMethod
        orderDetails.merchantOrderId = "order_id_001"
        orderDetails.amount = 50010.00
        orderDetails.currency = currency
        orderDetails.signatureHash = ""
        orderDetails.billingDetails = billingDetails
        orderDetails.shippingDetails = shippingDetails
        orderDetails.orderDetails = orderList
        orderDetails.successUrl = ""
        orderDetails.failureUrl = ""
        orderDetails.redirectUrl = "portone://checkout"
        orderDetails.environment = environment
        orderDetails.source = "mobile"
        orderDetails.bankDetails = bankDetails
        orderDetails.transactionType = transactionType

        return orderDetails
    }

    @RequiresApi(Build.VERSION_CODES.O)
    fun getCheckoutWithDirectBankTransferRequest(): CheckoutConnectDto.CheckoutRequest {
        
        val billingAddress: CheckoutConnectDto.Address = CheckoutConnectDto.Address()
        billingAddress.city = currency
        billingAddress.countryCode = "VN"
        billingAddress.locale = "en"
        billingAddress.line_1 = "address"
        billingAddress.line_2 = "address_2"
        billingAddress.postal_code = "400202"
        billingAddress.state = "Mah"
        val shippingAddress: CheckoutConnectDto.Address = billingAddress

        val billingDetails: CheckoutConnectDto.BillingDetails = CheckoutConnectDto.BillingDetails()
        billingDetails.billingName = "Test mark"
        billingDetails.billingEmail = "markweins@gmail.com"
        billingDetails.billingPhone = phoneNo
        billingDetails.billingAddress = billingAddress

        val shippingDetails: CheckoutConnectDto.ShippingDetails = CheckoutConnectDto.ShippingDetails()
        shippingDetails.shippingName = "Test mark"
        shippingDetails.shippingEmail = "markweins@gmail.com"
        shippingDetails.shippingPhone = phoneNo
        shippingDetails.shippingAddress = shippingAddress

        val orderDetail: CheckoutConnectDto.OrderDetail = CheckoutConnectDto.OrderDetail()
        orderDetail.id = "knb"
        orderDetail.name = "kim nguyen bao"
        orderDetail.price = 1000.00
        orderDetail.quantity = 1
        val orderList = ArrayList<CheckoutConnectDto.OrderDetail>()
        orderList.add(orderDetail)

        val dbtDetails: CheckoutConnectDto.DBTDetails = CheckoutConnectDto.DBTDetails()
        dbtDetails.amountPaid = 10202.00
        dbtDetails.customerName = "Aagam Shah"
        dbtDetails.transactionTime = DateTimeFormatter.ISO_INSTANT.format(Instant.now())

        val orderDetails = CheckoutConnectDto.CheckoutRequest()
        orderDetails.portoneKey = portoneKey
        orderDetails.paymentChannel = paymentChannel
        orderDetails.paymentMethod = paymentMethod
        orderDetails.merchantOrderId = "order_id_001"
        orderDetails.amount = 50010.00
        orderDetails.currency = currency
        orderDetails.signatureHash = ""
        orderDetails.billingDetails = billingDetails
        orderDetails.shippingDetails = shippingDetails
        orderDetails.orderDetails = orderList
        orderDetails.successUrl = ""
        orderDetails.failureUrl = ""
        orderDetails.redirectUrl = "portone://checkout"
        orderDetails.environment = environment
        orderDetails.directBankTransferDetails = dbtDetails
        orderDetails.source = "mobile"
        orderDetails.transactionType = transactionType

        return orderDetails
    }

    fun getBankListRequest(): CheckoutConnectDto.BankListRequest {
        val request = CheckoutConnectDto.BankListRequest()
        request.amount = 20023.00
        request.environment = environment
        request.portoneKey = portoneKey
        request.isMerchantSponsored = false
        request.paymentMethod = paymentMethod
        request.overrideDefault = false
        request.currency = currency
        return request
    }

}
```

# Initialize the PortOne SDK

<!-- kotlin@27-31 -->
<!-- kotlin@19 -->

This step initializes the PortOne SDK in the activity where the payment checkout process occurs. The SDK is set up with either the sandbox or live environment depending on the use case.

# Fetch Available Payment Methods

<!-- kotlin@50-68 -->
<!-- kotlin@14-16 -->

Retrieves the available payment channels and methods using the PortOne SDK. The method requires parameters such as portoneKey, subMerchantKey, and currency.

# Create Request Bodies

<!-- kotlin@10-244 -->

This module contains utility functions that dynamically generate request bodies for different payment scenarios. Each method builds a customized request object depending on the specific payment flow, such as card checkout, installment plans, direct bank transfers, or retrieving bank lists. By using meaningful method names like getCardCheckoutRequest, getCheckoutWithInstallationRequest, or getBankListRequest, developers can easily differentiate between the request types and understand the relevant fields used for each payment method.

# Process Checkout

<!-- kotlin@41-47,126,145 -->

All checkout requests follow the same structure, but the required parameters vary based on the type of payment method used:

1. Normal Checkout: This is the simplest checkout process, where you only need to pass the payment channel and payment method. It can be triggered using the getCheckoutRequest() method.

2. Installments and Direct Bank Transfer: These types of checkout require additional mandatory objects in the request, such as installment periods or bank transfer details. They may also need extra method calls as mentioned in the code and documentation. The methods getCheckoutWithInstallationRequest() and getCheckoutWithDirectBankTransferRequest() handle these cases.

3. Checkout Using a New Card: For this type, the request involves passing card details. It’s handled by the getCardCheckoutRequest() method, which works with a new card.

4. Checkout Using Saved Cards: This checkout type uses a previously saved card. It requires a call to fetch the saved cards, which is handled in the code using getCheckoutWithSavedCardsRequest().

# Retrieve Payment Status

<!-- kotlin@152-166 -->

Once the payment process is completed, you can retrieve the payment status in the onActivityResult method.

# Merchant centric card vault

<!-- kotlin@147-260 -->

1. Add Customer
Collect the customerData, clientKey, JWTToken and provide them to the addCustomer method

2. Get Customer Data
Collect the customerID, customerData, clientKey, JWTToken and provide them to the getCustomerData method

3. Add Card For Customer
Collect the customerId, clientKey, JWTToken and cardData and provide them to the addCardForCustomerId method

4. Delete card for Customer
Collect the customerId, clientKey, JWTToken and cardData and provide them to the deleteCardForCustomerId method

5. Fetch Customer Cards
Collect the customerId, clientKey, JWTToken and provide them to the fetchCustomerCards method

# PreAuth and Capture Payment

<!-- kotlin@262-280 -->
<!-- kotlin@18,50,103,167,227 -->

1. Setting the Transaction Type 

To designate a transaction for pre-authorization, a specific parameter must be configured in the payload:
transactionType= PREAUTH || PURCHASE

2.Capture the Payment

Following the pre-authorization of a transaction, captureTransactionAPI method is utilised for capturing the transaction.
Collect the transactionOrderRef, clientKey, JWTToken and provide them to the captureTransactionAPI method
// @param {String} order_ref
string
The order_ref of the transaction to capture

# Failover Routing

<!-- kotlin@282-301 -->
<!-- kotlin@48 -->

To support failover routing add the following two parameters to payload:

isRoutingEnabled= true

Routing Param type should be failover.
provide the Routing Ref which is set in the merchant portal.

To Fetch the List of Routes which are created from merchant portal
Collect the clientKey, JWTToken and provide them to the fetchRoutes method