{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-guides/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["sub-heading","admonition","br","details","required"]},"type":"markdown"},"seo":{"title":"Non-3DS transactions","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":"non-3ds-transactions","__idx":0},"children":["Non-3DS transactions"]},{"$$mdtype":"Tag","name":"SubHeading","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Process Google Pay transactions without 3D Secure authentication for faster, streamlined checkout."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"overview","__idx":1},"children":["Overview"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["By implementing a non-3DS Google Pay payment flow on Android, you benefit from:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Faster checkout:"]}," Streamlined payment process with fewer steps and no authentication redirects."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Better conversion:"]}," Reduced friction leads to higher completion rates."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Simplified integration:"]}," Fewer callbacks and less complex implementation."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Lower latency:"]}," Direct payment processing without authentication steps."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Native security:"]}," Benefits from Google Pay's tokenisation and biometric authentication."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["However, non-3DS payments may not qualify for liability shift protection and are best suited for low-risk transactions, trusted customers, or regions where Strong Customer Authentication (SCA) isn't mandated."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Google Pay provides inherent security through device-based authentication (fingerprint, face recognition, or PIN) and payment tokenisation, making non-3DS flows suitable for many transaction types."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"payment-flow","__idx":2},"children":["Payment flow"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The non-3DS Google Pay payment flow consists of five streamlined steps:"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-1-button-interaction","__idx":3},"children":["Step 1: Button interaction"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The customer taps the Google Pay button in your Android app, triggering the payment sheet to open. Google Pay handles device authentication (biometric or PIN) internally."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-2-payment-method-selection","__idx":4},"children":["Step 2: Payment method selection"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Within the Google Pay payment sheet, the customer selects their preferred payment method. Google Pay tokenises the payment data using its secure tokenisation system."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-3-payment-sheet-completion","__idx":5},"children":["Step 3: Payment sheet completion"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The customer confirms the payment in the Google Pay sheet. The SDK receives the encrypted payment token from Google Pay."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-4-evaluation","__idx":6},"children":["Step 4: Evaluation"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The SDK evaluates whether 3DS authentication is required. In non-3DS flows, authentication is skipped based on:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Configuration not requiring 3DS (no ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPreInitiateAuthentication"]}," callback provided)."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Transaction falling below risk thresholds."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Regulatory exemptions being applicable."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Merchant risk assessment."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Since 3DS isn't required, the flow proceeds directly to authorisation."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-5-authorisation","__idx":7},"children":["Step 5: Authorisation"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The SDK sends the authorisation request with the Google Pay token directly to the payment gateway without 3DS authentication data."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"associated-callbacks","__idx":8},"children":["Associated callbacks"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPreAuthorisation"]},": Provides transaction data for final review before authorisation. This is your last opportunity to add additional data or cancel the transaction."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPostAuthorisation"]},": Receives the final transaction result. The transaction is either authorised or declined."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"implementation","__idx":9},"children":["Implementation"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"before-you-start","__idx":10},"children":["Before you start"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To use non-3DS Google Pay payments on Android:"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Ensure your merchant account supports non-3DS transactions."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Configure Google Pay in the Unity Portal with your gateway merchant ID."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Register your Android app package name and certificate in the Unity Portal."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Consider implementing additional fraud prevention measures."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-1-initialise-the-sdk","__idx":11},"children":["Step 1: Initialise the SDK"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Initialise the PXP Checkout SDK with your merchant credentials:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"import com.pxp.PxpCheckout\nimport com.pxp.checkout.models.*\nimport java.text.SimpleDateFormat\nimport java.util.*\n\nval pxpCheckout = PxpCheckout.builder()\n    .withConfig(\n        PxpSdkConfig(\n            environment = Environment.TEST,\n            session = sessionData,\n            ownerId = \"your-owner-id\",\n            ownerType = \"MerchantGroup\",\n            transactionData = TransactionData(\n                currency = \"GBP\",\n                amount = 25.00,\n                merchantTransactionId = UUID.randomUUID().toString(),\n                merchantTransactionDate = { SimpleDateFormat(\"yyyy-MM-dd'T'HH:mm:ss'Z'\").format(Date()) },\n                entryType = EntryType.Ecom,\n                intent = TransactionIntentData(\n                    card = IntentType.Authorisation\n                ),\n                merchant = \"Merchant Name\"\n            )\n        )\n    )\n    .withContext(context)\n    .build()\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-2-implement-callbacks","__idx":12},"children":["Step 2: Implement callbacks"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Configure the Google Pay button with the required callbacks for non-3DS payments:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"import com.pxp.checkout.components.googlepay.*\nimport com.pxp.checkout.components.googlepay.types.*\nimport com.pxp.checkout.models.*\nimport com.pxp.checkout.services.kount.*\n\nval googlePayConfig = GooglePayButtonComponentConfig().apply {\n    \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                    // Both methods supported - Google Pay will use best available\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 = \"49.99\"\n        )\n    )\n    \n    // REQUIRED: Final transaction review before authorisation\n    onPreAuthorisation = suspend { data ->\n        Log.d(\"GooglePay\", \"Processing non-3DS payment\")\n        Log.d(\"GooglePay\", \"Gateway Token ID: ${data?.gatewayTokenId}\")\n        \n        // Add risk screening 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                items = listOf(\n                    RiskScreeningItem(\n                        price = 99.99,\n                        quantity = 1,\n                        category = \"Electronics\",\n                        sku = \"GPAY-PROD-001\"\n                    )\n                ),\n                fulfillments = listOf(\n                    RiskScreeningFulfillment(\n                        type = FulfillmentType.SHIPPED,\n                        shipping = RiskScreeningShipping(\n                            shippingMethod = ShippingMethod.STANDARD\n                        ),\n                        recipientPerson = RiskScreeningRecipientPerson(\n                            phoneNumber = \"+1234567890\",\n                            email = \"customer@example.com\"\n                        )\n                    )\n                )\n            )\n        )\n    }\n    \n    // REQUIRED: Handle the final result\n    onPostAuthorisation = { result, paymentData ->\n        Log.d(\"GooglePay\", \"Payment result: $result\")\n        \n        when (result) {\n            is MerchantSubmitResult -> {\n                // Success\n                Log.d(\"GooglePay\", \"Payment successful!\")\n                Log.d(\"GooglePay\", \"Transaction ID: ${result.merchantTransactionId}\")\n                Log.d(\"GooglePay\", \"System Txn ID: ${result.systemTransactionId}\")\n                \n                // Navigate to success screen\n                navigateToSuccess(result.merchantTransactionId)\n            }\n            is FailedSubmitResult -> {\n                // Failure\n                Log.e(\"GooglePay\", \"Payment declined: ${result.errorReason}\")\n                showError(\"Payment declined. Please try another payment method.\")\n            }\n        }\n    }\n    \n    // OPTIONAL: Handle errors\n    onError = { error ->\n        Log.e(\"GooglePay\", \"Payment error\", error)\n        showError(\"An error occurred. Please try again.\")\n    }\n    \n    // OPTIONAL: Handle cancellation\n    onCancel = {\n        Log.d(\"GooglePay\", \"Payment cancelled by user\")\n        showMessage(\"Payment cancelled\")\n    }\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-3-handle-common-scenarios","__idx":13},"children":["Step 3: Handle common scenarios"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"amount-based-risk-assessment","__idx":14},"children":["Amount-based risk assessment"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Apply different risk measures based on transaction amounts:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"val googlePayConfig = GooglePayButtonComponentConfig().apply {\n    // ... basic configuration\n    \n    onPreAuthorisation = suspend { data ->\n            Log.d(\"GooglePay\", \"Gateway Token ID: ${data?.gatewayTokenId}\")\n            \n            // Get transaction amount\n            val amount = getTransactionAmount().toDoubleOrNull() ?: 0.0\n            \n            // Different handling based on amount\n                when {\n                amount < 30.0 -> {\n                    // Low-value transaction - minimal checks\n                    Log.d(\"GooglePay\", \"Low-value transaction: $amount\")\n                    GooglePayTransactionInitData(\n                        riskScreeningData = RiskScreeningData(\n                            performRiskScreening = false,\n                            excludeDeviceData = true\n                        )\n                    )\n                }\n                amount < 100.0 -> {\n                    // Medium-value transaction - standard checks\n                    Log.d(\"GooglePay\", \"Medium-value transaction: $amount\")\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                                    shipping = RiskScreeningShipping(\n                                        shippingMethod = ShippingMethod.STANDARD\n                                    ),\n                                    recipientPerson = RiskScreeningRecipientPerson(\n                                        phoneNumber = \"+1234567890\"\n                                    )\n                                )\n                            )\n                        )\n                    )\n                }\n                else -> {\n                    // High-value transaction - enhanced checks\n                    Log.d(\"GooglePay\", \"High-value transaction: $amount\")\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                            items = listOf(\n                                RiskScreeningItem(\n                                    price = amount,\n                                    quantity = 1,\n                                    category = \"high-value\"\n                                )\n                            ),\n                            fulfillments = listOf(\n                                RiskScreeningFulfillment(\n                                    type = FulfillmentType.SHIPPED,\n                                    shipping = RiskScreeningShipping(\n                                        shippingMethod = ShippingMethod.EXPRESS\n                                    ),\n                                    recipientPerson = RiskScreeningRecipientPerson(\n                                        phoneNumber = \"+1234567890\"\n                                    )\n                                )\n                            )\n                        )\n                    )\n                }\n        }\n    }\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"customer-type-handling","__idx":15},"children":["Customer type handling"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Handle different customer types with varying risk profiles:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"data class CustomerRiskProfile(\n    val level: RiskLevel,\n    val verification: VerificationLevel,\n    val reason: String\n)\n\nenum class RiskLevel { HIGH, MEDIUM, LOW }\nenum class VerificationLevel { ENHANCED, STANDARD, MINIMAL }\n\nfun getCustomerRiskProfile(customerId: String): CustomerRiskProfile {\n    val customer = getCustomerDetails(customerId)\n    \n    return when {\n        customer.previousOrders == 0 -> {\n            CustomerRiskProfile(\n                level = RiskLevel.HIGH,\n                verification = VerificationLevel.ENHANCED,\n                reason = \"new-customer\"\n            )\n        }\n        customer.previousOrders > 10 && customer.chargebacks == 0 -> {\n            CustomerRiskProfile(\n                level = RiskLevel.LOW,\n                verification = VerificationLevel.MINIMAL,\n                reason = \"trusted-customer\"\n            )\n        }\n        else -> {\n            CustomerRiskProfile(\n                level = RiskLevel.MEDIUM,\n                verification = VerificationLevel.STANDARD,\n                reason = \"returning-customer\"\n            )\n        }\n    }\n}\n\nval googlePayConfig = GooglePayButtonComponentConfig().apply {\n    // ... basic configuration\n    \n    onPreAuthorisation = suspend { data ->\n            val customerId = getCurrentCustomerId()\n            val riskProfile = getCustomerRiskProfile(customerId)\n            \n            Log.d(\"GooglePay\", \"Customer risk profile: $riskProfile\")\n            \n            GooglePayTransactionInitData(\n                riskScreeningData = RiskScreeningData(\n                    performRiskScreening = riskProfile.level != RiskLevel.LOW,\n                    excludeDeviceData = false,\n                    userIp = \"192.168.1.100\",\n                    account = RiskScreeningAccount(\n                        id = customerId,\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","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"geographic-risk-assessment","__idx":16},"children":["Geographic risk assessment"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Apply different rules based on customer location:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"suspend fun getCustomerGeolocation(): Geolocation {\n    // Implement geolocation detection\n    return Geolocation(\n        countryCode = \"GB\",\n        region = \"England\",\n        city = \"London\"\n    )\n}\n\ndata class Geolocation(\n    val countryCode: String,\n    val region: String,\n    val city: String\n)\n\nval googlePayConfig = GooglePayButtonComponentConfig().apply {\n    // ... basic configuration\n    \n    onPreAuthorisation = suspend { data ->\n            Log.d(\"GooglePay\", \"Gateway Token ID: ${data?.gatewayTokenId}\")\n            \n            val geolocation = getCustomerGeolocation()\n            \n            // Check if customer is in high-risk region\n            val highRiskCountries = listOf(\"XX\", \"YY\", \"ZZ\")\n            val isHighRisk = geolocation.countryCode in highRiskCountries\n            \n            Log.d(\"GooglePay\", \"Customer location: ${geolocation.countryCode}, High risk: $isHighRisk\")\n            \n            GooglePayTransactionInitData(\n                riskScreeningData = RiskScreeningData(\n                    performRiskScreening = true,\n                    excludeDeviceData = false,\n                    userIp = geolocation.ipAddress,\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","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-4-handle-errors","__idx":17},"children":["Step 4: Handle errors"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Implement comprehensive error handling for non-3DS payments:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"val googlePayConfig = GooglePayButtonComponentConfig().apply {\n    // ... basic configuration\n    \n    onPostAuthorisation = { result, paymentData ->\n        when (result) {\n            is MerchantSubmitResult -> {\n                // Payment successful\n                handlePaymentSuccess(result, paymentData)\n            }\n            is FailedSubmitResult -> {\n                // Payment declined or failed\n                handlePaymentFailure(result)\n            }\n        }\n    }\n    \n    onError = { error ->\n        Log.e(\"GooglePay\", \"Payment error\", error)\n        \n        // Handle specific error types\n        val errorMessage = when (error) {\n            is GooglePayNotReadyException -> {\n                \"Google Pay is not available on this device. Please try another payment method.\"\n            }\n            is GooglePayConfigurationValidationFailedException -> {\n                logCriticalError(\"Google Pay configuration error\", error)\n                \"Payment system configuration error. Please contact support.\"\n            }\n            is GooglePayLoadFailedException -> {\n                \"Failed to load Google Pay. Please try again.\"\n            }\n            is GooglePayPaymentFailedException -> {\n                \"Payment failed. Please try another payment method.\"\n            }\n            else -> {\n                \"An error occurred. Please try again or use a different payment method.\"\n            }\n        }\n        \n        showError(errorMessage)\n    }\n    \n    onCancel = {\n        Log.d(\"GooglePay\", \"Payment cancelled by user\")\n        // Customer closed Google Pay sheet\n        showMessage(\"Payment cancelled. Your order is still in your cart.\")\n    }\n}\n\nfun handlePaymentSuccess(result: MerchantSubmitResult, paymentData: AuthorisationPaymentData) {\n    Log.d(\"GooglePay\", \"Payment successful\")\n    Log.d(\"GooglePay\", \"Transaction ID: ${result.merchantTransactionId}\")\n    Log.d(\"GooglePay\", \"System Txn ID: ${result.systemTransactionId}\")\n    \n    // Store transaction details\n    storeTransactionRecord(\n        TransactionRecord(\n            transactionId = result.merchantTransactionId,\n            systemTransactionId = result.systemTransactionId,\n            processingType = \"non-3ds\",\n            paymentMethod = \"google-pay\",\n            timestamp = System.currentTimeMillis()\n        )\n    )\n    \n    // Navigate to success screen\n    navigateToSuccess(result.merchantTransactionId)\n}\n\nfun handlePaymentFailure(result: FailedSubmitResult) {\n    Log.e(\"GooglePay\", \"Payment failed\")\n    Log.e(\"GooglePay\", \"Error code: ${result.errorCode}\")\n    Log.e(\"GooglePay\", \"Error reason: ${result.errorReason}\")\n    Log.e(\"GooglePay\", \"Correlation ID: ${result.correlationId}\")\n    \n    // Show user-friendly error message\n    showError(\"Payment declined. Please try another payment method.\")\n    \n    // Log decline for analysis\n    logPaymentDecline(\n        PaymentDeclineLog(\n            errorCode = result.errorCode,\n            errorReason = result.errorReason,\n            correlationId = result.correlationId,\n            httpStatusCode = result.httpStatusCode,\n            timestamp = System.currentTimeMillis()\n        )\n    )\n    \n    // Offer alternative payment methods\n    showAlternativePaymentOptions()\n}\n\ndata class TransactionRecord(\n    val transactionId: String,\n    val systemTransactionId: String,\n    val processingType: String,\n    val paymentMethod: String,\n    val timestamp: Long\n)\n\ndata class PaymentDeclineLog(\n    val errorCode: String,\n    val errorReason: String,\n    val correlationId: String,\n    val httpStatusCode: Int,\n    val timestamp: Long\n)\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"complete-example","__idx":18},"children":["Complete example"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The following example shows a complete non-3DS Google Pay implementation with Jetpack Compose:"]},{"$$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.services.kount.*\nimport com.pxp.checkout.types.ComponentType\nimport kotlinx.coroutines.CompletableDeferred\nimport java.util.*\n\n@Composable\nfun GooglePayCheckout(\n    pxpCheckout: PxpCheckout,\n    amount: String,\n    onSuccess: (String) -> Unit,\n    onError: (String) -> Unit\n) {\n    var isProcessing by remember { mutableStateOf(false) }\n    var errorMessage by remember { mutableStateOf<String?>(null) }\n    \n    // Create Google Pay button (non-3DS)\n    val googlePayComponent = remember {\n        pxpCheckout.createComponent<\n            GooglePayButtonComponent,\n            GooglePayButtonComponentConfig\n        >(\n            type = ComponentType.GOOGLE_PAY_BUTTON,\n            config = GooglePayButtonComponentConfig().apply {\n                \n                style = GooglePayButtonStyle(\n                    type = GooglePayButtonType.PAY,\n                    theme = GooglePayButtonTheme.DARK,\n                    cornerRadius = 8\n                )\n                \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                        countryCode = \"GB\",\n                        totalPriceStatus = TotalPriceStatus.FINAL,\n                        totalPrice = amount,\n                        totalPriceLabel = \"Total\"\n                    )\n                )\n                \n                // Handle button click\n                onGooglePaymentButtonClicked = {\n                    Log.d(\"GooglePay\", \"Button clicked\")\n                    isProcessing = true\n                    errorMessage = null\n                    CompletableDeferred(Unit)\n                }\n                \n                // Pre-authorisation - add risk data\n                onPreAuthorisation = suspend { data ->\n                    Log.d(\"GooglePay\", \"Processing non-3DS payment\")\n                    Log.d(\"GooglePay\", \"Gateway Token ID: ${data?.gatewayTokenId}\")\n                    \n                    // Assess risk\n                    val customerId = getCurrentCustomerId()\n                    val riskProfile = assessCustomerRisk(customerId)\n                    \n                    GooglePayTransactionInitData(\n                        riskScreeningData = RiskScreeningData(\n                            performRiskScreening = true,\n                            excludeDeviceData = false,\n                            userIp = \"192.168.1.100\",\n                            account = RiskScreeningAccount(\n                                id = customerId,\n                                creationDateTime = \"2024-01-15T10:30:00.000Z\"\n                            ),\n                            items = listOf(\n                                RiskScreeningItem(\n                                    price = 99.99,\n                                    quantity = 1,\n                                    category = \"Electronics\"\n                                )\n                            ),\n                            fulfillments = listOf(\n                                RiskScreeningFulfillment(\n                                    type = FulfillmentType.SHIPPED,\n                                    shipping = RiskScreeningShipping(\n                                        shippingMethod = ShippingMethod.STANDARD\n                                    ),\n                                    recipientPerson = RiskScreeningRecipientPerson(\n                                        phoneNumber = \"+1234567890\"\n                                    )\n                                )\n                            )\n                        )\n                    )\n                }\n                \n                // Post-authorisation - handle result\n                onPostAuthorisation = { result, _ ->\n                    Log.d(\"GooglePay\", \"Payment result received\")\n                    isProcessing = false\n                    \n                    when (result) {\n                        is MerchantSubmitResult -> {\n                            Log.d(\"GooglePay\", \"Payment authorised\")\n                            \n                            // Track successful payment\n                            trackPaymentSuccess(\n                                transactionId = result.merchantTransactionId,\n                                systemTransactionId = result.systemTransactionId,\n                                paymentMethod = \"google-pay\"\n                            )\n                            \n                            onSuccess(result.merchantTransactionId)\n                        }\n                        is FailedSubmitResult -> {\n                            Log.e(\"GooglePay\", \"Payment declined: ${result.errorReason}\")\n                            errorMessage = \"Payment declined. Please try another payment method.\"\n                            \n                            // Track decline\n                            trackPaymentDecline(\n                                errorCode = result.errorCode,\n                                errorReason = result.errorReason,\n                                correlationId = result.correlationId\n                            )\n                        }\n                    }\n                }\n                \n                // Error handling\n                onError = { error ->\n                    Log.e(\"GooglePay\", \"Payment error\", error)\n                    isProcessing = false\n                    errorMessage = \"An error occurred. Please try again.\"\n                    \n                    // Track error\n                    trackPaymentError(\n                        errorType = error::class.simpleName ?: \"Unknown\",\n                        errorMessage = error.message ?: \"Unknown error\"\n                    )\n                }\n                \n                // Cancellation handling\n                onCancel = {\n                    Log.d(\"GooglePay\", \"Payment cancelled by user\")\n                    isProcessing = false\n                    errorMessage = null\n                    \n                    // Track cancellation\n                    trackPaymentCancellation()\n                }\n            }\n        )\n    }\n    \n    // UI\n    Surface(\n        modifier = Modifier.fillMaxSize(),\n        color = MaterialTheme.colorScheme.background\n    ) {\n        Column(\n            modifier = Modifier\n                .fillMaxSize()\n                .padding(16.dp)\n        ) {\n            // Order summary\n            Card(\n                modifier = Modifier\n                    .fillMaxWidth()\n                    .padding(bottom = 24.dp)\n            ) {\n                Column(modifier = Modifier.padding(16.dp)) {\n                    Text(\n                        text = \"Order summary\",\n                        style = MaterialTheme.typography.titleLarge\n                    )\n                    \n                    Spacer(modifier = Modifier.height(16.dp))\n                    \n                    Row(\n                        modifier = Modifier.fillMaxWidth(),\n                        horizontalArrangement = Arrangement.SpaceBetween\n                    ) {\n                        Text(\"Premium Headphones\")\n                        Text(\"£45.00\")\n                    }\n                    \n                    Row(\n                        modifier = Modifier.fillMaxWidth(),\n                        horizontalArrangement = Arrangement.SpaceBetween\n                    ) {\n                        Text(\"VAT (20%)\")\n                        Text(\"£4.99\")\n                    }\n                    \n                    Divider(modifier = Modifier.padding(vertical = 8.dp))\n                    \n                    Row(\n                        modifier = Modifier.fillMaxWidth(),\n                        horizontalArrangement = Arrangement.SpaceBetween\n                    ) {\n                        Text(\n                            text = \"Total\",\n                            style = MaterialTheme.typography.titleMedium\n                        )\n                        Text(\n                            text = \"£$amount\",\n                            style = MaterialTheme.typography.titleMedium\n                        )\n                    }\n                }\n            }\n            \n            // Payment section\n            Card(modifier = Modifier.fillMaxWidth()) {\n                Column(modifier = Modifier.padding(16.dp)) {\n                    Text(\n                        text = \"Pay with Google Pay\",\n                        style = MaterialTheme.typography.titleLarge\n                    )\n                    \n                    Spacer(modifier = Modifier.height(16.dp))\n                    \n                    // Error message\n                    errorMessage?.let { error ->\n                        Card(\n                            modifier = Modifier\n                                .fillMaxWidth()\n                                .padding(bottom = 16.dp),\n                            colors = CardDefaults.cardColors(\n                                containerColor = MaterialTheme.colorScheme.errorContainer\n                            )\n                        ) {\n                            Text(\n                                text = error,\n                                modifier = Modifier.padding(12.dp),\n                                color = MaterialTheme.colorScheme.onErrorContainer\n                            )\n                        }\n                    }\n                    \n                    // Google Pay button\n                    googlePayComponent?.Content(\n                        modifier = Modifier\n                            .fillMaxWidth()\n                            .height(56.dp)\n                    )\n                    \n                    // Processing indicator\n                    if (isProcessing) {\n                        Spacer(modifier = Modifier.height(16.dp))\n                        \n                        LinearProgressIndicator(\n                            modifier = Modifier.fillMaxWidth()\n                        )\n                        \n                        Text(\n                            text = \"Processing payment...\",\n                            modifier = Modifier.padding(top = 8.dp),\n                            style = MaterialTheme.typography.bodyMedium,\n                            color = MaterialTheme.colorScheme.onSurfaceVariant\n                        )\n                    }\n                    \n                    Spacer(modifier = Modifier.height(16.dp))\n                    \n                    // Security info\n                    Column(\n                        modifier = Modifier.padding(vertical = 8.dp),\n                        verticalArrangement = Arrangement.spacedBy(4.dp)\n                    ) {\n                        Text(\n                            text = \"✓ Fast and secure checkout with Google Pay\",\n                            style = MaterialTheme.typography.bodySmall,\n                            color = MaterialTheme.colorScheme.onSurfaceVariant\n                        )\n                        Text(\n                            text = \"✓ No need to enter card details\",\n                            style = MaterialTheme.typography.bodySmall,\n                            color = MaterialTheme.colorScheme.onSurfaceVariant\n                        )\n                        Text(\n                            text = \"✓ Protected by Google Pay's security\",\n                            style = MaterialTheme.typography.bodySmall,\n                            color = MaterialTheme.colorScheme.onSurfaceVariant\n                        )\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Helper functions\nprivate fun getCurrentCustomerId(): String {\n    // Get customer ID from your auth system\n    return \"customer-123\"\n}\n\nprivate suspend fun assessCustomerRisk(customerId: String): String {\n    // Implement your risk assessment logic\n    val orderHistory = getCustomerOrderHistory(customerId)\n    \n    return when {\n        orderHistory.totalOrders > 10 && orderHistory.chargebacks == 0 -> \"low\"\n        orderHistory.totalOrders == 0 -> \"high\"\n        else -> \"medium\"\n    }\n}\n\nprivate fun trackPaymentSuccess(\n    transactionId: String,\n    systemTransactionId: String,\n    paymentMethod: String\n) {\n    Log.d(\"Analytics\", \"Tracking payment success: $transactionId\")\n    // Implement your analytics tracking\n}\n\nprivate fun trackPaymentDecline(\n    errorCode: String,\n    errorReason: String,\n    correlationId: String\n) {\n    Log.d(\"Analytics\", \"Tracking payment decline: $errorCode\")\n    // Implement your analytics tracking\n}\n\nprivate fun trackPaymentError(errorType: String, errorMessage: String) {\n    Log.d(\"Analytics\", \"Tracking payment error: $errorType\")\n    // Implement your analytics tracking\n}\n\nprivate fun trackPaymentCancellation() {\n    Log.d(\"Analytics\", \"Tracking payment cancellation\")\n    // Implement your analytics tracking\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"callback-data","__idx":19},"children":["Callback data"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This section describes the data received by the different callbacks as part of the non-3DS Google Pay flow on Android."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"onpreauthorisation","__idx":20},"children":["onPreAuthorisation"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPreAuthorisation"]}," callback receives pre-authorisation data containing token identifiers. Use this to retrieve token details and make authorisation decisions."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"event-data","__idx":21},"children":["Event data"]},{"$$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":"Parameter"},"children":["Parameter"]},{"$$mdtype":"Tag","name":"th","attributes":{"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":["data"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["PreAuthorisationData?"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Pre-authorisation data containing token identifiers."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["data.gatewayTokenId"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["String?"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The gateway token identifier for the payment. Use this ID to retrieve full token details from the Unity backend."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["data.schemeTokenId"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["String?"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The scheme token identifier for the payment (e.g., Visa Token Service, Mastercard Digital Enablement Service)."]}]}]}]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["gatewayTokenId"]}," with the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/apis/token-vault/other/get-masked-card-related-to-gateway-token"},"children":["Get masked card data related to gateway token"]}," API to retrieve full token details including card scheme, funding source (credit/debit), masked PAN, and expiry date."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-implementation","__idx":22},"children":["Example implementation"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"onPreAuthorisation = suspend { data ->\n    Log.d(\"GooglePay\", \"Non-3DS authorisation for token: ${data?.gatewayTokenId}\")\n    \n    // Retrieve token details and make authorisation decision\n    val transactionDecision = getAuthorisationDecision(data?.gatewayTokenId)\n    \n    if (transactionDecision == null) {\n        Log.d(\"GooglePay\", \"Not proceeding with authorisation\")\n        null\n    } else {\n        // Add risk screening 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","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"warning"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["3DS external data should no longer be provided via the callback. For non-3DS flows, no 3DS data is applicable."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"onpostauthorisation","__idx":23},"children":["onPostAuthorisation"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPostAuthorisation"]}," callback receives the authorisation result and the original payment data from Google Pay."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"event-data-1","__idx":24},"children":["Event data"]},{"$$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":"Parameter"},"children":["Parameter"]},{"$$mdtype":"Tag","name":"th","attributes":{"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":["result"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["SubmitResult?"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Transaction result - either ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MerchantSubmitResult"]}," (success) or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["FailedSubmitResult"]}," (failure)."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paymentData"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["AuthorisationPaymentData"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Required","attributes":{},"children":[]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Google Pay payment data collected during checkout (email, shipping address, shipping option)."]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"success-result","__idx":25},"children":["Success result"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When the payment is successful, you'll receive a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MerchantSubmitResult"]},":"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"data class MerchantSubmitResult(\n    val merchantTransactionId: String,\n    val systemTransactionId: String\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":{"data-label":"Property"},"children":["Property"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Type"},"children":["Type"]},{"$$mdtype":"Tag","name":"th","attributes":{"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":["merchantTransactionId"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The merchant's unique identifier for the transaction that was provided during SDK initialisation."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["systemTransactionId"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The system's unique identifier for the transaction. Use this with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["merchantTransactionId"]}," to retrieve full authorisation details from the Unity backend."]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"failure-result","__idx":26},"children":["Failure result"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When the payment fails, you'll receive a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["FailedSubmitResult"]},":"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"data class FailedSubmitResult(\n    val errorCode: String,\n    val errorReason: String,\n    val correlationId: String,\n    val httpStatusCode: Int\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":{"data-label":"Property"},"children":["Property"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Type"},"children":["Type"]},{"$$mdtype":"Tag","name":"th","attributes":{"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":["errorCode"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The error code indicating the type of failure."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["errorReason"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["A human-readable description of the error."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["correlationId"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["A unique identifier for this transaction attempt. Use this for support inquiries and debugging."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["httpStatusCode"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Int"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The HTTP status code associated with the failure."]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-implementation-1","__idx":27},"children":["Example implementation"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"onPostAuthorisation = { result, paymentData ->\n    Log.d(\"GooglePay\", \"Non-3DS Google Pay payment result\")\n    \n    when (result) {\n        is MerchantSubmitResult -> {\n            // Success\n            Log.d(\"GooglePay\", \"✅ Payment successful!\")\n            Log.d(\"GooglePay\", \"Merchant Transaction ID: ${result.merchantTransactionId}\")\n            Log.d(\"GooglePay\", \"System Transaction ID: ${result.systemTransactionId}\")\n            \n            // Store transaction details\n            storeTransactionRecord(\n                TransactionRecord(\n                    merchantTransactionId = result.merchantTransactionId,\n                    systemTransactionId = result.systemTransactionId,\n                    paymentMethod = \"google-pay\",\n                    processingType = \"non-3ds\",\n                    timestamp = System.currentTimeMillis()\n                )\n            )\n            \n            // Redirect to success page\n            navigateToSuccess(result.merchantTransactionId)\n        }\n        is FailedSubmitResult -> {\n            // Failure\n            Log.e(\"GooglePay\", \"❌ Payment failed\")\n            Log.e(\"GooglePay\", \"Error code: ${result.errorCode}\")\n            Log.e(\"GooglePay\", \"Error reason: ${result.errorReason}\")\n            Log.e(\"GooglePay\", \"Correlation ID: ${result.correlationId}\")\n            \n            // Handle payment failure\n            handlePaymentFailure(result)\n        }\n    }\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"onerror","__idx":28},"children":["onError"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onError"]}," callback is triggered when an error occurs during the Google Pay flow (before reaching authorisation)."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"event-data-2","__idx":29},"children":["Event data"]},{"$$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":"Parameter"},"children":["Parameter"]},{"$$mdtype":"Tag","name":"th","attributes":{"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":["error"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["BaseSdkException"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Required","attributes":{},"children":[]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The exception that occurred during the payment flow."]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-implementation-2","__idx":30},"children":["Example implementation"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"onError = { error ->\n    Log.e(\"GooglePay\", \"Google Pay error\", error)\n    \n    // Handle specific error types\n    val errorMessage = when (error) {\n        is GooglePayNotReadyException -> {\n            \"Google Pay is not available on this device. Please try another payment method.\"\n        }\n        is GooglePayConfigurationValidationFailedException -> {\n            logCriticalError(\"Google Pay configuration error\", error)\n            \"Payment system configuration error. Please contact support.\"\n        }\n        is GooglePayLoadFailedException -> {\n            \"Failed to load Google Pay. Please try again.\"\n        }\n        is GooglePayPaymentFailedException -> {\n            \"Payment failed. Please try another payment method.\"\n        }\n        else -> {\n            \"An error occurred. Please try again or use a different payment method.\"\n        }\n    }\n    \n    showError(errorMessage)\n    \n    // Re-enable payment options\n    hideLoadingSpinner()\n    enablePaymentOptions()\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"oncancel","__idx":31},"children":["onCancel"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onCancel"]}," callback is triggered when the customer closes the Google Pay payment sheet without completing the payment."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"event-data-3","__idx":32},"children":["Event data"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This callback does not receive any parameters."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-implementation-3","__idx":33},"children":["Example implementation"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"onCancel = {\n    Log.d(\"GooglePay\", \"Google Pay payment cancelled by user\")\n    \n    // Track cancellation for analytics\n    trackEvent(\"payment-cancelled\", mapOf(\n        \"paymentMethod\" to \"google-pay\",\n        \"timestamp\" to System.currentTimeMillis()\n    ))\n    \n    // Show message to user\n    showMessage(\"Payment cancelled. Your order is still in your cart.\")\n    \n    // Reset UI state\n    hideLoadingSpinner()\n    enablePaymentOptions()\n}\n","lang":"kotlin"},"children":[]}]},"headings":[{"value":"Non-3DS transactions","id":"non-3ds-transactions","depth":1},{"value":"Overview","id":"overview","depth":2},{"value":"Payment flow","id":"payment-flow","depth":2},{"value":"Step 1: Button interaction","id":"step-1-button-interaction","depth":3},{"value":"Step 2: Payment method selection","id":"step-2-payment-method-selection","depth":3},{"value":"Step 3: Payment sheet completion","id":"step-3-payment-sheet-completion","depth":3},{"value":"Step 4: Evaluation","id":"step-4-evaluation","depth":3},{"value":"Step 5: Authorisation","id":"step-5-authorisation","depth":3},{"value":"Associated callbacks","id":"associated-callbacks","depth":4},{"value":"Implementation","id":"implementation","depth":2},{"value":"Before you start","id":"before-you-start","depth":3},{"value":"Step 1: Initialise the SDK","id":"step-1-initialise-the-sdk","depth":3},{"value":"Step 2: Implement callbacks","id":"step-2-implement-callbacks","depth":3},{"value":"Step 3: Handle common scenarios","id":"step-3-handle-common-scenarios","depth":3},{"value":"Amount-based risk assessment","id":"amount-based-risk-assessment","depth":4},{"value":"Customer type handling","id":"customer-type-handling","depth":4},{"value":"Geographic risk assessment","id":"geographic-risk-assessment","depth":4},{"value":"Step 4: Handle errors","id":"step-4-handle-errors","depth":3},{"value":"Complete example","id":"complete-example","depth":2},{"value":"Callback data","id":"callback-data","depth":2},{"value":"onPreAuthorisation","id":"onpreauthorisation","depth":3},{"value":"Event data","id":"event-data","depth":4},{"value":"Example implementation","id":"example-implementation","depth":4},{"value":"onPostAuthorisation","id":"onpostauthorisation","depth":3},{"value":"Event data","id":"event-data-1","depth":4},{"value":"Success result","id":"success-result","depth":4},{"value":"Failure result","id":"failure-result","depth":4},{"value":"Example implementation","id":"example-implementation-1","depth":4},{"value":"onError","id":"onerror","depth":3},{"value":"Event data","id":"event-data-2","depth":4},{"value":"Example implementation","id":"example-implementation-2","depth":4},{"value":"onCancel","id":"oncancel","depth":3},{"value":"Event data","id":"event-data-3","depth":4},{"value":"Example implementation","id":"example-implementation-3","depth":4}],"frontmatter":{"seo":{"title":"Non-3DS transactions"}},"lastModified":"2026-06-12T11:56:36.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/guides/checkout/components/android/google-pay/non-3ds","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}