Skip to content

Troubleshooting

Learn how to diagnose and fix common issues with the Paze Android component.

Exception types and error codes

Component exceptions

The Paze Android component surfaces BaseSdkException errors with structured codes in the SDK12XX range. The following table maps common exception types to their error codes:

Exception Error codeDescription
PazeCheckoutLaunchException / PazeLoadFailedExceptionSDK1200Failed to launch Paze checkout. For example, Custom Tab launch failed.
PazeConfigurationValidationFailedException
(client ID)
SDK1202Missing session.allowedFundingTypes.wallets.paze.clientId.
PazeMerchantCategoryCodeRequiredExceptionSDK1202AMissing session.allowedFundingTypes.wallets.paze.merchantCategoryCode at complete.
PazeConfigurationValidationFailedException
(client name)
SDK1203clientName exceeds 50 characters when set.
PazeConfigurationValidationFailedException
(brand name)
SDK1204siteName exceeds 50 characters when set.
PazeConfigurationValidationFailedException
(statement descriptor)
SDK1205paymentDescription exceeds 25 characters when set.
PazeInitializationFailedExceptionSDK1206Paze initialisation or create-session failed.
PazeIdentityValidationFailedException
(email)
SDK1209-SDK1210Email too long or invalid format.
PazeIdentityValidationFailedException
(phone)
SDK1211-SDK1212Phone too long or invalid US E.164 format.
PazeConfigurationValidationFailedException
(currency)
SDK1213Transaction currency is not USD.
PazePaymentFailedExceptionSDK1214Generic Paze checkout or wallet flow failure.
PazeCheckoutResponseMissingExceptionSDK1215Paze checkout did not return a response for a COMPLETE result.
PazeCompleteResponseMissingExceptionSDK1216Paze complete did not return an expected response.
PazeCompleteSecuredPayloadMissingExceptionSDK1219Paze complete response did not contain a securedPayload.
PazeConfigurationValidationFailedException
(session ID)
SDK1222Component sessionId exceeds 255 characters.
PazeConfigurationValidationFailedException
(amount)
SDK1229Transaction amount is 0 or negative at checkout.
PazeInitializationFailedException / PazeProviderException
(shipping countries)
SDK1231acceptedShippingCountries contains invalid ISO 3166-1 alpha-2 country codes. Typically returned by the create-session API at checkout.
PazeInitializationFailedException / PazeProviderException
(cobrand)
SDK1232A cobrand entry is missing a non-empty cobrandName. Typically returned by the create-session API at checkout.
PazeDecryptFailedExceptionSDK1233Failed to decrypt the Paze secured payload.
PazeTransactionFailedExceptionSDK1235Transaction submission failed. Also surfaced through onSubmitError.

Shopper cancellation and closing the Custom Tab without completing checkout call onCheckoutIncomplete rather than throwing an exception. Missing Paze clientId surfaces as SDK1202 at presentment. Authorisation submission failures (SDK1235) route to onSubmitError, not onError. Create-session and complete API provider errors may also surface through PazeProviderException or PazeInitializationFailedException with provider-specific codes — map these using error.message and your backend logs. Codes such as SDK1231 and SDK1232 are defined in the SDK but are typically returned by the create-session API rather than thrown locally at presentment.

Error handling best practices

Comprehensive error handler

Route onError, onCheckoutIncomplete, and onSubmitError to appropriate user messaging and logging:

config.onError = { error ->
    Log.e("Paze", "Error: ${error.errorCode} ${error.message}")

    when (error.errorCode) {
        "SDK1202", "SDK1202A" -> {
            showAlternativePaymentMethods()
            showMessage("Paze is not available for this order.")
        }
        "SDK1210", "SDK1212" -> showMessage("Please check your contact details.")
        "SDK1213" -> showMessage("Paze is only available for USD transactions.")
        "SDK1233" -> showMessage("Payment token could not be processed. Please try again.")
        "SDK1200", "SDK1214" -> showMessage("Paze checkout failed. Please try again.")
        else -> showMessage("Payment could not be completed. Please try again.")
    }
}

config.onCheckoutIncomplete = { result ->
    if (result.reason?.contains("cancel", ignoreCase = true) == true) {
        showMessage("Payment cancelled.")
    } else {
        showMessage("Payment was not completed. Please try again.")
    }
}

config.onSubmitError = { submitResult ->
    val failed = submitResult as? FailedSubmitResult
    Log.e("Paze", "Submit error: ${failed?.errorCode} ${failed?.errorReason}")
    showMessage("Payment could not be processed. Please try another method.")
}

Logging for support

Include these fields when logging errors for PXP or Paze support:

fun logPazeError(error: BaseSdkException, context: Map<String, Any> = emptyMap()) {
    val payload = buildMap {
        put("errorCode", error.errorCode)
        put("errorMessage", error.message ?: "")
        put("timestamp", Instant.now().toString())
        putAll(context)
    }
    // Send to your logging or crash reporting service
    Log.e("Paze", "Support log: $payload")
}

Portal and session setup

Use this section when Paze is not appearing in the Unity Portal, missing from your session response, or failing during presentment with SDK1202. For portal setup steps, see Onboarding.

Paze service not visible on site

Symptom: The Paze service doesn't appear in your site's Services tab.

Solution: Enable Paze at the merchant group level first (Onboarding, Step 1), then return to the site configuration.

Missing client ID in session

Symptom: Session response doesn't include allowedFundingTypes.wallets.paze.clientId.

Solution:

  1. Verify the client ID is saved in Paze Account Settings for the correct site.
  2. Create a new session after saving portal changes.
  3. Confirm you are using the correct site name in your session request.

SDK1202 at presentment

Symptom: Presentment fails with missing clientId.

Solution: Confirm clientId is in the session response from your backend and passed through SessionConfig when initialising the SDK. Re-create the session after saving portal changes. Non-USD currency surfaces separately as SDK1213; invalid identity fields surface as SDK1210 or SDK1212.

Troubleshooting common issues

Paze button hidden or validation errors at presentment

The symptoms of this are:

  • onPresentmentResolved(false) fires alongside onError.
  • The button is hidden in your Compose UI after you render Content().
  • Checkout fails immediately on tap when presentment succeeded but checkout-time validation fails.

Diagnostic steps

Log session and component configuration when presentment fails:

fun diagnosePazePresentment(sdkConfig: PxpSdkConfig, config: PazeButtonComponentConfig) {
    Log.d("Paze", "=== Presentment Diagnostics ===")
    val paze = sdkConfig.session.allowedFundingTypes?.wallets?.paze
    Log.d("Paze", "Client ID: ${if (paze?.clientId.isNullOrBlank()) "Missing" else "Present"}")
    Log.d("Paze", "MCC: ${paze?.merchantCategoryCode ?: "Not set"}")
    Log.d("Paze", "Currency: ${sdkConfig.transactionData.currency}")
    Log.d("Paze", "Email: ${config.emailAddress ?: "Not set"}")
    Log.d("Paze", "Phone: ${config.phoneNumber ?: "Not set"}")
}

Common causes

These presentment and checkout validation issues map to the most frequent error codes:

CauseError codeSolution
Missing clientId in sessionSDK1202Configure Paze Account Settings and re-create session
Non-USD currencySDK1213Set transactionData.currency to "USD"
Invalid email or phoneSDK1210, SDK1212Fix format; see Data validation
clientName or siteName too long when setSDK1203, SDK1204Shorten to 50 characters or fewer
Statement descriptor too long when setSDK1205Shorten paymentDescription to 25 characters or fewer
Amount ≤ 0 at checkoutSDK1229Set a positive transactionData.amount
Invalid shipping country codesSDK1231Use valid ISO 3166-1 alpha-2 codes (for example US, CA); usually returned at create-session
Empty cobrand nameSDK1232Set a non-empty cobrandName on every PazeCobrandConfig entry; usually returned at create-session
No Custom Tab browseronPresentmentResolved(false) with button visibleInstall Chrome or another Custom Tabs-compatible browser

When presentment succeeds but no Custom Tabs-compatible browser is installed, the button remains visible and onPresentmentResolved(false) fires. Use the callback to show warnings or fallback payment methods.

Checkout fails or gets cancelled

The symptoms of this are:

  • The shopper taps the Paze button but checkout doesn't complete.
  • onCheckoutIncomplete fires unexpectedly.
  • The Custom Tab opens but the shopper cannot complete payment.

Solutions

Currency validation: Confirm transactionData.currency is "USD" before showing the Paze section.

User cancellation: When the shopper closes the Custom Tab, expect onCheckoutIncomplete:

config.onCheckoutIncomplete = { result ->
    if (result.reason?.contains("cancel", ignoreCase = true) == true) {
        showMessage("Payment cancelled. You can try again when ready.")
    } else {
        showMessage("Unable to complete checkout. Please try a different payment method.")
    }
}

Tab closed without redirect: If the shopper dismisses the Custom Tab without a redirect callback, onCheckoutIncomplete fires when the host Activity resumes.

Merchant rejection: Returning false from onCheckoutComplete triggers onCheckoutIncomplete.

Pre-checkout block: Disable the button in your UI until prerequisites are met. onPazeButtonClicked cannot cancel checkout — the SDK opens the Custom Tab when that callback completes.

UAT wallet access: In UAT, confirm the test shopper email or phone is provisioned for your Paze merchant account.

App doesn't return from checkout

The symptoms of this are:

  • The Paze Custom Tab completes but your app doesn't process the result.
  • Checkout hangs after the shopper finishes in the browser.
  • onCheckoutComplete never fires.

Diagnostic steps

Verify your host Activity handles redirects:

import com.pxp.checkout.components.paze.payment.deliverPazeCheckoutResult

override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    setIntent(intent)
    intent.deliverPazeCheckoutResult(pazeButton)
}

Confirm checkout was launched from an Activity context so PazeRedirectRegistry could register the host.

Common redirect handling issues and fixes:

IssueSolution
onNewIntent not implementedAdd deliverPazeCheckoutResult handler
setIntent(intent) omittedCall setIntent before delivering the result
Non-Activity contextCreate PxpCheckout with an Activity Context
Custom scheme mismatchRegister custom scheme via PazeRedirectRegistry and matching intent filter

The default pxpcheckout://callback and pxpcheckout://paze schemes are handled by the SDK-merged PazeSdkRedirectActivity. Your host Activity still must receive the forwarded intent and call deliverPazeCheckoutResult.

Complete or MCC errors

The symptoms of this are:

  • Checkout completes but the flow fails before decryption.
  • onError fires with SDK1202A.

Solution: Include merchantCategoryCode in the session response from your backend. The SDK requires it when building the Paze complete request.

Token decryption fails

The symptoms of this are:

  • Checkout completes but payment doesn't process.
  • onPostDecryption never fires.
  • onError fires with SDK1233.

onPostDecryption does not run when onPreDecryption returns false (merchant-managed decryption). That is expected — use onComplete to receive the securedPayload instead. See Events.

Solutions

Common decryption failure causes:

CauseSolution
Invalid or expired sessionCreate a fresh session and retry.
securedPayload missingCheck complete response; verify Paze wallet settings in the Unity Portal.
Manual decryption pathReturn false from onPreDecryption and decrypt in onComplete; onPostDecryption is skipped by design
Manual decryption misconfiguredEnsure onPreDecryption returns false and backend decrypts the payload from onComplete
Network error during decryptRetry; check device connectivity.

Decryption failures surface through onError with SDK1233. See Analytics for PazeDecryptionFailed events.

Authorisation fails after decryption

The symptoms of this are:

  • onSubmitError fires with FailedSubmitResult.
  • onPostAuthorisation may still fire with transaction IDs when Unity returns an error state and the callback is registered — always verify the outcome on your backend.

Solutions

Log submission failures with correlation IDs for support:

config.onSubmitError = { result ->
    val failed = result as? FailedSubmitResult
    Log.e("Paze", "Submit failed: ${failed?.errorCode} ${failed?.errorReason}")
    Log.e("Paze", "Correlation ID: ${failed?.correlationId}")
}

Common authorisation submission failure causes:

CauseSolution
Missing shopper dataImplement onGetShopper on PxpSdkConfig with a valid shopper id, or set transactionData.shopper
Invalid Kount dataFix riskScreeningData in onPreAuthorisation
Transaction declinedCheck PXP transaction response; verify amount and merchant setup
Missing entryTypeSet transactionData.entryType to EntryType.Ecom when initialising the SDK. The standalone button does not validate this at presentment

Hard submission failures surface through onSubmitError.

onPostAuthorisation behaviour

Symptom: You expected a successful payment but the transaction outcome is unclear, or the callback did not run.

Solution: Register onPostAuthorisation on the component config — the SDK only invokes it when the callback is set. The SDK calls it when it receives a MerchantSubmitResult with merchantTransactionId and systemTransactionId. It does not run on the merchant-managed decryption path (onPreDecryption returns false). Verify the payment outcome on your backend — Unity may return an error state while still providing transaction identifiers. Hard submission failures route to onSubmitError instead.

config.onPostAuthorisation = { result ->
    verifyPaymentOnBackend(result.systemTransactionId)
}