{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-guides/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["sub-heading","admonition","br","details","required"]},"type":"markdown"},"seo":{"title":"Configuration","description":"Transform your commerce with PXP's unified platform—seamless payments, real-time insights, and global growth in one powerful integration.","lang":"en-UK","siteUrl":"https://developer.pxp.io","llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"configuration","__idx":0},"children":["Configuration"]},{"$$mdtype":"Tag","name":"SubHeading","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Learn how to configure the Google Pay button component for Android with Kotlin and Jetpack Compose."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"basic-usage","__idx":1},"children":["Basic usage"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"minimal-configuration","__idx":2},"children":["Minimal configuration"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["At minimum, the Google Pay button component requires the following configuration to function:"]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The SDK automatically configures tokenisation with the correct gateway and merchant ID from your session. You only need to provide ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["allowedPaymentMethods"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["transactionInfo"]},"."]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"import com.pxp.checkout.components.googlepay.types.*\n\nval config = GooglePayButtonComponentConfig().apply {\n    paymentDataRequest = PaymentDataRequest(\n        allowedPaymentMethods = listOf(\n            PaymentMethodSpecification(\n                parameters = PaymentMethodParameters(\n                    allowedCardNetworks = listOf(\n                        CardNetwork.VISA,\n                        CardNetwork.MASTERCARD\n                    ),\n                    allowedAuthMethods = listOf(\n                        CardAuthMethod.PAN_ONLY,\n                        CardAuthMethod.CRYPTOGRAM_3DS\n                    )\n                )\n            )\n        ),\n        transactionInfo = TransactionInfo(\n            currencyCode = \"USD\",\n            totalPriceStatus = TotalPriceStatus.FINAL,\n            totalPrice = \"99.99\"\n        )\n    )\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"width":"50%","data-label":"Property"},"children":["Property "]},{"$$mdtype":"Tag","name":"th","attributes":{"width":"50%","data-label":"Description"},"children":["Description "]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paymentDataRequest"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["PaymentDataRequest"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Required","attributes":{},"children":[]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The Google Pay payment request configuration containing payment methods and transaction details."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paymentDataRequest.allowedPaymentMethods"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["List<PaymentMethodSpecification>"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Required","attributes":{},"children":[]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["List of supported payment methods. At least one payment method is required."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paymentDataRequest.allowedPaymentMethods[].parameters"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["PaymentMethodParameters"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Required","attributes":{},"children":[]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Payment method parameters including card networks and authentication methods."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paymentDataRequest.allowedPaymentMethods[].parameters.allowedCardNetworks"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["List<CardNetwork>"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Required","attributes":{},"children":[]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Supported card networks.",{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},"Possible values:",{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["VISA"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MASTERCARD"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["AMEX"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["DISCOVER"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["JCB"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["INTERAC"]}]}]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paymentDataRequest.allowedPaymentMethods[].parameters.allowedAuthMethods"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["List<CardAuthMethod>"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Required","attributes":{},"children":[]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Supported authentication methods.",{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},"Possible values:",{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PAN_ONLY"]},": Unencrypted card details"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CRYPTOGRAM_3DS"]},": 3DS cryptogram authentication"]}]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paymentDataRequest.transactionInfo"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["TransactionInfo"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Required","attributes":{},"children":[]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Details about the transaction, including the amount and currency."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paymentDataRequest.transactionInfo.currencyCode"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["String"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Required","attributes":{},"children":[]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The currency code, in ISO 4217 format (e.g., ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["USD"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GBP"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["EUR"]},")."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paymentDataRequest.transactionInfo.totalPriceStatus"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["TotalPriceStatus"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Required","attributes":{},"children":[]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The price finality status.",{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},"Possible values:",{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["FINAL"]},": Price is final"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ESTIMATED"]},": Price is estimated"]}]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paymentDataRequest.transactionInfo.totalPrice"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["String"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Required","attributes":{},"children":[]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The total monetary value of the transaction as a string (e.g., ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["99.99"]},")."]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"advanced-configuration","__idx":3},"children":["Advanced configuration"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For more complex implementations, you can configure additional settings and features:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"import com.pxp.checkout.components.googlepay.types.*\nimport com.pxp.checkout.services.kount.*\n\nval config = GooglePayButtonComponentConfig().apply {\n    // Payment details\n    paymentDataRequest = PaymentDataRequest(\n        allowedPaymentMethods = listOf(\n            PaymentMethodSpecification(\n                parameters = PaymentMethodParameters(\n                    allowedCardNetworks = listOf(\n                        CardNetwork.VISA,\n                        CardNetwork.MASTERCARD,\n                        CardNetwork.AMEX\n                    ),\n                    allowedAuthMethods = listOf(\n                        CardAuthMethod.PAN_ONLY,\n                        CardAuthMethod.CRYPTOGRAM_3DS\n                    ),\n                    billingAddressRequired = true,\n                    billingAddressParameters = BillingAddressParameters(\n                        format = BillingAddressFormat.FULL,\n                        phoneNumberRequired = true\n                    )\n                )\n            )\n        ),\n        transactionInfo = TransactionInfo(\n            currencyCode = \"USD\",\n            totalPriceStatus = TotalPriceStatus.FINAL,\n            totalPrice = \"99.99\",\n            countryCode = \"US\"\n        ),\n        emailRequired = true,\n        shippingAddressRequired = false\n    )\n    \n    // Button appearance\n    style = GooglePayButtonStyle(\n        type = GooglePayButtonType.BUY,\n        theme = GooglePayButtonTheme.DARK,\n        cornerRadius = 8\n    )\n    \n    // Enable 3DS authentication\n    useUnityAuthenticationStrategy = true\n    \n    // CVC collection\n    collectCvc = GooglePayButtonComponentConfig.CvcCollectionStrategy.DEFAULT\n    \n    // Event callbacks\n    onPreAuthorisation = suspend { data ->\n        GooglePayTransactionInitData(\n            riskScreeningData = RiskScreeningData(\n                performRiskScreening = true,\n                excludeDeviceData = false,\n                userIp = \"192.168.1.100\",\n                account = RiskScreeningAccount(\n                    id = \"user_12345678\",\n                    creationDateTime = \"2024-01-15T10:30:00.000Z\"\n                ),\n                fulfillments = listOf(\n                    RiskScreeningFulfillment(\n                        type = FulfillmentType.SHIPPED,\n                        recipientPerson = RiskScreeningRecipientPerson(\n                            phoneNumber = \"+1234567890\"\n                        )\n                    )\n                )\n            )\n        )\n    }\n    \n    onPostAuthorisation = { result, paymentData ->\n        when (result) {\n            is MerchantSubmitResult -> handleSuccess(result)\n            is FailedSubmitResult -> handleFailure(result)\n        }\n    }\n    \n    onError = { error ->\n        Log.e(\"GooglePay\", \"Error: ${error.message}\")\n    }\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"styling","__idx":4},"children":["Styling"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"button-types-and-themes","__idx":5},"children":["Button types and themes"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The Google Pay button can be customised to match your app's design:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"style = GooglePayButtonStyle(\n    type = GooglePayButtonType.CHECKOUT,  // Button text\n    theme = GooglePayButtonTheme.DARK,    // Color theme\n    cornerRadius = 12                     // Corner radius in dp\n)\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"button-types","__idx":6},"children":["Button types"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"enum class GooglePayButtonType {\n    BUY,        // \"Buy with G Pay\"\n    PAY,        // \"Pay with G Pay\" (default)\n    CHECKOUT,   // \"Checkout with G Pay\"\n    BOOK,       // \"Book with G Pay\"\n    DONATE,     // \"Donate with G Pay\"\n    ORDER,      // \"Order with G Pay\"\n    SUBSCRIBE,  // \"Subscribe with G Pay\"\n    PLAIN       // Google Pay logo only\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"themes","__idx":7},"children":["Themes"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"enum class GooglePayButtonTheme {\n    DARK,   // Black background with white text\n    LIGHT   // White background with black text\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"button-sizing","__idx":8},"children":["Button sizing"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Control button size using standard Compose modifiers:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"googlePayComponent?.Content(\n    modifier = Modifier\n        .fillMaxWidth()    // Full width\n        .height(48.dp)     // Fixed height\n)\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"event-callbacks","__idx":9},"children":["Event callbacks"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Configure callbacks to handle payment events. See ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/checkout/components/android/google-pay/events"},"children":["Events"]}," for detailed documentation."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"essential-callbacks","__idx":10},"children":["Essential callbacks"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"val config = GooglePayButtonComponentConfig().apply {\n    // Before payment authorisation\n    onPreAuthorisation = suspend { data ->\n        GooglePayTransactionInitData(\n            riskScreeningData = RiskScreeningData(\n                performRiskScreening = true,\n                excludeDeviceData = false,\n                userIp = \"192.168.1.100\",\n                account = RiskScreeningAccount(\n                    id = \"user_12345678\",\n                    creationDateTime = \"2024-01-15T10:30:00.000Z\"\n                ),\n                fulfillments = listOf(\n                    RiskScreeningFulfillment(\n                        type = FulfillmentType.SHIPPED,\n                        recipientPerson = RiskScreeningRecipientPerson(\n                            phoneNumber = \"+1234567890\"\n                        )\n                    )\n                )\n            )\n        )\n    }\n    \n    // After payment authorisation\n    onPostAuthorisation = { result, paymentData ->\n        when (result) {\n            is MerchantSubmitResult -> {\n                Log.d(\"GooglePay\", \"Success: ${result.merchantTransactionId}\")\n                navigateToSuccess()\n            }\n            is FailedSubmitResult -> {\n                Log.e(\"GooglePay\", \"Failed: ${result.errorReason}\")\n                showError(result.errorReason)\n            }\n        }\n    }\n    \n    // Error handling\n    onError = { error ->\n        Log.e(\"GooglePay\", \"Error: ${error.message}\", error)\n        showError(error.message)\n    }\n    \n    // User cancellation\n    onCancel = {\n        Log.d(\"GooglePay\", \"Payment cancelled\")\n    }\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"payment-sheet-interactions","__idx":11},"children":["Payment sheet interactions"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"overview","__idx":12},"children":["Overview"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Google Pay's payment sheet supports dynamic interactions that allow you to provide real-time updates based on user selections. This creates a seamless, interactive checkout experience where shipping costs, taxes, and totals update automatically as customers make choices within the payment sheet."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Payment sheet interactions enable you to:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Calculate shipping costs dynamically"]}," based on the customer's selected address"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Update transaction amounts"]}," in real-time without reloading the payment sheet"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Validate addresses"]}," and show errors for unserviceable locations"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Offer multiple shipping options"]}," with different costs and delivery times"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Apply discounts or offers"]}," based on customer selections"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Collect email addresses"]}," for order confirmations"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Request billing addresses"]}," for payment verification"]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Payment sheet interactions provide a native app-like experience whilst keeping customers within the Google Pay flow, significantly reducing checkout friction and cart abandonment."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"enabling-payment-sheet-interactions","__idx":13},"children":["Enabling payment sheet interactions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To enable dynamic interactions, configure your payment request with the required parameters:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"import com.pxp.checkout.components.googlepay.types.*\n\nval config = GooglePayButtonComponentConfig().apply {\n    paymentDataRequest = PaymentDataRequest(\n        allowedPaymentMethods = listOf(\n            PaymentMethodSpecification(\n                parameters = PaymentMethodParameters(\n                    allowedCardNetworks = listOf(\n                        CardNetwork.VISA,\n                        CardNetwork.MASTERCARD,\n                        CardNetwork.AMEX\n                    ),\n                    allowedAuthMethods = listOf(\n                        CardAuthMethod.PAN_ONLY,\n                        CardAuthMethod.CRYPTOGRAM_3DS\n                    )\n                )\n            )\n        ),\n        transactionInfo = TransactionInfo(\n            currencyCode = \"GBP\",\n            totalPriceStatus = TotalPriceStatus.FINAL,\n            totalPrice = \"50.00\",\n            displayItems = listOf(\n                DisplayItem(\n                    label = \"Subtotal\",\n                    type = DisplayItemType.LINE_ITEM,\n                    price = \"45.00\"\n                ),\n                DisplayItem(\n                    label = \"Estimated Tax\",\n                    type = DisplayItemType.TAX,\n                    price = \"5.00\"\n                )\n            )\n        ),\n        \n        // Enable shipping address collection\n        shippingAddressRequired = true,\n        shippingAddressParameters = ShippingAddressParameters(\n            allowedCountryCodes = listOf(\"GB\", \"FR\", \"DE\", \"US\"),\n            phoneNumberRequired = true\n        )\n    )\n    \n    // Handle payment data changes\n    onPaymentDataChanged = { intermediatePaymentData ->\n        handlePaymentDataChange(intermediatePaymentData)\n    }\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"shipping-address-interactions","__idx":14},"children":["Shipping address interactions"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"collecting-shipping-addresses","__idx":15},"children":["Collecting shipping addresses"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Request shipping addresses by configuring the payment request:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"val config = GooglePayButtonComponentConfig().apply {\n    paymentDataRequest = PaymentDataRequest(\n        allowedPaymentMethods = listOf(/* ... */),\n        transactionInfo = TransactionInfo(/* ... */),\n        \n        // Enable shipping address collection\n        shippingAddressRequired = true,\n        \n        // Configure shipping address parameters\n        shippingAddressParameters = ShippingAddressParameters(\n            allowedCountryCodes = listOf(\"GB\", \"FR\", \"DE\", \"US\"), // Restrict to specific countries\n            phoneNumberRequired = true // Request phone number\n        )\n    )\n    \n    onPaymentDataChanged = { intermediatePaymentData ->\n        intermediatePaymentData.shippingAddress?.let { address ->\n            // Calculate shipping and update totals\n            handleShippingAddressChange(address)\n        } ?: PaymentDataChangedResponse()\n    }\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"handling-address-changes","__idx":16},"children":["Handling address changes"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Respond to address changes with updated pricing and shipping options:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"suspend fun handleShippingAddressChange(address: Address): PaymentDataChangedResponse {\n    Log.d(\"GooglePay\", \"Shipping address changed: ${address.countryCode}, ${address.postalCode}\")\n    \n    return try {\n        // 1. Validate the address\n        if (!validateShippingAddress(address)) {\n            return PaymentDataChangedResponse(\n                error = PaymentDataError(\n                    reason = PaymentDataErrorReason.SHIPPING_ADDRESS_INVALID,\n                    message = \"Please enter a complete address\",\n                    intent = PaymentDataErrorIntent.SHIPPING_ADDRESS\n                )\n            )\n        }\n        \n        // 2. Check if we ship to this location\n        if (!checkShippingAvailability(address.countryCode)) {\n            return PaymentDataChangedResponse(\n                error = PaymentDataError(\n                    reason = PaymentDataErrorReason.SHIPPING_ADDRESS_UNSERVICEABLE,\n                    message = \"We do not currently ship to ${address.countryCode}\",\n                    intent = PaymentDataErrorIntent.SHIPPING_ADDRESS\n                )\n            )\n        }\n        \n        // 3. Calculate shipping cost\n        val shippingCost = calculateShipping(address)\n        \n        // 4. Calculate tax\n        val subtotal = 45.00\n        val tax = calculateTax(address, subtotal)\n        \n        // 5. Calculate new total\n        val newTotal = subtotal + tax + shippingCost\n        \n        // 6. Update SDK amount (synchronise with backend)\n        pxpCheckout.updateAmount(newTotal)\n        \n        // 7. Return updated transaction info\n        PaymentDataChangedResponse(\n            newTransactionInfo = TransactionInfo(\n                totalPriceStatus = TotalPriceStatus.FINAL,\n                totalPrice = newTotal.toPrice(),\n                totalPriceLabel = \"Total\",\n                displayItems = listOf(\n                    DisplayItem(\n                        label = \"Subtotal\",\n                        type = DisplayItemType.LINE_ITEM,\n                        price = subtotal.toPrice(),\n                        status = DisplayItemStatus.FINAL\n                    ),\n                    DisplayItem(\n                        label = \"Shipping\",\n                        type = DisplayItemType.LINE_ITEM,\n                        price = shippingCost.toPrice(),\n                        status = DisplayItemStatus.FINAL\n                    ),\n                    DisplayItem(\n                        label = \"Tax\",\n                        type = DisplayItemType.TAX,\n                        price = tax.toPrice(),\n                        status = DisplayItemStatus.FINAL\n                    )\n                )\n            )\n        )\n    } catch (e: Exception) {\n        Log.e(\"GooglePay\", \"Error handling address change\", e)\n        PaymentDataChangedResponse(\n            error = PaymentDataError(\n                reason = PaymentDataErrorReason.SHIPPING_ADDRESS_INVALID,\n                message = \"Unable to calculate shipping. Please try again.\",\n                intent = PaymentDataErrorIntent.SHIPPING_ADDRESS\n            )\n        )\n    }\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"address-validation-examples","__idx":17},"children":["Address validation examples"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"fun validateShippingAddress(address: Address): Boolean {\n    val requiredFields = listOf(\n        address.countryCode,\n        address.postalCode,\n        address.administrativeArea\n    )\n    \n    if (requiredFields.any { it.isNullOrEmpty() }) {\n        Log.e(\"GooglePay\", \"Missing required address fields\")\n        return false\n    }\n    \n    // Validate postal code format for UK\n    if (address.countryCode == \"GB\") {\n        val ukPostcodeRegex = Regex(\"^[A-Z]{1,2}\\\\d{1,2}[A-Z]?\\\\s?\\\\d[A-Z]{2}$\", RegexOption.IGNORE_CASE)\n        if (!ukPostcodeRegex.matches(address.postalCode ?: \"\")) {\n            Log.e(\"GooglePay\", \"Invalid UK postcode format\")\n            return false\n        }\n    }\n    \n    return true\n}\n\nsuspend fun checkShippingAvailability(countryCode: String): Boolean {\n    val shippableCountries = listOf(\"GB\", \"US\", \"CA\", \"FR\", \"DE\", \"ES\", \"IT\")\n    return shippableCountries.contains(countryCode)\n}\n\nsuspend fun calculateShipping(address: Address): Double {\n    val shippingRates = mapOf(\n        \"GB\" to 4.99,\n        \"US\" to 9.99,\n        \"CA\" to 12.99,\n        \"FR\" to 8.99,\n        \"DE\" to 8.99,\n        \"ES\" to 8.99,\n        \"IT\" to 8.99\n    )\n    \n    return shippingRates[address.countryCode] ?: 15.99 // Default international rate\n}\n\nsuspend fun calculateTax(address: Address, subtotal: Double): Double {\n    val taxRates = mapOf(\n        \"GB\" to 0.20, // 20% VAT\n        \"US\" to 0.08, // Example sales tax\n        \"CA\" to 0.13, // Example HST\n        \"FR\" to 0.20, // 20% TVA\n        \"DE\" to 0.19  // 19% MwSt\n    )\n    \n    val rate = taxRates[address.countryCode] ?: 0.0\n    return subtotal * rate\n}\n\n// Helper extension function\nfun Double.toPrice(): String = \"%.2f\".format(this)\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"shipping-option-interactions","__idx":18},"children":["Shipping option interactions"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"configuring-shipping-options","__idx":19},"children":["Configuring shipping options"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Provide multiple shipping methods for customers to choose from:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"val config = GooglePayButtonComponentConfig().apply {\n    paymentDataRequest = PaymentDataRequest(\n        allowedPaymentMethods = listOf(/* ... */),\n        transactionInfo = TransactionInfo(/* ... */),\n        \n        // Enable shipping option selection\n        shippingOptionRequired = true,\n        \n        // Configure available shipping options\n        shippingOptionParameters = ShippingOptionParameters(\n            defaultSelectedOptionId = \"standard\",\n            shippingOptions = listOf(\n                ShippingOption(\n                    id = \"standard\",\n                    label = \"Standard Delivery\",\n                    description = \"5-7 business days\"\n                ),\n                ShippingOption(\n                    id = \"express\",\n                    label = \"Express Delivery\",\n                    description = \"2-3 business days\"\n                ),\n                ShippingOption(\n                    id = \"next-day\",\n                    label = \"Next Day Delivery\",\n                    description = \"Order by 6pm for next day\"\n                )\n            )\n        )\n    )\n    \n    onPaymentDataChanged = { intermediatePaymentData ->\n        intermediatePaymentData.shippingOptionData?.let { shippingOption ->\n            handleShippingOptionChange(shippingOption)\n        } ?: PaymentDataChangedResponse()\n    }\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"handling-shipping-option-changes","__idx":20},"children":["Handling shipping option changes"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Update pricing when the customer selects a different shipping method:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"fun handleShippingOptionChange(shippingOption: ShippingOptionData): PaymentDataChangedResponse {\n    Log.d(\"GooglePay\", \"Shipping option changed: ${shippingOption.id}\")\n    \n    // Define shipping costs\n    val shippingCosts = mapOf(\n        \"standard\" to 4.99,\n        \"express\" to 9.99,\n        \"next-day\" to 14.99\n    )\n    \n    val subtotal = 45.00\n    val tax = 9.00\n    val shippingCost = shippingCosts[shippingOption.id] ?: 4.99\n    \n    // Calculate new total\n    val newTotal = subtotal + tax + shippingCost\n    \n    // Update SDK amount\n    pxpCheckout.updateAmount(newTotal)\n    \n    // Track shipping method selection\n    trackEvent(\"shipping-option-selected\", mapOf(\n        \"optionId\" to shippingOption.id,\n        \"cost\" to shippingCost\n    ))\n    \n    return PaymentDataChangedResponse(\n        newTransactionInfo = TransactionInfo(\n            totalPriceStatus = TotalPriceStatus.FINAL,\n            totalPrice = newTotal.toPrice(),\n            totalPriceLabel = \"Total\",\n            displayItems = listOf(\n                DisplayItem(\n                    label = \"Subtotal\",\n                    type = DisplayItemType.LINE_ITEM,\n                    price = subtotal.toPrice()\n                ),\n                DisplayItem(\n                    label = shippingOption.label,\n                    type = DisplayItemType.LINE_ITEM,\n                    price = shippingCost.toPrice()\n                ),\n                DisplayItem(\n                    label = \"Tax\",\n                    type = DisplayItemType.TAX,\n                    price = tax.toPrice()\n                )\n            )\n        )\n    )\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"email-collection","__idx":21},"children":["Email collection"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Request the customer's email address for order confirmations:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"val config = GooglePayButtonComponentConfig().apply {\n    paymentDataRequest = PaymentDataRequest(\n        allowedPaymentMethods = listOf(/* ... */),\n        transactionInfo = TransactionInfo(/* ... */),\n        \n        // Request email address\n        emailRequired = true\n    )\n    \n    onPostAuthorisation = { result, paymentData ->\n        when (result) {\n            is MerchantSubmitResult -> {\n                // Access email from payment data\n                val customerEmail = paymentData.email\n                \n                // Send confirmation email\n                sendOrderConfirmation(\n                    email = customerEmail,\n                    orderId = result.merchantTransactionId,\n                    systemTransactionId = result.systemTransactionId\n                )\n            }\n            else -> { /* Handle failure */ }\n        }\n    }\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"billing-address-collection","__idx":22},"children":["Billing address collection"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Request billing address for verification:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"val config = GooglePayButtonComponentConfig().apply {\n    paymentDataRequest = PaymentDataRequest(\n        allowedPaymentMethods = listOf(\n            PaymentMethodSpecification(\n                parameters = PaymentMethodParameters(\n                    allowedCardNetworks = listOf(\n                        CardNetwork.VISA,\n                        CardNetwork.MASTERCARD\n                    ),\n                    allowedAuthMethods = listOf(\n                        CardAuthMethod.PAN_ONLY,\n                        CardAuthMethod.CRYPTOGRAM_3DS\n                    ),\n                    \n                    // Request billing address\n                    billingAddressRequired = true,\n                    billingAddressParameters = BillingAddressParameters(\n                        format = BillingAddressFormat.FULL, // or MIN for minimal details\n                        phoneNumberRequired = false\n                    )\n                )\n            )\n        ),\n        transactionInfo = TransactionInfo(/* ... */)\n    )\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"billing-address-formats","__idx":23},"children":["Billing address formats"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Format"},"children":["Format"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Fields included"},"children":["Fields included"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MIN"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Name, country code, postal code"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["FULL"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Full billing address with street, city, state, postal code, country"]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"complete-interaction-example","__idx":24},"children":["Complete interaction example"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Here's a comprehensive example with all interaction types:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"import androidx.compose.foundation.layout.*\nimport androidx.compose.material3.*\nimport androidx.compose.runtime.*\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.unit.dp\nimport com.pxp.PxpCheckout\nimport com.pxp.checkout.components.googlepay.*\nimport com.pxp.checkout.components.googlepay.types.*\nimport com.pxp.checkout.types.ComponentType\n\n@Composable\nfun GooglePayCheckoutWithInteractions(pxpCheckout: PxpCheckout) {\n    val googlePayComponent = remember {\n        pxpCheckout.createComponent<\n            GooglePayButtonComponent,\n            GooglePayButtonComponentConfig\n        >(\n            type = ComponentType.GOOGLE_PAY_BUTTON,\n            config = GooglePayButtonComponentConfig().apply {\n                // Payment configuration with all interactions\n                paymentDataRequest = PaymentDataRequest(\n                    allowedPaymentMethods = listOf(\n                        PaymentMethodSpecification(\n                            parameters = PaymentMethodParameters(\n                                allowedCardNetworks = listOf(\n                                    CardNetwork.VISA,\n                                    CardNetwork.MASTERCARD,\n                                    CardNetwork.AMEX\n                                ),\n                                allowedAuthMethods = listOf(\n                                    CardAuthMethod.PAN_ONLY,\n                                    CardAuthMethod.CRYPTOGRAM_3DS\n                                ),\n                                billingAddressRequired = true,\n                                billingAddressParameters = BillingAddressParameters(\n                                    format = BillingAddressFormat.FULL,\n                                    phoneNumberRequired = true\n                                )\n                            )\n                        )\n                    ),\n                    transactionInfo = TransactionInfo(\n                        currencyCode = \"GBP\",\n                        countryCode = \"GB\",\n                        totalPriceStatus = TotalPriceStatus.FINAL,\n                        totalPrice = \"45.00\",\n                        totalPriceLabel = \"Total\",\n                        displayItems = listOf(\n                            DisplayItem(\n                                label = \"Wireless Headphones\",\n                                type = DisplayItemType.LINE_ITEM,\n                                price = \"39.99\",\n                                status = DisplayItemStatus.FINAL\n                            ),\n                            DisplayItem(\n                                label = \"Estimated Tax\",\n                                type = DisplayItemType.TAX,\n                                price = \"5.01\",\n                                status = DisplayItemStatus.PENDING\n                            )\n                        )\n                    ),\n                    \n                    // Email collection\n                    emailRequired = true,\n                    \n                    // Shipping address collection\n                    shippingAddressRequired = true,\n                    shippingAddressParameters = ShippingAddressParameters(\n                        allowedCountryCodes = listOf(\"GB\", \"FR\", \"DE\", \"ES\", \"IT\", \"NL\", \"BE\"),\n                        phoneNumberRequired = true\n                    ),\n                    \n                    // Shipping options\n                    shippingOptionRequired = true,\n                    shippingOptionParameters = ShippingOptionParameters(\n                        defaultSelectedOptionId = \"standard\",\n                        shippingOptions = listOf(\n                            ShippingOption(\n                                id = \"standard\",\n                                label = \"Standard Delivery\",\n                                description = \"5-7 business days\"\n                            ),\n                            ShippingOption(\n                                id = \"express\",\n                                label = \"Express Delivery\",\n                                description = \"2-3 business days\"\n                            )\n                        )\n                    )\n                )\n                \n                // Handle dynamic updates\n                onPaymentDataChanged = { intermediatePaymentData ->\n                    handleDynamicPaymentUpdates(intermediatePaymentData, pxpCheckout)\n                }\n                \n                // Handle successful payment\n                onPostAuthorisation = { result, paymentData ->\n                    when (result) {\n                        is MerchantSubmitResult -> {\n                            Log.d(\"GooglePay\", \"Payment successful with collected data: \" +\n                                \"email=${paymentData.email}, \" +\n                                \"shippingAddress=${paymentData.shippingAddress}, \" +\n                                \"shippingOption=${paymentData.shippingOption}\")\n                            \n                            // Send confirmation email\n                            sendOrderConfirmation(\n                                email = paymentData.email,\n                                orderId = result.merchantTransactionId,\n                                systemTransactionId = result.systemTransactionId,\n                                shippingAddress = paymentData.shippingAddress\n                            )\n                            \n                            navigateToOrderConfirmation()\n                        }\n                        else -> { /* Handle failure */ }\n                    }\n                }\n            }\n        )\n    }\n    \n    Column(\n        modifier = Modifier\n            .fillMaxWidth()\n            .padding(16.dp)\n    ) {\n        Text(\n            text = \"Complete Your Purchase\",\n            style = MaterialTheme.typography.headlineMedium,\n            modifier = Modifier.padding(bottom = 16.dp)\n        )\n        \n        googlePayComponent?.Content(\n            modifier = Modifier\n                .fillMaxWidth()\n                .height(56.dp)\n        )\n    }\n}\n\nfun handleDynamicPaymentUpdates(\n    intermediatePaymentData: IntermediatePaymentData,\n    pxpCheckout: PxpCheckout\n): PaymentDataChangedResponse {\n    Log.d(\"GooglePay\", \"Payment data changed: \" +\n        \"hasShippingAddress=${intermediatePaymentData.shippingAddress != null}, \" +\n        \"hasShippingOption=${intermediatePaymentData.shippingOptionData != null}\")\n    \n    return try {\n        val subtotal = 39.99\n        var shippingCost = 0.0\n        var tax = 0.0\n        var error: PaymentDataError? = null\n        \n        // Handle shipping address change\n        intermediatePaymentData.shippingAddress?.let { address ->\n            // Validate address\n            if (address.postalCode.isNullOrEmpty() || address.countryCode.isNullOrEmpty()) {\n                error = PaymentDataError(\n                    reason = PaymentDataErrorReason.SHIPPING_ADDRESS_INVALID,\n                    message = \"Please enter a complete address\",\n                    intent = PaymentDataErrorIntent.SHIPPING_ADDRESS\n                )\n            }\n            // Check if we ship to this country\n            else if (address.countryCode !in listOf(\"GB\", \"FR\", \"DE\", \"ES\", \"IT\", \"NL\", \"BE\")) {\n                error = PaymentDataError(\n                    reason = PaymentDataErrorReason.SHIPPING_ADDRESS_UNSERVICEABLE,\n                    message = \"We do not ship to ${address.countryCode}\",\n                    intent = PaymentDataErrorIntent.SHIPPING_ADDRESS\n                )\n            }\n            // Calculate shipping and tax\n            else {\n                val shippingRates = mapOf(\n                    \"GB\" to 4.99,\n                    \"FR\" to 8.99,\n                    \"DE\" to 8.99,\n                    \"ES\" to 8.99,\n                    \"IT\" to 8.99,\n                    \"NL\" to 8.99,\n                    \"BE\" to 8.99\n                )\n                shippingCost = shippingRates[address.countryCode] ?: 4.99\n                \n                // Calculate tax\n                val taxRates = mapOf(\n                    \"GB\" to 0.20,\n                    \"FR\" to 0.20,\n                    \"DE\" to 0.19,\n                    \"ES\" to 0.21,\n                    \"IT\" to 0.22,\n                    \"NL\" to 0.21,\n                    \"BE\" to 0.21\n                )\n                tax = subtotal * (taxRates[address.countryCode] ?: 0.20)\n            }\n        }\n        \n        // Handle shipping option change\n        intermediatePaymentData.shippingOptionData?.let { option ->\n            val shippingCosts = mapOf(\n                \"standard\" to 4.99,\n                \"express\" to 9.99\n            )\n            shippingCost = shippingCosts[option.id] ?: 4.99\n        }\n        \n        // Calculate new total\n        val newTotal = subtotal + tax + shippingCost\n        \n        // Update SDK amount\n        pxpCheckout.updateAmount(newTotal)\n        \n        // Return response\n        PaymentDataChangedResponse(\n            newTransactionInfo = TransactionInfo(\n                totalPriceStatus = TotalPriceStatus.FINAL,\n                totalPrice = newTotal.toPrice(),\n                totalPriceLabel = \"Total\",\n                displayItems = listOf(\n                    DisplayItem(\n                        label = \"Wireless Headphones\",\n                        type = DisplayItemType.LINE_ITEM,\n                        price = subtotal.toPrice(),\n                        status = DisplayItemStatus.FINAL\n                    ),\n                    DisplayItem(\n                        label = \"Shipping\",\n                        type = DisplayItemType.LINE_ITEM,\n                        price = shippingCost.toPrice(),\n                        status = DisplayItemStatus.FINAL\n                    ),\n                    DisplayItem(\n                        label = \"VAT\",\n                        type = DisplayItemType.TAX,\n                        price = tax.toPrice(),\n                        status = DisplayItemStatus.FINAL\n                    )\n                )\n            ),\n            error = error\n        )\n    } catch (e: Exception) {\n        Log.e(\"GooglePay\", \"Error in onPaymentDataChanged\", e)\n        PaymentDataChangedResponse(\n            error = PaymentDataError(\n                reason = PaymentDataErrorReason.OTHER_ERROR,\n                message = \"An error occurred. Please try again.\",\n                intent = PaymentDataErrorIntent.SHIPPING_ADDRESS\n            )\n        )\n    }\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"cvc-collection","__idx":25},"children":["CVC collection"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Configure when and how to collect CVC codes:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"// CVC collection strategy\ncollectCvc = GooglePayButtonComponentConfig.CvcCollectionStrategy.DEFAULT\n\n// Custom CVC dialog (optional)\ncvcVerificationPopupConfig = CvcVerificationDialogConfig(\n    title = \"Security Verification\",\n    description = \"Please enter your card's CVV code\",\n    submitButtonText = \"Confirm Payment\",\n    cancelButtonText = \"Go Back\"\n)\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["These strategies control when the SDK prompts customers to enter their CVV/CVC code:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"enum class CvcCollectionStrategy {\n    ALWAYS,   // Always show CVC dialog for FPAN\n    NEVER,    // Never show CVC dialog\n    DEFAULT   // Show CVC only when 3DS not available/skipped\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"3d-secure-authentication","__idx":26},"children":["3D Secure authentication"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"authentication-strategy","__idx":27},"children":["Authentication strategy"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["useUnityAuthenticationStrategy"]}," property controls how 3DS authentication is handled:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"useUnityAuthenticationStrategy: Boolean = false\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["true"]},": Uses Unity's automatic authentication strategy. The SDK automatically handles authentication decisions and session updates based on backend responses. This is the ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["recommended"]}," approach as it simplifies integration and ensures consistent authentication handling."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["false"]}," (default): Uses manual authentication callbacks. You must handle authentication decisions and session updates in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPostInitiateAuthentication"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPostAuthentication"]}," callbacks."]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When using ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["useUnityAuthenticationStrategy = true"]},", you still need to provide the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPreInitiateAuthentication"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPreAuthentication"]}," callbacks to configure authentication parameters, but the SDK will automatically handle the post-authentication logic."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"example-configuration","__idx":28},"children":["Example configuration"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Enable 3DS authentication with Unity's automatic strategy:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"val config = GooglePayButtonComponentConfig().apply {\n    // Enable Unity's automatic 3DS handling\n    useUnityAuthenticationStrategy = true\n    \n    // Minimal 3DS configuration\n    onPreInitiateAuthentication = {\n        PreInitiateIntegratedAuthenticationData(\n            providerId = \"pxpfinancial\",\n            timeout = 12\n        )\n    }\n    \n    onPreAuthentication = suspend {\n        InitiateIntegratedAuthenticationData(\n            merchantCountryNumericCode = \"840\",\n            merchantLegalName = \"Your Store Name\",\n            challengeWindowSize = ChallengeWindowSize.FULL_SCREEN,\n            requestorChallengeIndicator = RequestorChallengeIndicatorType.NO_PREFERENCE,\n            timeout = 180\n        )\n    }\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["See ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/checkout/components/android/google-pay/3ds"},"children":["3DS"]}," for detailed 3DS configuration."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"consent-and-recurring-payments","__idx":29},"children":["Consent and recurring payments"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Enable consent collection for payment tokens:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"// Create consent component\nval consentComponent = pxpCheckout.createComponent<\n    GooglePayConsentComponent,\n    GooglePayConsentConfig\n>(\n    type = ComponentType.GOOGLE_PAY_CONSENT,\n    config = GooglePayConsentConfig(\n        label = \"Save this payment method for future purchases\",\n        initialChecked = false\n    )\n)\n\n// Attach to Google Pay config\nval googlePayConfig = GooglePayButtonComponentConfig().apply {\n    googlePayConsentComponent = consentComponent\n    \n    // Or use callback\n    onGetConsent = {\n        consentComponent?.getValue() as? Boolean ?: false\n    }\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["See ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/checkout/components/android/google-pay/recurring-payments"},"children":["Recurring payments"]}," for more details."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"component-lifecycle","__idx":30},"children":["Component lifecycle"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"creating-components","__idx":31},"children":["Creating components"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"val googlePayComponent = pxpCheckout.createComponent<\n    GooglePayButtonComponent,\n    GooglePayButtonComponentConfig\n>(\n    type = ComponentType.GOOGLE_PAY_BUTTON,\n    config = googlePayConfig\n)\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"rendering-components","__idx":32},"children":["Rendering components"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"@Composable\nfun PaymentScreen(pxpCheckout: PxpCheckout) {\n    val googlePayComponent = remember {\n        pxpCheckout.createComponent<\n            GooglePayButtonComponent,\n            GooglePayButtonComponentConfig\n        >(\n            type = ComponentType.GOOGLE_PAY_BUTTON,\n            config = googlePayConfig\n        )\n    }\n    \n    // Render the component\n    googlePayComponent?.Content(\n        modifier = Modifier\n            .fillMaxWidth()\n            .height(56.dp)\n    )\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"complete-example","__idx":33},"children":["Complete example"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Here's a complete configuration example:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"import androidx.compose.foundation.layout.*\nimport androidx.compose.material3.*\nimport androidx.compose.runtime.*\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.unit.dp\nimport com.pxp.PxpCheckout\nimport com.pxp.checkout.components.googlepay.*\nimport com.pxp.checkout.components.googlepay.types.*\nimport com.pxp.checkout.models.*\nimport com.pxp.checkout.services.kount.*\nimport com.pxp.checkout.types.ComponentType\n\n@Composable\nfun GooglePayCheckout(pxpCheckout: PxpCheckout) {\n    val googlePayComponent = remember {\n        pxpCheckout.createComponent<\n            GooglePayButtonComponent,\n            GooglePayButtonComponentConfig\n        >(\n            type = ComponentType.GOOGLE_PAY_BUTTON,\n            config = GooglePayButtonComponentConfig().apply {\n                // Payment configuration\n                paymentDataRequest = PaymentDataRequest(\n                    allowedPaymentMethods = listOf(\n                        PaymentMethodSpecification(\n                            parameters = PaymentMethodParameters(\n                                allowedCardNetworks = listOf(\n                                    CardNetwork.VISA,\n                                    CardNetwork.MASTERCARD,\n                                    CardNetwork.AMEX\n                                ),\n                                allowedAuthMethods = listOf(\n                                    CardAuthMethod.PAN_ONLY,\n                                    CardAuthMethod.CRYPTOGRAM_3DS\n                                ),\n                                billingAddressRequired = true,\n                                billingAddressParameters = BillingAddressParameters(\n                                    format = BillingAddressFormat.FULL,\n                                    phoneNumberRequired = true\n                                )\n                            )\n                        )\n                    ),\n                    transactionInfo = TransactionInfo(\n                        currencyCode = \"GBP\",\n                        totalPriceStatus = TotalPriceStatus.FINAL,\n                        totalPrice = \"99.99\",\n                        countryCode = \"GB\"\n                    ),\n                    emailRequired = true\n                )\n                \n                // Button styling\n                style = GooglePayButtonStyle(\n                    type = GooglePayButtonType.PAY,\n                    theme = GooglePayButtonTheme.DARK,\n                    cornerRadius = 8\n                )\n                \n                // Enable 3DS\n                useUnityAuthenticationStrategy = true\n                \n                // CVC collection\n                collectCvc = GooglePayButtonComponentConfig.CvcCollectionStrategy.DEFAULT\n                \n                // Pre-authorisation\n                onPreAuthorisation = suspend { data ->\n                    GooglePayTransactionInitData(\n                        riskScreeningData = RiskScreeningData(\n                            performRiskScreening = true,\n                            excludeDeviceData = false,\n                            userIp = \"192.168.1.100\",\n                            account = RiskScreeningAccount(\n                                id = \"user_12345678\",\n                                creationDateTime = \"2024-01-15T10:30:00.000Z\"\n                            ),\n                            fulfillments = listOf(\n                                RiskScreeningFulfillment(\n                                    type = FulfillmentType.SHIPPED,\n                                    recipientPerson = RiskScreeningRecipientPerson(\n                                        phoneNumber = \"+1234567890\"\n                                    )\n                                )\n                            )\n                        )\n                    )\n                }\n                \n                // Post-authorisation\n                onPostAuthorisation = { result, paymentData ->\n                    when (result) {\n                        is MerchantSubmitResult -> {\n                            // Payment successful\n                            navigateToSuccess(result.merchantTransactionId)\n                        }\n                        is FailedSubmitResult -> {\n                            // Payment failed\n                            showError(result.errorReason)\n                        }\n                    }\n                }\n                \n                // Error handling\n                onError = { error ->\n                    showError(error.message)\n                }\n                \n                // Cancellation\n                onCancel = {\n                    Log.d(\"GooglePay\", \"Payment cancelled\")\n                }\n            }\n        )\n    }\n    \n    Column(\n        modifier = Modifier\n            .fillMaxWidth()\n            .padding(16.dp)\n    ) {\n        Text(\n            text = \"Complete Your Purchase\",\n            style = MaterialTheme.typography.headlineMedium,\n            modifier = Modifier.padding(bottom = 16.dp)\n        )\n        \n        googlePayComponent?.Content(\n            modifier = Modifier\n                .fillMaxWidth()\n                .height(56.dp)\n        )\n    }\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"best-practices","__idx":34},"children":["Best practices"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"configuration-organisation","__idx":35},"children":["Configuration organisation"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Extract configuration into separate functions for better maintainability:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"fun createGooglePayConfig(\n    amount: String,\n    onSuccess: (String) -> Unit,\n    onError: (String) -> Unit\n): GooglePayButtonComponentConfig {\n    return GooglePayButtonComponentConfig().apply {\n        paymentDataRequest = createPaymentDataRequest(amount)\n        style = createButtonStyle()\n        useUnityAuthenticationStrategy = true\n        \n        onPreAuthorisation = suspend { data ->\n            createTransactionInitData()\n        }\n        \n        onPostAuthorisation = { result, _ ->\n            handlePaymentResult(result, onSuccess, onError)\n        }\n    }\n}\n\nprivate fun createPaymentDataRequest(amount: String): PaymentDataRequest {\n    return PaymentDataRequest(\n        allowedPaymentMethods = listOf(\n            PaymentMethodSpecification(\n                parameters = PaymentMethodParameters(\n                    allowedCardNetworks = listOf(\n                        CardNetwork.VISA,\n                        CardNetwork.MASTERCARD\n                    ),\n                    allowedAuthMethods = listOf(\n                        CardAuthMethod.PAN_ONLY,\n                        CardAuthMethod.CRYPTOGRAM_3DS\n                    )\n                )\n            )\n        ),\n        transactionInfo = TransactionInfo(\n            currencyCode = \"GBP\",\n            totalPriceStatus = TotalPriceStatus.FINAL,\n            totalPrice = amount\n        )\n    )\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"error-handling","__idx":36},"children":["Error handling"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Always implement comprehensive error handling:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"onError = { error ->\n    when (error) {\n        is GooglePayNotReadyException -> {\n            showError(\"Google Pay is not available on this device\")\n            showAlternativePaymentMethods()\n        }\n        is GooglePayConfigurationValidationFailedException -> {\n            Log.e(\"GooglePay\", \"Configuration error\", error)\n            showError(\"Payment system configuration error\")\n        }\n        else -> {\n            Log.e(\"GooglePay\", \"Unexpected error\", error)\n            showError(\"An error occurred. Please try again.\")\n        }\n    }\n}\n","lang":"kotlin"},"children":[]}]},"headings":[{"value":"Configuration","id":"configuration","depth":1},{"value":"Basic usage","id":"basic-usage","depth":2},{"value":"Minimal configuration","id":"minimal-configuration","depth":3},{"value":"Advanced configuration","id":"advanced-configuration","depth":3},{"value":"Styling","id":"styling","depth":2},{"value":"Button types and themes","id":"button-types-and-themes","depth":3},{"value":"Button types","id":"button-types","depth":4},{"value":"Themes","id":"themes","depth":4},{"value":"Button sizing","id":"button-sizing","depth":3},{"value":"Event callbacks","id":"event-callbacks","depth":2},{"value":"Essential callbacks","id":"essential-callbacks","depth":3},{"value":"Payment sheet interactions","id":"payment-sheet-interactions","depth":2},{"value":"Overview","id":"overview","depth":3},{"value":"Enabling payment sheet interactions","id":"enabling-payment-sheet-interactions","depth":3},{"value":"Shipping address interactions","id":"shipping-address-interactions","depth":3},{"value":"Collecting shipping addresses","id":"collecting-shipping-addresses","depth":4},{"value":"Handling address changes","id":"handling-address-changes","depth":4},{"value":"Address validation examples","id":"address-validation-examples","depth":4},{"value":"Shipping option interactions","id":"shipping-option-interactions","depth":3},{"value":"Configuring shipping options","id":"configuring-shipping-options","depth":4},{"value":"Handling shipping option changes","id":"handling-shipping-option-changes","depth":4},{"value":"Email collection","id":"email-collection","depth":3},{"value":"Billing address collection","id":"billing-address-collection","depth":3},{"value":"Billing address formats","id":"billing-address-formats","depth":4},{"value":"Complete interaction example","id":"complete-interaction-example","depth":3},{"value":"CVC collection","id":"cvc-collection","depth":2},{"value":"3D Secure authentication","id":"3d-secure-authentication","depth":2},{"value":"Authentication strategy","id":"authentication-strategy","depth":3},{"value":"Example configuration","id":"example-configuration","depth":3},{"value":"Consent and recurring payments","id":"consent-and-recurring-payments","depth":2},{"value":"Component lifecycle","id":"component-lifecycle","depth":2},{"value":"Creating components","id":"creating-components","depth":3},{"value":"Rendering components","id":"rendering-components","depth":3},{"value":"Complete example","id":"complete-example","depth":2},{"value":"Best practices","id":"best-practices","depth":2},{"value":"Configuration organisation","id":"configuration-organisation","depth":3},{"value":"Error handling","id":"error-handling","depth":3}],"frontmatter":{"seo":{"title":"Configuration"}},"lastModified":"2026-06-12T11:56:36.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/guides/checkout/components/android/google-pay/configuration","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}