{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-guides/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["sub-heading","admonition","br","details","required"]},"type":"markdown"},"seo":{"title":"Events","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":"events","__idx":0},"children":["Events"]},{"$$mdtype":"Tag","name":"SubHeading","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Implement callbacks to customise your PayPal payout flow for iOS."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"overview","__idx":1},"children":["Overview"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The PayPal payout submission component emits events throughout the payout lifecycle. You can use these to implement callback functions, which allow you to inject your own business logic and user experience customisations into the payout flow at critical moments. They ensure that while the SDK handles the complex technical aspects of payout processing, you retain full control over the user experience and can seamlessly integrate payouts into your broader business workflows and systems."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PayoutAmountComponent"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PayPalPayoutReceiverComponent"]}," are display-only components and don't emit events."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Callbacks enable you to:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Validate business rules before payouts execute."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Implement custom approval flows for payout authorisation."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Display custom error, failure, or success messages."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Tailor user interfaces to match your brand's look and feel."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Integrate with your own systems for compliance or audit logging."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Control exactly how your recipients experience both successful and failed payouts."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Track user interactions and payout status for analytics."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["All events are optional and can be mixed and matched based on your business needs."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"supported-events","__idx":2},"children":["Supported events"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The PayPal payout submission component supports the following events:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onClick"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPrePayoutSubmit"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPostPayout"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onCancel"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onError"]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"callbacks","__idx":3},"children":["Callbacks"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The following sections describe each callback in detail."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"onclick","__idx":4},"children":["onClick"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This callback is triggered when the user taps the payout button before payout validation begins."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use it to:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Trigger analytics tracking for user engagement."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Show loading indicators or status messages."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Perform pre-validation checks."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Log user interactions for monitoring."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"event-data","__idx":5},"children":["Event data"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This callback receives no parameters."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-implementation","__idx":6},"children":["Example implementation"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"let config = PayoutSubmissionComponentConfig(\n    submitText: \"Withdraw to PayPal\",\n    onClick: {\n        print(\"PayPal payout button clicked\")\n        \n        // Track button click\n        Analytics.track(\"paypal_payout_clicked\", properties: [\n            \"timestamp\": Date().timeIntervalSince1970,\n            \"payoutAmount\": getCurrentPayoutAmount()\n        ])\n        \n        // Show loading state\n        showLoadingIndicator()\n        \n        // Perform pre-flight checks\n        validateUserEligibleForPayout()\n    }\n)\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"onprepayoutsubmit","__idx":7},"children":["onPrePayoutSubmit"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This callback is triggered to allow merchant approval before the payout executes. This is where you implement your business logic to decide whether to proceed with the payout."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This callback is only triggered when ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["proceedPayoutWithSdk: true"]}," in your PayPal configuration. If set to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["false"]},", payouts are managed entirely by your backend."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use it to:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Show confirmation dialogs to verify payout details."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Implement compliance checks or fraud prevention."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Allow users to review payout amount and recipient."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Apply business rules before authorising payout."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Provide an opportunity to cancel the payout."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"event-data-1","__idx":8},"children":["Event data"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This callback receives no parameters."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"return-value","__idx":9},"children":["Return value"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Returns an optional ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PrePayoutSubmitResult"]}," object:"]},{"$$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":"Property"},"children":["Property"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["isApproved"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["Bool"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Required","attributes":{},"children":[]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Whether the merchant/user approves the payout. Return ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["false"]}," to cancel."]}]}]}]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PayoutSubmissionComponent"]}," doesn't require a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["payerId"]}," because it uses the payer ID already configured in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PayPalConfig.payout.paypalWallet.payerId"]}," for users with stored credentials."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-implementation-1","__idx":10},"children":["Example implementation"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"let config = PayoutSubmissionComponentConfig(\n    submitText: \"Withdraw to PayPal\",\n    onPrePayoutSubmit: {\n        print(\"Pre-payout approval requested\")\n        \n        // Show approval dialog and wait for user response\n        let approved = await showPayoutApprovalDialog(\n            amount: getCurrentPayoutAmount(),\n            currency: \"USD\",\n            recipientEmail: getCurrentPayPalEmail()\n        )\n        \n        // If user cancelled\n        guard approved else {\n            Analytics.track(\"payout_approval_rejected\")\n            return nil  // or return result with isApproved: false\n        }\n        \n        // User approved - proceed with payout\n        Analytics.track(\"payout_approval_granted\", properties: [\n            \"amount\": getCurrentPayoutAmount(),\n            \"currency\": \"USD\",\n            \"timestamp\": Date().timeIntervalSince1970\n        ])\n        \n        // Return approval\n        return PrePayoutSubmitResult(isApproved: true)\n    }\n)\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-with-async-confirmation-dialog","__idx":11},"children":["Example with async confirmation dialog"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"// State for managing approval flow\n@State private var showApprovalAlert = false\n@State private var pendingApprovalContinuation: CheckedContinuation<PrePayoutSubmitResult?, Never>?\n\nlet config = PayoutSubmissionComponentConfig(\n    submitText: \"Withdraw to PayPal\",\n    onPrePayoutSubmit: { [self] in\n        // Show approval dialog and wait for user response\n        return await withCheckedContinuation { continuation in\n            Task { @MainActor in\n                self.pendingApprovalContinuation = continuation\n                self.showApprovalAlert = true\n            }\n        }\n    }\n)\n\n// In your SwiftUI view\n.alert(\"Confirm Payout\", isPresented: $showApprovalAlert) {\n    Button(\"Cancel\", role: .cancel) {\n        // User rejected\n        pendingApprovalContinuation?.resume(returning: nil)\n        pendingApprovalContinuation = nil\n    }\n    Button(\"Confirm\") {\n        // User approved\n        pendingApprovalContinuation?.resume(returning: \n            PrePayoutSubmitResult(isApproved: true)\n        )\n        pendingApprovalContinuation = nil\n    }\n} message: {\n    Text(\"Send $\\(payoutAmount) to your PayPal account?\")\n}\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"onpostpayout","__idx":12},"children":["onPostPayout"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This callback is triggered after the payout transaction completes successfully. This is where you update your system and notify the user of the successful payout."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use it to:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Update transaction records in your database."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Display success messages to users."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Send notifications about completed payouts."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Update user balance or pending payout status."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Navigate to a success screen."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Track successful payout metrics."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"event-data-2","__idx":13},"children":["Event data"]},{"$$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 data"},"children":["Event data"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["result"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["MerchantSubmitResult"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The payout transaction result object."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["result.merchantTransactionId"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Your unique transaction identifier."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["result.systemTransactionId"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The PXP system transaction ID for tracking."]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-implementation-2","__idx":14},"children":["Example implementation"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"let config = PayoutSubmissionComponentConfig(\n    submitText: \"Withdraw to PayPal\",\n    onPostPayout: { result in\n        print(\"Payout successful!\")\n        print(\"Merchant Transaction ID: \\(result.merchantTransactionId)\")\n        print(\"System Transaction ID: \\(result.systemTransactionId)\")\n        \n        // Update payout record in your system\n        updatePayoutStatus(\n            merchantTxId: result.merchantTransactionId,\n            systemTxId: result.systemTransactionId,\n            status: \"completed\",\n            completedAt: Date()\n        )\n        \n        // Update user balance\n        updateUserBalance(\n            userId: currentUser.id,\n            amount: getCurrentPayoutAmount(),\n            type: \"payout_completed\"\n        )\n        \n        // Send push notification\n        sendPushNotification(\n            title: \"Payout Complete\",\n            body: \"Your payout of $\\(getCurrentPayoutAmount()) has been sent to your PayPal account\"\n        )\n        \n        // Track successful payout\n        Analytics.track(\"payout_completed\", properties: [\n            \"merchantTransactionId\": result.merchantTransactionId,\n            \"systemTransactionId\": result.systemTransactionId,\n            \"amount\": getCurrentPayoutAmount(),\n            \"currency\": \"USD\",\n            \"timestamp\": Date().timeIntervalSince1970\n        ])\n        \n        // Navigate to success screen\n        navigateToPayoutSuccessScreen(result.merchantTransactionId)\n    }\n)\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"oncancel","__idx":15},"children":["onCancel"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"oncancel-1","__idx":16},"children":["onCancel"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This callback is triggered when the user cancels the payout during the approval dialog (returning ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["nil"]}," or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["isApproved: false"]}," from ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPrePayoutSubmit"]},")."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use it to:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Track cancellation rates for conversion analysis."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Show helpful messages about the payout process."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Offer alternative payout methods."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Update UI to reflect cancelled state."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Log cancellation events for analytics."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"event-data-3","__idx":17},"children":["Event data"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This callback receives no parameters."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-implementation-3","__idx":18},"children":["Example implementation"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"let config = PayoutSubmissionComponentConfig(\n    submitText: \"Withdraw to PayPal\",\n    onCancel: {\n        print(\"User cancelled payout submission\")\n        \n        // Track cancellation\n        Analytics.track(\"payout_submission_cancelled\", properties: [\n            \"amount\": getCurrentPayoutAmount(),\n            \"timestamp\": Date().timeIntervalSince1970\n        ])\n        \n        // Hide loading indicator\n        hideLoadingIndicator()\n        \n        // Show message\n        showMessage(\"Withdrawal cancelled\")\n        \n        // Reset UI state\n        resetPayoutForm()\n    }\n)\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"onerror","__idx":19},"children":["onError"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This callback is triggered when an error occurs during the payout process, such as network issues, invalid configuration, or payout processing errors."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use it to:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Log errors for debugging and monitoring."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Display user-friendly error messages."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Handle specific error types differently."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Implement retry logic for transient errors."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Offer alternative payout methods on failure."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"event-data-4","__idx":20},"children":["Event data"]},{"$$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 data"},"children":["Event data"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["error"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["BaseSdkException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The error object containing details about what went wrong."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["error.errorCode"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The error code for identifying specific error types."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["error.errorMessage"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["A human-readable error message."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["error.localizedDescription"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The localised error description (same as ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["errorMessage"]},")."]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"common-error-codes","__idx":21},"children":["Common error codes"]},{"$$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":"Error code"},"children":["Error code"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK0809"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PayoutPayerIdRequiredException"]},": Payer ID is empty or not provided."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK0810"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PayoutAmountInvalidException"]},": Amount is NaN or infinite."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK0811"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PayoutAmountNotPositiveException"]},": Amount must be greater than zero."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK0817"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PayoutPayerIdMaxLengthException"]},": Payer ID exceeds 13 characters."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK0818"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PayoutPayerIdInvalidException"]},": Payer ID contains invalid characters."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK0819"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PayoutFailedException"]},": Payout transaction failed."]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For a complete list of error codes including ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK0812-SDK0816"]}," (amount/currency validation) and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK0803-SDK0808"]}," (submission component errors), see ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/checkout/components/ios/paypal/payouts/data-validation"},"children":["Data validation"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-implementation-4","__idx":22},"children":["Example implementation"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"let config = PayoutSubmissionComponentConfig(\n    submitText: \"Withdraw to PayPal\",\n    onError: { error in\n        print(\"Payout error: \\(error.errorMessage)\")\n        print(\"Error code: \\(error.errorCode)\")\n        \n        // Log error for debugging\n        Crashlytics.crashlytics().log(\"PayPal payout error: \\(error.errorMessage)\")\n        Crashlytics.crashlytics().record(error: error)\n        \n        // Hide loading indicator\n        hideLoadingIndicator()\n        \n        // Handle different error types\n        let errorMessage: String\n        let errorCode = error.errorCode\n        \n        switch errorCode {\n        case \"SDK0809\":\n            errorMessage = \"PayPal account information is missing. Please try again.\"\n            \n        case \"SDK0810\":\n            errorMessage = \"Invalid payout amount. Please contact support.\"\n            \n        case \"SDK0811\":\n            errorMessage = \"Payout amount must be greater than zero.\"\n            \n        case \"SDK0817\":\n            errorMessage = \"PayPal account identifier is too long. Please try again.\"\n            \n        case \"SDK0818\":\n            errorMessage = \"Invalid PayPal account format. Please try again.\"\n            \n        case \"SDK0819\":\n            errorMessage = \"Payout transaction failed. Please try again or contact support.\"\n            \n        default:\n            errorMessage = \"Payout failed. Please try again or contact support.\"\n        }\n        \n        // Show error dialog\n        showErrorDialog(\n            title: \"Payout Error\",\n            message: errorMessage\n        )\n        \n        // Offer alternative actions based on error type\n        if errorCode.contains(\"PayerId\") {\n            // Show contact support option\n            showContactSupportOption()\n        } else if errorCode.contains(\"Network\") {\n            // Offer retry\n            showRetryOption()\n        } else {\n            // Show alternative payout methods\n            showAlternativePayoutMethods()\n        }\n        \n        // Track error metrics\n        Analytics.track(\"payout_error\", properties: [\n            \"errorCode\": errorCode,\n            \"errorMessage\": error.errorMessage,\n            \"payoutAmount\": getCurrentPayoutAmount(),\n            \"timestamp\": Date().timeIntervalSince1970\n        ])\n    }\n)\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"complete-example","__idx":23},"children":["Complete example"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Here's a complete example with all event callbacks configured:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"import SwiftUI\nimport PXPCheckoutSDK\n\nstruct PayoutView: View {\n    @State private var pxpCheckout: PxpCheckout?\n    @State private var submissionComponent: BaseComponent?\n    @State private var showApprovalAlert = false\n    @State private var pendingApprovalContinuation: CheckedContinuation<PrePayoutSubmitResult?, Never>?\n    \n    var body: some View {\n        VStack(spacing: 20) {\n            Text(\"Receive Your Payout\")\n                .font(.headline)\n            \n            if let component = submissionComponent {\n                component.buildContent()\n                    .frame(height: 50)\n            }\n        }\n        .padding()\n        .alert(\"Confirm Payout\", isPresented: $showApprovalAlert) {\n            Button(\"Cancel\", role: .cancel) {\n                pendingApprovalContinuation?.resume(returning: nil)\n                pendingApprovalContinuation = nil\n            }\n            Button(\"Confirm\") {\n                pendingApprovalContinuation?.resume(returning: \n                    PrePayoutSubmitResult(isApproved: true)\n                )\n                pendingApprovalContinuation = nil\n            }\n        } message: {\n            Text(\"Send $100.00 to your PayPal account?\")\n        }\n        .onAppear {\n            createPayoutComponent()\n        }\n    }\n    \n    private func createPayoutComponent() {\n        Task {\n            do {\n                // Initialise SDK (see Setup for full configuration)\n                let checkout = try await initializePxpCheckout()\n                \n                // Configure payout component with all callbacks\n                let config = PayoutSubmissionComponentConfig(\n                    submitText: \"Withdraw to PayPal\",\n                    submitAccessibilityLabel: \"Withdraw funds to PayPal account\",\n                    \n                    // 1. Button clicked\n                    onClick: {\n                        print(\"📱 PayPal payout button clicked\")\n                        Analytics.track(\"paypal_payout_clicked\")\n                    },\n                    \n                    // 2. Pre-payout approval\n                    onPrePayoutSubmit: { [self] in\n                        print(\"💰 Pre-payout approval requested\")\n                        \n                        // Show approval dialog and wait for user response\n                        return await withCheckedContinuation { continuation in\n                            Task { @MainActor in\n                                self.pendingApprovalContinuation = continuation\n                                self.showApprovalAlert = true\n                            }\n                        }\n                    },\n                    \n                    // 3. Payout completed\n                    onPostPayout: { result in\n                        print(\"🎉 Payout successful!\")\n                        print(\"   Merchant TX ID: \\(result.merchantTransactionId)\")\n                        print(\"   System TX ID: \\(result.systemTransactionId)\")\n                        \n                        // Update payout status\n                        updatePayoutStatus(\n                            merchantTxId: result.merchantTransactionId,\n                            status: \"completed\"\n                        )\n                        \n                        // Show success message\n                        showSuccessMessage(\"Payout completed!\")\n                        \n                        // Track success\n                        Analytics.track(\"payout_completed\", properties: [\n                            \"merchantTransactionId\": result.merchantTransactionId,\n                            \"systemTransactionId\": result.systemTransactionId\n                        ])\n                    },\n                    \n                    // 4. User cancelled\n                    onCancel: {\n                        print(\"❌ User cancelled payout\")\n                        \n                        // Track cancellation\n                        Analytics.track(\"payout_cancelled\")\n                        \n                        // Show message\n                        showMessage(\"Withdrawal cancelled\")\n                    },\n                    \n                    // 5. Error occurred\n                    onError: { error in\n                        print(\"⚠️ Error occurred:\")\n                        print(\"   Code: \\(error.errorCode)\")\n                        print(\"   Message: \\(error.errorMessage)\")\n                        \n                        // Log error\n                        logError(error)\n                        \n                        // Show error dialog\n                        showErrorDialog(\n                            title: \"Payout Error\",\n                            message: error.errorMessage\n                        )\n                        \n                        // Track error\n                        Analytics.track(\"payout_error\", properties: [\n                            \"errorCode\": error.errorCode,\n                            \"errorMessage\": error.errorMessage\n                        ])\n                    }\n                )\n                \n                // Create component\n                let component = try checkout.create(\n                    .payoutSubmission,\n                    componentConfig: config\n                )\n                \n                await MainActor.run {\n                    self.submissionComponent = component\n                }\n            } catch {\n                print(\"Failed to create payout component: \\(error)\")\n            }\n        }\n    }\n}\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"best-practices","__idx":24},"children":["Best practices"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"error-handling","__idx":25},"children":["Error handling"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Always implement the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onError"]}," callback to handle failures gracefully:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"config.onError = { error in\n    // Log for debugging\n    logError(error)\n    \n    // Show user-friendly message\n    showErrorDialog(getUserFriendlyMessage(for: error.errorCode))\n    \n    // Track for analytics\n    trackError(error)\n    \n    // Offer alternatives\n    showAlternativeOptions()\n}\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"approval-flow","__idx":26},"children":["Approval flow"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPrePayoutSubmit"]},", always show clear information to users:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"config.onPrePayoutSubmit = {\n    return await showApprovalDialog(\n        title: \"Confirm Payout\",\n        message: \"Send $\\(amount) to your PayPal account?\",\n        details: [\n            \"Amount: $\\(amount)\",\n            \"Fee: $\\(fee)\",\n            \"Total: $\\(total)\",\n            \"PayPal Account: \\(email)\"\n        ]\n    )\n}\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"analytics-tracking","__idx":27},"children":["Analytics tracking"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Track key events for monitoring and optimisation:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"// Track funnel\nonClick: {\n    Analytics.track(\"payout_started\")\n}\n\nonPostPayout: { _ in\n    Analytics.track(\"payout_completed\")\n}\n\n// Track drop-offs\nonCancel: {\n    Analytics.track(\"payout_cancelled\")\n}\n\nonError: { error in\n    Analytics.track(\"payout_error\", properties: [\n        \"errorCode\": error.errorCode,\n        \"stage\": determineErrorStage(error)\n    ])\n}\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"state-management","__idx":28},"children":["State management"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Maintain clean state throughout the payout flow:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"enum PayoutState {\n    case idle\n    case awaitingApproval\n    case processing\n    case completed\n    case failed\n    case cancelled\n}\n\n@State private var payoutState: PayoutState = .idle\n\n// Update state in callbacks\nonClick: {\n    payoutState = .awaitingApproval\n}\n\nonPrePayoutSubmit: {\n    payoutState = .processing\n    // ...\n}\n\nonPostPayout: { _ in\n    payoutState = .completed\n}\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"sdk-analytics-events","__idx":29},"children":["SDK analytics events"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In addition to component-level callbacks, you can receive analytics events from the SDK by configuring the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["analyticsEvent"]}," callback on ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CheckoutConfig"]},". This provides visibility into SDK-level events for monitoring, debugging, and analytics integration."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"configuration","__idx":30},"children":["Configuration"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Configure the analytics callback when initialising the SDK:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"let checkoutConfig = CheckoutConfig(\n    environment: .test,\n    session: sessionData,\n    transactionData: transactionData,\n    merchantShopperId: \"user-123\",\n    ownerId: \"merchant-456\",\n    paypalConfig: paypalConfig,\n    analyticsEvent: { event in\n        // Handle analytics events\n        print(\"Analytics event: \\(event.eventName)\")\n        \n        // Forward to your analytics service\n        Analytics.track(event.eventName, properties: [\n            \"timestamp\": Date().timeIntervalSince1970\n        ])\n    }\n)\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"baseanalyticsevent","__idx":31},"children":["BaseAnalyticsEvent"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["All analytics events inherit from ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["BaseAnalyticsEvent"]}," and include the following properties:"]},{"$$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":"Property"},"children":["Property"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["eventName"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["String"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Required","attributes":{},"children":[]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The name of the analytics event."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sessionId"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["String"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Required","attributes":{},"children":[]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The session ID associated with the event."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["timestamp"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["Date"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Required","attributes":{},"children":[]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The timestamp when the event occurred."]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"use-cases","__idx":32},"children":["Use cases"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use the analytics callback to:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Monitor SDK performance:"]}," Track initialisation times, component lifecycle events, and error rates."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Debug integration issues:"]}," Log events during development to understand the SDK flow."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Integration with analytics platforms:"]}," Forward events to services like Firebase Analytics, Amplitude, or Mixpanel."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Audit logging:"]}," Record SDK events for compliance and audit purposes."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"example-comprehensive-analytics-tracking","__idx":33},"children":["Example: Comprehensive analytics tracking"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"let checkoutConfig = CheckoutConfig(\n    environment: .test,\n    session: sessionData,\n    transactionData: transactionData,\n    merchantShopperId: \"user-123\",\n    ownerId: \"merchant-456\",\n    paypalConfig: paypalConfig,\n    analyticsEvent: { event in\n        // Log to console during development\n        #if DEBUG\n        print(\"📊 SDK Analytics: \\(event.eventName)\")\n        #endif\n        \n        // Send to analytics service\n        AnalyticsService.shared.track(\n            event: event.eventName,\n            properties: [\n                \"sdk_version\": \"1.0.0\",\n                \"platform\": \"iOS\",\n                \"environment\": \"test\"\n            ]\n        )\n        \n        // Log to crash reporting for debugging\n        Crashlytics.crashlytics().log(\"SDK event: \\(event.eventName)\")\n    }\n)\n","lang":"swift"},"children":[]}]},"headings":[{"value":"Events","id":"events","depth":1},{"value":"Overview","id":"overview","depth":2},{"value":"Supported events","id":"supported-events","depth":2},{"value":"Callbacks","id":"callbacks","depth":2},{"value":"onClick","id":"onclick","depth":3},{"value":"Event data","id":"event-data","depth":4},{"value":"Example implementation","id":"example-implementation","depth":4},{"value":"onPrePayoutSubmit","id":"onprepayoutsubmit","depth":3},{"value":"Event data","id":"event-data-1","depth":4},{"value":"Return value","id":"return-value","depth":4},{"value":"Example implementation","id":"example-implementation-1","depth":4},{"value":"Example with async confirmation dialog","id":"example-with-async-confirmation-dialog","depth":4},{"value":"onPostPayout","id":"onpostpayout","depth":3},{"value":"Event data","id":"event-data-2","depth":4},{"value":"Example implementation","id":"example-implementation-2","depth":4},{"value":"onCancel","id":"oncancel","depth":3},{"value":"onCancel","id":"oncancel-1","depth":3},{"value":"Event data","id":"event-data-3","depth":4},{"value":"Example implementation","id":"example-implementation-3","depth":4},{"value":"onError","id":"onerror","depth":3},{"value":"Event data","id":"event-data-4","depth":4},{"value":"Common error codes","id":"common-error-codes","depth":4},{"value":"Example implementation","id":"example-implementation-4","depth":4},{"value":"Complete example","id":"complete-example","depth":2},{"value":"Best practices","id":"best-practices","depth":2},{"value":"Error handling","id":"error-handling","depth":3},{"value":"Approval flow","id":"approval-flow","depth":3},{"value":"Analytics tracking","id":"analytics-tracking","depth":3},{"value":"State management","id":"state-management","depth":3},{"value":"SDK analytics events","id":"sdk-analytics-events","depth":2},{"value":"Configuration","id":"configuration","depth":3},{"value":"BaseAnalyticsEvent","id":"baseanalyticsevent","depth":3},{"value":"Use cases","id":"use-cases","depth":3},{"value":"Example: Comprehensive analytics tracking","id":"example-comprehensive-analytics-tracking","depth":3}],"frontmatter":{"seo":{"title":"Events"}},"lastModified":"2026-06-12T11:56:36.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/guides/checkout/components/ios/paypal/payouts/events","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}