Implement callbacks to customise your Paze payment flow for Android.
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 Custom Tab checkout and decryption flow requirements.
Configure these callbacks on PxpSdkConfig, not on the Paze button component. The Paze button calls onGetShopper when building the Unity transaction request after decryption.
onGetShopper(recommended): Called during authorisation to retrieve shopper data for the transaction payload.
The SDK calls this callback when building the transaction request, after decryption and before Unity authorisation. If onGetShopper is not set, the SDK uses transactionData.shopper when present.
val sdkConfig = PxpSdkConfig(
environment = Environment.TEST,
session = sessionData,
transactionData = transactionData,
clientName = "Your Merchant",
siteName = "Your Store",
ownerType = "MerchantGroup",
ownerId = "MERCHANT-1",
onGetShopper = {
Shopper(
id = "shopper-123",
firstName = "John",
lastName = "Doe",
email = "customer@example.com",
)
},
)| Property | Description |
|---|---|
idString? | A unique shopper identifier. Return your customer account ID or a persistent guest session ID. |
firstNameString? | The shopper's given name. |
lastNameString? | The shopper's family name. |
emailString? | The shopper's email address. |
phoneNumberString? | The contact phone number for the transaction shopper profile. |
dateOfBirthString? | The date of birth, when required by your integration or risk screening rules. |
houseNumberOrNameString? | The first line of the shopper's address. |
streetString? | The street name or remaining address line. |
cityString? | The city or locality. |
postalCodeString? | The postal or ZIP code. |
countryCodeString? | The country code in ISO 3166-1 alpha-2 format (e.g., "US"). |
stateString? | The state, province, or region. |
All properties are optional in the type, but you should always return an id so transactions can be linked to your customer records.
Paze wallet identity (emailAddress / phoneNumber on the component) is separate from onGetShopper. Component identity is forwarded to Paze during create-session when provided. onGetShopper supplies the shopper object sent to Unity during authorisation.
For shipping constraints on Paze checkout, set acceptedShippingCountries on the component config. See Configuration.
Configure these callbacks on PazeButtonComponentConfig before calling createComponent<PazeButtonComponent>(...).
For a successful payment, callbacks fire in this order:
onInit→onPresentmentResolvedafter presentment validation succeeds, when the componentContent()is composed.onPazeButtonClickedwhen the shopper taps the button (after checkout validation, before the Custom Tab opens).onCheckoutCompleteoronCheckoutIncompleteafter the Custom Tab returns.onCompleteafter the complete API succeeds and the response is decoded.onPreDecryption→onPostDecryption(if SDK decryption proceeds).onPreAuthorisation→ Unity authorisation (the SDK callsonGetShopperortransactionData.shopperhere) →onPostAuthorisation(if registered) oronSubmitError.
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.
When onPreDecryption returns false, the SDK skips steps 5–6. Use onComplete to receive the securedPayload for backend decryption instead.
SDK initialisation callbacks are configured on PxpSdkConfig. The Paze button calls onGetShopper during authorisation. Paze component callbacks handle checkout, decryption, and authorisation events. Several Paze callbacks are suspend functions and can perform asynchronous work before the SDK continues.
Called after presentment validation succeeds, immediately before onPresentmentResolved on success.
config.onInit = {
Log.d("Paze", "Component ready")
}Called when presentment resolves.
| Parameter | Description |
|---|---|
customTabAvailableBoolean | When presentment succeeds, true when a Custom Tab can launch; false when no compatible browser is installed (the button remains visible). When presentment validation fails, the button is hidden and this callback receives false (see onError). |
config.onPresentmentResolved = { customTabAvailable ->
if (!customTabAvailable) {
showCustomTabWarning()
}
}Called when the shopper taps the button, after checkout validation succeeds and before the Custom Tab opens. Checkout validation failures surface through onError, not this callback. 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 after onPazeButtonClicked completes and immediately before the Custom Tab opens. See Analytics.
config.onPazeButtonClicked = {
clearErrorMessages()
}The SDK opens the Custom Tab after this callback completes. There is no return value — you cannot cancel checkout from this callback. Disable the button in your UI until prerequisites are met. To block after the shopper returns from Paze, return false from 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.
| Parameter | Description |
|---|---|
resultPazeCheckoutResult | The checkout result data. |
result.resultPazeCheckoutResultType | The checkout outcome from Paze. In this callback, the value is always COMPLETE, meaning the shopper finished checkout in the Custom Tab and Paze returned review data. INCOMPLETE is delivered through onCheckoutIncomplete instead. |
result.checkoutDecodedResponsePazeCheckoutReviewData? | Decoded session and masked card data when complete. |
result.checkoutDecodedResponse?.maskedCard?.panLastFourString | The last four digits of the selected card. |
result.checkoutDecodedResponse?.maskedCard?.paymentCardBrandString | The card brand returned by Paze (for example, VISA). |
result.reasonString? | An optional reason from Paze. |
config.onCheckoutComplete = { result ->
val decoded = result.checkoutDecodedResponse ?: return@onCheckoutComplete false
validateCheckoutOnBackend(
sessionId = decoded.sessionId,
cardLastFour = decoded.maskedCard.panLastFour,
)
}Called when checkout ends without completion, the shopper cancels, the Custom Tab closes without a redirect, or you return false from onCheckoutComplete. When you reject in onCheckoutComplete, the reason is set from the SDK's localised merchant-validation message.
config.onCheckoutIncomplete = { result ->
if (result.reason?.contains("cancel", ignoreCase = true) == true) {
return@onCheckoutIncomplete
}
showError("Checkout was not completed. Please try again.")
}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 ->
Log.d("Paze", "Payload ID: ${result.completeDecodedResponse?.payloadId}")
}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 — the SDK skips decrypt and authorisation; use onComplete to forward the securedPayload.
SDK-managed (recommended):
config.onPreDecryption = { true }
config.onPostDecryption = { decryptedPayload ->
val masked = decryptedPayload.fundingData.networkToken.take(6) + "..."
Log.d("Paze", "Decrypted token prefix: $masked")
}Merchant-managed:
config.onPreDecryption = { false }
config.onComplete = { result ->
val securedPayload = result.completeDecodedResponse?.securedPayload ?: return@onComplete
sendToBackendForDecryption(securedPayload)
}See Backend decryption for PXP API endpoints.
Called after Unity successfully decrypts the network token. Skipped when onPreDecryption returns false.
| Parameter | Description |
|---|---|
decryptedPayload.shopperPazeDecryptTokenShopper | Customer name, email, and phone from the decrypt response. |
decryptedPayload.billingAddressPazeDecryptTokenBillingAddress? | Billing address when returned by Paze. |
decryptedPayload.fundingDataPazeDecryptTokenFundingData | Network token, expiry, card network, and related fields. |
config.onPostDecryption = { decrypted ->
Log.d("Paze", "Card network: ${decrypted.fundingData.cardNetwork}")
val maskedToken = decrypted.fundingData.networkToken.take(6) + "..."
Log.d("Paze", "Token prefix: $maskedToken")
}Called before the transaction is submitted to Unity.
| Return value | Behaviour |
|---|---|
Proceed | Continue without extra data (default when omitted). |
Cancel | Abort authorisation silently. The SDK does not call onSubmitError. |
TransactionInitData(...) | Continue with risk screening or other init data. |
config.onPreAuthorisation = {
if (!validateOrderDetails()) {
PazePreAuthorisationResult.Cancel
} else {
PazePreAuthorisationResult.TransactionInitData(
PazeTransactionInitData(
riskScreeningData = buildRiskScreeningData(),
),
)
}
}Called when the SDK receives a MerchantSubmitResult. Only invoked when this callback is registered on the config. Verify the transaction outcome on your backend — the Unity response may report an error state while still returning transaction identifiers. Hard submission failures route to onSubmitError, not this callback.
| Parameter | Description |
|---|---|
result.merchantTransactionIdString | Your transaction identifier. |
result.systemTransactionIdString | The system transaction identifier generated by PXP. |
config.onPostAuthorisation = { result ->
verifyPaymentOnBackend(systemTransactionId = result.systemTransactionId)
}Called when authorisation submission fails, including invalid Kount riskScreeningData (ValidationException). Cast to FailedSubmitResult for error details.
config.onSubmitError = { result ->
val failed = result as? FailedSubmitResult
showError(failed?.errorReason ?: "Payment failed")
}Called on presentment, checkout, complete, or decryption errors. Shopper cancellation is surfaced through onCheckoutIncomplete, not onError.
config.onError = { error ->
when (error.errorCode) {
"SDK1202", "SDK1202A" -> showError("Paze is not configured for this session.")
"SDK1210", "SDK1212" -> showError("Please check your contact details and try again.")
"SDK1213" -> showError("Paze is only available for USD transactions.")
"SDK1233" -> showError("Token decryption failed. Please try again.")
"SDK1200", "SDK1214" -> showError("Paze checkout failed. Please try again.")
else -> showError(error.message ?: "Payment could not be completed.")
}
}Returned by onGetShopper:
data class Shopper(
val id: String? = null,
val firstName: String? = null,
val lastName: String? = null,
val email: String? = null,
val phoneNumber: String? = null,
val dateOfBirth: String? = null,
// address fields...
)Passed to onCheckoutComplete and onCheckoutIncomplete:
data class PazeCheckoutResult(
val result: PazeCheckoutResultType,
val reason: String?,
val checkoutDecodedResponse: PazeCheckoutReviewData?,
)
data class PazeCheckoutReviewData(
val sessionId: String?,
val maskedCard: PazeMaskedCard,
)Included on checkoutDecodedResponse when checkout completes:
data class PazeMaskedCard(
val digitalCardId: String?,
val panLastFour: String,
val paymentAccountReference: String?,
val panExpirationMonth: String?,
val panExpirationYear: String?,
val paymentCardDescriptor: String,
val paymentCardType: String,
val paymentCardBrand: String,
val paymentCardNetwork: String,
val digitalCardData: PazeDigitalCardData,
val billingAddress: PazeCheckoutAddress?,
)Passed to onComplete:
data class PazeCompleteResult(
val completeDecodedResponse: PazeCompleteDecoded?,
val decryptedPayload: PazeDecryptTokenResponseSuccess?,
)At onComplete, decryptedPayload is always null. Decrypted token data is passed to onPostDecryption when SDK decryption proceeds.
data class PazeCompleteDecoded(
val payloadId: String?,
val sessionId: String?,
val securedPayload: String?,
)Passed to onPostDecryption:
data class PazeDecryptTokenResponseSuccess(
val shopper: PazeDecryptTokenShopper,
val billingAddress: PazeDecryptTokenBillingAddress?,
val fundingData: PazeDecryptTokenFundingData,
)
data class PazeDecryptTokenShopper(
val firstName: String?,
val lastName: String?,
val fullName: String,
val emailAddress: String,
val phoneCountryCode: String?,
val phoneNumber: String?,
val countryCode: String?,
val languageCode: String?,
)
data class PazeDecryptTokenBillingAddress(
val addressLine1: String,
val city: String,
val state: String,
val countryCode: String,
val postalCode: String,
)
data class PazeDecryptTokenFundingData(
val networkToken: String,
val expirationMonth: String,
val expirationYear: String,
val accountReference: String?,
val cardNetwork: String,
val tokenUsageType: String?,
val dynamicDataExpiration: String?,
)Passed to onPostAuthorisation when the SDK receives the Unity authorisation response. Verify the outcome on your backend; hard failures route to onSubmitError.
data class MerchantSubmitResult(
val merchantTransactionId: String,
val systemTransactionId: String,
) : SubmitResult()Typical type received in onSubmitError:
data class FailedSubmitResult(
val errorCode: String?,
val errorReason: String?,
val correlationId: String?,
val httpStatusCode: Int?,
val details: List<String>?,
)Passed to onError:
open class BaseSdkException(
message: String,
cause: Throwable? = null,
val errorCode: String,
)