Skip to content

Troubleshooting

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

Exception types and error codes

Component exceptions

The Paze iOS component surfaces BaseSdkException errors with structured codes for different failure scenarios:

Exception Error codeDescription
UnsupportedFundingTypePazeSdkExceptionSDK0118Paze is not included in the allowed funding types for this session.
PazeLoadFailedExceptionSDK1200Paze checkout session failed to start. For example, due to network issues or an error returned by the Paze API.
PazeConfigurationValidationFailedExceptionSDK1202SDK1205, SDK1231, SDK1232Configuration validation failed. For example, missing client ID, invalid field lengths, invalid shipping countries, or empty cobrand names.
PazeMerchantCategoryCodeRequiredExceptionSDK1202AmerchantCategoryCode is missing from the session. Required on iOS for payment completion.
PazeInitializationFailedExceptionSDK1206Paze initialisation failed.
PazeIdentityValidationFailedExceptionSDK1209SDK1212Email or phone number validation failed. Check format and length requirements.
PazeCurrencyNotSupportedExceptionSDK1213Paze only supports USD currency.
PazePaymentFailedExceptionSDK1214Paze checkout or wallet flow failed before authorisation.
PazeCheckoutResponseMissingExceptionSDK1215Paze checkout did not return a checkoutResponse for a COMPLETE result.
PazeCompleteResponseMissingExceptionSDK1216Paze complete() did not return a completeResponse.
PazeCompleteSecuredPayloadMissingExceptionSDK1219Paze completeResponse did not contain a securedPayload for decryption.
PazeCompleteSecuredPayloadMissingException / PazePaymentFailedExceptionSDK1219 / SDK1214 (or provider error codes)Token decryption failed. Check session encryption key and Paze wallet settings in Unity Portal. Surfaced via onError and the PazeDecryptionFailed analytics event.
PazeTransactionFailedExceptionSDK1235Transaction submission failed. Surfaced via onSubmitError, not onError. The callback typically receives a FailedSubmitResult with gateway or provider error codes.

User cancellation isn't thrown as an exception. When the shopper dismisses the ASWebAuthenticationSession, the SDK calls onCheckoutIncomplete with reason: "User cancelled.".

Error handling best practices

Comprehensive error handler

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

config.onError = { error in
    print("Paze error:", error.errorCode, error.errorMessage)

    switch error.errorCode {
    case "SDK0118", "SDK1202":
        hidePazeButton()
        showAlternativePaymentMethods()
    case "SDK1202A":
        showMessage("Paze merchant category code is missing from the session.")
    case "SDK1213":
        showMessage("Paze is only available for USD transactions.")
    case "SDK1210", "SDK1212":
        showMessage("Please check your contact details and try again.")
    case "SDK1214", "SDK1200":
        showMessage("Paze checkout failed. Please try again.")
    default:
        showMessage("Payment could not be completed. Please try again.")
    }
}

config.onCheckoutIncomplete = { result async in
    if result.reason?.lowercased().contains("cancel") == true {
        showMessage("Payment cancelled.")
    } else {
        showMessage("Payment was not completed. Please try again.")
    }
}

config.onSubmitError = { submitResult async in
    if let failed = submitResult as? FailedSubmitResult {
        print("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:

func logPazeError(_ error: BaseSdkException, context: [String: Any] = [:]) {
    var payload: [String: Any] = [
        "errorCode": error.errorCode,
        "errorMessage": error.errorMessage,
        "timestamp": ISO8601DateFormatter().string(from: Date())
    ]
    context.forEach { payload[$0.key] = $0.value }
    // Send to your logging or crash reporting service
    print("Paze support log:", payload)
}

Portal and session setup

Use this section when Paze isn't appearing in the Unity Portal, missing from your session response, or failing during component creation with SDK0118. 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.

SDK0118 on create

Symptom: Component creation fails with Paze is missing in allow funding types.

Solution: The session was created before Paze was configured, or Paze isn't enabled for the site. Complete Onboarding, Steps 3–4, then re-create the session and re-initialise the SDK.

SDK1202 at presentment

Symptom: Presentment fails with Missing session.allowedFundingTypes.wallets.paze.clientId and the button doesn't appear.

Solution: Confirm clientId is in the session response from your backend and passed through SessionData when initialising the SDK. Re-create the session after saving portal changes.

SDK1202A during complete

Symptom: Complete step fails after checkout returns COMPLETE with Missing session.allowedFundingTypes.wallets.paze.merchantCategoryCode.

Solution: Include merchantCategoryCode in your backend session response and pass it through SessionData when initialising the SDK. See Onboarding, Step 4.

Troubleshooting common issues

Paze button isn't showing

The symptoms of this are:

  • onPresentmentResolved(false) fires and no button appears in your SwiftUI view.
  • The Paze option isn't visible to shoppers.

Diagnostic steps

Run these checks to narrow down why the button isn't visible:

func diagnosePazePresentment(checkoutConfig: CheckoutConfig, componentConfig: PazeButtonComponentConfig) {
    print("=== Paze Presentment Diagnostics ===")

    let paze = checkoutConfig.session.allowedFundingTypes?.wallets?.paze
    print("Client ID:", paze?.clientId?.isEmpty == false ? "Present" : "Missing")
    print("MCC:", paze?.merchantCategoryCode?.isEmpty == false ? "Present" : "Missing (required at complete, not for button visibility)")
    print("Currency:", checkoutConfig.transactionData.currency)
    print("Amount:", checkoutConfig.transactionData.amount)
    print("Email:", componentConfig.emailAddress ?? "Not set")
    print("Phone:", componentConfig.phoneNumber ?? "Not set")
}

Listen for presentment and error callbacks:

config.onPresentmentResolved = { isVisible in
    print("Presentment resolved:", isVisible)
}

config.onError = { error in
    print("Presentment error:", error.errorCode, error.errorMessage)
}

Common causes

CauseError codeSolution
Paze not in session at create()SDK0118Enable Paze in Portal and include clientId in session
Missing clientId at presentmentSDK1202Configure Paze Account Settings and re-create session
Non-USD currencySDK1213Set transactionData.currency to "USD"
Invalid email or phoneSDK1210SDK1212Fix format. See Data validation
clientName or siteName too longSDK1203, SDK1204Shorten to 50 characters or fewer
Statement descriptor too longSDK1205Shorten paymentDescription to 25 characters or fewer

On iOS, the button uses static presentment. It appears after SDK validation without calling Paze canCheckout(). If the button is hidden, check onError for validation failures rather than wallet eligibility.

Solution: hide Paze gracefully

When Paze is unavailable, hide the button and show alternatives:

config.onPresentmentResolved = { isVisible in
    showPazeSection(isVisible)
}

config.onError = { error in
    if ["SDK0118", "SDK1202", "SDK1213"].contains(error.errorCode) {
        showPazeSection(false)
        showAlternativePaymentMethods()
    }
}

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 Paze web session opens but the shopper can't complete payment.

Diagnostic steps

Instrument checkout callbacks to log each step:

config.onPazeButtonClicked = { async in
    print("Step 1: Button clicked")
    print("Currency:", checkoutConfig.transactionData.currency)
    print("Amount:", checkoutConfig.transactionData.amount)
}

config.onCheckoutComplete = { result async in
    print("Step 2: Checkout complete")
    print("Session ID:", result.checkoutDecodedResponse?.sessionId ?? "")
    return true
}

config.onCheckoutIncomplete = { result async in
    print("Checkout incomplete:", result.reason ?? "")
}

config.onError = { error in
    print("Checkout error:", error.errorCode, error.errorMessage)
}

Solutions

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

User cancellation: When the shopper dismisses the web session, expect onCheckoutIncomplete with a cancellation reason — not onError:

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

Merchant rejection: Returning false from onCheckoutComplete triggers onCheckoutIncomplete:

config.onCheckoutComplete = { result async in
    guard validateCheckout(result) else { return false }
    return true
}

UAT wallet access: In UAT, confirm the test shopper email or phone is provisioned for your Paze merchant account. Checkout may fail if the wallet account exists but isn't accessible to the merchant.

App doesn't return from checkout

The symptoms of this are:

  • The Paze web session completes but your app doesn't resume.
  • Checkout hangs after the shopper finishes in the browser sheet.
  • onCheckoutComplete never fires.

Diagnostic steps

Verify your URL callback scheme is registered:

<!-- Info.plist -->
<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>pxpcheckout</string>
        </array>
    </dict>
</array>

Confirm the scheme matches your SDK build configuration. The default callback URL is pxpcheckout://paze.

Solutions

IssueSolution
Scheme not in Info.plistRegister CFBundleURLSchemes before testing checkout
Scheme mismatchEnsure PXP_CALLBACK_SCHEME matches your registered scheme
Another app claims the schemeUse a unique scheme for your app
Testing only in SimulatorTest full return flow on a physical device
Presentation context missingPresent checkout from a view controller with a valid window

If multiple apps register the same URL scheme, iOS may route the callback to the wrong app. Use a scheme unique to your application.

Token decryption fails

The symptoms of this are:

  • Checkout completes but payment doesn't process.
  • onPostDecryption never fires.
  • onError fires or the PazeDecryptionFailed analytics event is recorded.

Diagnostic steps

Log each stage of the decryption flow:

config.onCheckoutComplete = { result async in
    print("Step 1: Checkout complete, merchant approved")
    return true
}

config.onComplete = { result async in
    print("Step 2: Complete API succeeded")
    print("Secured payload present:", result.completeDecodedResponse?.securedPayload != nil)
}

config.onPreDecryption = { async in
    print("Step 3: Pre-decryption")
    let hasKey = !checkoutConfig.session.encryptionKey.isEmpty
    print("Session encryption key present:", hasKey)
    return true
}

config.onPostDecryption = { payload async in
    print("Step 4: Decryption successful")
    print("Network token present:", !payload.fundingData.networkToken.isEmpty)
}

config.onError = { error in
    print("Decryption or checkout error:", error.errorCode, error.errorMessage)
}

Solutions

SDK-managed decryption: Return true from onPreDecryption (default) and confirm session.encryptionKey is present in the session from your backend.

Manual decryption: Return false from onPreDecryption and decrypt securedPayload on your backend. See Backend decryption.

Missing secured payload: SDK1219 means the complete response had no securedPayload. Contact PXP support with the checkout session ID.

Authorisation or submission fails

The symptoms of this are:

  • Decryption succeeds but the transaction doesn't complete.
  • onSubmitError fires with error details.
  • onSubmitError fires with FailedSubmitResult details (typically gateway or provider codes such as DECLINED, not SDK1235).

Diagnostic steps

config.onPreAuthorisation = { async in
    print("Pre-authorisation gate")
    return .proceed
}

config.onPostAuthorisation = { data async in
    print("Authorisation result:", data.systemTransactionId)
}

config.onSubmitError = { submitResult async in
    if let failed = submitResult as? FailedSubmitResult {
        print("Submit failed:", failed.errorCode ?? "", failed.errorReason ?? "")
    }
}

Solutions

CauseSolution
Missing shopper dataImplement onGetShopper on CheckoutConfig with valid shopper details
Pre-auth cancelledReturning .cancel from onPreAuthorisation aborts submission intentionally
Backend rejectionInspect failed.errorCode and failed.errorReason from onSubmitError
Session expiredCreate a new session and re-initialise the SDK

Invalid identity format

Symptom: SDK1210 or SDK1212 during presentment or checkout.

Solution:

  • Email: valid RFC 5322 format, 128 characters or fewer.
  • Phone: US E.164 without +, exactly 1 followed by 10 digits (e.g. 15551234567).
// Incorrect
config.phoneNumber = "+1 (555) 123-4567"

// Correct
config.phoneNumber = "15551234567"

Quick reference

When to use which callback

SituationCallbackAction
Configuration or SDK erroronErrorShow message, log errorCode, offer alternatives
Shopper dismissed web checkoutonCheckoutIncompleteShow cancellation message
Merchant rejects checkout dataonCheckoutCompletefalseTriggers onCheckoutIncomplete
Decryption failureonError or PazeDecryptionFailed analyticsRetry or offer alternative payment
Unity submission failureonSubmitError (FailedSubmitResult)Show failure message, log errorCode and errorReason
Button visibilityonPresentmentResolvedShow or hide Paze section

Error code reference

The following tables list the most common Paze error codes surfaced through onError and onSubmitError. For the complete SDK reference — including complete-step validation (SDK1222SDK1230), decode failures, and dynamic-presentment codes — see Full Paze error reference.

Component creation errors

Error codeMessageCause
SDK0118Paze is missing in allow funding types.session.allowedFundingTypes.wallets.paze.clientId is missing or empty at create(.pazeButton) time

Presentment errors

Presentment errors occur during component initialisation before the button is shown. The button remains hidden and onPresentmentResolved(false) is called.

Error codeMessageCause
SDK1202Missing session.allowedFundingTypes.wallets.paze.clientId.Paze clientId not in session data
SDK1203client.name must be 50 characters or fewer.CheckoutConfig.clientName too long
SDK1204client.brandName must be 50 characters or fewer.CheckoutConfig.siteName too long
SDK1205client.statementDescriptor must be 25 characters or fewer.paymentDescription too long
SDK1209emailAddress must be 128 characters or fewer.Email exceeds max length
SDK1210emailAddress must be a valid RFC 5322 email address.Invalid email format
SDK1211phoneNumber must be 15 characters or fewer.Phone exceeds max length
SDK1212phoneNumber must be a US E.164 number without '+', for example 15551234567.Invalid phone format
SDK1213Paze only supports USD currency. Received: '{currency}'.Transaction currency is not USD
SDK1206Failed to initialize Paze SDK.Generic presentment failure

Checkout and payment errors

Error codeMessageCause
SDK1200Failed to load Paze SDK.Session creation failed
SDK1214Paze checkout failed.Generic checkout failure
SDK1215Paze checkout did not return checkoutResponse for a COMPLETE result.Missing checkout response
SDK1216Paze complete did not return completeResponse.Missing complete response code
SDK1219Paze completeResponse did not contain securedPayload.Secured payload missing after complete
SDK1202AMissing session.allowedFundingTypes.wallets.paze.merchantCategoryCode.MCC not configured in session
SDK1231acceptedShippingCountries contains invalid country codes: {invalidCountryCodes}.Invalid ISO country codes
SDK1232cobrand.cobrandName is required for each cobrand entry.Empty cobrand name
SDK1235Paze payment transaction failed.Authorisation request failed. onSubmitError typically receives a FailedSubmitResult with gateway or provider error codes

Additional codes (SDK1201, SDK1207, SDK1208, SDK1217, SDK1218, SDK1220-SDK1230, SDK1233, SDK1234) are documented in the Full Paze error reference.