Learn how to use the PayPal components in your Android project.
Every component follows the same basic three-step lifecycle:
- Create the component and optionally add your own configuration.
- Render the component using Jetpack Compose. This is what makes the component visible and interactive.
- Dispose the component. This is a clean-up step that clears up resources and is handled automatically by Compose.
To use the PayPal components, you first need to:
- Install Components for Android.
- Complete the PayPal onboarding process in the Unity Portal.
- Configure your
gradle.propertieswith the required environment variables.
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:
DisposableEffect(paypalComponent) {
onDispose {
// Component resources are automatically cleaned up
Log.d("PayPal", "Component disposed")
}
}To get started, initialise the Checkout SDK in your Android application.
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 |
|---|---|
environmentEnvironment required | The environment type. Possible values:
|
sessionSessionData required | Details about the checkout session. |
ownerIdString required | The identifier of the owner related to the ownerType. |
ownerTypeOwnerType required | The type of owner. Possible values:
|
merchantShopperIdString required | A unique identifier for this shopper. |
transactionDataTransactionData required | Details about the transaction. |
transactionData.currencyString | The currency code associated with the transaction (e.g., USD, EUR). |
transactionData.amountDouble required | The transaction amount in the smallest currency unit (e.g., cents for USD). |
transactionData.entryTypeEntryType required | The entry type. Possible values:
|
transactionData.intentIntentType required | The transaction intent. Possible values:
|
transactionData.merchantTransactionIdString required | A unique identifier for this transaction. |
transactionData.merchantTransactionDate() -> Long required | A function that returns the current timestamp in milliseconds. |
Create the PayPal component configuration with basic settings:
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 |
|---|---|
payeeEmailAddressString? | Your email address. |
paymentDescriptionString? | A description of the payment. |
shippingPreferenceString required | The shipping details to use. Possible values:
|
userActionString required | The next step in the payment flow. Possible values:
|
renderTypeString required | The type of button to render. Possible values:
|
fundingSourcesAny? required | The payment method(s) to support. The type depends on the renderType:
Possible values:
|
shippingAddressShippingAddress? | Details about the shipping address. Provide this only when the shippingPreference is SetProvidedAddress. |
shippingOptionsList<ShippingOption>? | Details about the shipping options. Provide this only when the shippingPreference is GetFromFile. |
Create and render the component using Jetpack Compose:
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()
)
}Implement event handling callbacks to manage payment outcomes:
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.")
}
)Here's a complete working example with the PayPal component:
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")
}
}
)
}
}
}You can configure the appearance and behaviour of the PayPal component to fit your brand. We've documented all configurable parameters in the Configuration section.
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
)
)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 page.
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
}
)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 page.
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
)
}To get real-time updates about PayPal transactions, you can subscribe to the PayPal webhooks in the Unity Portal.