Test your Aeropay integration before accepting live payments or payouts.
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.
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 environment | Aeropay and Aerosync configuration | Purpose |
|---|---|---|
Environment.TEST | UAT or sandbox configuration (SANDBOX) | Development, automated testing, and UAT |
Environment.LIVE | Production configuration (PROD) | Live payments and payouts |
Confirm which credentials and test identities apply to each environment before testing.
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.
Test each required configuration rule before testing the shopper flow:
| Scenario | Expected result |
|---|---|
| Valid Aeropay-enabled session | The component is created and Content() renders the button. |
Missing externalMerchantId | createComponent() throws SDK0113. |
Missing configurationId | createComponent() throws SDK0113. |
| Missing Aeropay intent | createComponent() throws SDK0115. |
Entry type other than Ecom | createComponent() throws SDK0114. |
Currency other than USD | createComponent() 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"
}Verify basic button behaviour:
- The Aeropay presentation and default payment label render.
- The payout label renders when the intent is
Payout. - Custom
labelandstylesvalues are applied. - Disabled and loading states remain readable.
disabled = trueon the config before creation, orsetDisabled(true)after creation, prevents the flow from starting.onCustomValidationreturningfalsekeeps the popup closed afteronClick.- After changing component config (
AeropayButtonComponentConfig), callclearStateComponents()orunmount()on the samePxpCheckout, thencreateComponent()again. After changing SDK config (PxpSdkConfigsession,transactionData, or environment), build a newPxpCheckoutwith 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.
Omit onGetShopper or return only a shopper ID. Confirm that:
- The consumer data screen opens with empty fields.
- All four fields are required.
- Inline errors appear for empty or invalid values.
- Valid data advances to OTP verification.
- Successful OTP verification calls
onUserVerificationSuccess. - Bank selection opens after verification.
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.
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.
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.editableFieldscontains a value.
If a supplied field is invalid, confirm that onError receives SDK1300 and the popup doesn't open.
Test valid, missing, boundary, and invalid values:
| Field | Valid examples | Invalid or boundary examples |
|---|---|---|
| First name | Test, María, Test User | Empty, more than 100 characters, Test-User, Test2 |
| Last name | Shopper, García, Test Shopper | Empty, more than 100 characters, O'Neil, Shopper2 |
test@example.com | Empty, missing @, missing domain dot, whitespace, more than 128 characters | |
Phone number from onGetShopper | +14155550123 | Empty when skipping, missing +1, too few or too many digits, formatting characters |
| Phone number entered in the form | 4155550123 | Empty, 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.
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
onErrorwithSDK1302, including provider codeAP112if your UAT setup returns it.
Test bank account loading, selection, and linking:
| Scenario | Expected result |
|---|---|
| One or more linked accounts | Accounts load and the shopper can select an account. |
| No linked accounts | The component shows the empty state and offers bank linking for payment flows. |
| Successful bank linking | Aerosync completes, the account is linked, and the bank list refreshes. |
| Failed bank linking | onError receives an Aerosync or link-account failure code. |
| Payout with default settings | Link-bank is hidden. |
Payout with allowLinkBankOnPayout = true | Link-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.
Pass a stored Aeropay user ID and confirm that:
- Consumer data and OTP screens are skipped.
- Bank selection opens after user lookup.
- An inactive user calls
onErrorwithSDK1307. - A failed user lookup from a recognised API error calls
onErrorwithSDK1308. Network or transport failures useSDK0500instead. - Your app can clear the stored ID and restart the new-shopper flow.
Run end-to-end tests for each supported intent:
AuthorisationPurchaseEstimatedAuthorisationPayout
For each intent, confirm:
onPreAuthorisationreturningfalsestops submission. The popup stays open andonSubmitErrorisn't called.- Omitting
onPreAuthorisationalso stops submission. The popup stays open andonSubmitErrorisn't called. Plain{ true }or{ false }lambdas are fine when the callback doesn't call suspend functions. - When
onPostAuthorisationis configured, successful submission invokes it. Submission can still succeed whenonPostAuthorisationis omitted (unlikeonPreAuthorisation, which must be set and returntrue). - Failed submission calls
onSubmitError. - Your backend verification accepts only authoritative PXP transaction data.
Confirm that dismissing the popup with the close control or system back or scrim calls onCancel, and that a successful payment dismissal doesn't.