# Implementation

Learn how to use the PayPal components in your Android project.

## Overview

Every component follows the same basic three-step lifecycle:

1. Create the component and optionally add your own configuration.
2. Render the component using Jetpack Compose. This is what makes the component visible and interactive.
3. Dispose the component. This is a clean-up step that clears up resources and is handled automatically by Compose.


## Before you start

To use the PayPal components, you first need to:

* [Install Components for Android](/guides/checkout/components/android/install).
* Complete the [PayPal onboarding](/guides/checkout/components/android/paypal/onboarding) process in the Unity Portal.
* Configure your `gradle.properties` with the required environment variables.


## Choose your implementation approach

Android offers three ways to implement PayPal payments, depending on your requirements:

- **Simple PayPal:** Use this approach when you need basic PayPal payments without one-click or vaulting features. Ideal for guest checkout, simple payments, and digital products.
- **Pre-built PayPal** Use the pre-configured composite component that includes the basic PayPal component and the toggle component for one-click payments. This approach offers a quick integration path with built-in vaulting support.
- **Custom composition** Manually compose the PayPal, toggle, and consent components for maximum control over layout and behaviour. This approach gives you the most flexibility for custom UX requirements.


The component lifecycle is automatically managed by Jetpack Compose across all three approaches. However, you can manually dispose of resources if needed:


```kotlin
DisposableEffect(paypalComponent) {
    onDispose {
        // Component resources are automatically cleaned up
        Log.d("PayPal", "Component disposed")
    }
}
```

## Implement PayPal payments

Simple
### Step 1: Initialise the SDK

To get started, initialise the Checkout SDK in your Android application.


```kotlin
import com.pxp.checkout.PxpCheckout
import com.pxp.checkout.models.PxpCheckoutConfig
import com.pxp.checkout.models.Environment
import com.pxp.checkout.models.OwnerType
import com.pxp.checkout.models.TransactionData
import com.pxp.checkout.models.EntryType
import com.pxp.checkout.models.IntentType
import java.util.UUID

val pxpCheckout = PxpCheckout.builder()
    .withConfig(
        PxpCheckoutConfig(
            environment = Environment.TEST,
            session = sessionData,
            ownerId = "Unity",
            ownerType = OwnerType.MERCHANT_GROUP,
            merchantShopperId = "Shopper_01",
            transactionData = TransactionData(
                currency = "USD",
                amount = 2500.0, // Amount in cents ($25.00)
                entryType = EntryType.Ecom,
                intent = IntentType.Purchase,
                merchantTransactionId = UUID.randomUUID().toString(),
                merchantTransactionDate = { System.currentTimeMillis() }
            )
        )
    )
    .withContext(context)
    .build()
```

| Parameter | Description |
|  --- | --- |
| `environment`Environment | The environment type.Possible values:`Environment.TEST`: For sandbox.`Environment.LIVE`: For production. |
| `session`SessionData | Details about the checkout session. |
| `ownerId`String | The identifier of the owner related to the `ownerType`. |
| `ownerType`OwnerType | The type of owner.Possible values:`OwnerType.MERCHANT_GROUP``OwnerType.MERCHANT` `OwnerType.SITE`  |
| `merchantShopperId`String | A unique identifier for this shopper. |
| `transactionData`TransactionData | Details about the transaction. |
| `transactionData.currency`String | The currency code associated with the transaction (e.g., `USD`, `EUR`). |
| `transactionData.amount`Double | The transaction amount in the smallest currency unit (e.g., cents for USD). |
| `transactionData.entryType`EntryType | The entry type.Possible values:`EntryType.Ecom``EntryType.MOTO` |
| `transactionData.intent`IntentType | The transaction intent.Possible values:`IntentType.Authorisation``IntentType.Purchase``IntentType.Verification``IntentType.EstimatedAuthorisation``IntentType.Payout` |
| `transactionData.merchantTransactionId`String | A unique identifier for this transaction. |
| `transactionData.merchantTransactionDate`() -> Long | A function that returns the current timestamp in milliseconds. |


### Step 2: Configure the component

Create the PayPal component configuration with basic settings:


```kotlin
import com.pxp.checkout.components.paypal.PayPalComponentConfig
import com.pxp.checkout.components.paypal.types.*

val paypalConfig = PayPalComponentConfig(
    payeeEmailAddress = "merchant@example.com",
    paymentDescription = "Order #12345",
    shippingPreference = ShippingPreference.NoShipping.toString(),
    userAction = UserAction.PayNow.toString(),
    renderType = "standalone",
    fundingSources = "paypal", // String for standalone mode
    enableOneClickPayment = false // No vaulting
)
```

| Parameter | Description |
|  --- | --- |
| `payeeEmailAddress`String? | Your email address. |
| `paymentDescription`String? | A description of the payment. |
| `shippingPreference`String | The shipping details to use.Possible values:`NoShipping`: No shipping address required.`GetFromFile`: Get shipping address from PayPal account.`SetProvidedAddress`: Use provided shipping address. |
| `userAction`String | The next step in the payment flow.Possible values:`PayNow`: Immediate payment capture.`Continue`: Continue to PayPal for payment. |
| `renderType`String | The type of button to render.Possible values:`standalone`: A single button. Choose this when there is only one payment method.`setOfButtons`: Multiple buttons. Choose this when there are multiple payment methods. |
| `fundingSources`Any? | The payment method(s) to support. The type depends on the `renderType`:`String` for `standalone` mode (e.g., `paypal`)`List&lt;String&gt;` for `setOfButtons` mode (e.g., `listOf("paypal", "paylater")`)Possible values:`paypal`: Standard PayPal payments.`paylater`: PayPal Pay Later financing. |
| `shippingAddress`ShippingAddress? | Details about the shipping address. Provide this only when the `shippingPreference` is `SetProvidedAddress`. |
| `shippingOptions`List<ShippingOption>? | Details about the shipping options. Provide this only when the `shippingPreference` is `GetFromFile`. |


### Step 3: Create and render the component

Create and render the component using Jetpack Compose:


```kotlin
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import com.pxp.checkout.types.ComponentType

@Composable
fun PayPalPaymentScreen() {
    val paypalComponent = remember {
        pxpCheckout.createComponent(
            type = ComponentType.PAYPAL,
            config = paypalConfig
        )
    }
    
    // Render the PayPal button
    pxpCheckout.buildComponentView(
        component = paypalComponent,
        modifier = Modifier.fillMaxWidth()
    )
}
```

### Step 4: Handle the payment result

Implement event handling callbacks to manage payment outcomes:


```kotlin
val paypalConfig = PayPalComponentConfig(
    // ... previous config
    onSuccess = { data ->
        // Payment was successful
        Log.d("PayPal", "Payment successful: $data")
        
        // Parse the payment data
        val jsonObject = JSONObject(data)
        val orderID = jsonObject.getString("orderID")
        val payerID = jsonObject.getString("payerID")
        
        // Navigate to success screen or update UI
        navigateToSuccessScreen(orderID)
    },
    
    onError = { error ->
        // Payment failed
        Log.e("PayPal", "Payment error: $error")
        
        // Show error message to user
        showErrorDialog("Payment failed. Please try again.")
    },
    
    onCancel = {
        // User cancelled the payment
        Log.d("PayPal", "Payment cancelled by user")
        
        // Show cancellation message
        showMessage("Payment was cancelled.")
    }
)
```

Pre-built
### Step 1: Initialise the SDK

To get started, initialise the Checkout SDK in your Android application.


```kotlin
import com.pxp.checkout.PxpCheckout
import com.pxp.checkout.models.PxpCheckoutConfig
import com.pxp.checkout.models.Environment
import com.pxp.checkout.models.OwnerType
import com.pxp.checkout.models.TransactionData
import com.pxp.checkout.models.EntryType
import com.pxp.checkout.models.IntentType
import java.util.UUID

val pxpCheckout = PxpCheckout.builder()
    .withConfig(
        PxpCheckoutConfig(
            environment = Environment.TEST,
            session = sessionData,
            ownerId = "Unity",
            ownerType = OwnerType.MERCHANT_GROUP,
            merchantShopperId = "Shopper_01",
            transactionData = TransactionData(
                currency = "USD",
                amount = 2500.0, // Amount in cents ($25.00)
                entryType = EntryType.Ecom,
                intent = IntentType.Purchase,
                merchantTransactionId = UUID.randomUUID().toString(),
                merchantTransactionDate = { System.currentTimeMillis() }
            )
        )
    )
    .withContext(context)
    .build()
```

| Parameter | Description |
|  --- | --- |
| `environment`Environment | The environment type.Possible values:`Environment.TEST`: For sandbox.`Environment.LIVE`: For production. |
| `session`SessionData | Details about the checkout session. |
| `ownerId`String | The identifier of the owner related to the `ownerType`. |
| `ownerType`OwnerType | The type of owner.Possible values:`OwnerType.MERCHANT_GROUP``OwnerType.MERCHANT` `OwnerType.SITE`  |
| `merchantShopperId`String | A unique identifier for this shopper. |
| `transactionData`TransactionData | Details about the transaction. |
| `transactionData.currency`String | The currency code associated with the transaction (e.g., `USD`, `EUR`). |
| `transactionData.amount`Double | The transaction amount in the smallest currency unit (e.g., cents for USD). |
| `transactionData.entryType`EntryType | The entry type.Possible values:`EntryType.Ecom``EntryType.MOTO` |
| `transactionData.intent`IntentType | The transaction intent.Possible values:`IntentType.Authorisation``IntentType.Purchase``IntentType.Verification``IntentType.EstimatedAuthorisation``IntentType.Payout` |
| `transactionData.merchantTransactionId`String | A unique identifier for this transaction. |
| `transactionData.merchantTransactionDate`() -> Long | A function that returns the current timestamp in milliseconds. |


### Step 2: Configuration

Create the PreBuilt PayPal component configuration:


```kotlin
import com.pxp.checkout.components.prebuiltpaypal.PreBuiltPayPalComponentConfig
import com.pxp.checkout.components.paypal.PayPalComponentConfig
import com.pxp.checkout.components.toggle.ToggleComponentConfig

val prebuiltConfig = PreBuiltPayPalComponentConfig(
    paypalConfig = PayPalComponentConfig(
        payeeEmailAddress = "merchant@example.com",
        paymentDescription = "Order #12345",
        shippingPreference = "NoShipping",
        userAction = "PayNow",
        renderType = "standalone",
        fundingSources = "paypal",
        enableOneClickPayment = true, // Enable vaulting
        scriptParams = PayPalScriptParams(
            userIdToken = getUserIdToken() // From vault status check
        )
    ),
    toggleConfig = ToggleComponentConfig(
        label = "Change payment method",
        initialChecked = false
    )
)
```

| Parameter | Description |
|  --- | --- |
| `paypalConfig`PayPalComponentConfig | Configuration for the PayPal component (same parameters as Simple PayPal approach). |
| `toggleConfig`ToggleComponentConfig | Configuration for the toggle component. |
| `paypalConfig.enableOneClickPayment`Boolean | Set to `true` to enable vaulting and one-click payments. |
| `paypalConfig.scriptParams.userIdToken`String? | The user ID token from your vault status check. |


### Step 3: Create and render the component

The PreBuilt component handles all sub-components automatically:


```kotlin
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import com.pxp.checkout.types.ComponentType

@Composable
fun PreBuiltPayPalScreen() {
    val prebuiltComponent = remember {
        pxpCheckout.createComponent(
            type = ComponentType.PREBUILT_PAYPAL,
            config = prebuiltConfig
        )
    }
    
    // Pre-built component handles all sub-components automatically
    pxpCheckout.buildComponentView(
        component = prebuiltComponent,
        modifier = Modifier.fillMaxWidth()
    )
}
```

### Step 4: Handle the payment result

Implement event handling for the PayPal component within the configuration:


```kotlin
val prebuiltConfig = PreBuiltPayPalComponentConfig(
    paypalConfig = PayPalComponentConfig(
        // ... previous config
        onSuccess = { data ->
            Log.d("PayPal", "Payment successful: $data")
            val jsonObject = JSONObject(data)
            val orderID = jsonObject.getString("orderID")
            navigateToSuccessScreen(orderID)
        },
        onError = { error ->
            Log.e("PayPal", "Payment error: $error")
            showErrorDialog("Payment failed. Please try again.")
        },
        onCancel = {
            Log.d("PayPal", "Payment cancelled by user")
            showMessage("Payment was cancelled.")
        }
    ),
    toggleConfig = ToggleComponentConfig(
        label = "Change payment method",
        initialChecked = false
    )
)
```

Custom
### Step 1: Initialise the SDK

To get started, initialise the Checkout SDK in your Android application.


```kotlin
import com.pxp.checkout.PxpCheckout
import com.pxp.checkout.models.PxpCheckoutConfig
import com.pxp.checkout.models.Environment
import com.pxp.checkout.models.OwnerType
import com.pxp.checkout.models.TransactionData
import com.pxp.checkout.models.EntryType
import com.pxp.checkout.models.IntentType
import java.util.UUID

val pxpCheckout = PxpCheckout.builder()
    .withConfig(
        PxpCheckoutConfig(
            environment = Environment.TEST,
            session = sessionData,
            ownerId = "Unity",
            ownerType = OwnerType.MERCHANT_GROUP,
            merchantShopperId = "Shopper_01",
            transactionData = TransactionData(
                currency = "USD",
                amount = 2500.0, // Amount in cents ($25.00)
                entryType = EntryType.Ecom,
                intent = IntentType.Purchase,
                merchantTransactionId = UUID.randomUUID().toString(),
                merchantTransactionDate = { System.currentTimeMillis() }
            )
        )
    )
    .withContext(context)
    .build()
```

| Parameter | Description |
|  --- | --- |
| `environment`Environment | The environment type.Possible values:`Environment.TEST`: For sandbox.`Environment.LIVE`: For production. |
| `session`SessionData | Details about the checkout session. |
| `ownerId`String | The identifier of the owner related to the `ownerType`. |
| `ownerType`OwnerType | The type of owner.Possible values:`OwnerType.MERCHANT_GROUP``OwnerType.MERCHANT` `OwnerType.SITE`  |
| `merchantShopperId`String | A unique identifier for this shopper. |
| `transactionData`TransactionData | Details about the transaction. |
| `transactionData.currency`String | The currency code associated with the transaction (e.g., `"USD"`, `"EUR"`). |
| `transactionData.amount`Double | The transaction amount in the smallest currency unit (e.g., cents for USD). |
| `transactionData.entryType`EntryType | The entry type.Possible values:`EntryType.Ecom``EntryType.MOTO` |
| `transactionData.intent`IntentType | The transaction intent.Possible values:`IntentType.Authorisation``IntentType.Purchase``IntentType.Verification``IntentType.EstimatedAuthorisation``IntentType.Payout` |
| `transactionData.merchantTransactionId`String | A unique identifier for this transaction. |
| `transactionData.merchantTransactionDate`() -> Long | A function that returns the current timestamp in milliseconds. |


### Step 2: Configuration

Create individual components and link them together:


```kotlin
import com.pxp.checkout.components.paypal.PayPalComponentConfig
import com.pxp.checkout.components.paypalconsent.PayPalConsentConfig
import com.pxp.checkout.components.toggle.ToggleComponentConfig

// Create consent component
val consentComponent = pxpCheckout.createComponent(
    type = ComponentType.PAYPAL_CONSENT,
    config = PayPalConsentConfig(
        label = "Save my PayPal account for faster checkout",
        initialChecked = false
    )
)

// Create toggle component
val toggleComponent = pxpCheckout.createComponent(
    type = ComponentType.TOGGLE,
    config = ToggleComponentConfig(
        label = "Use different PayPal account",
        initialChecked = false
    )
)

// Create PayPal component with linked components
val paypalConfig = PayPalComponentConfig(
    payeeEmailAddress = "merchant@example.com",
    paymentDescription = "Order #12345",
    shippingPreference = "NoShipping",
    userAction = "PayNow",
    renderType = "standalone",
    fundingSources = "paypal",
    enableOneClickPayment = true,
    scriptParams = PayPalScriptParams(
        userIdToken = getUserIdToken()
    ),
    // Link the components
    consentComponent = consentComponent,
    toggleComponent = toggleComponent,
    // Handle consent retrieval
    onGetConsent = {
        consentComponent.getValue() as? Boolean ?: false
    }
)
```

| Parameter | Description |
|  --- | --- |
| `consentComponent`Component? | The consent component instance to link to the PayPal component. |
| `toggleComponent`Component? | The toggle component instance to link to the PayPal component. |
| `onGetConsent`() -> Boolean | Callback function to retrieve the consent state from the consent component. |


### Step 3: Create and render the component

Compose the components in your desired layout:


```kotlin
import androidx.compose.foundation.layout.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.pxp.checkout.types.ComponentType

@Composable
fun CustomPayPalScreen() {
    // Create consent component
    val consentComponent = remember {
        pxpCheckout.createComponent(
            type = ComponentType.PAYPAL_CONSENT,
            config = PayPalConsentConfig(
                label = "Save my PayPal account for faster checkout",
                initialChecked = false
            )
        )
    }
    
    // Create toggle component
    val toggleComponent = remember {
        pxpCheckout.createComponent(
            type = ComponentType.TOGGLE,
            config = ToggleComponentConfig(
                label = "Use different PayPal account",
                initialChecked = false
            )
        )
    }
    
    // Create PayPal component with linked components
    val paypalComponent = remember {
        pxpCheckout.createComponent(
            type = ComponentType.PAYPAL,
            config = PayPalComponentConfig(
                // ... configuration with linked components
                consentComponent = consentComponent,
                toggleComponent = toggleComponent,
                onGetConsent = {
                    consentComponent.getValue() as? Boolean ?: false
                }
            )
        )
    }
    
    Column(
        modifier = Modifier.fillMaxWidth(),
        verticalArrangement = Arrangement.spacedBy(16.dp)
    ) {
        // Toggle at the top
        pxpCheckout.buildComponentView(
            component = toggleComponent,
            modifier = Modifier.fillMaxWidth()
        )
        
        // PayPal button in the middle
        pxpCheckout.buildComponentView(
            component = paypalComponent,
            modifier = Modifier.fillMaxWidth()
        )
        
        // Consent at the bottom
        pxpCheckout.buildComponentView(
            component = consentComponent,
            modifier = Modifier.fillMaxWidth()
        )
    }
}
```

### Step 4: Handle the payment result

Implement event handling and manage component interactions:


```kotlin
val paypalConfig = PayPalComponentConfig(
    // ... previous config
    onSuccess = { data ->
        Log.d("PayPal", "Payment successful: $data")
        
        // Check if user consented to save their account
        val consentGiven = consentComponent.getValue() as? Boolean ?: false
        if (consentGiven) {
            Log.d("PayPal", "User consented to save PayPal account")
            // Save vaulting preference
        }
        
        val jsonObject = JSONObject(data)
        val orderID = jsonObject.getString("orderID")
        navigateToSuccessScreen(orderID)
    },
    onError = { error ->
        Log.e("PayPal", "Payment error: $error")
        showErrorDialog("Payment failed. Please try again.")
    },
    onCancel = {
        Log.d("PayPal", "Payment cancelled by user")
        showMessage("Payment was cancelled.")
    }
)
```

## Complete examples

Simple
Here's a complete working example with the PayPal component:


```kotlin
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.pxp.checkout.PxpCheckout
import com.pxp.checkout.components.paypal.PayPalComponentConfig
import com.pxp.checkout.components.paypal.types.*
import com.pxp.checkout.types.ComponentType
import org.json.JSONObject

class SimplePayPalActivity : ComponentActivity() {
    
    private lateinit var pxpCheckout: PxpCheckout
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // Initialise SDK
        pxpCheckout = PxpCheckout.builder()
            .withConfig(sdkConfig)
            .withContext(this)
            .build()
        
        setContent {
            MaterialTheme {
                SimplePayPalScreen()
            }
        }
    }
    
    @Composable
    fun SimplePayPalScreen() {
        var paymentStatus by remember { mutableStateOf<String?>(null) }
        var showSuccessDialog by remember { mutableStateOf(false) }
        var showErrorDialog by remember { mutableStateOf(false) }
        
        val paypalConfig = remember {
            PayPalComponentConfig(
                renderType = "standalone",
                payeeEmailAddress = "merchant@example.com",
                paymentDescription = "Order #12345",
                shippingPreference = "NoShipping",
                userAction = "PayNow",
                fundingSources = "paypal",
                enableOneClickPayment = false,
                style = PayPalButtonStyle(
                    layout = "vertical",
                    color = "gold",
                    shape = "rect",
                    label = "paypal",
                    height = 45
                ),
                onSuccess = { data ->
                    val jsonObject = JSONObject(data)
                    val orderID = jsonObject.getString("orderID")
                    paymentStatus = "Payment successful! Order ID: $orderID"
                    showSuccessDialog = true
                },
                onError = { error ->
                    paymentStatus = "Payment failed: $error"
                    showErrorDialog = true
                },
                onCancel = {
                    paymentStatus = "Payment was cancelled"
                }
            )
        }
        
        val paypalComponent = remember {
            pxpCheckout.createComponent(
                type = ComponentType.PAYPAL,
                config = paypalConfig
            )
        }
        
        Surface(
            modifier = Modifier.fillMaxSize(),
            color = MaterialTheme.colorScheme.background
        ) {
            Column(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(16.dp),
                verticalArrangement = Arrangement.spacedBy(16.dp)
            ) {
                Text(
                    text = "Complete your payment",
                    style = MaterialTheme.typography.headlineMedium
                )
                
                Text(
                    text = "Amount: $25.00",
                    style = MaterialTheme.typography.titleMedium
                )
                
                // PayPal button
                pxpCheckout.buildComponentView(
                    component = paypalComponent,
                    modifier = Modifier.fillMaxWidth()
                )
                
                // Status message
                paymentStatus?.let { status ->
                    Text(
                        text = status,
                        style = MaterialTheme.typography.bodyMedium
                    )
                }
            }
        }
        
        // Success dialog
        if (showSuccessDialog) {
            AlertDialog(
                onDismissRequest = { showSuccessDialog = false },
                title = { Text("Payment Successful") },
                text = { Text(paymentStatus ?: "") },
                confirmButton = {
                    Button(onClick = { 
                        showSuccessDialog = false
                        finish()
                    }) {
                        Text("OK")
                    }
                }
            )
        }
        
        // Error dialog
        if (showErrorDialog) {
            AlertDialog(
                onDismissRequest = { showErrorDialog = false },
                title = { Text("Payment Error") },
                text = { Text(paymentStatus ?: "") },
                confirmButton = {
                    Button(onClick = { showErrorDialog = false }) {
                        Text("OK")
                    }
                }
            )
        }
    }
}
```

Pre-built
Here's a complete working example with one-click payment support:


```kotlin
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.pxp.checkout.PxpCheckout
import com.pxp.checkout.components.prebuiltpaypal.PreBuiltPayPalComponentConfig
import com.pxp.checkout.components.paypal.PayPalComponentConfig
import com.pxp.checkout.components.toggle.ToggleComponentConfig
import com.pxp.checkout.types.ComponentType
import org.json.JSONObject

class PreBuiltPayPalActivity : ComponentActivity() {
    
    private lateinit var pxpCheckout: PxpCheckout
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // Initialise SDK
        pxpCheckout = PxpCheckout.builder()
            .withConfig(sdkConfig)
            .withContext(this)
            .build()
        
        setContent {
            MaterialTheme {
                PreBuiltPayPalScreen()
            }
        }
    }
    
    @Composable
    fun PreBuiltPayPalScreen() {
        var paymentStatus by remember { mutableStateOf<String?>(null) }
        var showSuccessDialog by remember { mutableStateOf(false) }
        
        val prebuiltConfig = remember {
            PreBuiltPayPalComponentConfig(
                paypalConfig = PayPalComponentConfig(
                    renderType = "standalone",
                    payeeEmailAddress = "merchant@example.com",
                    paymentDescription = "Order #12345",
                    shippingPreference = "NoShipping",
                    userAction = "PayNow",
                    fundingSources = "paypal",
                    enableOneClickPayment = true,
                    scriptParams = PayPalScriptParams(
                        userIdToken = getUserIdToken()
                    ),
                    style = PayPalButtonStyle(
                        layout = "vertical",
                        color = "blue",
                        shape = "pill",
                        label = "buynow",
                        height = 45
                    ),
                    onSuccess = { data ->
                        val jsonObject = JSONObject(data)
                        val orderID = jsonObject.getString("orderID")
                        paymentStatus = "Payment successful! Order ID: $orderID"
                        showSuccessDialog = true
                    },
                    onError = { error ->
                        paymentStatus = "Payment failed: $error"
                    },
                    onCancel = {
                        paymentStatus = "Payment was cancelled"
                    }
                ),
                toggleConfig = ToggleComponentConfig(
                    label = "Change payment method",
                    initialChecked = false
                )
            )
        }
        
        val prebuiltComponent = remember {
            pxpCheckout.createComponent(
                type = ComponentType.PREBUILT_PAYPAL,
                config = prebuiltConfig
            )
        }
        
        Surface(
            modifier = Modifier.fillMaxSize(),
            color = MaterialTheme.colorScheme.background
        ) {
            Column(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(16.dp),
                verticalArrangement = Arrangement.spacedBy(16.dp)
            ) {
                Text(
                    text = "Complete your payment",
                    style = MaterialTheme.typography.headlineMedium
                )
                
                Text(
                    text = "Amount: $25.00",
                    style = MaterialTheme.typography.titleMedium
                )
                
                Text(
                    text = "One-click payment enabled",
                    style = MaterialTheme.typography.bodySmall,
                    color = MaterialTheme.colorScheme.primary
                )
                
                // Pre-built PayPal component
                pxpCheckout.buildComponentView(
                    component = prebuiltComponent,
                    modifier = Modifier.fillMaxWidth()
                )
                
                // Status message
                paymentStatus?.let { status ->
                    Text(
                        text = status,
                        style = MaterialTheme.typography.bodyMedium
                    )
                }
            }
        }
        
        // Success dialog
        if (showSuccessDialog) {
            AlertDialog(
                onDismissRequest = { showSuccessDialog = false },
                title = { Text("Payment Successful") },
                text = { Text(paymentStatus ?: "") },
                confirmButton = {
                    Button(onClick = { 
                        showSuccessDialog = false
                        finish()
                    }) {
                        Text("OK")
                    }
                }
            )
        }
    }
    
    private fun getUserIdToken(): String? {
        // Check vault status and return user ID token if available
        // This would typically come from your backend or vault service
        return null // Return actual token when user has vaulted account
    }
}
```

Custom
Here's a complete working example with custom component composition:


```kotlin
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.pxp.checkout.PxpCheckout
import com.pxp.checkout.components.paypal.PayPalComponentConfig
import com.pxp.checkout.components.paypalconsent.PayPalConsentConfig
import com.pxp.checkout.components.toggle.ToggleComponentConfig
import com.pxp.checkout.types.ComponentType
import org.json.JSONObject

class CustomCompositionActivity : ComponentActivity() {
    
    private lateinit var pxpCheckout: PxpCheckout
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // Initialise SDK
        pxpCheckout = PxpCheckout.builder()
            .withConfig(sdkConfig)
            .withContext(this)
            .build()
        
        setContent {
            MaterialTheme {
                CustomPayPalScreen()
            }
        }
    }
    
    @Composable
    fun CustomPayPalScreen() {
        var paymentStatus by remember { mutableStateOf<String?>(null) }
        var showSuccessDialog by remember { mutableStateOf(false) }
        
        // Create consent component
        val consentComponent = remember {
            pxpCheckout.createComponent(
                type = ComponentType.PAYPAL_CONSENT,
                config = PayPalConsentConfig(
                    label = "Save my PayPal account for faster checkout",
                    initialChecked = false
                )
            )
        }
        
        // Create toggle component
        val toggleComponent = remember {
            pxpCheckout.createComponent(
                type = ComponentType.TOGGLE,
                config = ToggleComponentConfig(
                    label = "Use different PayPal account",
                    initialChecked = false
                )
            )
        }
        
        // Create PayPal component with linked components
        val paypalComponent = remember {
            pxpCheckout.createComponent(
                type = ComponentType.PAYPAL,
                config = PayPalComponentConfig(
                    renderType = "standalone",
                    payeeEmailAddress = "merchant@example.com",
                    paymentDescription = "Order #12345",
                    shippingPreference = "NoShipping",
                    userAction = "PayNow",
                    fundingSources = "paypal",
                    enableOneClickPayment = true,
                    scriptParams = PayPalScriptParams(
                        userIdToken = getUserIdToken()
                    ),
                    style = PayPalButtonStyle(
                        layout = "vertical",
                        color = "gold",
                        shape = "rect",
                        label = "checkout",
                        height = 45
                    ),
                    consentComponent = consentComponent,
                    toggleComponent = toggleComponent,
                    onGetConsent = {
                        consentComponent.getValue() as? Boolean ?: false
                    },
                    onSuccess = { data ->
                        val jsonObject = JSONObject(data)
                        val orderID = jsonObject.getString("orderID")
                        
                        val consentGiven = consentComponent.getValue() as? Boolean ?: false
                        paymentStatus = if (consentGiven) {
                            "Payment successful! Order ID: $orderID (Account saved)"
                        } else {
                            "Payment successful! Order ID: $orderID"
                        }
                        showSuccessDialog = true
                    },
                    onError = { error ->
                        paymentStatus = "Payment failed: $error"
                    },
                    onCancel = {
                        paymentStatus = "Payment was cancelled"
                    }
                )
            )
        }
        
        Surface(
            modifier = Modifier.fillMaxSize(),
            color = MaterialTheme.colorScheme.background
        ) {
            Column(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(16.dp),
                verticalArrangement = Arrangement.spacedBy(16.dp)
            ) {
                Text(
                    text = "Complete your payment",
                    style = MaterialTheme.typography.headlineMedium
                )
                
                Text(
                    text = "Amount: $25.00",
                    style = MaterialTheme.typography.titleMedium
                )
                
                Card(
                    modifier = Modifier.fillMaxWidth(),
                    colors = CardDefaults.cardColors(
                        containerColor = MaterialTheme.colorScheme.surfaceVariant
                    )
                ) {
                    Column(
                        modifier = Modifier.padding(16.dp),
                        verticalArrangement = Arrangement.spacedBy(12.dp)
                    ) {
                        // Toggle at the top
                        pxpCheckout.buildComponentView(
                            component = toggleComponent,
                            modifier = Modifier.fillMaxWidth()
                        )
                        
                        Divider()
                        
                        // PayPal button in the middle
                        pxpCheckout.buildComponentView(
                            component = paypalComponent,
                            modifier = Modifier.fillMaxWidth()
                        )
                        
                        // Consent at the bottom
                        pxpCheckout.buildComponentView(
                            component = consentComponent,
                            modifier = Modifier.fillMaxWidth()
                        )
                    }
                }
                
                // Status message
                paymentStatus?.let { status ->
                    Text(
                        text = status,
                        style = MaterialTheme.typography.bodyMedium
                    )
                }
            }
        }
        
        // Success dialog
        if (showSuccessDialog) {
            AlertDialog(
                onDismissRequest = { showSuccessDialog = false },
                title = { Text("Payment Successful") },
                text = { Text(paymentStatus ?: "") },
                confirmButton = {
                    Button(onClick = { 
                        showSuccessDialog = false
                        finish()
                    }) {
                        Text("OK")
                    }
                }
            )
        }
    }
    
    private fun getUserIdToken(): String? {
        // Check vault status and return user ID token if available
        return null
    }
}
```

## What's next?

### Customise the look and feel

You can configure the appearance and behaviour of the PayPal component to fit your brand. We've documented all configurable parameters in the [Configuration](/guides/checkout/components/android/paypal/about-configuration) section.


```kotlin
val paypalConfig = PayPalComponentConfig(
    renderType = "standalone",
    payeeEmailAddress = "merchant@example.com",
    paymentDescription = "Premium Subscription",
    shippingPreference = "NoShipping",
    userAction = "PayNow",
    fundingSources = "paypal",
    locale = "en-US",
    style = PayPalButtonStyle(
        layout = "horizontal",
        color = "blue",
        shape = "pill",
        label = "buynow",
        height = 45,
        borderRadius = 4
    ),
    queryParams = PayPalQueryParams(
        buyerCountry = "US",
        debug = false
    )
)
```

### Add more event handling

The PayPal component emits events based on user interaction or validation. As seen in the steps above, you can implement callback functions to handle these events. For more information about all the available events, see the [Events](/guides/checkout/components/android/paypal/events) page.


```kotlin
val paypalConfig = PayPalComponentConfig(
    onShippingAddressChange = { data ->
        // Validate shipping address
        val isValid = validateShippingAddress(data)
        if (isValid) null else "reject:INVALID_ADDRESS"
    },
    onShippingOptionsChange = { data ->
        // Handle shipping option changes
        updateShippingCosts(data)
        null
    }
)
```

### Add error handling

Error handling is crucial for payment components because they deal with sensitive financial data and complex validation rules. For more details about error handling, see the [Troubleshooting](/guides/checkout/components/android/paypal/troubleshooting) page.


```kotlin
try {
    val paypalComponent = pxpCheckout.createComponent(
        type = ComponentType.PAYPAL,
        config = paypalConfig
    )
    
    pxpCheckout.buildComponentView(
        component = paypalComponent,
        modifier = Modifier.fillMaxWidth()
    )
} catch (e: Exception) {
    Log.e("PayPal", "Failed to initialise PayPal component", e)
    
    // Show fallback UI or error message to user
    Text(
        text = "Payment system temporarily unavailable. Please try again later.",
        color = MaterialTheme.colorScheme.error
    )
}
```

### Subscribe to webhooks

To get real-time updates about PayPal transactions, you can subscribe to the PayPal webhooks in the Unity Portal.