{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-guides/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["sub-heading","admonition"]},"type":"markdown"},"seo":{"title":"Testing","description":"Transform your commerce with PXP's unified platform—seamless payments, real-time insights, and global growth in one powerful integration.","lang":"en-UK","siteUrl":"https://developer.pxp.io","llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"testing","__idx":0},"children":["Testing"]},{"$$mdtype":"Tag","name":"SubHeading","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Learn how to test your Paze integration effectively before going live."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"overview","__idx":1},"children":["Overview"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Thorough testing is essential to ensure your Paze integration works correctly across presentment, checkout, decryption, and error scenarios on iOS. This guide covers test environments, configuration, test scenarios, and debugging techniques."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Always test your integration in the UAT environment before deploying to production. Use test credentials and Paze UAT wallets to avoid processing real payments during development."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"test-environments","__idx":2},"children":["Test environments"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"development-environment","__idx":3},"children":["Development environment"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Initialise the SDK with test environment settings, USD transaction data, and a test shopper callback:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"let sessionData = SessionData(\n    sessionId: session.sessionId,\n    hmacKey: session.hmacKey,\n    encryptionKey: session.encryptionKey,\n    allowedFundingTypes: AllowedFundingType(\n        wallets: Wallets(\n            paze: Paze(\n                clientId: session.pazeClientId,\n                profileId: session.pazeProfileId,\n                merchantCategoryCode: session.merchantCategoryCode\n            )\n        )\n    )\n)\n\nlet checkoutConfig = CheckoutConfig(\n    environment: .test,\n    session: sessionData,\n    transactionData: TransactionData(\n        amount: 10.00,\n        currency: \"USD\",\n        entryType: .ecom,\n        intent: TransactionIntentData(card: .authorisation),\n        merchantTransactionId: \"test-\\(UUID().uuidString)\",\n        merchantTransactionDate: { Date() }\n    ),\n    merchantShopperId: \"test-shopper-1\",\n    ownerId: \"MERCHANT-GROUP-1\",\n    clientName: \"Test Merchant\",\n    siteName: \"Test Store\",\n    kountDisabled: true,\n    onGetShopper: { async in\n        TransactionShopper(\n            id: \"test-shopper-1\",\n            email: \"test@example.com\",\n            firstName: \"Test\",\n            lastName: \"Shopper\"\n        )\n    }\n)\n\nlet pxpCheckout = try PxpCheckout.initialize(config: checkoutConfig)\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"environment-options","__idx":4},"children":["Environment options"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The SDK maps portal environments to these settings:"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Environment"},"children":["Environment"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"SDK setting"},"children":["SDK setting"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Purpose"},"children":["Purpose"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["UAT"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".test"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Development and UAT testing"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Production"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".live"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Live payments"]}]}]}]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"warning"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Never use production Paze credentials in development. UAT and live environments use separate client IDs and API endpoints."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"paze-uat-wallets","__idx":5},"children":["Paze UAT wallets"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To test checkout in UAT:"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Use UAT credentials end-to-end:"]}," Portal Paze client ID on your site, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["environment: .test"]}," in the SDK, and sessions created against the UAT API (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["api-services.dev.pxp.io"]},")."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Register test shoppers with Paze:"]}," Use email and phone combinations that Paze has provisioned for your UAT merchant account. Contact your Paze integration contact if you don't have UAT shopper credentials."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Register your URL scheme:"]}," Confirm ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["pxpcheckout"]}," (or your custom ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PXP_CALLBACK_SCHEME"]},") is in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Info.plist"]},". The default return URL is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["pxpcheckout://paze"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Test on a physical device:"]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ASWebAuthenticationSession"]}," behaviour is most reliable on device. Use the Simulator for presentment and validation testing."]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The iOS component uses static presentment. The button appears after SDK validation without calling ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["canCheckout()"]},". This simplifies testing checkout and payment flows before you have UAT-eligible wallet identities."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"test-configuration","__idx":6},"children":["Test configuration"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"basic-test-setup","__idx":7},"children":["Basic test setup"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Create a Paze button with logging callbacks on each stage of the payment flow:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"let config = PazeButtonComponentConfig()\nconfig.emailAddress = \"test.shopper@example.com\"\nconfig.phoneNumber = \"15551234567\"\nconfig.style = PazeButtonStyleConfig(color: .pazeBlue, shape: .pill, label: .checkoutWith)\n\nconfig.onInit = { print(\"TEST: Paze initialised\") }\nconfig.onPresentmentResolved = { isVisible in print(\"TEST: Button visible:\", isVisible) }\nconfig.onPazeButtonClicked = { async in print(\"TEST: Button clicked\") }\n\nconfig.onCheckoutComplete = { result async in\n    print(\"TEST: Checkout complete:\", result)\n    return true\n}\n\nconfig.onComplete = { result async in\n    print(\"TEST: Complete payload ID:\", result.completeDecodedResponse?.payloadId ?? \"\")\n}\n\nconfig.onPostDecryption = { payload async in\n    print(\"TEST: Card network:\", payload.fundingData.cardNetwork)\n}\n\nconfig.onPostAuthorisation = { data async in\n    print(\"TEST: Authorisation result:\", data.systemTransactionId)\n}\n\nconfig.onError = { error in\n    print(\"TEST: Error:\", error.errorCode, error.errorMessage)\n}\n\nlet pazeButton = try pxpCheckout.create(.pazeButton, componentConfig: config)\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Display the component in your test view:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"pazeButton.buildContent()\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"test-scenarios","__idx":8},"children":["Test scenarios"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"presentment-testing","__idx":9},"children":["Presentment testing"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["After presentment validation succeeds, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onInit"]}," fires, the button renders, and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPresentmentResolved(true)"]}," is called. If validation fails, the button stays hidden and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPresentmentResolved(false)"]}," is called followed by ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onError"]},"."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"config.onPresentmentResolved = { isVisible in\n    print(\"Presentment resolved:\", isVisible)\n}\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Test presentment failure by initialising with a non-USD currency:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"let invalidTransactionData = TransactionData(\n    amount: 10.00,\n    currency: \"GBP\",\n    entryType: .ecom,\n    intent: TransactionIntentData(card: .authorisation),\n    merchantTransactionId: \"test-gbp\",\n    merchantTransactionDate: { Date() }\n)\n// Expected: SDK1213 via onError, onPresentmentResolved(false)\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"checkout-flow-testing","__idx":10},"children":["Checkout flow testing"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"approve-checkout","__idx":11},"children":["Approve checkout"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Return ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["true"]}," from ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onCheckoutComplete"]}," to exercise the full happy path:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"config.onCheckoutComplete = { result async in\n    print(\"Checkout data:\", result.checkoutDecodedResponse?.sessionId ?? \"\")\n    print(\"Card brand:\", result.checkoutDecodedResponse?.maskedCard?.paymentCardBrand ?? \"\")\n    return true\n}\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"reject-checkout","__idx":12},"children":["Reject checkout"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Return ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["false"]}," from ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onCheckoutComplete"]}," to confirm the SDK treats checkout as incomplete:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"config.onCheckoutComplete = { _ async in false }\n\nconfig.onCheckoutIncomplete = { result async in\n    print(\"Expected incomplete result:\", result.reason ?? \"\")\n    // Merchant rejection reason from localised resources\n}\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"user-cancellation","__idx":13},"children":["User cancellation"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Dismiss the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ASWebAuthenticationSession"]}," without completing checkout. Expect ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onCheckoutIncomplete"]}," with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["reason: \"User cancelled.\""]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"decryption-testing","__idx":14},"children":["Decryption testing"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"sdk-managed-decryption","__idx":15},"children":["SDK-managed decryption"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Return ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["true"]}," from ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPreDecryption"]}," (or omit the callback) to test the default SDK decryption path:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"config.onPreDecryption = { async in true }\n\nconfig.onPostDecryption = { payload async in\n    print(\"Network token present:\", !payload.fundingData.networkToken.isEmpty)\n    print(\"Card network:\", payload.fundingData.cardNetwork)\n}\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"manual-decryption","__idx":16},"children":["Manual decryption"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Return ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["false"]}," from ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPreDecryption"]}," and handle ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["securedPayload"]}," in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onComplete"]},". Your test backend should call the PXP decrypt-token API. See ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/checkout/components/ios/paze/implementation#backend-decryption"},"children":["Backend decryption"]},"."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"config.onPreDecryption = { async in false }\n\nconfig.onComplete = { result async in\n    let securedPayload = result.completeDecodedResponse?.securedPayload\n    print(\"Secured payload received:\", securedPayload != nil)\n    await sendToTestBackend(securedPayload: securedPayload)\n}\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"error-scenario-testing","__idx":17},"children":["Error scenario testing"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use these patterns to trigger common validation failures:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"// Invalid currency (fails at presentment)\n// Set transactionData.currency to \"GBP\" → SDK1213\n\n// Invalid phone format\nconfig.phoneNumber = \"+15551234567\"\n// Expected: SDK1212 at presentment or checkout\n\n// Missing merchant category code in session\n// Omit merchantCategoryCode from session → SDK1202A at complete (via onError)\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"debugging-tools","__idx":18},"children":["Debugging tools"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"callback-logging","__idx":19},"children":["Callback logging"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Log each callback during manual testing:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"config.onInit = { print(\"[Paze] onInit\") }\nconfig.onPresentmentResolved = { v in print(\"[Paze] onPresentmentResolved:\", v) }\nconfig.onPazeButtonClicked = { async in print(\"[Paze] onPazeButtonClicked\") }\nconfig.onCheckoutComplete = { r async in print(\"[Paze] onCheckoutComplete:\", r); return true }\nconfig.onCheckoutIncomplete = { r async in print(\"[Paze] onCheckoutIncomplete:\", r.reason ?? \"\") }\nconfig.onComplete = { r async in print(\"[Paze] onComplete\") }\nconfig.onPreDecryption = { async in print(\"[Paze] onPreDecryption\"); return true }\nconfig.onPostDecryption = { r async in print(\"[Paze] onPostDecryption\") }\nconfig.onPreAuthorisation = { async in print(\"[Paze] onPreAuthorisation\"); return .proceed }\nconfig.onPostAuthorisation = { r async in print(\"[Paze] onPostAuthorisation:\", r.systemTransactionId) }\nconfig.onSubmitError = { e async in print(\"[Paze] onSubmitError:\", e) }\nconfig.onError = { e in print(\"[Paze] onError:\", e.errorCode, e.errorMessage) }\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"analytics-event-tracking","__idx":20},"children":["Analytics event tracking"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Log analytics events from ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CheckoutConfig"]}," to verify the payment funnel. For the full event list, see ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/checkout/components/ios/paze/analytics"},"children":["Analytics"]},":"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"analyticsEvent: { event in\n    print(\"Analytics:\", event.eventName, event)\n}\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Key events to verify during testing:"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Event"},"children":["Event"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"When it fires"},"children":["When it fires"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PazeButtonRendered"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The Paze button became visible."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PazeButtonClicked"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Checkout-time validation passes after the shopper taps the button, before the Paze web session opens."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PazePopupLaunched"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The Paze web checkout session opened."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PazeCheckoutCompleted"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Checkout returned ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["COMPLETE"]}," and the merchant approved."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PazeCheckoutAbandoned"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Checkout was incomplete, the session was dismissed, or the merchant rejected checkout."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PazeDecryptionInitiated"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["SDK decryption started."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PazeDecryptionCompleted"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["SDK decryption succeeded."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PazeTransactionInitiated"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Transaction submission to PXP started."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PostAuthorisation"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPostAuthorisation"]}," is configured and the SDK receives a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MerchantSubmitResult"]},", immediately before your callback runs."]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Button visibility isn't an analytics event. Track it with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPresentmentResolved"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"environment-diagnostics","__idx":21},"children":["Environment diagnostics"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Run these checks when the button doesn't appear or checkout fails to return to your app:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"func diagnosePaze(checkoutConfig: CheckoutConfig) {\n    print(\"=== Paze Diagnostics ===\")\n    print(\"Environment:\", checkoutConfig.environment == .test ? \"test\" : \"live\")\n    print(\"Currency:\", checkoutConfig.transactionData.currency)\n    print(\"Amount:\", checkoutConfig.transactionData.amount)\n\n    let paze = checkoutConfig.session.allowedFundingTypes?.wallets?.paze\n    print(\"Client ID:\", paze?.clientId?.isEmpty == false ? \"Present\" : \"Missing\")\n    print(\"MCC:\", paze?.merchantCategoryCode?.isEmpty == false ? \"Present\" : \"Missing\")\n\n    if let urlTypes = Bundle.main.object(forInfoDictionaryKey: \"CFBundleURLTypes\") as? [[String: Any]],\n       let schemes = urlTypes.first?[\"CFBundleURLSchemes\"] as? [String] {\n        print(\"URL schemes:\", schemes)\n    } else {\n        print(\"URL schemes: NOT REGISTERED\")\n    }\n}\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"test-checklist","__idx":22},"children":["Test checklist"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Before going live, verify each scenario."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"configuration","__idx":23},"children":["Configuration"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Confirm your session and SDK setup:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Session includes ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["allowedFundingTypes.wallets.paze.clientId"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Session includes ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["merchantCategoryCode"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Currency is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["USD"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["transactionData.entryType"]}," is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".ecom"]}," (required for authorisation, not validated at presentment)."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Amount is greater than 0."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onGetShopper"]}," returns valid shopper data."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["URL callback scheme is registered in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Info.plist"]},"."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"presentment","__idx":24},"children":["Presentment"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Verify button visibility and presentment callbacks:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Button renders after successful validation."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onInit"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPresentmentResolved(true)"]}," fire when the button is visible."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Validation failures call ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPresentmentResolved(false)"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onError"]},"."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"checkout","__idx":25},"children":["Checkout"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Exercise the web checkout flow:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Button tap opens the Paze web checkout session."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Successful checkout triggers ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onCheckoutComplete"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Returning ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["false"]}," from ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onCheckoutComplete"]}," triggers ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onCheckoutIncomplete"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Dismissing the web session triggers ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onCheckoutIncomplete"]}," with user cancellation."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["App returns via ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["pxpcheckout://paze"]}," (or your configured ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{scheme}://paze"]}," callback)."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"decryption-and-authorisation","__idx":26},"children":["Decryption and authorisation"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Verify decryption and submission callbacks:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["SDK-managed decryption returns token data in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPostDecryption"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Manual decryption receives ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["securedPayload"]}," in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onComplete"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPreAuthorisation"]}," returning ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".cancel"]}," aborts authorisation."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPostAuthorisation"]}," fires when the SDK receives a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MerchantSubmitResult"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Submission failures fire ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onSubmitError"]}," (not ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onError"]},")."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"error-handling","__idx":27},"children":["Error handling"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Confirm errors surface through the right callbacks:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Invalid configuration surfaces errors via ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onError"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Network errors are handled gracefully."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Session expiry is handled with user guidance."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"pre-launch-checklist","__idx":28},"children":["Pre-launch checklist"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"technical-setup","__idx":29},"children":["Technical setup"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Confirm URL scheme, environment, and device coverage:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["URL callback scheme is registered and unique to your app."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Paze client ID is configured in Unity Portal for the correct site."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["environment: .live"]}," is set with production Paze credentials."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Transaction currency is set to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["USD"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["You've tested on physical iOS devices (recommended for the full checkout flow)."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Comprehensive error handling covers all payment scenarios."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"button-and-branding","__idx":30},"children":["Button and branding"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Verify the Paze button meets branding and layout requirements:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The integration uses ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PazeButtonStyleConfig"]}," with approved style values."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The Paze button has equal prominence with other payment methods."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The button renders correctly across supported iPhone and iPad layouts."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"security","__idx":31},"children":["Security"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Confirm credentials and data handling meet your security requirements:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["No sensitive payment data is stored in app storage."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Session credentials are fetched from the backend at runtime."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["All successful transactions are verified on the backend."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["HMAC credentials are stored securely on the server only."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The privacy policy covers payment and identity data usage."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"user-experience","__idx":32},"children":["User experience"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Check error handling and fallback behaviour in the app:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Clear error messages appear when Paze is unavailable."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The app falls back gracefully to other payment methods."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Loading indicators appear during checkout and processing."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Expired sessions are handled with user guidance."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"go-live-testing","__idx":33},"children":["Go-live testing"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Complete end-to-end tests in UAT before switching to live credentials:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["End-to-end payment testing completed in the UAT environment."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Checkout approval and rejection flows tested."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["SDK-managed and manual decryption paths tested."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Transaction failure scenarios tested."]}]}]},"headings":[{"value":"Testing","id":"testing","depth":1},{"value":"Overview","id":"overview","depth":2},{"value":"Test environments","id":"test-environments","depth":2},{"value":"Development environment","id":"development-environment","depth":3},{"value":"Environment options","id":"environment-options","depth":3},{"value":"Paze UAT wallets","id":"paze-uat-wallets","depth":2},{"value":"Test configuration","id":"test-configuration","depth":2},{"value":"Basic test setup","id":"basic-test-setup","depth":3},{"value":"Test scenarios","id":"test-scenarios","depth":2},{"value":"Presentment testing","id":"presentment-testing","depth":3},{"value":"Checkout flow testing","id":"checkout-flow-testing","depth":3},{"value":"Approve checkout","id":"approve-checkout","depth":4},{"value":"Reject checkout","id":"reject-checkout","depth":4},{"value":"User cancellation","id":"user-cancellation","depth":4},{"value":"Decryption testing","id":"decryption-testing","depth":3},{"value":"SDK-managed decryption","id":"sdk-managed-decryption","depth":4},{"value":"Manual decryption","id":"manual-decryption","depth":4},{"value":"Error scenario testing","id":"error-scenario-testing","depth":3},{"value":"Debugging tools","id":"debugging-tools","depth":2},{"value":"Callback logging","id":"callback-logging","depth":3},{"value":"Analytics event tracking","id":"analytics-event-tracking","depth":3},{"value":"Environment diagnostics","id":"environment-diagnostics","depth":3},{"value":"Test checklist","id":"test-checklist","depth":2},{"value":"Configuration","id":"configuration","depth":3},{"value":"Presentment","id":"presentment","depth":3},{"value":"Checkout","id":"checkout","depth":3},{"value":"Decryption and authorisation","id":"decryption-and-authorisation","depth":3},{"value":"Error handling","id":"error-handling","depth":3},{"value":"Pre-launch checklist","id":"pre-launch-checklist","depth":2},{"value":"Technical setup","id":"technical-setup","depth":3},{"value":"Button and branding","id":"button-and-branding","depth":3},{"value":"Security","id":"security","depth":3},{"value":"User experience","id":"user-experience","depth":3},{"value":"Go-live testing","id":"go-live-testing","depth":3}],"frontmatter":{"seo":{"title":"Testing"}},"lastModified":"2026-06-30T10:00:28.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/guides/checkout/components/ios/paze/testing","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}