{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-guides/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["sub-heading","admonition","br","details","required"]},"type":"markdown"},"seo":{"title":"Pay now flow","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":"pay-now-flow","__idx":0},"children":["Pay now flow"]},{"$$mdtype":"Tag","name":"SubHeading","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Capture funds instantly upon customer approval for Android."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"overview","__idx":1},"children":["Overview"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The pay now flow is designed for immediate payment capture, making it ideal for digital products, services, or when instant payment confirmation is required."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"payment-flow","__idx":2},"children":["Payment flow"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The PayPal pay now flow consists of five key steps for immediate payment processing."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-1-submission","__idx":3},"children":["Step 1: Submission"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The customer taps the PayPal button, which triggers the payment flow. The SDK validates the PayPal configuration and transaction data before proceeding to order creation. If validation fails, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onError"]}," is triggered."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-2-order-creation","__idx":4},"children":["Step 2: Order creation"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The SDK creates a PayPal order using the provided transaction details. This involves sending the payment amount, currency, merchant information, and any additional order details to PayPal's API. If order creation fails, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onError"]}," is triggered."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-3-paypal-approval","__idx":5},"children":["Step 3: PayPal approval"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The customer is redirected to PayPal (via WebView) where they can log in and approve the payment."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This step has three associated callbacks:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onSuccess"]},": Proceeds with payment capture if the customer successfully approves the payment."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onCancel"]},": Cancels the transaction if the customer cancels the payment."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onError"]},":  Receives error data if any error occurs during the approval process."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["PayPal handles all authentication and payment method selection within their secure environment."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-4-payment-capture","__idx":6},"children":["Step 4: Payment capture"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Once the customer approves the payment, the SDK processes the payment immediately and automatically captures the funds. This happens within the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onSuccess"]}," callback handler, where you process the capture and handle success/failure."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-5-payment-result","__idx":7},"children":["Step 5: Payment result"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You receive the final payment result from PayPal and the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onSuccess"]}," callback completes processing. The transaction is either completed successfully with payment confirmation, or fails with specific error details."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"implementation","__idx":8},"children":["Implementation"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"before-you-start","__idx":9},"children":["Before you start"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To use PayPal pay now payments in your Android application:"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Ensure you have a valid PayPal Business account with API credentials."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Configure your PayPal merchant account to accept the currencies you need."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Set up your merchant configuration in the Unity Portal (API credentials, payment methods, risk settings)."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Install and configure the PXP Checkout SDK for Android."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-1-configure-your-sdk","__idx":10},"children":["Step 1: Configure your SDK"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Set up your SDK configuration with transaction information for PayPal payments. For pay now, use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["IntentType.Purchase"]},", which maps to PayPal's ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["capture"]}," intent."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Intent for Pay Now:"]}," For immediate payment capture (pay now flow), use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["IntentType.Purchase"]},", which maps to PayPal's \"capture\" intent."]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"import com.pxp.checkout.PxpCheckout\nimport com.pxp.checkout.models.Environment\nimport com.pxp.checkout.models.OwnerType\nimport com.pxp.checkout.models.TransactionData\nimport com.pxp.checkout.models.EntryType\nimport com.pxp.checkout.models.IntentType\nimport com.pxp.checkout.models.Shopper\nimport com.pxp.checkout.models.ShippingAddress\nimport java.util.UUID\n\nval pxpCheckout = PxpCheckout.builder()\n    .withConfig(\n        PxpCheckoutConfig(\n            environment = Environment.TEST,\n            session = sessionData,\n            ownerId = \"Unity\",\n            ownerType = OwnerType.MERCHANT_GROUP,\n            transactionData = TransactionData(\n                amount = 2500.0, // Amount in cents ($25.00)\n                currency = \"USD\",\n                entryType = EntryType.Ecom,\n                intent = IntentType.Purchase,\n                merchantTransactionId = UUID.randomUUID().toString(),\n                merchantTransactionDate = { System.currentTimeMillis() }\n            ),\n            onGetShopper = {\n                Shopper(\n                    id = \"Shopper_01\",\n                    email = \"customer@example.com\",\n                    firstName = \"John\",\n                    lastName = \"Doe\"\n                )\n            },\n            onGetShippingAddress = {\n                ShippingAddress(\n                    addressLine1 = \"123 Main Street\",\n                    city = \"New York\",\n                    state = \"NY\",\n                    postalCode = \"10001\",\n                    countryCode = \"US\"\n                )\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":11},"children":["Step 2: Implement callbacks"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Implement the required callbacks for PayPal pay now payments."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"import com.pxp.checkout.components.paypal.PayPalComponentConfig\nimport com.pxp.checkout.components.paypal.types.ShippingPreference\nimport com.pxp.checkout.components.paypal.types.UserAction\nimport org.json.JSONObject\nimport android.util.Log\nimport kotlinx.coroutines.launch\n\nval paypalConfig = PayPalComponentConfig(\n    // Required PayPal configuration\n    payeeEmailAddress = \"merchant@example.com\",\n    paymentDescription = \"Product purchase\",\n    shippingPreference = ShippingPreference.NoShipping.toString(),\n    userAction = UserAction.PayNow.toString(),\n    renderType = \"standalone\",\n    fundingSources = \"paypal\",\n\n    // REQUIRED: Handle successful payment approval\n    onSuccess = { data ->\n        Log.d(\"PayPal\", \"Payment approved: $data\")\n        \n        try {\n            // Parse the payment data\n            val jsonObject = JSONObject(data)\n            val orderID = jsonObject.getString(\"orderID\")\n            val payerID = jsonObject.getString(\"payerID\")\n            \n            // Process the payment on your backend\n            viewModelScope.launch {\n                val result = repository.capturePayPalPayment(\n                    orderID = orderID,\n                    payerID = payerID,\n                    merchantTransactionId = transactionId\n                )\n                \n                if (result.isSuccess) {\n                    Log.d(\"PayPal\", \"Payment captured successfully\")\n                    \n                    // Navigate to success screen\n                    navController.navigate(\"payment_success/$orderID\")\n                } else {\n                    throw Exception(result.error ?: \"Payment capture failed\")\n                }\n            }\n        } catch (e: Exception) {\n            Log.e(\"PayPal\", \"Payment processing error\", e)\n            showError(\"Payment failed. Please try again.\")\n        }\n    },\n\n    // REQUIRED: Handle payment errors\n    onError = { error ->\n        Log.e(\"PayPal\", \"Payment error: $error\")\n        showError(\"Payment failed. Please try again.\")\n    },\n\n    // OPTIONAL: Handle payment cancellation\n    onCancel = {\n        Log.d(\"PayPal\", \"Payment cancelled by user\")\n        showMessage(\"Payment was cancelled. You can try again anytime.\")\n    }\n)\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-3-render-the-component","__idx":12},"children":["Step 3: Render the component"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Create and render the PayPal component in your Compose UI."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"import androidx.compose.runtime.*\nimport androidx.compose.ui.Modifier\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport com.pxp.checkout.types.ComponentType\nimport com.pxp.checkout.PxpCheckout\n\n@Composable\nfun PayPalPaymentScreen(pxpCheckout: PxpCheckout, paypalConfig: PayPalComponentConfig) {\n    val paypalComponent = remember {\n        pxpCheckout.createComponent(\n            type = ComponentType.PAYPAL,\n            config = paypalConfig\n        )\n    }\n    \n    pxpCheckout.buildComponentView(\n        component = paypalComponent,\n        modifier = Modifier.fillMaxWidth()\n    )\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-4-handle-common-scenarios","__idx":13},"children":["Step 4: Handle common scenarios"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"amount-based-processing","__idx":14},"children":["Amount-based processing"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use different processing logic based on transaction amounts."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"val paypalConfig = PayPalComponentConfig(\n    onSuccess = { data ->\n        val amount = transactionData.amount\n        \n        // Add additional verification for high-value transactions\n        if (amount > 10000) { // Over $100.00\n            viewModelScope.launch {\n                val confirmed = showConfirmationDialog(\n                    \"Confirm payment of $${amount / 100.0}?\"\n                )\n                \n                if (confirmed) {\n                    processPayPalPayment(data)\n                } else {\n                    showMessage(\"Payment cancelled by user.\")\n                }\n            }\n        } else {\n            processPayPalPayment(data)\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 processing requirements."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"fun getCustomerProcessingOptions(customerType: String): ProcessingOptions {\n    return when (customerType) {\n        \"new\" -> ProcessingOptions(\n            verification = VerificationLevel.ENHANCED,\n            emailConfirmation = true\n        )\n        \"returning\" -> ProcessingOptions(\n            verification = VerificationLevel.STANDARD,\n            emailConfirmation = false\n        )\n        \"vip\" -> ProcessingOptions(\n            verification = VerificationLevel.MINIMAL,\n            fastProcessing = true\n        )\n        else -> ProcessingOptions(\n            verification = VerificationLevel.STANDARD,\n            emailConfirmation = true\n        )\n    }\n}\n\nval paypalConfig = PayPalComponentConfig(\n    onSuccess = { data ->\n        val processingOptions = getCustomerProcessingOptions(\"returning\")\n        \n        viewModelScope.launch {\n            processPayPalPayment(\n                data = data,\n                options = processingOptions,\n                customerType = \"returning\",\n                timestamp = System.currentTimeMillis()\n            )\n        }\n    }\n)\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-5-handle-errors","__idx":16},"children":["Step 5: Handle errors"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Implement comprehensive error handling for PayPal payments."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"val paypalConfig = PayPalComponentConfig(\n    onError = { error ->\n        Log.e(\"PayPal\", \"Error: $error\")\n        \n        // Handle specific PayPal error types\n        when {\n            error.contains(\"VALIDATION_ERROR\") -> {\n                showErrorDialog(\n                    title = \"Validation Error\",\n                    message = \"Payment details validation failed. Please try again.\"\n                )\n            }\n            error.contains(\"INSTRUMENT_DECLINED\") -> {\n                showErrorDialog(\n                    title = \"Payment Declined\",\n                    message = \"Your PayPal payment method was declined. Please try a different method.\"\n                )\n            }\n            error.contains(\"PAYER_ACTION_REQUIRED\") -> {\n                showErrorDialog(\n                    title = \"Action Required\",\n                    message = \"Additional action required in PayPal. Please complete the payment process.\"\n                )\n            }\n            error.contains(\"UNPROCESSABLE_ENTITY\") -> {\n                showErrorDialog(\n                    title = \"Processing Error\",\n                    message = \"Payment cannot be processed. Please contact support.\"\n                )\n            }\n            else -> {\n                showErrorDialog(\n                    title = \"Payment Error\",\n                    message = \"Payment failed. Please try again or contact support.\"\n                )\n            }\n        }\n    },\n\n    onSuccess = { data ->\n        try {\n            processPayPalPayment(data)\n        } catch (e: Exception) {\n            // Handle backend processing errors\n            when {\n                e is HttpException && e.code() == 422 -> {\n                    showError(\"Payment details could not be verified. Please try again.\")\n                }\n                e is HttpException && e.code() == 409 -> {\n                    showError(\"This payment has already been processed.\")\n                }\n                e is HttpException && e.code() >= 500 -> {\n                    showError(\"Payment system temporarily unavailable. Please try again later.\")\n                }\n                else -> {\n                    showError(\"Payment processing failed. Please try again.\")\n                }\n            }\n        }\n    }\n)\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"example","__idx":17},"children":["Example"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The following example shows a complete PayPal pay now 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 androidx.lifecycle.viewModelScope\nimport com.pxp.checkout.PxpCheckout\nimport com.pxp.checkout.components.paypal.PayPalComponentConfig\nimport com.pxp.checkout.components.paypal.types.ShippingPreference\nimport com.pxp.checkout.components.paypal.types.UserAction\nimport com.pxp.checkout.components.paypal.types.PayPalButtonStyle\nimport com.pxp.checkout.types.ComponentType\nimport kotlinx.coroutines.launch\nimport org.json.JSONObject\nimport android.util.Log\n\n@Composable\nfun PayPalPayNowScreen(\n    pxpCheckout: PxpCheckout,\n    viewModel: PaymentViewModel\n) {\n    var showLoadingSpinner by remember { mutableStateOf(false) }\n    var showSuccessDialog by remember { mutableStateOf(false) }\n    var showErrorDialog by remember { mutableStateOf(false) }\n    var paymentData by remember { mutableStateOf<PaymentResult?>(null) }\n    var errorMessage by remember { mutableStateOf<String?>(null) }\n    \n    val paypalConfig = remember {\n        PayPalComponentConfig(\n            // PayPal configuration\n            payeeEmailAddress = \"merchant@example.com\",\n            paymentDescription = \"Product Purchase - $25.00\",\n            shippingPreference = ShippingPreference.NoShipping.toString(),\n            userAction = UserAction.PayNow.toString(),\n            renderType = \"standalone\",\n            fundingSources = \"paypal\",\n            \n            // Styling\n            style = PayPalButtonStyle(\n                layout = \"vertical\",\n                color = \"gold\",\n                shape = \"rect\",\n                label = \"paypal\"\n            ),\n\n            // Step 1: Handle payment approval\n            onSuccess = { data ->\n                Log.d(\"PayPal\", \"Processing PayPal payment\")\n                showLoadingSpinner = true\n                \n                try {\n                    // Log transaction details\n                    val jsonObject = JSONObject(data)\n                    val orderID = jsonObject.getString(\"orderID\")\n                    val payerID = jsonObject.getString(\"payerID\")\n                    \n                    Log.d(\"PayPal\", \"Order ID: $orderID\")\n                    Log.d(\"PayPal\", \"Payer ID: $payerID\")\n                    \n                    // Process payment on backend\n                    viewModel.viewModelScope.launch {\n                        val result = viewModel.capturePayment(\n                            orderID = orderID,\n                            payerID = payerID\n                        )\n                        \n                        showLoadingSpinner = false\n                        \n                        if (result.isSuccess) {\n                            Log.d(\"PayPal\", \"Payment completed successfully\")\n                            paymentData = result.data\n                            showSuccessDialog = true\n                        } else {\n                            errorMessage = result.error ?: \"Payment capture failed\"\n                            showErrorDialog = true\n                        }\n                    }\n                } catch (e: Exception) {\n                    Log.e(\"PayPal\", \"Payment processing failed\", e)\n                    showLoadingSpinner = false\n                    errorMessage = e.message ?: \"Please try again\"\n                    showErrorDialog = true\n                }\n            },\n\n            // Step 2: Handle cancellation\n            onCancel = {\n                Log.d(\"PayPal\", \"Payment cancelled by user\")\n                showSnackbar(\"Payment was cancelled. Your order is still available.\")\n            },\n\n            // Step 3: Handle errors\n            onError = { error ->\n                Log.e(\"PayPal\", \"Payment error: $error\")\n                showLoadingSpinner = false\n                errorMessage = error\n                showErrorDialog = true\n            }\n        )\n    }\n    \n    val paypalComponent = remember(paypalConfig) {\n        pxpCheckout.createComponent(\n            type = ComponentType.PAYPAL,\n            config = paypalConfig\n        )\n    }\n\n    Surface(\n        modifier = Modifier.fillMaxSize(),\n        color = MaterialTheme.colorScheme.background\n    ) {\n        Column(\n            modifier = Modifier\n                .fillMaxSize()\n                .padding(16.dp),\n            verticalArrangement = Arrangement.spacedBy(16.dp)\n        ) {\n            Text(\n                text = \"Complete your payment\",\n                style = MaterialTheme.typography.headlineMedium\n            )\n            \n            Text(\n                text = \"Amount: $25.00\",\n                style = MaterialTheme.typography.titleMedium\n            )\n            \n            // PayPal button\n            pxpCheckout.buildComponentView(\n                component = paypalComponent,\n                modifier = Modifier.fillMaxWidth()\n            )\n            \n            // Loading indicator\n            if (showLoadingSpinner) {\n                CircularProgressIndicator(\n                    modifier = Modifier.size(48.dp)\n                )\n            }\n        }\n    }\n    \n    // Success dialog\n    if (showSuccessDialog) {\n        AlertDialog(\n            onDismissRequest = { },\n            title = { Text(\"Payment Successful\") },\n            text = { \n                Text(\"Your payment has been processed successfully!\")\n            },\n            confirmButton = {\n                Button(onClick = {\n                    showSuccessDialog = false\n                    // Navigate or finish\n                }) {\n                    Text(\"OK\")\n                }\n            }\n        )\n    }\n    \n    // Error dialog\n    if (showErrorDialog) {\n        AlertDialog(\n            onDismissRequest = { },\n            title = { Text(\"Payment Error\") },\n            text = { \n                Text(errorMessage ?: \"An error occurred\")\n            },\n            confirmButton = {\n                Button(onClick = { showErrorDialog = false }) {\n                    Text(\"OK\")\n                }\n            }\n        )\n    }\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"callback-data","__idx":18},"children":["Callback data"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This section describes the data received by the different callbacks as part of the PayPal pay now flow."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"onsuccess","__idx":19},"children":["onSuccess"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onSuccess"]}," callback receives payment approval data when the customer successfully approves the payment in PayPal. The approval data includes the PayPal order ID and payer information needed to capture the payment."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"orderID\": \"7YH53119ML8957234\",\n  \"payerID\": \"ABCDEFGHIJKLM\",\n  \"paymentID\": \"PAYID-ABCDEFG\",\n  \"billingToken\": null,\n  \"facilitatorAccessToken\": \"A21AAFExi...\"\n}\n","lang":"json"},"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":"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":["orderID"]},{"$$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 unique PayPal order ID that identifies this payment."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["payerID"]},{"$$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 unique PayPal payer ID that identifies the customer who approved the payment."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paymentID"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The PayPal payment ID for this transaction."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["billingToken"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["String?"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The billing agreement token if applicable, otherwise ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["null"]},"."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["facilitatorAccessToken"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The PayPal facilitator access token for processing the payment."]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Here's an example of what to do with this data:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"onSuccess = { data ->\n    Log.d(\"PayPal\", \"Payment approved: $data\")\n    \n    try {\n        // Parse the payment data\n        val jsonObject = JSONObject(data)\n        val orderID = jsonObject.getString(\"orderID\")\n        val payerID = jsonObject.getString(\"payerID\")\n        \n        // Capture the payment immediately for pay now flow\n        viewModelScope.launch {\n            val captureResponse = repository.capturePayPalPayment(\n                orderID = orderID,\n                payerID = payerID,\n                merchantTransactionId = generateTransactionId(),\n                timestamp = System.currentTimeMillis()\n            )\n            \n            if (captureResponse.status == \"COMPLETED\") {\n                // Payment captured successfully\n                Log.d(\"PayPal\", \"Payment captured: ${captureResponse.id}\")\n                \n                // Store transaction record\n                database.insertTransaction(\n                    Transaction(\n                        paypalOrderId = orderID,\n                        paypalPayerId = payerID,\n                        transactionId = captureResponse.id,\n                        amount = captureResponse.amount,\n                        currency = captureResponse.currency,\n                        status = \"completed\",\n                        timestamp = System.currentTimeMillis()\n                    )\n                )\n                \n                // Navigate to success\n                navController.navigate(\"success/$orderID\")\n            } else {\n                throw Exception(\"Payment capture failed: ${captureResponse.status}\")\n            }\n        }\n    } catch (e: Exception) {\n        Log.e(\"PayPal\", \"Payment capture error\", e)\n        showError(\"Payment processing failed. Please contact support.\")\n    }\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"onerror","__idx":20},"children":["onError"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onError"]}," callback receives error information when PayPal payments fail. PayPal errors include specific error names and details to help with troubleshooting."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"name\": \"VALIDATION_ERROR\",\n  \"message\": \"Invalid payment method\",\n  \"details\": [{\n    \"issue\": \"INSTRUMENT_DECLINED\",\n    \"description\": \"The instrument presented was either declined by the processor or bank, or it can't be used for this payment.\"\n  }]\n}\n","lang":"json"},"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":"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":["name"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The error name.",{"$$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":["VALIDATION_ERROR"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["INSTRUMENT_DECLINED"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PAYER_ACTION_REQUIRED"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["UNPROCESSABLE_ENTITY"]}]}]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["message"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["A human-readable error message."]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Here's an example of how to handle PayPal errors:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"onError = { error ->\n    Log.e(\"PayPal\", \"Payment error: $error\")\n    \n    // Handle specific error types\n    when {\n        error.contains(\"VALIDATION_ERROR\") -> {\n            showErrorDialog(\n                title = \"Validation Error\",\n                message = \"Payment information is invalid. Please try again.\"\n            )\n        }\n        error.contains(\"INSTRUMENT_DECLINED\") -> {\n            showErrorDialog(\n                title = \"Payment Declined\",\n                message = \"Your PayPal payment method was declined. Please try a different payment method.\"\n            )\n        }\n        error.contains(\"PAYER_ACTION_REQUIRED\") -> {\n            showErrorDialog(\n                title = \"Action Required\",\n                message = \"Additional verification required. Please complete the process in PayPal.\"\n            )\n        }\n        error.contains(\"UNPROCESSABLE_ENTITY\") -> {\n            showErrorDialog(\n                title = \"Processing Error\",\n                message = \"This payment cannot be processed. Please contact support.\"\n            )\n        }\n        error.contains(\"INTERNAL_SERVICE_ERROR\") -> {\n            showErrorDialog(\n                title = \"Service Error\",\n                message = \"PayPal service temporarily unavailable. Please try again later.\"\n            )\n        }\n        else -> {\n            showErrorDialog(\n                title = \"Payment Error\",\n                message = \"Payment failed. Please try again or contact support.\"\n            )\n        }\n    }\n    \n    // Log error details for monitoring\n    analytics.track(\"paypal_payment_error\", mapOf(\n        \"errorMessage\" to error,\n        \"timestamp\" to System.currentTimeMillis(),\n        \"paymentMethod\" to \"paypal\"\n    ))\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"oncancel","__idx":21},"children":["onCancel"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onCancel"]}," callback receives no data when the customer cancels the PayPal payment process."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Here's an example of how to handle cancellations:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"onCancel = {\n    Log.d(\"PayPal\", \"Payment cancelled by user\")\n    \n    // Log cancellation for analytics\n    analytics.track(\"paypal_payment_cancelled\", mapOf(\n        \"timestamp\" to System.currentTimeMillis(),\n        \"paymentMethod\" to \"paypal\"\n    ))\n    \n    // Show user-friendly message\n    showSnackbar(\"Payment was cancelled. Your cart items are still saved.\")\n    \n    // Optional: Offer alternative payment methods\n    showAlternativePaymentOptions()\n}\n","lang":"kotlin"},"children":[]}]},"headings":[{"value":"Pay now flow","id":"pay-now-flow","depth":1},{"value":"Overview","id":"overview","depth":2},{"value":"Payment flow","id":"payment-flow","depth":2},{"value":"Step 1: Submission","id":"step-1-submission","depth":3},{"value":"Step 2: Order creation","id":"step-2-order-creation","depth":3},{"value":"Step 3: PayPal approval","id":"step-3-paypal-approval","depth":3},{"value":"Step 4: Payment capture","id":"step-4-payment-capture","depth":3},{"value":"Step 5: Payment result","id":"step-5-payment-result","depth":3},{"value":"Implementation","id":"implementation","depth":2},{"value":"Before you start","id":"before-you-start","depth":3},{"value":"Step 1: Configure your SDK","id":"step-1-configure-your-sdk","depth":3},{"value":"Step 2: Implement callbacks","id":"step-2-implement-callbacks","depth":3},{"value":"Step 3: Render the component","id":"step-3-render-the-component","depth":3},{"value":"Step 4: Handle common scenarios","id":"step-4-handle-common-scenarios","depth":3},{"value":"Amount-based processing","id":"amount-based-processing","depth":4},{"value":"Customer type handling","id":"customer-type-handling","depth":4},{"value":"Step 5: Handle errors","id":"step-5-handle-errors","depth":3},{"value":"Example","id":"example","depth":3},{"value":"Callback data","id":"callback-data","depth":3},{"value":"onSuccess","id":"onsuccess","depth":4},{"value":"onError","id":"onerror","depth":4},{"value":"onCancel","id":"oncancel","depth":4}],"frontmatter":{"seo":{"title":"Pay now flow"}},"lastModified":"2026-02-26T12:14:32.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/guides/checkout/components/android/paypal/pay-now","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}