Skip to content

Testing

Test your Aeropay integration before accepting live payments or payouts.

Overview

Test the complete Aeropay journey, including component configuration, new and returning shoppers, OTP verification, bank linking, every supported intent, transaction failures, and backend verification.

Use Environment.TEST with UAT credentials and test data. Don't use production Aeropay credentials, real bank accounts, or real shopper data during development.

Get approved UAT users, OTP behaviour, bank account scenarios, and expected provider responses from your PXP or Aeropay integration contact.

Test environment

Initialise the SDK with a UAT session and matching test transaction data:

import com.pxp.checkout.models.AeropayIntentType
import com.pxp.checkout.models.EntryType
import com.pxp.checkout.models.Environment
import com.pxp.checkout.models.PxpSdkConfig
import com.pxp.checkout.models.TransactionData
import com.pxp.checkout.models.TransactionIntentData
import com.pxp.checkout.services.models.transaction.Shopper
import java.time.Instant

val sdkConfig = PxpSdkConfig(
    environment = Environment.TEST,
    session = mapToSessionConfig(sessionResult), // SessionConfig, not the raw API model
    transactionData = TransactionData(
        amount = 10.00,
        currency = "USD",
        entryType = EntryType.Ecom,
        intent = TransactionIntentData(aeropay = AeropayIntentType.Authorisation),
        merchant = "your-merchant-id",
        merchantTransactionId = sessionResult.merchantTransactionId,
        merchantTransactionDate = { Instant.now().toString() },
    ),
    clientId = "your-client-id",
    ownerType = "MerchantGroup",
    ownerId = "MERCHANT_GROUP_1",
    onGetShopper = {
        Shopper(
            id = "test-shopper-1",
            firstName = "Test",
            lastName = "Shopper",
            email = "test.shopper@example.com",
            phoneNumber = "+14155550123",
        )
    },
    analyticsEvent = { event ->
        // Log event.eventName only. Don't log personal or bank data.
    },
)

Use environment settings consistently:

SDK environmentAeropay and Aerosync configurationPurpose
Environment.TESTUAT or sandbox configuration (SANDBOX)Development, automated testing, and UAT
Environment.LIVEProduction configuration (PROD)Live payments and payouts

Confirm which credentials and test identities apply to each environment before testing.

Add diagnostic callbacks

Use callbacks to trace the flow without logging personal or bank data:

val config = AeropayButtonComponentConfig().apply {
    onClick = {
        // Button tapped
    }
    onCustomValidation = {
        true
    }
    onUserVerificationSuccess = {
        // User verified
    }
    onCancel = {
        // Popup dismissed
    }
    onPreAuthorisation = {
        true
    }
    onPostAuthorisation = { result ->
        // Log only that a result was received
    }
    onSubmitError = { error ->
        // Log FailedSubmitResult.errorCode and correlationId only
    }
    onError = { error ->
        // Log error.errorCode and a redacted message
    }
}

Don't log shopper details, OTPs, Aeropay user IDs, bank account IDs, credentials, or complete provider responses.

Configuration tests

Test each required configuration rule before testing the shopper flow:

ScenarioExpected result
Valid Aeropay-enabled sessionThe component is created and Content() renders the button.
Missing externalMerchantIdcreateComponent() throws SDK0113.
Missing configurationIdcreateComponent() throws SDK0113.
Missing Aeropay intentcreateComponent() throws SDK0115.
Entry type other than EcomcreateComponent() throws SDK0114.
Currency other than USDcreateComponent() throws SDK0116.

For example, confirm that an unsupported currency fails during component creation. createCheckoutWithCurrency is a test helper that builds a new PxpCheckout with transactionData.currency = "GBP" and an otherwise valid Aeropay session and intent:

import com.pxp.checkout.exceptions.BaseSdkException
import com.pxp.checkout.types.ComponentType
import com.pxp.checkout.components.aeropaybutton.types.AeropayButtonComponentConfig

val invalidCheckout = createCheckoutWithCurrency("GBP")

try {
    invalidCheckout.createComponent(
        ComponentType.AERO_PAY_BUTTON,
        AeropayButtonComponentConfig().apply {
            onPreAuthorisation = { true }
        },
    )
} catch (error: BaseSdkException) {
    // Expected: error.errorCode == "SDK0116"
}

Component tests

Verify basic button behaviour:

  • The Aeropay presentation and default payment label render.
  • The payout label renders when the intent is Payout.
  • Custom label and styles values are applied.
  • Disabled and loading states remain readable.
  • disabled = true on the config before creation, or setDisabled(true) after creation, prevents the flow from starting.
  • onCustomValidation returning false keeps the popup closed after onClick.
  • After changing component config (AeropayButtonComponentConfig), call clearStateComponents() or unmount() on the same PxpCheckout, then createComponent() again. After changing SDK config (PxpSdkConfig session, transactionData, or environment), build a new PxpCheckout with the updated config, then create the component. Keep only one Aeropay component reference in your UI.

Test the button on phone and tablet layouts in portrait and landscape.

New-shopper tests

No prefilled data

Omit onGetShopper or return only a shopper ID. Confirm that:

  1. The consumer data screen opens with empty fields.
  2. All four fields are required.
  3. Inline errors appear for empty or invalid values.
  4. Valid data advances to OTP verification.
  5. Successful OTP verification calls onUserVerificationSuccess.
  6. Bank selection opens after verification.

Partial prefilled data

Return some consumer fields:

onGetShopper = {
    Shopper(
        id = "test-shopper-2",
        firstName = "Test",
        email = "test.shopper@example.com",
    )
}

Confirm that provided fields are prefilled and read-only unless listed in editableFields, while missing fields remain empty for the shopper to complete.

Editable prefilled data

Make selected fields editable:

val config = AeropayButtonComponentConfig().apply {
    consumerDataCollectionConfig = ConsumerDataCollectionConfig(
        editableFields = listOf(ConsumerDataField.EMAIL),
    )
    onPreAuthorisation = { true }
}

Confirm that only the configured fields can be changed and that edited values still receive validation.

Skip consumer data collection

Return all four valid consumer fields and set skipConsumerDataCollection to true:

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

Confirm that the SDK creates the user in the background and opens OTP verification directly.

Also test that the data screen still appears when:

  • A required field is missing or empty.
  • consumerDataCollectionConfig.editableFields contains a value.

If a supplied field is invalid, confirm that onError receives SDK1300 and the popup doesn't open.

Consumer data tests

Test valid, missing, boundary, and invalid values:

FieldValid examplesInvalid or boundary examples
First nameTest, María, Test UserEmpty, more than 100 characters, Test-User, Test2
Last nameShopper, García, Test ShopperEmpty, more than 100 characters, O'Neil, Shopper2
Emailtest@example.comEmpty, missing @, missing domain dot, whitespace, more than 128 characters
Phone number from onGetShopper+14155550123Empty when skipping, missing +1, too few or too many digits, formatting characters
Phone number entered in the form4155550123Empty, fewer or more than 10 digits

The current name rules accept Unicode letters and spaces only. Test real customer-name patterns against this limitation before launch.

OTP tests

Test the OTP screen with provider-approved UAT scenarios:

  • Confirm that verification remains unavailable until all six-digit cells contain a value.
  • Confirm that typed or pasted non-digit characters are filtered out.
  • Test an incorrect six-digit code.
  • Test a correct six-digit code.
  • Test a network failure during verification or resend.
  • Try to resend while the countdown is active.
  • Resend successfully after the countdown.
  • Confirm that provider verification failures call onError with SDK1302, including provider code AP112 if your UAT setup returns it.

Bank selection and Aerosync tests

Test bank account loading, selection, and linking:

Scenario Expected result
One or more linked accountsAccounts load and the shopper can select an account.
No linked accountsThe component shows the empty state and offers bank linking for payment flows.
Successful bank linkingAerosync completes, the account is linked, and the bank list refreshes.
Failed bank linkingonError receives an Aerosync or link-account failure code.
Payout with default settingsLink-bank is hidden.
Payout with allowLinkBankOnPayout = trueLink-bank is available.

Verify end-to-end bank linking in UAT: completing Aerosync returns to checkout and refreshes linked accounts. The SDK handles pxpcheckout://aerosync/callback through the library manifest; merchants don't register this URI themselves.

Returning-shopper tests

Pass a stored Aeropay user ID and confirm that:

  1. Consumer data and OTP screens are skipped.
  2. Bank selection opens after user lookup.
  3. An inactive user calls onError with SDK1307.
  4. A failed user lookup from a recognised API error calls onError with SDK1308. Network or transport failures use SDK0500 instead.
  5. Your app can clear the stored ID and restart the new-shopper flow.

Intent and transaction tests

Run end-to-end tests for each supported intent:

  • Authorisation
  • Purchase
  • EstimatedAuthorisation
  • Payout

For each intent, confirm:

  • onPreAuthorisation returning false stops submission. The popup stays open and onSubmitError isn't called.
  • Omitting onPreAuthorisation also stops submission. The popup stays open and onSubmitError isn't called. Plain { true } or { false } lambdas are fine when the callback doesn't call suspend functions.
  • When onPostAuthorisation is configured, successful submission invokes it. Submission can still succeed when onPostAuthorisation is omitted (unlike onPreAuthorisation, which must be set and return true).
  • Failed submission calls onSubmitError.
  • Your backend verification accepts only authoritative PXP transaction data.

Cancellation tests

Confirm that dismissing the popup with the close control or system back or scrim calls onCancel, and that a successful payment dismissal doesn't.