Learn how to diagnose and fix common issues with the Paze Android component.
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 code | Description |
|---|---|---|
PazeCheckoutLaunchException / PazeLoadFailedException | SDK1200 | Failed to launch Paze checkout. For example, Custom Tab launch failed. |
PazeConfigurationValidationFailedException(client ID) | SDK1202 | Missing session.allowedFundingTypes.wallets.paze.clientId. |
PazeMerchantCategoryCodeRequiredException | SDK1202A | Missing session.allowedFundingTypes.wallets.paze.merchantCategoryCode at complete. |
PazeConfigurationValidationFailedException(client name) | SDK1203 | clientName exceeds 50 characters when set. |
PazeConfigurationValidationFailedException(brand name) | SDK1204 | siteName exceeds 50 characters when set. |
PazeConfigurationValidationFailedException(statement descriptor) | SDK1205 | paymentDescription exceeds 25 characters when set. |
PazeInitializationFailedException | SDK1206 | Paze initialisation or create-session failed. |
PazeIdentityValidationFailedException(email) | SDK1209-SDK1210 | Email too long or invalid format. |
PazeIdentityValidationFailedException(phone) | SDK1211-SDK1212 | Phone too long or invalid US E.164 format. |
PazeConfigurationValidationFailedException(currency) | SDK1213 | Transaction currency is not USD. |
PazePaymentFailedException | SDK1214 | Generic Paze checkout or wallet flow failure. |
PazeCheckoutResponseMissingException | SDK1215 | Paze checkout did not return a response for a COMPLETE result. |
PazeCompleteResponseMissingException | SDK1216 | Paze complete did not return an expected response. |
PazeCompleteSecuredPayloadMissingException | SDK1219 | Paze complete response did not contain a securedPayload. |
PazeConfigurationValidationFailedException(session ID) | SDK1222 | Component sessionId exceeds 255 characters. |
PazeConfigurationValidationFailedException(amount) | SDK1229 | Transaction amount is 0 or negative at checkout. |
PazeInitializationFailedException / PazeProviderException(shipping countries) | SDK1231 | acceptedShippingCountries contains invalid ISO 3166-1 alpha-2 country codes. Typically returned by the create-session API at checkout. |
PazeInitializationFailedException / PazeProviderException(cobrand) | SDK1232 | A cobrand entry is missing a non-empty cobrandName. Typically returned by the create-session API at checkout. |
PazeDecryptFailedException | SDK1233 | Failed to decrypt the Paze secured payload. |
PazeTransactionFailedException | SDK1235 | Transaction 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.
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.")
}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")
}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.
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.
Symptom: Session response doesn't include allowedFundingTypes.wallets.paze.clientId.
Solution:
- Verify the client ID is saved in Paze Account Settings for the correct site.
- Create a new session after saving portal changes.
- Confirm you are using the correct site name in your session request.
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.
The symptoms of this are:
onPresentmentResolved(false)fires alongsideonError.- 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.
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"}")
}These presentment and checkout validation issues map to the most frequent error codes:
| Cause | Error code | Solution |
|---|---|---|
Missing clientId in session | SDK1202 | Configure Paze Account Settings and re-create session |
| Non-USD currency | SDK1213 | Set transactionData.currency to "USD" |
| Invalid email or phone | SDK1210, SDK1212 | Fix format; see Data validation |
clientName or siteName too long when set | SDK1203, SDK1204 | Shorten to 50 characters or fewer |
| Statement descriptor too long when set | SDK1205 | Shorten paymentDescription to 25 characters or fewer |
| Amount ≤ 0 at checkout | SDK1229 | Set a positive transactionData.amount |
| Invalid shipping country codes | SDK1231 | Use valid ISO 3166-1 alpha-2 codes (for example US, CA); usually returned at create-session |
| Empty cobrand name | SDK1232 | Set a non-empty cobrandName on every PazeCobrandConfig entry; usually returned at create-session |
| No Custom Tab browser | onPresentmentResolved(false) with button visible | Install 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.
The symptoms of this are:
- The shopper taps the Paze button but checkout doesn't complete.
onCheckoutIncompletefires unexpectedly.- The Custom Tab opens but the shopper cannot complete payment.
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.
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.
onCheckoutCompletenever fires.
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:
| Issue | Solution |
|---|---|
onNewIntent not implemented | Add deliverPazeCheckoutResult handler |
setIntent(intent) omitted | Call setIntent before delivering the result |
| Non-Activity context | Create PxpCheckout with an Activity Context |
| Custom scheme mismatch | Register 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.
The symptoms of this are:
- Checkout completes but the flow fails before decryption.
onErrorfires withSDK1202A.
Solution: Include merchantCategoryCode in the session response from your backend. The SDK requires it when building the Paze complete request.
The symptoms of this are:
- Checkout completes but payment doesn't process.
onPostDecryptionnever fires.onErrorfires withSDK1233.
onPostDecryption does not run when onPreDecryption returns false (merchant-managed decryption). That is expected — use onComplete to receive the securedPayload instead. See Events.
Common decryption failure causes:
| Cause | Solution |
|---|---|
| Invalid or expired session | Create a fresh session and retry. |
securedPayload missing | Check complete response; verify Paze wallet settings in the Unity Portal. |
| Manual decryption path | Return false from onPreDecryption and decrypt in onComplete; onPostDecryption is skipped by design |
| Manual decryption misconfigured | Ensure onPreDecryption returns false and backend decrypts the payload from onComplete |
| Network error during decrypt | Retry; check device connectivity. |
Decryption failures surface through onError with SDK1233. See Analytics for PazeDecryptionFailed events.
The symptoms of this are:
onSubmitErrorfires withFailedSubmitResult.onPostAuthorisationmay still fire with transaction IDs when Unity returns an error state and the callback is registered — always verify the outcome on your backend.
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:
| Cause | Solution |
|---|---|
| Missing shopper data | Implement onGetShopper on PxpSdkConfig with a valid shopper id, or set transactionData.shopper |
| Invalid Kount data | Fix riskScreeningData in onPreAuthorisation |
| Transaction declined | Check PXP transaction response; verify amount and merchant setup |
Missing entryType | Set transactionData.entryType to EntryType.Ecom when initialising the SDK. The standalone button does not validate this at presentment |
Hard submission failures surface through onSubmitError.
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)
}