Learn how to use the Google Pay component for Android in your project.
Every component follows the same basic two-step lifecycle:
- Create the component and configure it with your settings.
- Render the component using Jetpack Compose. This makes the component visible and interactive. Cleanup happens automatically when the Composable leaves composition.
To use the Google Pay button component, you first need to:
- Install the Android SDK.
- Complete the Google Pay onboarding process in the Unity Portal. See Onboarding for details.
- Configure your Google Pay merchant account and link it to the Unity Portal.
To get started, initialise the PXP Checkout SDK with your merchant credentials and transaction data.
import com.pxp.PxpCheckout
import com.pxp.checkout.models.*
import com.pxp.checkout.services.models.transaction.Shopper
import java.text.SimpleDateFormat
import java.util.*
class PaymentActivity : ComponentActivity() {
private lateinit var pxpCheckout: PxpCheckout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Get session config from your backend API
val sessionConfig = fetchSessionFromYourBackend()
// Initialise PxpCheckout SDK
pxpCheckout = PxpCheckout.builder()
.withConfig(
PxpSdkConfig(
environment = Environment.TEST,
session = sessionConfig,
ownerId = "your-owner-id",
ownerType = "MerchantGroup",
kountDisabled = false, // OPTIONAL: Set to true to disable Kount fraud detection
transactionData = TransactionData(
amount = 99.99,
currency = "GBP",
merchant = "your-merchant-id",
merchantTransactionId = UUID.randomUUID().toString(),
merchantTransactionDate = {
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US)
.apply { timeZone = TimeZone.getTimeZone("UTC") }
.format(Date())
},
entryType = EntryType.Ecom,
intent = TransactionIntentData(
card = IntentType.Authorisation
)
),
onGetShopper = {
// Return current shopper data dynamically
Shopper(
id = "shopper-${System.currentTimeMillis()}",
email = "customer@example.com",
firstName = "John",
lastName = "Doe"
)
},
onGetShippingAddress = {
// Return current shipping address dynamically (optional)
ShippingAddress(
addressLine1 = "123 Main Street",
city = "London",
postalCode = "SW1A 1AA",
countryCode = "GB"
)
}
)
)
.withContext(this)
.build()
setContent {
YourAppTheme {
PaymentScreen(pxpCheckout = pxpCheckout)
}
}
}
private fun fetchSessionFromYourBackend(): SessionConfig {
// Call your merchant backend API to create a session
// Your backend should call PXP API to create a session
return SessionConfig(
sessionId = "session-123",
hmacKey = "hmac-key",
data = "session-data",
encryptionKey = "encryption-key",
locale = "en-GB"
)
}
}| Parameter | Description |
|---|---|
environmentEnvironment required | The environment type. Possible values:
|
sessionSessionConfig required | Session configuration obtained from your backend. |
session.sessionIdString required | Unique session identifier. |
session.hmacKeyString required | HMAC key for session validation. |
session.dataString required | Session data payload. |
session.encryptionKeyString required | Encryption key for secure data transmission. |
ownerIdString required | The identifier of the owner. |
ownerTypeString required | The type of owner. Use "MerchantGroup". |
kountDisabledBoolean | Whether to disable the Kount fraud detection service. Defaults to false (fraud detection enabled). |
onGetShopper() -> Shopper? | Callback function to provide shopper data dynamically. Returns Shopper object from com.pxp.checkout.services.models.transaction package with shopper information including ID, email, name, and contact details. Required when using consent tokens for storing payment methods. |
onGetShippingAddress() -> ShippingAddress? | Callback function to provide shipping address dynamically. Returns ShippingAddress object from com.pxp.checkout.models package with shipping address information. Optional. |
transactionDataTransactionData required | Details about the transaction. |
transactionData.amountDouble required | Transaction amount. |
transactionData.currencyString (3 characters) required | Currency code in ISO 4217 format (e.g., "GBP", "USD", "EUR"). |
transactionData.merchantString required | Your merchant identifier. |
transactionData.merchantTransactionIdString required | Your unique identifier for this transaction. |
transactionData.merchantTransactionDate() -> String required | Function that returns the transaction date in ISO 8601 format. |
transactionData.entryTypeEntryType | Entry type. Use EntryType.Ecom for e-commerce transactions. |
transactionData.intentTransactionIntentData | Transaction intents for each payment method. Possible values for card:
|
Create the configuration for your Google Pay button with payment settings and event handlers.
The SDK automatically configures tokenizationSpecification and merchantInfo with the correct gateway, merchant ID, and merchant name from your session. You only need to provide allowedPaymentMethods with the card parameters and transactionInfo.
import com.pxp.checkout.components.googlepay.types.*
import com.pxp.checkout.services.kount.*
import com.pxp.checkout.models.MerchantSubmitResult
import com.pxp.checkout.models.FailedSubmitResult
val googlePayConfig = GooglePayButtonComponentConfig().apply {
// Button style
style = GooglePayButtonStyle(
type = GooglePayButtonType.PAY,
theme = GooglePayButtonTheme.DARK,
cornerRadius = 8
)
// Payment data request (REQUIRED)
paymentDataRequest = PaymentDataRequest(
allowedPaymentMethods = listOf(
PaymentMethodSpecification(
parameters = PaymentMethodParameters(
allowedCardNetworks = listOf(
CardNetwork.VISA,
CardNetwork.MASTERCARD,
CardNetwork.AMEX
),
allowedAuthMethods = listOf(
CardAuthMethod.PAN_ONLY,
CardAuthMethod.CRYPTOGRAM_3DS
)
)
)
),
transactionInfo = TransactionInfo(
currencyCode = "GBP",
totalPriceStatus = TotalPriceStatus.FINAL,
totalPrice = "99.99"
)
)
// Pre-authorisation callback
onPreAuthorisation = suspend { preAuthData ->
Log.d("GooglePay", "Processing payment")
// Return risk screening data
GooglePayTransactionInitData(
riskScreeningData = RiskScreeningData(
performRiskScreening = true,
excludeDeviceData = false,
userIp = "192.168.1.100",
account = RiskScreeningAccount(
id = "user_12345678",
creationDateTime = "2024-01-15T10:30:00.000Z"
),
items = listOf(
RiskScreeningItem(
price = 99.99,
quantity = 1,
category = "Electronics",
sku = "GPAY-001"
)
),
fulfillments = listOf(
RiskScreeningFulfillment(
type = FulfillmentType.SHIPPED,
shipping = RiskScreeningShipping(
shippingMethod = ShippingMethod.STANDARD
),
recipientPerson = RiskScreeningRecipientPerson(
phoneNumber = "+1234567890"
)
)
)
)
)
}
// Handle successful payment
onPostAuthorisation = { result, paymentData ->
when (result) {
is MerchantSubmitResult -> {
Log.d("GooglePay", "Payment successful: ${result.systemTransactionId}")
handlePaymentSuccess(result)
}
is FailedSubmitResult -> {
Log.e("GooglePay", "Payment failed: ${result.errorReason}")
handlePaymentFailure(result)
}
}
}
// Handle errors
onError = { error ->
Log.e("GooglePay", "Error: ${error.message}")
showError(error.message)
}
}Create the Google Pay component and render it in your Compose UI.
import com.pxp.checkout.components.googlepay.GooglePayButtonComponent
import com.pxp.checkout.types.ComponentType
@Composable
fun PaymentScreen(pxpCheckout: PxpCheckout) {
val googlePayComponent = remember {
pxpCheckout.createComponent<GooglePayButtonComponent, GooglePayButtonComponentConfig>(
type = ComponentType.GOOGLE_PAY_BUTTON,
config = googlePayConfig
)
}
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Complete your purchase",
style = MaterialTheme.typography.headlineMedium,
modifier = Modifier.padding(bottom = 16.dp)
)
// Render the Google Pay button
googlePayComponent?.Content(
modifier = Modifier
.fillMaxWidth()
.height(56.dp)
)
}
}Here's a complete working example that puts everything together:
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.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.lifecycleScope
import com.pxp.PxpCheckout
import com.pxp.checkout.components.googlepay.GooglePayButtonComponent
import com.pxp.checkout.components.googlepay.types.*
import com.pxp.checkout.models.*
import com.pxp.checkout.services.kount.*
import com.pxp.checkout.services.models.transaction.Shopper
import com.pxp.checkout.types.ComponentType
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.*
class MainActivity : ComponentActivity() {
private lateinit var pxpCheckout: PxpCheckout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launch {
// Initialise SDK
pxpCheckout = initializeSDK()
setContent {
MaterialTheme {
GooglePayScreen(pxpCheckout)
}
}
}
}
private suspend fun initializeSDK(): PxpCheckout {
val sessionConfig = fetchSessionFromYourBackend()
return PxpCheckout.builder()
.withConfig(
PxpSdkConfig(
environment = Environment.TEST,
session = sessionConfig,
ownerId = "your-owner-id",
ownerType = "MerchantGroup",
kountDisabled = false,
transactionData = TransactionData(
amount = 99.99,
currency = "GBP",
merchant = "your-merchant-id",
merchantTransactionId = UUID.randomUUID().toString(),
merchantTransactionDate = {
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US)
.apply { timeZone = TimeZone.getTimeZone("UTC") }
.format(Date())
},
entryType = EntryType.Ecom,
intent = TransactionIntentData(
card = IntentType.Authorisation
)
),
onGetShopper = {
Shopper(
id = "shopper-${System.currentTimeMillis()}",
email = "customer@example.com",
firstName = "John",
lastName = "Doe"
)
},
onGetShippingAddress = {
ShippingAddress(
addressLine1 = "123 Main Street",
city = "London",
postalCode = "SW1A 1AA",
countryCode = "GB"
)
}
)
)
.withContext(this)
.build()
}
private suspend fun fetchSessionFromYourBackend(): SessionConfig {
// Call your backend to fetch session
return SessionConfig(
sessionId = "session-123",
hmacKey = "hmac-key",
data = "session-data",
encryptionKey = "encryption-key",
locale = "en-GB"
)
}
}
@Composable
fun GooglePayScreen(pxpCheckout: PxpCheckout) {
var showSuccess by remember { mutableStateOf(false) }
var errorMessage by remember { mutableStateOf<String?>(null) }
val googlePayConfig = remember {
GooglePayButtonComponentConfig().apply {
style = GooglePayButtonStyle(
type = GooglePayButtonType.PAY,
theme = GooglePayButtonTheme.DARK,
cornerRadius = 8
)
paymentDataRequest = PaymentDataRequest(
allowedPaymentMethods = listOf(
PaymentMethodSpecification(
parameters = PaymentMethodParameters(
allowedCardNetworks = listOf(
CardNetwork.VISA,
CardNetwork.MASTERCARD,
CardNetwork.AMEX
),
allowedAuthMethods = listOf(
CardAuthMethod.PAN_ONLY,
CardAuthMethod.CRYPTOGRAM_3DS
)
)
)
),
transactionInfo = TransactionInfo(
currencyCode = "GBP",
totalPriceStatus = TotalPriceStatus.FINAL,
totalPrice = "99.99"
)
)
onPreAuthorisation = suspend { preAuthData ->
GooglePayTransactionInitData(
riskScreeningData = RiskScreeningData(
performRiskScreening = true,
excludeDeviceData = false,
userIp = "192.168.1.100",
account = RiskScreeningAccount(
id = "user_12345678",
creationDateTime = "2024-01-15T10:30:00.000Z"
),
fulfillments = listOf(
RiskScreeningFulfillment(
type = FulfillmentType.SHIPPED,
recipientPerson = RiskScreeningRecipientPerson(
phoneNumber = "+1234567890"
)
)
)
)
)
}
onPostAuthorisation = { result, paymentData ->
when (result) {
is MerchantSubmitResult -> {
showSuccess = true
}
is FailedSubmitResult -> {
errorMessage = result.errorReason
}
}
}
onError = { error ->
errorMessage = error.message
}
}
}
val googlePayComponent = remember {
pxpCheckout.createComponent<GooglePayButtonComponent, GooglePayButtonComponentConfig>(
type = ComponentType.GOOGLE_PAY_BUTTON,
config = googlePayConfig
)
}
Scaffold { paddingValues ->
Column(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
if (showSuccess) {
Text(
text = "✓ Payment Successful!",
style = MaterialTheme.typography.headlineMedium,
color = MaterialTheme.colorScheme.primary
)
} else {
Text(
text = "Complete your purchase",
style = MaterialTheme.typography.headlineMedium,
modifier = Modifier.padding(bottom = 24.dp)
)
googlePayComponent?.Content(
modifier = Modifier
.fillMaxWidth()
.height(56.dp)
)
errorMessage?.let { error ->
Text(
text = error,
color = MaterialTheme.colorScheme.error,
modifier = Modifier.padding(top = 16.dp)
)
}
}
}
}
}Now that you've implemented the basic Google Pay integration, you can:
- Configure 3D Secure authentication for enhanced security.
- Set up recurring payments to enable subscriptions.
- Implement CVC collection for additional security.
- Handle payment events to track the payment lifecycle.