Skip to content

Data validation

Learn about validation requirements for PayPal payout data in your Android app.

Overview

The PayPal Android SDK validates payout data at multiple stages to ensure successful transactions. Understanding these validation rules helps you prevent errors and provide better user experiences.

Validation stages

Validation occurs at three key stages:

  1. SDK initialisation: Validates transaction data and configuration.
  2. Component creation: Validates component-specific configuration.
  3. Payout submission: Validates wallet details and payout parameters before sending to the backend.

Transaction data validation

Amount validation

RuleDescriptionError
Amount requiredAmount must be provided.Validation error.
Positive valueAmount must be greater than zero.PO02: "Transaction amount should be greater than 0."
Numeric valueAmount must be a valid number.Validation error.
// Valid amounts
transactionData = TransactionData(
    amount = 100.0,    // Valid
    amount = 0.01,     // Valid: minimum positive value
    amount = 999999.99 // Valid
)

// Invalid amounts
transactionData = TransactionData(
    amount = 0.0,      // Invalid: must be > 0
    amount = -50.0     // Invalid: cannot be negative
)

Currency validation

RuleDescriptionError
Currency requiredCurrency must be provided.Validation error.
FormatMust be a valid 3-letter ISO currency code.PO03: "Invalid currency code".
SupportedMust be supported by PayPal.Validation error.
// Valid currencies
transactionData = TransactionData(
    currency = "USD",  // Valid
    currency = "EUR",  // Valid
    currency = "GBP"   // Valid
)

// Invalid currencies
transactionData = TransactionData(
    currency = "",      // Invalid: empty
    currency = "US",    // Invalid: not 3 letters
    currency = "DOLLAR" // Invalid: not ISO code
)

Entry type validation

RuleDescriptionError
Entry type requiredEntry type must be provided.Error during initialisation.
ValueMust be EntryType.Ecom for payouts.Error during initialisation.
// Valid entry type for payouts
transactionData = TransactionData(
    entryType = EntryType.Ecom  // Required for payouts
)

// Invalid entry types
transactionData = TransactionData(
    entryType = EntryType.Moto  // Not supported for payouts
)

Intent validation

RuleDescriptionError
Intent requiredIntent must be provided.Error during initialisation.
ValueMust be TransactionIntentData(paypal = IntentType.Payout) for payouts.Error during initialisation.
// Valid intent for payouts
transactionData = TransactionData(
    intent = TransactionIntentData(paypal = IntentType.Payout)  // Required for payouts
)

// Invalid intents
transactionData = TransactionData(
    intent = TransactionIntentData(paypal = IntentType.Purchase)      // Not for payouts
    intent = TransactionIntentData(paypal = IntentType.Authorisation) // Not for payouts
)

Wallet data validation

PayPal wallet validation

RuleDescriptionError
Email requiredPayPal email must be provided for withdrawal flow.PO04: "Receiver cannot be empty".
PayerId requiredPayPal payer ID must be provided for withdrawal flow.PO04: "Payer ID is required for PayPal wallet payout".
Email formatEmail must be valid format (max 127 characters).PO04: "Invalid email format".
// Valid PayPal wallet (withdrawal flow)
paypalConfig = PaypalConfig(
    payout = PayoutConfig(
        proceedPayoutWithSdk = true,
        paypalWallet = PayPalPayOutWalletConfig(
            email = "customer@example.com",  // Required
            payerId = "PAYER_ID_XXX"         // Required
        )
    )
)

// Invalid PayPal wallet
paypalConfig = PaypalConfig(
    payout = PayoutConfig(
        proceedPayoutWithSdk = true,
        paypalWallet = PayPalPayOutWalletConfig(
            email = "customer@example.com",
            payerId = ""  // Invalid: empty payer ID
        )
    )
)

Component validation

Recipient wallet validation

RuleDescriptionError
Supported valuesOnly "Paypal" is currently supported (case-sensitive).PO04: "Invalid recipient wallet. Only 'Paypal' is supported."
Default valueEmpty/blank values default to "Paypal".N/A
// Valid recipient wallet
PayoutSubmissionComponentConfig(
    recipientWallet = "Paypal"  // Valid (case-sensitive)
)

PayoutSubmissionComponentConfig(
    recipientWallet = ""  // Valid: empty/blank defaults to "Paypal"
)

// Invalid recipient wallet
PayoutSubmissionComponentConfig(
    recipientWallet = "Venmo"   // Not supported on Android
)

PayoutSubmissionComponentConfig(
    recipientWallet = "paypal"  // Invalid: case-sensitive (must be "Paypal")
)

Validation error codes

Payout error codes

Error codeDescriptionSolution
PO02Transaction amount should be greater than 0.Provide a positive amount value.
PO03Invalid currency code.Use a valid 3-letter ISO currency code.
PO04Invalid recipient.Ensure paypalWallet.email and paypalWallet.payerId are provided correctly.
PO07Invalid merchant transaction date.Use ISO 8601 format (e.g., 2025-10-28T10:00:00Z).

Validation best practices

Validate early

Validate data before SDK initialisation:

fun validatePayoutData(amount: Double, currency: String): ValidationResult {
    return when {
        amount <= 0 -> ValidationResult(
            isValid = false,
            message = "Amount must be greater than zero"
        )
        currency.length != 3 -> ValidationResult(
            isValid = false,
            message = "Currency must be 3-letter ISO code"
        )
        else -> ValidationResult(isValid = true)
    }
}

// Use validation before initialisation
val validation = validatePayoutData(amount, currency)
if (!validation.isValid) {
    showError(validation.message)
    return
}

// Proceed with SDK initialisation
val pxpCheckout = PxpCheckout.builder()
    .withConfig(config)
    .build()

Provide clear error messages

Show user-friendly error messages:

onError = { error ->
    val userMessage = when (error.errorCode) {
        "PO02" -> "The payout amount must be greater than zero."
        "PO03" -> "Please specify a valid currency."
        "PO04" -> "Please verify your PayPal account information."
        "PO07" -> "Invalid transaction date."
        else -> "An error occurred: ${error.errorReason}"
    }
    
    showError(userMessage)
}

Log validation errors

Implement comprehensive error logging:

onError = { error ->
    // Log for debugging
    Log.e("Payout", """
        Validation error occurred:
        Code: ${error.errorCode}
        Reason: ${error.errorReason}
        HTTP Status: ${error.httpStatusCode}
        Correlation ID: ${error.correlationId}
    """.trimIndent())
    
    // Track in analytics
    trackEvent("payout_validation_error", mapOf(
        "errorCode" to error.errorCode,
        "errorReason" to error.errorReason
    ))
    
    // Show user-friendly message
    showError(getUserFriendlyMessage(error))
}

Handle validation in onPrePayoutSubmit

Perform custom validation before payout:

onPrePayoutSubmit = {
    // Validate balance
    val balance = getUserBalance()
    if (balance < payoutAmount) {
        showError("Insufficient balance. Available: $$balance")
        return@PayoutSubmissionComponentConfig PrePayoutSubmitResult(isApproved = false)
    }
    
    // Validate daily limit
    val dailyTotal = getTodayPayoutTotal()
    if (dailyTotal + payoutAmount > DAILY_LIMIT) {
        showError("Daily payout limit exceeded")
        return@PayoutSubmissionComponentConfig PrePayoutSubmitResult(isApproved = false)
    }
    
    // Validate minimum payout
    if (payoutAmount < MINIMUM_PAYOUT) {
        showError("Minimum payout amount is $$MINIMUM_PAYOUT")
        return@PayoutSubmissionComponentConfig PrePayoutSubmitResult(isApproved = false)
    }
    
    // All validations passed
    PrePayoutSubmitResult(isApproved = true)
}

Custom validation rules

Implement your own business rules:

data class PayoutValidationRules(
    val minimumAmount: Double = 10.0,
    val maximumAmount: Double = 10000.0,
    val dailyLimit: Double = 5000.0,
    val requiredVerificationLevel: Int = 2
)

fun validatePayout(
    amount: Double,
    customerVerificationLevel: Int,
    todayTotal: Double
): ValidationResult {
    val rules = PayoutValidationRules()
    
    return when {
        amount < rules.minimumAmount -> ValidationResult(
            isValid = false,
            message = "Minimum payout is $${rules.minimumAmount}"
        )
        amount > rules.maximumAmount -> ValidationResult(
            isValid = false,
            message = "Maximum payout is $${rules.maximumAmount}"
        )
        todayTotal + amount > rules.dailyLimit -> ValidationResult(
            isValid = false,
            message = "Daily limit of $${rules.dailyLimit} would be exceeded"
        )
        customerVerificationLevel < rules.requiredVerificationLevel -> ValidationResult(
            isValid = false,
            message = "Account verification required for payouts"
        )
        else -> ValidationResult(isValid = true)
    }
}