Skip to content

Events

Implement callbacks to customise your Aeropay payment flow for Android.

Overview

Aeropay callbacks let your application respond to shopper interaction, custom validation, user verification, popup cancellation, transaction submission, and errors.

Use callbacks to:

  • Block the flow when checkout isn't ready.
  • Save the verified Aeropay user ID for returning-shopper flows.
  • Validate business rules before submitting a transaction.
  • Verify successful transactions on your backend.
  • Restore your checkout interface when the shopper dismisses the popup.
  • Log errors and show appropriate recovery options.

Configure onGetShopper on PxpSdkConfig. Configure the other callbacks on AeropayButtonComponentConfig.

Basic event handling

The following example implements the main Aeropay callbacks:

val sdkConfig = PxpSdkConfig(
    // ...session and transaction configuration
    onGetShopper = {
        Shopper(
            id = "shopper-123",
            firstName = "John",
            lastName = "Doe",
            email = "john.doe@example.com",
            phoneNumber = "+14155550123",
        )
    },
)

val config = AeropayButtonComponentConfig().apply {
    onClick = {
        clearPaymentErrors()
    }
    onCustomValidation = {
        val checkoutReady = validateCheckoutReady()
        if (!checkoutReady) {
            showPaymentError("Checkout isn't ready for Aeropay.")
        }
        checkoutReady
    }
    onUserVerificationSuccess = { user ->
        saveAeropayUserId(user.id)
    }
    onCancel = {
        resetCheckoutState()
    }
    onPreAuthorisation = {
        val validation = validateOrderOnBackend()
        if (!validation.approved) {
            showPaymentError(validation.message)
        }
        validation.approved
    }
    onPostAuthorisation = { result ->
        verifyPaymentOnBackend(result)
    }
    onSubmitError = { error ->
        showAlternativePaymentMethods()
    }
    onError = { error ->
        showPaymentError("Unable to complete the Aeropay flow.")
    }
}

Client callbacks aren't proof of payment. Verify every transaction on your backend before fulfilling an order or confirming a payout.

Callback order

New-shopper flow

For a successful new-shopper transaction, callbacks run in this order:

  1. onClick runs when the shopper taps the button.
  2. onCustomValidation runs. Return false to stop before the flow starts.
  3. After onCustomValidation returns true, the SDK calls onGetShopper (if configured) to load shopper details for prefilling and validation.
  4. The component displays the consumer data and OTP screens.
  5. onUserVerificationSuccess runs after successful OTP verification.
  6. onPreAuthorisation runs after the shopper selects a bank account and confirms the transaction.
  7. After onPreAuthorisation returns true, the SDK may call onGetShopper again when building the transaction request, then submits the transaction.
  8. onPostAuthorisation runs after successful transaction submission.

If the shopper dismisses the popup, onCancel runs. Flow errors call onError, while transaction submission failures call onSubmitError.

Returning-shopper flow

When you provide userId, the SDK skips consumer data collection and OTP verification. A successful returning-shopper transaction follows this order:

  1. onClick runs after the shopper taps the button.
  2. onCustomValidation runs. Return false to stop before user lookup.
  3. The SDK validates userId and opens bank selection.
  4. onPreAuthorisation runs after the shopper selects a bank account and confirms the transaction.
  5. onPostAuthorisation runs after successful transaction submission.

The returning-shopper flow doesn't call onUserVerificationSuccess.

SDK data callbacks

onGetShopper

Configure onGetShopper on PxpSdkConfig. The SDK can call it more than once during a successful flow:

  1. After onCustomValidation returns true, to prefill and validate consumer data before the popup opens.
  2. At transaction submission, to populate TransactionRequest.shopper. If the callback is null or omitted, the SDK falls back to transactionData.shopper.

For a returning shopper with userId, the SDK doesn't need onGetShopper to open the popup, but it can still call the callback when building the transaction request.

Return consistent shopper data on every invocation, or set transactionData.shopper if the callback shouldn't run again at submit.

Use the callback to return the latest shopper data from your application:

onGetShopper = {
    val shopper = getCurrentShopper()
    Shopper(
        id = shopper.id,
        firstName = shopper.firstName,
        lastName = shopper.lastName,
        email = shopper.email,
        phoneNumber = shopper.phoneNumber,
    )
}

The Aeropay flow uses these shopper properties:

Property Description
id
String?
Your shopper identifier. Include a stable value so you can associate the transaction with your customer record.
firstName
String?
The shopper's given name. Used to prefill consumer data and included in the transaction request.
lastName
String?
The shopper's family name. Used to prefill consumer data and included in the transaction request.
email
String?
The shopper's email address. Used to prefill consumer data and included in the transaction request.
phoneNumber
String?
The shopper's US phone number, including the +1 country prefix. Used to prefill consumer data, OTP delivery, and the transaction request.

The new-shopper flow validates any values returned for firstName, lastName, email, and phoneNumber. Invalid data calls onError and prevents the popup from opening.

Aeropay component callbacks

Configure the following callbacks on AeropayButtonComponentConfig.

onClick

The SDK calls onClick when the shopper taps the Aeropay button. Custom validation and popup opening happen after this callback.

Use this callback to clear previous errors, update your checkout interface, or track the interaction:

onClick = {
    clearPaymentErrors()
    setCheckoutActive(true)
    trackEvent("aeropay-button-clicked")
}

This callback receives no parameters.

onCustomValidation

The SDK calls onCustomValidation after onClick and before the Aeropay flow starts. Because the callback is suspend, you can call network APIs directly.

Return true to continue or false to stop:

onCustomValidation = {
    val checkoutReady = validateCheckoutReady()
    if (!checkoutReady) {
        showPaymentError("Checkout isn't ready for Aeropay.")
    }
    checkoutReady
}

If the callback is omitted, the SDK treats the result as true.

Return value Behaviour
trueThe SDK continues with returning-user lookup or new-shopper shopper-data checks.
falseThe SDK stops and doesn't open the popup.

onUserVerificationSuccess

The SDK calls onUserVerificationSuccess after a new shopper enters the correct OTP. The callback isn't called for returning shoppers who enter the flow with userId.

This callback is optional. If you don't configure it, the SDK continues the Aeropay flow after OTP verification.

Store the returned Aeropay user ID securely so you can use the returning-shopper flow:

onUserVerificationSuccess = { user ->
    saveAeropayUserId(
        shopperId = getCurrentShopperId(),
        aeropayUserId = user.id,
    )
}

The callback receives an AeropayUser object:

Property Description
id
String
required
The verified Aeropay user ID.
firstName
String?
The user's given name.
lastName
String?
The user's family name.
type
String?
The Aeropay user type.
email
String?
The user's email address.
phoneNumber
String?
The user's phone number.
createdDate
String?
The date and time when the Aeropay user was created.

onCancel

The SDK calls onCancel when the shopper dismisses the Aeropay popup, including the close control and system back or scrim dismiss.

Programmatic dismissal after a successful payment doesn't call onCancel.

Use this callback to restore your checkout interface without treating cancellation as an error:

onCancel = {
    setCheckoutActive(false)
    setLoading(false)
    showAlternativePaymentMethods()
}

This callback receives no parameters and has no return value.

onPreAuthorisation

The SDK calls onPreAuthorisation after the shopper selects a bank account and confirms the payment or payout. Use it to validate your order or payout before the SDK submits the transaction.

Return true to continue or false to stop submission:

onPreAuthorisation = {
    val validation = validateOrderOnBackend()
    if (!validation.approved) {
        showPaymentError(validation.message)
    }
    validation.approved
}

The callback controls transaction submission as follows:

Return valueBehaviour
trueThe SDK builds and submits the transaction.
falseThe SDK stops transaction submission and leaves the Aeropay flow open.

Implement onPreAuthorisation and return true when the transaction can proceed. If the callback is omitted or doesn't return true, the SDK doesn't submit the transaction.

onPostAuthorisation

The SDK calls onPostAuthorisation after PXP accepts the transaction submission. The successful payload is a MerchantSubmitResult containing the transaction identifiers.

This callback is optional. If you don't configure it, the SDK continues the Aeropay flow after successful submission and the popup still closes.

Send the identifiers to your backend and verify the final transaction state:

onPostAuthorisation = { submitResult ->
    verifyPaymentOnBackend(
        merchantTransactionId = submitResult.merchantTransactionId,
        systemTransactionId = submitResult.systemTransactionId,
    )
}

The successful payload contains these properties:

Property Description
merchantTransactionId
String
required
Your unique transaction identifier.
systemTransactionId
String
required
PXP's unique transaction identifier.

onSubmitError

The SDK calls onSubmitError when transaction submission fails. It isn't used for consumer data, user verification, bank account, or Aerosync failures. Those errors call onError.

Handle submission failures without exposing technical details to the shopper:

import com.pxp.checkout.models.FailedSubmitResult

onSubmitError = { submitError ->
    if (submitError is FailedSubmitResult) {
        logPaymentFailure(
            errorCode = submitError.errorCode,
            correlationId = submitError.correlationId,
        )
    }
    setLoading(false)
    showPaymentError("We could not complete the transaction. Try again or use another payment method.")
}

A failed PXP response typically passes a FailedSubmitResult:

Property Description
errorCode
String?
The transaction error code.
errorReason
String?
A description of the failure.
correlationId
String?
The correlation identifier to include in logs and support requests.
httpStatusCode
Int?
The HTTP status code returned by PXP.
details
List<String>?
Additional error details.

When a failed Unity transaction response is mapped to FailedSubmitResult, the SDK also emits ComponentError analytics with SDK1326. Network or transport failures still call onSubmitError, but their ComponentError analytics can use a different code, such as SDK0500. Neither path delivers SDK1326 through onError. Handle the response details from onSubmitError.

onError

The SDK calls onError for errors outside transaction submission, including:

  • Invalid shopper data.
  • Aeropay user creation or verification failure.
  • Returning-user lookup: SDK1307 (inactive), SDK1308 (recognised API failure). Network errors on the same call use SDK0500 or SDK0000, not SDK1308. See Returning-shopper issues.
  • Bank account retrieval or linking failure.
  • Aerosync failure.
  • Missing host Activity when launching Aerosync (SDK1311).

Log recognised SDK errors and show a message that helps the shopper recover:

onError = { error ->
    logErrorToMonitoring(
        errorCode = error.errorCode,
        message = error.message,
        details = error.details,
    )
    setLoading(false)
    showPaymentError("Unable to continue with Aeropay. Try again or use another payment method.")
}

For prefilled shopper validation failures (SDK1300), inspect error.details for the field keys and localised validation messages.

Recognised SDK failures use BaseSdkException:

Property Description
errorCode
String
required
The PXP Android SDK error code (e.g., SDK1300).
message
String
required
A description of the error.
details
Any?
Optional structured detail. For SDK1300, a map of field names to validation messages.

Event data structures

AeropayUser

onUserVerificationSuccess receives the following object:

import com.pxp.checkout.components.aeropaybutton.types.AeropayUser

data class AeropayUser(
    val id: String,
    val firstName: String? = null,
    val lastName: String? = null,
    val type: String? = null,
    val email: String? = null,
    val phoneNumber: String? = null,
    val createdDate: String? = null,
)

MerchantSubmitResult

Successful transaction submission produces a MerchantSubmitResult with merchantTransactionId and systemTransactionId.

FailedSubmitResult

A failed PXP transaction response produces a FailedSubmitResult with errorCode, errorReason, correlationId, httpStatusCode, and details.

BaseSdkException

Recognised onError failures use BaseSdkException with errorCode, message, and optional details.

Error-handling pattern

Keep error logging separate from the message shown to the shopper. The following pattern records diagnostic information while displaying a neutral recovery message:

val config = AeropayButtonComponentConfig().apply {
    onPreAuthorisation = { true }

    onPostAuthorisation = { result ->
        try {
            verifyPaymentOnBackend(result)
            showPaymentSuccess()
        } catch (exception: Exception) {
            showPaymentError("We could not confirm the transaction status. Contact support before trying again.")
        }
    }

    onSubmitError = { error ->
        reportErrorToMonitoring(error)
        showPaymentError("We could not complete the transaction. Try another payment method.")
    }

    onError = { error ->
        reportErrorToMonitoring(
            errorCode = error.errorCode,
            message = error.message,
            details = error.details,
        )
        showPaymentError("Unable to continue with Aeropay. Try again or use another payment method.")
    }
}