Skip to content

Aeropay

Accept Aeropay pay-by-bank payments with automatic consumer verification, bank linking via Aerosync, and the same Drop-in callbacks as other payment methods.

Overview

Aeropay is included in Checkout Drop-in when it's enabled in your session and the transaction meets Aeropay eligibility rules. When the shopper selects Pay by bank via Aeropay and taps the pay button, the SDK mounts an internal Aeropay button component and drives consumer data collection (when required), OTP verification, bank selection or linking, and Unity transaction authorisation.

There's no separate Aeropay factory call in Drop-in. Configure Aeropay through CheckoutDropInConfig and DropInMethodConfig.aeropay.

Key benefits

Aeropay in Drop-in gives you these benefits:

  • Aeropay appears automatically in the payment method list when the session includes Aeropay funding, the currency is USD, and the entry type is .ecom.
  • Drop-in handles consumer verification, Aerosync bank linking, and payment authorisation. You don't need Aeropay-specific UI code.
  • Aeropay uses the same onSuccess and onError callbacks as other payment methods for a unified integration.
  • Site branding from the Unity Portal is applied automatically to the Aeropay launcher button, popup, and form fields.
  • Currency and entry-type gating is enforced automatically.

How it works

When a shopper selects Aeropay in Checkout Drop-in and taps the pay button:

  1. The shopper selects the Aeropay panel. The SDK shows the Aeropay launcher in the panel.
  2. The shopper taps Pay by bank.
  3. Your onBeforeSubmit callback runs (if configured). Return false to stop the flow before the popup opens.
  4. Consumer data collection runs when required (skipped for a non-empty userId, or when skipConsumerDataCollection is true with all four valid onGetShopper fields and empty/nil editable fields).
  5. OTP verification runs when required (skipped when userId is set).
  6. Aerosync bank selection or bank linking runs.
  7. Your onSubmit callback fires, then the SDK submits the Unity transaction. Drop-in always proceeds after onSubmit (there's no merchant onPreAuthorisation gate).
  8. Your onSuccess callback fires with paymentMethod == .aeropay.

If the shopper closes the Aeropay popup without completing, methodConfig.global.onCancel fires with .aeropay and a nil payload. Errors during setup or the flow are delivered to onError.

Consumer data decision tree

How the SDK decides whether to collect consumer data:

  1. userId provided: When methodConfig.aeropay.userId is set to a non-empty value, skip consumer data collection and OTP. Open Aerosync (bank selection) directly after validating that the user is active.
  2. Skip data collection: When skipConsumerDataCollection is true, onGetShopper returns all four fields (firstName, lastName, email, and phoneNumber), and editableConsumerDataFields is nil or empty, auto-create the Aeropay user, skip the data screen, and go to OTP.
  3. Otherwise: Show the consumer data collection screen (prefilled from onGetShopper). Prefill fields with values are read-only unless listed in editableConsumerDataFields. Missing fields stay available for the shopper to complete.

Configuration

Configure Aeropay-specific behaviour at methodConfig.aeropay. All properties are optional.

Configuration properties

The following properties are available for Aeropay configuration:

Property Description
userId
String?
Pre-configured Aeropay user ID. When provided, consumer data collection and OTP are skipped and the flow opens directly at bank selection (Aerosync). The SDK validates that the user is active before opening the popup. When userId is set, Drop-in also skips shopper-data validation at load.
editableConsumerDataFields
[ConsumerDataField]?
Fields returned from onGetShopper that remain editable on the consumer data collection screen. Possible values: .firstName, .lastName, .email, .phoneNumber. When nil or empty, prefilled fields are read-only. Must be empty or nil when using skipConsumerDataCollection.
excludedBankAccountIds
[AeropayBankAccountId]?
Bank account IDs to hide from the bank selection screen. Use string or integer literals (e.g., ["12345"] or [12345]).
skipConsumerDataCollection
Bool
When true, onGetShopper provides all four consumer fields, and editableConsumerDataFields is empty or nil, the consumer data screen is skipped and the flow goes directly to OTP verification (the user is created automatically). Defaults to false.

Don't set skipConsumerDataCollection to true together with a non-empty editableConsumerDataFields list. The skip path requires editable fields to be nil or empty.

Settings used from global configuration

Aeropay inherits the following setting from methodConfig.global:

Property Description
onCancel
(DropInPaymentMethod, Any?) -> Void
Called when the shopper closes the Aeropay popup. For Aeropay, the payload is nil. Cancellation doesn't call onError.

onGetConsent doesn't apply to Aeropay in Drop-in (Card, PayPal, and Apple Pay only).

What Drop-in doesn't expose via methodConfig.aeropay

The following are handled internally from your Unity site branding and Drop-in wiring:

  • Popup, OTP, bank selection, and launcher button styling.
  • Component-level callbacks such as onClick and onUserVerificationSuccess.
  • Merchant-controlled onPreAuthorisation (Drop-in always proceeds after onSubmit).
  • Payout intent and allowLinkBankOnPayout.

If you need merchant-controlled pre-authorisation gating, payout intent, or styling and callbacks beyond Drop-in's unified surface, those capabilities aren't part of the Drop-in Aeropay integration. See What Drop-in exposes vs what it manages.

Complete example

This example shows Aeropay intent, shopper identity, cancellation handling, and optional methodConfig.aeropay settings. The skip path below is consistent: all four consumer fields are provided and editable fields are omitted.

import PXPCheckoutSDK

let dropInConfig = CheckoutDropInConfig(
    environment: .test,
    session: sessionData,
    transactionData: DropInTransactionData(
        amount: Decimal(string: "25.00") ?? 0,
        currency: "USD",
        entryType: .ecom,
        intent: DropInTransactionIntentData(
            aeropay: .authorisation
        ),
        merchantTransactionId: UUID().uuidString,
        merchantTransactionDate: { Date() }
    ),
    merchantShopperId: "shopper-001",
    ownerId: "MERCHANT_GROUP_1", // Merchant group ID (ownerType is always "MerchantGroup")
    methodConfig: DropInMethodConfig(
        global: DropInGlobalConfig(
            onCancel: { paymentMethod, _ in
                guard paymentMethod == .aeropay else { return }
                // Shopper closed Pay by Bank — not an error
            }
        ),
        aeropay: DropInAeropayConfig(
            // userId: "existing-aeropay-user-id",
            skipConsumerDataCollection: true
            // editableConsumerDataFields must stay nil or empty when skip is true
        )
    ),
    onGetShopper: {
        TransactionShopper(
            id: "shopper-001",
            firstName: "John",
            lastName: "Doe",
            email: "shopper@example.com",
            // When non-empty: +1 followed by 10 digits (e.g. +16465180948). Omit or leave empty to collect in the popup.
            phoneNumber: "+16465180948"
        )
    },
    onBeforeSubmit: { paymentMethod async in
        guard paymentMethod == .aeropay else { return true }
        return await validateCheckoutForm()
    },
    onSubmit: { paymentMethod in
        // Unity transaction is about to submit for Aeropay
        print("Submit: \(paymentMethod.rawValue)")
    },
    onSuccess: { result in
        guard result.paymentMethod == .aeropay else { return }
        verifyPaymentOnBackend(result)
    },
    onError: { paymentMethod, error in
        guard paymentMethod == .aeropay else { return }
        showError(error.errorCode, error.errorMessage)
    }
)

let checkoutDropIn = try CheckoutDropIn(config: dropInConfig)
// create() does not throw for Aeropay eligibility or render failures — those arrive on onError after create completes.
await checkoutDropIn.create()

Aeropay requirements

Aeropay requires the following to function correctly:

  • Currency: Transaction currency must be USD. If another currency is set, the Aeropay panel isn't shown and Drop-in fires onError with SDK0116.
  • Entry type: Must be .ecom. If it isn't, the Aeropay panel isn't shown and Drop-in fires onError with SDK0114.
  • Unity Portal: Aeropay must be enabled for your merchant site. The session response must contain allowedFundingTypes.payByBanks.aeropay with externalMerchantId and configurationId. If Aeropay funding is absent, the panel isn't shown and no onError fires.
  • Intent: transactionData.intent.aeropay must be set to .authorisation, .purchase, or .estimatedAuthorisation. If it's missing, Drop-in calls onError with SDK0115 and the Aeropay panel doesn't load.
  • Shopper identity: Implement onGetShopper with valid consumer data when values are provided, or set methodConfig.aeropay.userId. Non-empty invalid shopper fields at Drop-in load fire SDK1300 and hide the Aeropay panel. Nil shopper, empty fields, and empty phone are allowed at load and collected in the popup when needed. When you supply phoneNumber in onGetShopper, use +1 followed by 10 digits (for example +16465180948). Omit or leave empty to collect in the popup.
  • Site branding: Checkout Drop-in site configuration must be available from Unity for branding and styling.
  • Placement: Aeropay appears in the Drop-in payment method list with the label Pay by bank via Aeropay (localisable). Panel order follows site paymentMethodOrdering.
  • onError before create(): Aeropay eligibility and render failures during await create() surface on onError, not as thrown errors from create(). Keep onError implemented before calling create().

Implementation

Aeropay works through the standard Drop-in implementation. Set the Aeropay intent, provide shopper data or a userId, and use the shared success and error callbacks.

Session configuration (backend)

Enable Aeropay in the Unity Portal for your merchant and site. Create a session with the standard Sessions API and include the Aeropay intent.

{
  "merchant": "MERCHANT-1",
  "site": "SITE-1",
  "sessionTimeout": 120,
  "merchantTransactionId": "0ce72cfd-014d-4256-a006-a56601b2ffc4",
  "transactionMethod": {
    "intent": {
      "card": "Authorisation",
      "paypal": "Purchase",
      "aeropay": "Authorisation"
    }
  },
  "amounts": {
    "currencyCode": "USD",
    "transactionValue": 25.00
  },
  "allowTransaction": true,
  "serviceType": "CheckoutDropIn"
}

When Aeropay is enabled, the session response includes:

{
  "sessionId": "...",
  "hmacKey": "...",
  "encryptionKey": "...",
  "allowedFundingTypes": {
    "payByBanks": {
      "aeropay": {
        "externalMerchantId": "...",
        "configurationId": "..."
      }
    }
  }
}

Pass the session credentials and funding types into SessionData when you initialise Drop-in. If allowedFundingTypes.payByBanks.aeropay is absent, the Aeropay panel isn't shown. If externalMerchantId or configurationId is blank, the panel doesn't load and Drop-in calls onError with SDK0113.

Aeropay credentials (externalMerchantId, configurationId) come from the Unity Portal on the session response. Don't hardcode production values in the app.

Intent requirements

Set the Aeropay intent in transactionData.intent.aeropay:

intent: DropInTransactionIntentData(
    aeropay: .authorisation
    // or .purchase
    // or .estimatedAuthorisation
)

Supported Aeropay intents in Drop-in:

Intent value (Sessions API)SDK valueSupportedNotes
Authorisation.authorisationYesRecommended for checkout. There is no SDK default; you must set intent.aeropay.
Purchase.purchaseYesNone
EstimatedAuthorisation.estimatedAuthorisationYesNone
PayoutNot availableNoNot available on DropInAeropayIntentType.

Consumer data validation rules

When userId isn't provided, Drop-in validates non-empty onGetShopper fields before showing the Aeropay panel. Invalid formats raise SDK1300 through onError and hide Aeropay. Nil shopper, empty or omitted fields, and empty phone don't fail this load check.

FieldRules
firstNameIf provided and non-empty: letters and spaces only (Unicode), max 100 characters
lastNameIf provided and non-empty: letters and spaces only (Unicode), max 100 characters
emailIf provided and non-empty: valid email format, max 128 characters
phoneNumberIf provided and non-empty: US format +1 + 10 digits matching ^\+1\d{10}$ (for example +16465180948). Values without the +1 prefix (for example 6465180948) fail load validation with SDK1300. Empty or nil is OK at load; omit or leave empty to collect in the popup.

skipConsumerDataCollection additionally requires all four values to be non-empty.

Updating the amount at runtime

Use updateAmount(amount:) when the order total changes. This updates all enabled payment methods, including Aeropay.

await checkoutDropIn.create()
checkoutDropIn.updateAmount(amount: Decimal(150))

Handling responses

Aeropay callback data

When an Aeropay payment succeeds, your onSuccess callback receives a DropInSubmitResult:

onSuccess: { result in
    guard result.paymentMethod == .aeropay else { return }
    // result.systemTransactionId
    // result.merchantTransactionId
    // result.paymentData is nil for Aeropay
    verifyPaymentOnBackend(result)
}

Cancellation

Handle shopper cancellation with methodConfig.global.onCancel. Don't treat this as an error.

methodConfig: DropInMethodConfig(
    global: DropInGlobalConfig(
        onCancel: { paymentMethod, _ in
            guard paymentMethod == .aeropay else { return }
            // Shopper closed the Aeropay popup
        }
    )
)

Error handling

Handle Aeropay-specific Drop-in errors by branching on error.errorCode:

onError: { paymentMethod, error in
    guard paymentMethod == .aeropay else { return }
    switch error.errorCode {
    case "SDK0114":
        showError("Pay by Bank is only available for e-commerce checkout.")
    case "SDK0116":
        showError("Pay by Bank only supports USD.")
    case "SDK0113":
        showError("Aeropay isn't configured for this session. Choose another payment method.")
    case "SDK0115":
        showError("Aeropay intent is missing. Choose another payment method.")
    case "SDK1300":
        showError(
            "Please check your name, email, and US phone number (+1 followed by 10 digits)."
        )
    case "SDK1125":
        // Fallback when Aeropay fails to render for unexpected reasons.
        // Credential and intent setup failures usually keep SDK0113 or SDK0115.
        showError(
            "Aeropay is temporarily unavailable. Please try another payment method."
        )
    case "SDK1126":
        // Fallback when Drop-in can't map a richer failed-submit result.
        // Mapped Unity failures often deliver the API errorCode from FailedSubmitResult instead.
        showError(
            "Aeropay payment failed. Please try again or use a different payment method."
        )
    default:
        // Mapped submit failures may use the API errorCode from FailedSubmitResult.
        showError(error.errorMessage)
    }
}

Common error scenarios

The following table describes common Aeropay error scenarios:

ScenarioHow to detectRecommended action
Shopper cancelledmethodConfig.global.onCancel with .aeropayNo alert needed. The shopper action was intentional.
Currency not USDAeropay panel not shown, and onError with SDK0116Use currency = "USD" when Aeropay is in the session.
Entry type not .ecomAeropay panel not shown, and onError with SDK0114Use entryType: .ecom.
Aeropay not in sessionPanel not shown (no onError)Enable Aeropay in the Unity Portal. Ensure the session includes payByBanks.aeropay.
Blank credentials or missing intentExpect SDK0113 (blank credentials) or SDK0115 (missing intent) via onError. SDK1125 is only the fallback when Aeropay fails to render for other unexpected reasons (not the usual code for credential or intent setup).Check externalMerchantId, configurationId, and intent.aeropay.
Invalid shopper data at loadSDK1300 via onError; Aeropay panel not shownCheck onGetShopper field formats (especially phone +1XXXXXXXXXX), or provide userId.
User not activeSDK1307 via onErrorThe user must complete Aeropay verification before paying.
Transaction declinedAPI errorCode from the failed submit result on onError when present; otherwise SDK1126. Don't expect SDK1326 as the Drop-in merchant onError code for mapped submit failures (SDK1326 is a component-level analytics code).Suggest another payment method.

Backend verification

Always verify Aeropay payments on your backend before fulfilling orders:

onSuccess: { result in
    guard result.paymentMethod == .aeropay else { return }
    Task {
        let verified = await verifyPaymentOnBackend(
            systemTransactionId: result.systemTransactionId,
            merchantTransactionId: result.merchantTransactionId
        )
        if verified {
            navigateToConfirmation(result.systemTransactionId)
        } else {
            showError("Payment verification failed")
        }
    }
}

Confirm the transaction state, merchant transaction ID, amount, and funding type (PayByBank) against your order records using the Transactions API.

Error codes

Drop-in–specific errors

Create and payment failures surface through onError. Branch on error.errorCode.

Error codeWhen it occurs
SDK1125Fallback when Aeropay fails to load in Drop-in for unexpected reasons. Expect SDK0113 or SDK0115 for credential or intent setup failures; those codes are preserved on onError when the underlying create error is a BaseSdkException.
SDK1126Fallback when a Unity Aeropay submit fails and there is no API errorCode on FailedSubmitResult. When the failed result includes an API errorCode, Drop-in delivers that code on onError instead.

SDK configuration errors

Error codeMessageWhen it occurs in Drop-in
SDK0114Aeropay only supports Ecom entry typeentryType isn't .ecom (panel hidden). Fired directly via onError.
SDK0116Aeropay only supports USD currencycurrency isn't USD (panel hidden). Fired directly via onError.
SDK0113Aeropay is missing in allow funding typesSession Aeropay credentials are blank. The panel doesn't load and onError returns SDK0113.
SDK0115Intent type for Aeropay is required but not providedintent.aeropay is missing. The panel doesn't load and onError returns SDK0115.

Aeropay flow errors

During the popup flow, Aeropay component errors may also surface through onError. Representative codes:

Error codeScenario
SDK1300Invalid onGetShopper data (at Drop-in load when malformed and non-empty, or during the popup flow)
SDK1301User creation API failure
SDK1302OTP verification failure (including provider code AP112)
SDK1303Missing or invalid Aerosync payload (including bank-list load when no verified user ID is available yet). Prefer this over SDK1311 for that diagnosis.
SDK1304Aerosync widget error
SDK1305Bank account linking failure
SDK1306Bank account list retrieval failure
SDK1307Pre-configured userId isn't active
SDK1308Get user API failure (including when retrieving a returning userId fails)
SDK1319Aeropay aggregator credentials lookup failure
API errorCode or SDK1126Unity transaction failure. Drop-in onError receives the API errorCode from FailedSubmitResult when present; otherwise SDK1126. SDK1326 is an internal component analytics code for mapped failed submits, not the primary Drop-in merchant onError code. There is no separate merchant onSubmitError callback in Drop-in.

What Drop-in exposes vs what it manages

Aeropay in Drop-in uses a fixed merchant surface. Use this table as the Drop-in contract:

ConcernDrop-in behaviour
UI placementPanel inside CheckoutDropIn.buildContent()
BrandingUnity Portal Drop-in site configuration (launcher, popup, fields)
Merchant callbacksUnified Drop-in sequence: onBeforeSubmit, onSubmit, onSuccess, onError, and methodConfig.global.onCancel
Pre-authorisation gateAlways proceeds after onSubmit (no merchant veto after bank confirmation)
Payout intentNot available (DropInAeropayIntentType has no payout case)
Eligibility failuresPanel hidden; some failures also call onError (see Error codes)

How Drop-in's unified callbacks relate to the Aeropay flow:

Drop-in callbackWhen it fires for Aeropay
onBeforeSubmitShopper taps Pay by bank, before the popup opens. Return false to stop.
onSubmitBank selected and Unity transaction is about to submit. Drop-in always continues afterward.
onSuccessUnity authorises the transaction.
methodConfig.global.onCancelShopper closes the popup. Payload is nil. Doesn't call onError.
onErrorSetup, flow, or transaction error. For Unity transaction failure: API errorCode from FailedSubmitResult when present; otherwise SDK1126. SDK1326 is internal component analytics, not the primary Drop-in merchant callback code.

Drop-in doesn't expose merchant callbacks for button click, user-verification success, or a separate submit-error channel. Handle those concerns through the unified callbacks and analytics events above.

Troubleshooting

Use these checks when Aeropay doesn't appear or the pay-by-bank flow fails.

Aeropay panel not shown

Verify these conditions:

  • allowedFundingTypes.payByBanks.aeropay is present in the session response with non-blank externalMerchantId and configurationId.
  • transactionData.currency is "USD".
  • transactionData.entryType is .ecom.
  • transactionData.intent.aeropay is set to a supported intent.
  • onError may fire with SDK0116 (currency), SDK0114 (entry type), SDK1300 (invalid shopper data at load), SDK0113 (credentials), SDK0115 (missing intent), or SDK1125 (Aeropay failed to load).

Invalid shopper data (SDK1300)

Look for these symptoms:

  • Non-empty invalid onGetShopper fields at Drop-in load hide the Aeropay panel and call onError.
  • Name, email, or US phone format (+1 + 10 digits) is wrong, and methodConfig.aeropay.userId isn't set.

onError with create or render failure

Aeropay eligibility and render failures during await create() surface on onError, not as thrown errors from create(). Keep onError implemented before calling create().

Check the following:

  • The session is missing Aeropay credentials, or intent.aeropay isn't set.
  • Branch on error.errorCode. Expect SDK0113 or SDK0115 for credential or intent setup failures. SDK1125 indicates Aeropay failed to render for other unexpected reasons (not the usual code for those setup failures).
  • Log error.errorMessage for extra detail.

Consumer data screen shown when userId is provided

Check the following:

  • methodConfig.aeropay.userId is empty or missing after trim.
  • If the user isn't active, onError receives SDK1307. If retrieving the user fails, onError receives SDK1308. Clear or replace the stored userId and restart the new-shopper flow.

onBeforeSubmit not preventing the popup

Check the following:

  • Confirm onBeforeSubmit is implemented on CheckoutDropInConfig. If it's omitted, Drop-in doesn't register the Aeropay pre-popup validation hook and the flow always opens after the button tap.
  • onBeforeSubmit returns false for .aeropay.
  • The callback is set on CheckoutDropInConfig, not only inside methodConfig.

OTP screen not skipped with skipConsumerDataCollection

Check the following:

  • One or more of firstName, lastName, email, and phoneNumber is missing from onGetShopper.
  • editableConsumerDataFields is set to a non-empty list.

Quick integration checklist

Before you go live with Aeropay, confirm the following:

  1. Enable Aeropay in the Unity Portal for your merchant site.
  2. Confirm the session includes allowedFundingTypes.payByBanks.aeropay with externalMerchantId and configurationId.
  3. Include "aeropay": "Authorisation" (or another supported intent) in the session intent.
  4. Set transactionData.currency to "USD" and entryType to .ecom.
  5. Set transactionData.intent.aeropay to a supported Drop-in intent.
  6. Implement onGetShopper with valid formats when you supply values, or provide methodConfig.aeropay.userId.
  7. Implement onSuccess and onError.
  8. Optionally configure methodConfig.aeropay for user ID, skip data collection, editable fields, or excluded bank accounts.
  9. Optionally handle cancellation via methodConfig.global.onCancel.
  10. Verify payments on your backend before fulfilling orders.