# Events

Implement callbacks to customise your PayPal payout flow for Android.

## Overview

Components emit events based on user interaction or validation. You can use these to implement callback functions, which allow you to inject your own business logic and user experience customisations into the payout flow at critical moments. They ensure that while the SDK handles the complex technical aspects of payout processing, you retain full control over the customer experience and can seamlessly integrate payouts into your broader business workflows and systems.

Callbacks enable you to:

* Validate business rules before payouts proceed.
* Display custom error, failure, or success messages.
* Tailor user interfaces to match your brand's look and feel.
* Integrate with your own systems for fraud detection or compliance checks.
* Control exactly how your customers experience both successful and failed payouts.


* Store customer wallet details for future payouts.
* Implement merchant-initiated payout flows with custom approval logic.


## Available callbacks

The following callbacks are available on the `PayoutSubmissionComponent`, used for returning customers with stored wallet details.

Only the submission component (`PayoutSubmissionComponent`) supports event callbacks. The display components (`PayoutAmountComponent` and `PaypalPayoutReceiverComponent`) are configuration-only and don't emit events.

### onClick

This callback is triggered when the customer taps the withdrawal button, before any validation occurs.

You can use it to:

* Track button tap analytics.
* Show loading indicators.
* Perform pre-validation checks.


#### Example implementation


```kotlin
val submitConfig = PayoutSubmissionComponentConfig(
    recipientWallet = "Paypal",
    onClick = {
        Log.d("Payout", "Withdrawal button tapped")
        
        // Track button tap
        trackEvent("payout-button-tapped", mapOf(
            "walletType" to "paypal",
            "timestamp" to System.currentTimeMillis()
        ))
        
        // Show loading indicator
        showLoadingState()
    }
)
```

### onPrePayoutSubmit

This callback is triggered after the customer taps the withdrawal button and validation passes. The merchant should show their own approval modal/UI and return the approval status.

You can use it to:

* Display a confirmation dialog before proceeding.
* Perform final validation before payout execution.
* Check compliance requirements.
* Verify sufficient balance.


#### Return value

| Property | Description |
|  --- | --- |
| `isApproved`Boolean   | Whether to proceed with the payout. |


#### Example implementation


```kotlin
val submitConfig = PayoutSubmissionComponentConfig(
    recipientWallet = "Paypal",
    onPrePayoutSubmit = {
        Log.d("Payout", "Pre-payout submission triggered")
        
        try {
            // Show confirmation modal
            val confirmation = showConfirmationDialog(
                title = "Confirm Withdrawal",
                message = "Are you sure you want to withdraw $$amount $currency?"
            )
            
            if (!confirmation.confirmed) {
                return@PayoutSubmissionComponentConfig PrePayoutSubmitResult(isApproved = false)
            }
            
            // Check withdrawal limits
            val limitsCheck = checkWithdrawalLimits(
                customerId = getCurrentCustomerId(),
                amount = amount,
                currency = currency
            )
            
            if (!limitsCheck.allowed) {
                showMessage("Withdrawal limit exceeded. Maximum: ${limitsCheck.maxAmount} $currency")
                return@PayoutSubmissionComponentConfig PrePayoutSubmitResult(isApproved = false)
            }
            
            // Verify sufficient balance
            val balanceCheck = verifyBalance(amount, currency)
            
            if (!balanceCheck.sufficient) {
                showMessage("Insufficient funds for this withdrawal.")
                return@PayoutSubmissionComponentConfig PrePayoutSubmitResult(isApproved = false)
            }
            
            // Approve the payout
            PrePayoutSubmitResult(isApproved = true)
            
        } catch (error: Exception) {
            Log.e("Payout", "Pre-payout check failed", error)
            showMessage("Unable to process withdrawal. Please try again.")
            PrePayoutSubmitResult(isApproved = false)
        }
    }
)
```

### onPostPayout

This callback is triggered when the payout is successfully processed.

You can use it to:

* Display success confirmation to the customer.
* Update your internal records.
* Send confirmation notifications.
* Redirect to a success screen.


#### Event data

| Parameter | Description |
|  --- | --- |
| `data`PostPayoutResult | Object containing transaction identifiers. |
| `data.merchantTransactionId`String? | Your unique identifier for the transaction. Use this with `systemTransactionId` to retrieve full authorisation details from the Unity backend. |
| `data.systemTransactionId`String | The system's unique identifier for the transaction. Use this with `merchantTransactionId` to retrieve full authorisation details from the Unity backend. |


#### Example implementation


```kotlin
val submitConfig = PayoutSubmissionComponentConfig(
    recipientWallet = "Paypal",
    onPostPayout = { result ->
        Log.d("Payout", "Payout successful: ${result.systemTransactionId}")
        
        // Store transaction record
        storeTransaction(
            merchantTransactionId = result.merchantTransactionId,
            systemTransactionId = result.systemTransactionId,
            customerId = getCurrentCustomerId()
        )
        
        // Send confirmation email
        sendPayoutConfirmationEmail(
            email = getCustomerEmail(),
            merchantTransactionId = result.merchantTransactionId
        )
        
        // Track successful payout
        trackEvent("payout-completed", mapOf(
            "merchantTransactionId" to result.merchantTransactionId,
            "systemTransactionId" to result.systemTransactionId,
            "timestamp" to System.currentTimeMillis()
        ))
        
        // Show success message
        showMessage("Withdrawal processed successfully!")
        
        // Redirect to success screen
        Handler(Looper.getMainLooper()).postDelayed({
            navigateToSuccessScreen(result.merchantTransactionId)
        }, 2000)
    }
)
```

### onError

This callback is triggered when an error occurs during payout processing.

You can use it to:

* Display user-friendly error messages.
* Log errors for debugging.
* Offer retry options.
* Show alternative payout methods.


#### Event data

| Parameter | Description |
|  --- | --- |
| `error`PayOutError | The error object containing details about what went wrong. |
| `error.correlationId`String? | The correlation ID for tracking the error. |
| `error.details`List<String?>? | List of additional error details. |
| `error.errorCode`String? | The error code identifier (e.g., "NOT_AUTHENTICATED"). |
| `error.errorReason`String? | Human-readable error reason (e.g., "Invalid or missing credentials."). |
| `error.httpStatusCode`Int? | The HTTP status code of the response. |


#### Example implementation


```kotlin
val submitConfig = PayoutSubmissionComponentConfig(
    recipientWallet = "Paypal",
    onError = { error ->
        Log.e("Payout", "Payout error: ${error.errorReason}")
        
        // Log error for debugging
        logError("payout-error", mapOf(
            "correlationId" to error.correlationId,
            "errorCode" to error.errorCode,
            "errorReason" to error.errorReason,
            "httpStatusCode" to error.httpStatusCode.toString(),
            "timestamp" to System.currentTimeMillis(),
            "deviceInfo" to getDeviceInfo()
        ))
        
        // Display user-friendly message based on error
        showMessage("Withdrawal failed. Please try again or contact support.")
        
        // Track error
        trackEvent("payout-failed", mapOf(
            "errorCode" to error.errorCode,
            "httpStatusCode" to error.httpStatusCode.toString(),
            "timestamp" to System.currentTimeMillis()
        ))
    }
)
```