Skip to content

Events

Implement callbacks to customise your Paze payment flow for iOS.

Overview

The Paze component emits callbacks based on shopper interaction and payment flow state. Use them to inject business logic and UX customisations at critical moments. While the SDK handles checkout, decryption, and authorisation, you retain control over approval gates, error handling, and backend integration.

Callbacks enable you to:

  • Validate business rules before payments proceed.
  • Display custom error, failure, or success messages.
  • Integrate with fraud detection or customer management systems.
  • Control how shoppers experience successful and failed transactions.
  • Handle Paze web checkout and decryption flow requirements.

SDK data callbacks

Configure onGetShopper on CheckoutConfig when calling PxpCheckout.initialize(config:), not on the Paze button component. The SDK calls onGetShopper when building the Unity transaction request after decryption.

  • onGetShopper (recommended): Called during authorisation to retrieve shopper data for the transaction payload.
  • onGetShippingAddress (optional on CheckoutConfig): Available for other checkout components, but not called by the Paze button during authorisation.

onGetShopper

The SDK calls this callback when building the transaction request, after decryption and before Unity authorisation.

You can use it to:

  • Provide a stable shopper ID for your customer account or guest session.
  • Return the latest name, email, and contact details from your application.
  • Associate the Paze network-token transaction with your customer records.

Configuration

let checkoutConfig = CheckoutConfig(
    environment: .test,
    session: sessionData,
    transactionData: transactionData,
    merchantShopperId: "shopper-123",
    ownerId: "owner-456",
    onGetShopper: { async in
        TransactionShopper(
            id: "shopper-123",
            firstName: "John",
            lastName: "Doe",
            email: "customer@example.com"
        )
    }
)

let pxpCheckout = try PxpCheckout.initialize(config: checkoutConfig)

Return value

PropertyDescription
id
String?
A unique shopper identifier. Return your customer account ID or a persistent guest session ID.
firstName
String?
The shopper's given name.
lastName
String?
The shopper's family name.
email
String?
The shopper's email address.
phoneNumber
String?
The contact phone number for the transaction shopper profile.
dateOfBirth
String?
The date of birth, when required by your integration or risk screening rules.
houseNumberOrName
String?
The first line of the shopper's address.
street
String?
The street name or remaining address line.
city
String?
The city or locality.
postalCode
String?
The postal or ZIP code.
countryCode
String?
The country code in ISO 3166-1 alpha-2 format (e.g., "US").
state
String?
The state, province, or region.
products
[String: String]?
Key-value metadata describing products in the order.
orderDescription
String?
A human-readable order description.

All properties are optional in the type, but you should always return an id so transactions can be linked to your customer records.

Example implementation

onGetShopper: { async in
    let customer = await getCurrentCustomer()

    if let customer {
        return TransactionShopper(
            id: customer.id,
            email: customer.email,
            firstName: customer.firstName,
            lastName: customer.lastName,
            phoneNumber: customer.phone
        )
    }

    return TransactionShopper(id: getOrCreateGuestShopperId())
}

Paze wallet identity (emailAddress / phoneNumber on the component) is separate from onGetShopper. Component identity is passed to Paze during session creation when provided. onGetShopper supplies the shopper object sent to Unity during authorisation.

onGetShippingAddress

onGetShippingAddress is defined on CheckoutConfig for other payment flows (for example, card submit or drop-in). The Paze button component doesn't call it when building the authorisation request.

If you need shipping context for Paze, pass it through enhancedTransactionData.ecomData.finalShippingAddress on the component config instead. See Configuration.

Paze-specific events

Configure these callbacks on PazeButtonComponentConfig before calling create(.pazeButton, componentConfig:).

CallbackSDK signature
onInit(() -> Void)?
onPresentmentResolved((Bool) -> Void)?
onError((BaseSdkException) -> Void)?
onPazeButtonClicked(() async -> Void)?
onCheckoutComplete((PazeCheckoutResult) async -> Bool)?
onCheckoutIncomplete((PazeCheckoutResult) async -> Void)?
onComplete((PazeCompleteResult) async -> Void)?
onPreDecryption(() async -> Bool)?
onPostDecryption((PazeDecryptTokenResponseSuccess) async -> Void)?
onPreAuthorisation(() async -> PazePreAuthorisationResult)?
onPostAuthorisation((MerchantSubmitResult) async -> Void)?
onSubmitError((BaseSubmitResult) async -> Void)?
onGetShopper (CheckoutConfig)(() async -> TransactionShopper?)?

Callback order

For a successful payment, callbacks fire in this order:

  1. onInitonPresentmentResolved(true) when the component view appears.
  2. onPazeButtonClicked when the shopper taps the button.
  3. onCheckoutComplete or onCheckoutIncomplete after the Paze web checkout session returns.
  4. onComplete after the complete API succeeds and the response is decoded.
  5. onPreDecryptiononPostDecryption (if SDK decryption proceeds).
  6. onPreAuthorisation → Unity authorisation (the SDK calls onGetShopper here) → onPostAuthorisation or onSubmitError.

onError handles presentment, checkout, complete, and decryption errors. onSubmitError handles authorisation submission failures, including invalid Kount riskScreeningData. Shopper cancellation is surfaced through onCheckoutIncomplete, not onError.

Configure onGetShopper on CheckoutConfig when calling PxpCheckout.initialize(config:). Paze component callbacks handle checkout, decryption, and authorisation events.

onInit

Called after presentment validation succeeds, immediately before onPresentmentResolved(true).

config.onInit = {
    print("Paze component ready")
}

onPresentmentResolved

Called when presentment resolves with whether the button is visible.

ParameterDescription
isVisible
Bool
true when the button is shown, false when validation failed (see onError).
config.onPresentmentResolved = { isVisible in
    if !isVisible {
        showAlternativePaymentMethods()
    }
}

onPazeButtonClicked

Called when the shopper taps the button, before the Paze web checkout session opens. Use it for analytics, clearing error messages, or showing a loading state.

onPazeButtonClicked is a component callback. The PazeButtonClicked analytics event is separate — it fires only after checkout-time validation succeeds, immediately before the web session opens. See Analytics.

config.onPazeButtonClicked = { async in
    clearErrorMessages()
    trackEvent("paze_button_clicked")
}

The SDK always opens the Paze checkout session after this callback completes. To block checkout when validation fails, keep the button disabled until your prerequisites are met, or return false from onCheckoutComplete after the shopper finishes in Paze.

onCheckoutComplete

Called when checkout returns COMPLETE, before the SDK calls the complete API.

Return true to approve and continue (default when omitted). Return false to reject. The SDK calls onCheckoutIncomplete.

ParameterDescription
result
PazeCheckoutResult
The checkout result data.
result.result
enum
The result: .complete or .incomplete.
result.checkoutResponse
String?
The encoded checkout response JWT when complete.
result.checkoutDecodedResponse
PazeCheckoutDecoded?
The decoded consumer, session, and masked card data.
result.checkoutDecodedResponse?.maskedCard?.panLastFour
String
The last four digits of the selected card.
result.checkoutDecodedResponse?.maskedCard?.paymentCardBrand
String
The card brand returned by Paze (for example, VISA).
result.checkoutDecodedResponse?.maskedCard?.paymentCardNetwork
String
The card network returned by Paze.
result.reason
String?
An optional reason from Paze.
config.onCheckoutComplete = { result async in
    guard let decoded = result.checkoutDecodedResponse else { return false }

    let isValid = await validateCheckoutOnBackend(
        sessionId: decoded.sessionId,
        cardLastFour: decoded.maskedCard?.panLastFour
    )

    return isValid
}

onCheckoutIncomplete

Called when checkout ends without completion, the shopper cancels, or you return false from onCheckoutComplete. When you reject in onCheckoutComplete, the reason is set from the SDK's localised merchant-validation message.

ParameterDescription
result.reason
String?
The reason for the incomplete checkout (e.g. "User cancelled.").
config.onCheckoutIncomplete = { result async in
    if result.reason == "User cancelled." {
        return
    }
    showError("Checkout was not completed. Please try again.")
}

onComplete

Called when the complete API succeeds and the response is decoded. Runs before onPreDecryption.

Use result.completeDecodedResponse?.securedPayload for manual decryption when onPreDecryption returns false.

config.onComplete = { result async in
    print("Payload ID:", result.completeDecodedResponse?.payloadId ?? "")
}

onPreDecryption

Called after onComplete, before the SDK decrypts the secured payload.

Return true to allow SDK decryption (default when omitted). Return false to handle decryption on your backend.

config.onPreDecryption = { async in
    let approved = await requestManagerApproval()
    return approved
}

onPostDecryption

Called after Unity successfully decrypts the network token. Fires when SDK decryption proceeds — including when onPreDecryption is omitted or returns true. Skipped when onPreDecryption returns false.

ParameterDescription
decryptedPayload.shopper
object
The customer name, email, and phone from the decrypt response.
decryptedPayload.billingAddress
object?
The billing address when returned by Paze.
decryptedPayload.fundingData
object
The network token, expiry, card network, and related fields.
config.onPostDecryption = { decrypted async in
    print("Card network:", decrypted.fundingData.cardNetwork)
}

onPreAuthorisation

Called before the transaction is submitted to Unity.

Return valueBehaviour
.proceedContinue without extra data (default when omitted).
.cancelAbort authorisation.
.transactionInitData(...)Continue with risk screening or other init data.
config.onPreAuthorisation = { async in
    guard await validateOrderDetails() else {
        return .cancel
    }

    return .transactionInitData(PazeTransactionInitData(
        riskScreeningData: RiskScreeningData(
            performRiskScreening: true,
            userIp: await getUserIpAddress()
        )
    ))
}

onPostAuthorisation

Called when the SDK receives a MerchantSubmitResult, immediately before your callback runs. Verify the transaction outcome on your backend — the Unity response may report an error state while still returning transaction identifiers.

ParameterDescription
data.merchantTransactionId
String
Your transaction identifier.
data.systemTransactionId
String
The system transaction identifier generated by PXP.
config.onPostAuthorisation = { data async in
    await verifyPaymentOnBackend(systemTransactionId: data.systemTransactionId)
    navigateToOrderConfirmation(merchantTransactionId: data.merchantTransactionId)
}

onSubmitError

Called when authorisation submission fails, including invalid Kount riskScreeningData (ValidationException). Cast to FailedSubmitResult for error details.

config.onSubmitError = { result async in
    if let failed = result as? FailedSubmitResult {
        showError(failed.errorReason ?? "Payment failed")
    }
}

onError

Called on presentment, checkout, complete, or decryption errors. Shopper cancellation is surfaced through onCheckoutIncomplete, not onError.

ParameterDescription
error.errorCode
String
The SDK error code (e.g. SDK1213).
error.errorMessage
String
A human-readable error message.
config.onError = { error in
    switch error.errorCode {
    case "SDK0118":
        showError("Paze isn't enabled for this session.")
    case "SDK1213":
        showError("Paze is only available for USD transactions.")
    case "SDK1202":
        showError("Paze client ID is missing from the session.")
    case "SDK1202A":
        showError("Paze merchant category code is missing from the session.")
    case "SDK1214", "SDK1200":
        showError("Paze checkout failed. Please try again.")
    default:
        showError(error.errorMessage)
    }
}

Event data structures

TransactionShopper

Returned by onGetShopper:

struct TransactionShopper {
    var id: String?
    var firstName: String?
    var lastName: String?
    var dateOfBirth: String?
    var email: String?
    var phoneNumber: String?
    var houseNumberOrName: String?
    var street: String?
    var city: String?
    var postalCode: String?
    var countryCode: String?
    var state: String?
    var products: [String: String]?
    var orderDescription: String?
}

ShippingAddress

Defined on CheckoutConfig for other payment flows. Not used by the Paze button component.

struct ShippingAddress {
    var countryCode: String?
    var postalCode: String?
    var address: String?
    var addressLine2: String?
    var city: String?
    var county: String?
    var state: String?
}

PazeCheckoutResult

Passed to onCheckoutComplete and onCheckoutIncomplete:

public struct PazeCheckoutResult {
    var result: CheckoutResultType          // PazeCheckoutResult.CheckoutResultType
    var checkoutResponse: String?
    var reason: String?
    var checkoutDecodedResponse: PazeCheckoutDecoded?
}

public extension PazeCheckoutResult {
    enum CheckoutResultType {
        case complete    // raw value "COMPLETE"
        case incomplete  // raw value "INCOMPLETE"
    }
}

checkoutDecodedResponse is populated when result is .complete.

PazeMaskedCard

Included on checkoutDecodedResponse when checkout completes:

struct PazeMaskedCard {
    var panLastFour: String
    var paymentCardBrand: String
    var paymentCardNetwork: String
    var paymentCardDescriptor: String
    var paymentCardType: String
    var digitalCardData: PazeDigitalCardData
    var digitalCardId: String?
    var paymentAccountReference: String?
    var panExpirationMonth: String?
    var panExpirationYear: String?
    var billingAddress: PazeCheckoutAddress?
}

PazeCompleteResult

Passed to onComplete:

struct PazeCompleteResult {
    var completeDecodedResponse: PazeCompleteDecoded?  // payloadId, sessionId, securedPayload
    var decryptedPayload: PazeDecryptTokenResponseSuccess?  // always nil at onComplete
}

Decrypted token data is passed to onPostDecryption when SDK decryption proceeds.

PazeDecryptTokenResponseSuccess

Passed to onPostDecryption:

// decryptedPayload.shopper — fullName, emailAddress, phone fields
// decryptedPayload.billingAddress — addressLine1, city, state, countryCode, postalCode
// decryptedPayload.fundingData — networkToken, expirationMonth, expirationYear, cardNetwork

MerchantSubmitResult

Passed to onPostAuthorisation:

class MerchantSubmitResult {
    let merchantTransactionId: String
    let systemTransactionId: String
}

FailedSubmitResult

Typical type received in onSubmitError:

class FailedSubmitResult {
    let errorCode: String?
    let errorReason: String?
    let correlationId: String?
    let httpStatusCode: Int?
    let details: [String]?
}

BaseSdkException

Passed to onError:

// error.errorCode — e.g. "SDK1213"
// error.errorMessage — human-readable description