{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-guides/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["sub-heading","admonition","br"]},"type":"markdown"},"seo":{"title":"Non-3DS transactions","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":"non-3ds-transactions","__idx":0},"children":["Non-3DS transactions"]},{"$$mdtype":"Tag","name":"SubHeading","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Integrate a frictionless checkout experience."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"overview","__idx":1},"children":["Overview"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["By implementing non-3DS transactions into your payment flow, you benefit from:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Streamlined checkout:"]}," No additional authentication required, providing faster payment completion."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Lower transaction friction:"]}," Reduced cart abandonment with seamless payment flow."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Faster processing:"]}," Immediate payment completion without authentication delays."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Better mobile experience:"]}," Optimised for mobile checkouts where 3DS challenges can be problematic."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Non-3DS transactions are ideal for low-risk scenarios, trusted customers, or when implementing other fraud prevention measures. However, they may have different liability arrangements and potentially higher processing fees."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"payment-flow","__idx":2},"children":["Payment flow"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The non-3DS flow is made up of six key steps."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-1-submission","__idx":3},"children":["Step 1: Submission"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The customer taps the submit button or the payment is triggered programmatically. The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["submitAsync()"]}," method in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CardSubmitComponent"]}," is invoked and validation occurs inside it. If validation passes, the method continues with the payment processing. If it fails, the method exits early and doesn't proceed with the transaction."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-2-card-tokenisation","__idx":4},"children":["Step 2: Card tokenisation"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If it's a new card, the SDK sends the card details to the tokenisation service. If it's a saved card, the SDK retrieves the existing token."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-3-evaluation","__idx":5},"children":["Step 3: Evaluation"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The SDK evaluates whether 3DS authentication is required. In this flow, 3DS isn't required based on factors such as:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The transaction intent being ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".payout"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Your configuration not requiring 3DS authentication (i.e., ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPreInitiateAuthentication"]}," callback not provided)."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The transaction falling below risk thresholds."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Regulatory exemptions being applicable."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Since 3DS isn't required, the flow skips all authentication steps and proceeds directly to authorisation."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-4-authorisation","__idx":6},"children":["Step 4: Authorisation"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This is the final processing step where the SDK sends the authorisation request directly to the payment gateway without any 3DS authentication data. The transaction data is processed using standard card payment protocols."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The authorisation step has two associated callbacks:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPreAuthorisation"]},": Provides transaction data for final review. This is your last chance to modify the transaction before authorisation. Note that in non-3DS flows, no authentication results are included."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPostAuthorisation"]},": Receives the final transaction result from the payment gateway. The transaction is either approved or declined with standard payment processing details."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-5-capture","__idx":7},"children":["Step 5: Capture"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Depending on your configuration, the transaction may be automatically captured or require manual capture later."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-6-completion","__idx":8},"children":["Step 6: Completion"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You receive the final authorisation response from the payment gateway. The transaction is either approved or declined and final transaction details are available. Since this is a non-3DS flow, no authentication confirmation data is included in the response."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"non-3ds-callback-details","__idx":9},"children":["Non-3DS callback details"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Non-3DS transactions use simplified callbacks without authentication complexity:"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"core-callbacks","__idx":10},"children":["Core callbacks"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPreAuthorisation"]},": ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["((PreAuthorizationData?) async -> TransactionInitiationData?)?"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Purpose:"]}," Last chance to modify transaction data before authorisation."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Parameter:"]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PreAuthorizationData?"]}," (optional) containing token identifiers (no 3DS data)."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Return:"]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["TransactionInitiationData"]}," with additional metadata, exemption data, or custom parameters."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Return nil:"]}," To cancel the transaction."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Note:"]}," This callback is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["async"]}," as it returns data for the SDK to process."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPostAuthorisation"]},": ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["((BaseSubmitResult) -> Void)?"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Purpose:"]}," Receives the final transaction result from the payment gateway."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Parameter:"]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["BaseSubmitResult"]}," (one of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["AuthorisedSubmitResult"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CapturedSubmitResult"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RefusedSubmitResult"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["FailedSubmitResult"]},")."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Contains:"]}," Transaction status, provider response, transaction reference, processing details."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Usage:"]}," Handle payment success/failure, navigate to appropriate screens, update order status."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Note:"]}," This callback is NOT ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["async"]}," as it only receives results."]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"additional-callbacks","__idx":11},"children":["Additional callbacks"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPreTokenisation"]},": ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["(() -> Bool)?"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Purpose:"]}," Called before card tokenisation begins."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Return:"]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["true"]}," to proceed with tokenisation, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["false"]}," to abort."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Usage:"]}," Perform final validation, show loading states."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPostTokenisation"]},": ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["((CardTokenizationResult) -> Void)?"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Purpose:"]}," Receives tokenisation results."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Parameter:"]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CardTokenizationResult"]}," (either success with token ID or failure with error)."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Usage:"]}," Handle tokenisation success/failure, store token references."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onSubmitError"]},": ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["((BaseSdkException) -> Void)?"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Purpose:"]}," Handles submission errors."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Parameter:"]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["BaseSdkException"]}," containing error details and codes."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Usage:"]}," Display error messages, implement retry logic, track failures."]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"implementation","__idx":12},"children":["Implementation"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"before-you-start","__idx":13},"children":["Before you start"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To use non-3DS payments in your application:"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Ensure your merchant account supports non-3DS transactions."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Configure your risk settings appropriately in the Unity Portal."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Consider implementing additional fraud prevention measures."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-1-configure-your-sdk","__idx":14},"children":["Step 1: Configure your SDK"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To start, set up your ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CheckoutConfig"]}," with the required transaction details."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"import PXPCheckoutSDK\n\nlet sessionData = SessionData(\n    sessionId: \"your-session-id\",\n    hmacKey: \"your-hmac-key\",\n    encryptionKey: \"your-encryption-key\"\n)\n\nlet transactionData = TransactionData(\n    amount: Decimal(string: \"99.99\")!,\n    currency: \"USD\",\n    entryType: .ecom,\n    intent: TransactionIntentData(card: .authorisation),\n    merchantTransactionId: \"order-\\(UUID().uuidString)\",\n    merchantTransactionDate: { Date() }\n)\n\nlet checkoutConfig = CheckoutConfig(\n    environment: .test,\n    session: sessionData,\n    transactionData: transactionData,\n    merchantShopperId: \"shopper-123\",\n    ownerType: \"MerchantGroup\",\n    ownerId: \"your-owner-id\",\n    onGetShopper: { async in\n        TransactionShopper(\n            id: \"shopper-123\",\n            email: \"customer@example.com\",\n            firstName: \"John\",\n            lastName: \"Doe\"\n        )\n    }\n)\n\nlet pxpCheckout = try PxpCheckout.initialize(config: checkoutConfig)\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-2-create-components","__idx":15},"children":["Step 2: Create components"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Create your card components and submit configuration without 3DS callbacks."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"let cardNumber = try pxpCheckout.create(\n    .cardNumber,\n    componentConfig: CardNumberComponentConfig(\n        label: \"Card number\",\n        validationOnChange: true\n    )\n) as! CardNumberComponent\n\nlet cardExpiry = try pxpCheckout.create(\n    .cardExpiryDate,\n    componentConfig: CardExpiryDateComponentConfig(\n        label: \"Expiry date\",\n        validationOnChange: true\n    )\n) as! CardExpiryDateComponent\n\nlet cardCvc = try pxpCheckout.create(\n    .cardCvc,\n    componentConfig: CardCvcComponentConfig(\n        label: \"Security code\",\n        validationOnChange: true\n    )\n) as! CardCvcComponent\n\nvar submitConfig = CardSubmitComponentConfig()\nsubmitConfig.submitText = \"Pay £99.99\"\nsubmitConfig.cardNumberComponent = cardNumber\nsubmitConfig.cardExpiryDateComponent = cardExpiry\nsubmitConfig.cardCvcComponent = cardCvc\n\n// Note: No 3DS callbacks = non-3DS transaction\n\n// onPreAuthorisation is async as it returns data\nsubmitConfig.onPreAuthorisation = { preAuth async in\n    print(\"Pre-authorisation data: \\(String(describing: preAuth))\")\n    return TransactionInitiationData()\n}\n\nsubmitConfig.onPostAuthorisation = { result in\n    switch result {\n    case let authorised as AuthorisedSubmitResult:\n        print(\"Payment successful: \\(authorised.provider.message)\")\n        // Navigate to success screen\n    case let captured as CapturedSubmitResult:\n        print(\"Payment captured: \\(captured.provider.message)\")\n        // Navigate to success screen\n    case let refused as RefusedSubmitResult:\n        print(\"Payment declined: \\(refused.stateData?.message ?? \"Unknown\")\")\n        // Show error message\n    case let failed as FailedSubmitResult:\n        print(\"Payment failed: \\(failed.errorReason ?? \"Unknown error\")\")\n        // Show error message\n    default:\n        print(\"Unknown result type\")\n    }\n}\n\nsubmitConfig.onSubmitError = { error in\n    print(\"Payment error: \\(error.errorMessage)\")\n    // Show error message\n}\n\nlet cardSubmit = try pxpCheckout.create(.cardSubmit, componentConfig: submitConfig) as! CardSubmitComponent\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"warning"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Never set only one of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPreInitiateAuthentication"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPreAuthentication"]},". The SDK throws an exception if they are mismatched. For a pure non-3DS path, leave all 3DS callbacks unset on ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CardSubmitComponentConfig"]},". If you need optional 3DS (for example by amount), configure both hooks and return ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["nil"]}," from ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPreInitiateAuthentication"]}," when you want to skip—see ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/checkout/components/ios/card/3ds"},"children":["3DS"]},"."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-3-handle-common-scenarios","__idx":16},"children":["Step 3: Handle common scenarios"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"low-value-transactions","__idx":17},"children":["Low-value transactions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For low-value transactions where 3DS exemptions apply:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"class LowValuePaymentManager {\n    private let transactionAmount: Decimal\n    \n    init(transactionAmount: Decimal) {\n        self.transactionAmount = transactionAmount\n    }\n    \n    func createNon3DSConfig() -> CardSubmitComponentConfig {\n        var config = CardSubmitComponentConfig()\n        \n        config.submitText = \"Pay \\(formatCurrency(transactionAmount))\"\n        \n        config.onPreAuthorisation = { _ async in\n            // Add risk screening data for fraud detection\n            return TransactionInitiationData(\n                psd2Data: PSD2Data(scaExemption: .lowValue),\n                riskScreeningData: RiskScreeningData(\n                    performRiskScreening: true,\n                    excludeDeviceData: false,\n                    deviceSessionId: generateDeviceSessionId(),\n                    userIp: \"192.168.1.100\",\n                    account: RiskScreeningAccount(\n                        id: \"user_12345678\",\n                        creationDateTime: \"2024-01-15T10:30:00.000Z\"\n                    ),\n                    items: [\n                        RiskScreeningItem(\n                            price: transactionAmount,\n                            quantity: 1,\n                            category: \"General\"\n                        )\n                    ],\n                    fulfillments: [\n                        RiskScreeningFulfillment(\n                            type: .shipped,\n                            recipientPerson: RiskScreeningRecipientPerson(\n                                phoneNumber: \"+1234567890\"\n                            )\n                        )\n                    ]\n                )\n            )\n        }\n        \n        config.onPostAuthorisation = { result in\n            switch result {\n            case is AuthorisedSubmitResult, is CapturedSubmitResult:\n                print(\"Low-value payment successful\")\n                // Track successful low-value payment\n                self.trackPaymentSuccess(amount: self.transactionAmount, type: \"low_value_non_3ds\")\n            case let refused as RefusedSubmitResult:\n                print(\"Low-value payment declined: \\(refused.stateData?.message ?? \"Unknown\")\")\n            default:\n                print(\"Low-value payment failed\")\n            }\n        }\n        \n        return config\n    }\n    \n    private func formatCurrency(_ amount: Decimal) -> String {\n        return \"£\\(amount)\"\n    }\n    \n    private func generateDeviceSessionId() -> String {\n        return UUID().uuidString.replacingOccurrences(of: \"-\", with: \"\")\n    }\n    \n    private func trackPaymentSuccess(amount: Decimal, type: String) {\n        // Analytics tracking for successful payments\n        print(\"Payment successful: amount=\\(amount), type=\\(type)\")\n    }\n}\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"trusted-customer-transactions","__idx":18},"children":["Trusted customer transactions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For returning customers with established trust:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"class TrustedCustomerPaymentManager {\n    private let customerId: String\n    \n    init(customerId: String) {\n        self.customerId = customerId\n    }\n    \n    func createTrustedCustomerConfig() -> CardSubmitComponentConfig {\n        var config = CardSubmitComponentConfig()\n        \n        config.submitText = \"Pay securely\"\n        \n        config.onPreAuthorisation = { _ async in\n            // Add risk screening data with trusted customer indicators\n            return TransactionInitiationData(\n                psd2Data: PSD2Data(scaExemption: .trustedBeneficiary),\n                riskScreeningData: RiskScreeningData(\n                    performRiskScreening: true,\n                    excludeDeviceData: false,\n                    deviceSessionId: generateDeviceSessionId(),\n                    userIp: \"192.168.1.100\",\n                    account: RiskScreeningAccount(\n                        id: self.customerId,\n                        creationDateTime: \"2024-01-15T10:30:00.000Z\"\n                    ),\n                    items: [\n                        RiskScreeningItem(\n                            price: 89.99,\n                            quantity: 1,\n                            category: \"Electronics\"\n                        )\n                    ],\n                    fulfillments: [\n                        RiskScreeningFulfillment(\n                            type: .shipped,\n                            shipping: RiskScreeningShipping(\n                                shippingMethod: .standard\n                            ),\n                            recipientPerson: RiskScreeningRecipientPerson(\n                                phoneNumber: \"+1234567890\",\n                                email: \"customer@example.com\"\n                            )\n                        )\n                    ]\n                )\n            )\n        }\n        \n        config.onPostAuthorisation = { result in\n            switch result {\n            case is AuthorisedSubmitResult, is CapturedSubmitResult:\n                print(\"Trusted customer payment successful\")\n                self.updateCustomerTrustScore(customerId: self.customerId, event: \"successful_payment\")\n            case is RefusedSubmitResult:\n                print(\"Trusted customer payment declined\")\n                self.updateCustomerTrustScore(customerId: self.customerId, event: \"declined_payment\")\n            default:\n                print(\"Unknown payment result\")\n            }\n        }\n        \n        return config\n    }\n    \n    private func updateCustomerTrustScore(customerId: String, event: String) {\n        print(\"Updating trust score for \\(customerId): \\(event)\")\n    }\n}\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-4-handle-errors","__idx":19},"children":["Step 4: Handle errors"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Implement comprehensive error handling for non-3DS transactions:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"class Non3DSErrorHandler {\n    \n    func handlePaymentError(_ error: BaseSdkException) {\n        switch error.errorCode {\n        case \"SDK0304\":\n            showError(\"Your card was declined. Please try a different payment method.\")\n        case \"SDK0500\":\n            showError(\"Network error. Please check your connection and try again.\")\n        case \"SDK0305\":\n            showError(\"Invalid card details. Please check and try again.\")\n        default:\n            showError(\"Payment failed. Please try again or use a different payment method.\")\n        }\n    }\n    \n    private func showError(_ message: String) {\n        // Implementation depends on your UI framework\n        print(\"Error: \\(message)\")\n    }\n}\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"complete-example","__idx":20},"children":["Complete example"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The following example shows a complete non-3DS implementation using SwiftUI:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"import SwiftUI\nimport PXPCheckoutSDK\n\nstruct Non3DSPaymentView: View {\n    @StateObject private var viewModel = Non3DSPaymentViewModel()\n    \n    var body: some View {\n        ScrollView {\n            VStack(alignment: .leading, spacing: 16) {\n                Text(\"Express checkout\")\n                    .font(.title)\n                    .padding(.bottom, 8)\n                \n                Text(\"Fast and secure payment without additional verification\")\n                    .font(.subheadline)\n                    .foregroundColor(.secondary)\n                    .padding(.bottom, 16)\n                \n                // Show error message if any\n                if let error = viewModel.errorMessage {\n                    HStack {\n                        Image(systemName: \"exclamationmark.triangle\")\n                        Text(error)\n                    }\n                    .padding()\n                    .background(Color.red.opacity(0.1))\n                    .foregroundColor(.red)\n                    .cornerRadius(8)\n                }\n                \n                // Render payment component\n                if let newCard = viewModel.newCardComponent {\n                    newCard.buildContent()\n                }\n                \n                // Loading indicator\n                if viewModel.isLoading {\n                    HStack {\n                        Spacer()\n                        VStack(spacing: 8) {\n                            ProgressView()\n                            Text(\"Processing payment...\")\n                                .font(.caption)\n                        }\n                        Spacer()\n                    }\n                    .padding()\n                }\n            }\n            .padding()\n        }\n        .onAppear {\n            viewModel.setupComponents()\n        }\n    }\n}\n\nclass Non3DSPaymentViewModel: ObservableObject {\n    @Published var isLoading = false\n    @Published var errorMessage: String?\n    var newCardComponent: NewCardComponent?\n    \n    private var pxpCheckout: PxpCheckout?\n    private let errorHandler = Non3DSErrorHandler()\n    \n    func setupComponents() {\n        do {\n            // Setup checkout\n            let sessionData = SessionData(\n                sessionId: \"session-\\(UUID().uuidString)\",\n                hmacKey: \"your-hmac-key\",\n                encryptionKey: \"your-encryption-key\"\n            )\n            \n            let transactionData = TransactionData(\n                amount: 29.99,\n                currency: \"GBP\",\n                entryType: .ecom,\n                intent: TransactionIntentData(card: .authorisation),\n                merchantTransactionId: \"order-\\(UUID().uuidString)\",\n                merchantTransactionDate: { Date() }\n            )\n            \n            let checkoutConfig = CheckoutConfig(\n                environment: .test,\n                session: sessionData,\n                transactionData: transactionData,\n                merchantShopperId: \"shopper-456\",\n                ownerType: \"MerchantGroup\",\n                ownerId: \"your-owner-id\",\n                onGetShopper: { async in\n                    TransactionShopper(\n                        id: \"shopper-456\",\n                        email: \"customer@example.com\",\n                        firstName: \"Jane\",\n                        lastName: \"Smith\"\n                    )\n                }\n            )\n            \n            pxpCheckout = try PxpCheckout.initialize(config: checkoutConfig)\n            \n            // Setup submit config without 3DS\n            var submitConfig = CardSubmitComponentConfig()\n            \n            // No 3DS callbacks - transaction will be non-3DS\n            // onPreAuthorisation is async as it returns data\n            submitConfig.onPreAuthorisation = { _ async in\n                return TransactionInitiationData(\n                    psd2Data: PSD2Data(scaExemption: .lowValue)\n                )\n            }\n            \n            submitConfig.onPostAuthorisation = { [weak self] result in\n                DispatchQueue.main.async {\n                    self?.isLoading = false\n                    \n                    switch result {\n                    case let authorised as AuthorisedSubmitResult:\n                        print(\"Payment successful: \\(authorised.provider.message)\")\n                        self?.navigateToSuccessScreen()\n                    case let captured as CapturedSubmitResult:\n                        print(\"Payment captured: \\(captured.provider.message)\")\n                        self?.navigateToSuccessScreen()\n                    case let refused as RefusedSubmitResult:\n                        print(\"Payment declined: \\(refused.stateData?.message ?? \"Unknown\")\")\n                        self?.handlePaymentDecline(refused)\n                    case let failed as FailedSubmitResult:\n                        print(\"Payment failed: \\(failed.errorReason ?? \"Unknown error\")\")\n                        self?.showError(\"Payment failed. Please try again.\")\n                    default:\n                        print(\"Unknown result type\")\n                        self?.showError(\"Payment completed with unknown status.\")\n                    }\n                }\n            }\n            \n            submitConfig.onSubmitError = { [weak self] error in\n                print(\"Submit error: \\(error.errorMessage)\")\n                DispatchQueue.main.async {\n                    self?.isLoading = false\n                    self?.errorHandler.handlePaymentError(error)\n                }\n            }\n            \n            submitConfig.onStartSubmit = { [weak self] in\n                DispatchQueue.main.async {\n                    self?.isLoading = true\n                }\n            }\n            \n            // Create new card component\n            let newCardConfig = NewCardComponentConfig(submit: submitConfig)\n            newCardComponent = try pxpCheckout?.create(.newCard, componentConfig: newCardConfig) as? NewCardComponent\n            \n        } catch {\n            showError(\"Failed to initialise payment: \\(error.localizedDescription)\")\n        }\n    }\n    \n    private func handlePaymentDecline(_ result: RefusedSubmitResult) {\n        let declineReason = result.stateData?.code ?? \"Unknown\"\n        \n        let message: String\n        switch declineReason {\n        case \"05\":\n            message = \"Payment declined by your bank\"\n        case \"14\":\n            message = \"Invalid card number\"\n        case \"54\":\n            message = \"Card has expired\"\n        case \"61\":\n            message = \"Amount limit exceeded\"\n        default:\n            message = \"Payment was declined\"\n        }\n        \n        showError(message)\n    }\n    \n    private func navigateToSuccessScreen() {\n        // Navigate to success screen\n        print(\"Payment successful!\")\n    }\n    \n    private func showError(_ message: String) {\n        errorMessage = message\n    }\n}\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"callback-data","__idx":21},"children":["Callback data"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This section describes the data received by the different callbacks as part of the non-3DS flow."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"onpreauthorisation","__idx":22},"children":["onPreAuthorisation"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPreAuthorisation"]}," callback receives pre-authorisation data. For non-3DS transactions, the 3DS-related data will be ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["nil"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"pre-authorisation-data","__idx":23},"children":["Pre-authorisation data"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The pre-authorisation data contains token identifiers when available."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"PreAuthorizationData(\n    gatewayTokenId: \"gw_token_abc123def456789\",\n    schemeTokenId: nil\n)\n","lang":"swift"},"children":[]},{"$$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":"Parameter"},"children":["Parameter"]},{"$$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":["gatewayTokenId"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The token identifier from the gateway."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["schemeTokenId"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The token identifier from the card scheme (if available)."]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Here's an example of what to do with this data:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"submitConfig.onPreAuthorisation = { preAuth async in\n    print(\"Non-3DS authorisation for token: \\(String(describing: preAuth?.gatewayTokenId))\")\n    \n    // Access optional token data if available\n    if let tokenId = preAuth?.gatewayTokenId {\n        print(\"Gateway token: \\(tokenId)\")\n        \n        // Merchant can use gatewayTokenId to retrieve token details from backend\n        // and make authorisation decision\n        let transactionDecision = await getAuthorisationDecision(tokenId)\n        \n        if !transactionDecision {\n            // Not proceeding with authorisation\n            print(\"Not proceeding with authorisation\")\n            return nil\n        }\n    }\n    \n    // Add fraud prevention data\n    return TransactionInitiationData(\n        psd2Data: PSD2Data(scaExemption: .lowValue),\n        riskScreeningData: RiskScreeningData(\n            performRiskScreening: true,\n            excludeDeviceData: false,\n            deviceSessionId: generateDeviceSessionId(),\n            userIp: \"192.168.1.100\",\n            account: RiskScreeningAccount(\n                id: \"user_12345678\",\n                creationDateTime: \"2024-01-15T10:30:00.000Z\"\n            ),\n            items: [\n                RiskScreeningItem(\n                    price: 89.99,\n                    quantity: 1,\n                    category: \"Electronics\"\n                )\n            ],\n            fulfillments: [\n                RiskScreeningFulfillment(\n                    type: .shipped,\n                    shipping: RiskScreeningShipping(\n                        shippingMethod: .standard\n                    ),\n                    recipientPerson: RiskScreeningRecipientPerson(\n                        phoneNumber: \"+1234567890\",\n                        email: \"customer@example.com\"\n                    )\n                )\n            ]\n        )\n    )\n}\n\nprivate func generateDeviceSessionId() -> String {\n    return UUID().uuidString.replacingOccurrences(of: \"-\", with: \"\")\n}\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["gatewayTokenId"]}," with the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/apis/token-vault/other/get-masked-card-related-to-gateway-token"},"children":["Get masked card data related to gateway token"]}," API to retrieve full token details including card scheme, funding source (credit/debit), masked PAN, and expiry date."]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"warning"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Important:"]}," 3DS external data should no longer be provided via the callback. For non-3DS flows, no 3DS data is applicable."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"onpostauthorisation","__idx":24},"children":["onPostAuthorisation"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPostAuthorisation"]}," callback receives the final transaction result (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SubmitResult"]},")."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"success","__idx":25},"children":["Success"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If the transaction was successful, you'll receive either an ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["AuthorisedSubmitResult"]}," or a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CapturedSubmitResult"]},":"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"AuthorisedSubmitResult(\n    state: \"Authorised\",\n    provider: ProviderResponse(\n        code: \"00\",\n        message: \"Approved\",\n        cardVerificationCodeResult: \"M\",\n        addressVerificationServiceResult: \"Y\"\n    ),\n    fundingData: FundingData(\n        cardVerificationCodeResult: \"Matched\",\n        addressVerificationServiceResult: \"Y\"\n    )\n)\n","lang":"swift"},"children":[]},{"$$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":"Parameter"},"children":["Parameter"]},{"$$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":["state"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The final state of the transaction.",{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},"Possible values:",{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Authorised"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Captured"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Refused"]}]}]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["provider"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Details about the provider's response including code and message."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["provider.code"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The raw result code returned by the provider that processed the transaction."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["provider.message"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The raw message associated with the result code from the provider that processed the transaction."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["provider.cardVerificationCodeResult"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The Card Verification Code (CVC) result returned by the provider."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["provider.addressVerificationServiceResult"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The Address Verification Service (AVS) result returned by the provider."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fundingData"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Details about the payment method."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fundingData.cardVerificationCodeResult"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The Card Verification Code (CVC) result in human-readable format."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fundingData.addressVerificationServiceResult"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The Address Verification Service (AVS) result in human-readable format."]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Here's an example of what to do with this data:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"submitConfig.onPostAuthorisation = { result in\n    print(\"Non-3DS payment result: \\(result)\")\n    \n    switch result {\n    case let authorised as AuthorisedSubmitResult:\n        print(\"Payment successful!\")\n        print(\"Provider response: \\(authorised.provider.message)\")\n        print(\"Transaction ID: \\(authorised.fundingData.transactionId)\")\n        \n        // Check verification results\n        let fundingData = authorised.fundingData\n        if fundingData.cardVerificationCodeResult == \"Matched\" {\n            print(\"CVC verification passed\")\n        }\n        \n        if fundingData.addressVerificationServiceResult == \"Y\" {\n            print(\"Address verification passed\")\n        }\n        \n        // Store transaction details\n        storeTransactionRecord(TransactionRecord(\n            amount: Decimal(string: \"99.99\")!,\n            currency: \"USD\",\n            cardType: \"card\", // FundingDataResult doesn't have a scheme property\n            processingType: \"non-3ds\",\n            timestamp: Date().toISOString()\n        ))\n        \n        // Navigate to success screen\n        navigateToSuccessScreen()\n        \n    case let captured as CapturedSubmitResult:\n        print(\"Payment captured successfully!\")\n        print(\"Provider response: \\(captured.provider.message)\")\n        navigateToSuccessScreen()\n        \n    case let refused as RefusedSubmitResult:\n        print(\"Payment declined: \\(refused.stateData?.message ?? \"Unknown\")\")\n        handlePaymentFailure(refused)\n        \n    case let failed as FailedSubmitResult:\n        print(\"Payment failed: \\(failed.errorReason ?? \"Unknown error\")\")\n        showError(\"Payment failed: \\(failed.errorReason ?? \"Unknown error\")\")\n        \n    default:\n        print(\"Unknown result type\")\n        showError(\"Payment completed with unknown status\")\n    }\n}\n\nstruct TransactionRecord {\n    let amount: Decimal\n    let currency: String\n    let cardType: String\n    let processingType: String\n    let timestamp: String\n}\n\nprivate func navigateToSuccessScreen() {\n    // Navigate to success screen\n    print(\"Navigating to success screen\")\n}\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"failure-declined","__idx":26},"children":["Failure (Declined)"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If the bank or issuer declines the transaction, you'll receive a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RefusedSubmitResult"]},":"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"RefusedSubmitResult(\n    state: \"Refused\",\n    stateData: StateData(\n        code: \"05\",\n        message: \"Do not honour\"\n    ),\n    provider: ProviderResponse(\n        code: \"05\",\n        message: \"Do not honour\",\n        merchantAdvice: MerchantAdvice(\n            code: \"01\",\n            message: \"Try another payment method\"\n        ),\n        cardVerificationCodeResult: \"M\",\n        addressVerificationServiceResult: \"Y\"\n    ),\n    fundingData: FundingData(\n        cardVerificationCodeResult: \"Matched\",\n        addressVerificationServiceResult: \"Y\"\n    )\n)\n","lang":"swift"},"children":[]},{"$$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":"Parameter"},"children":["Parameter"]},{"$$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":["state"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The final state of the transaction. Value: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Refused"]},"."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["stateData"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Details about the refusal including code and message."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["stateData.code"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The state code."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["stateData.message"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The state message."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["provider"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Provider response with merchant advice (if available)."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["provider.merchantAdvice"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Guidance for handling the decline."]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Here's an example of how to handle failures:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"private func handlePaymentFailure(_ result: RefusedSubmitResult) {\n    print(\"Payment declined: \\(result.stateData?.message ?? \"Unknown\")\")\n    \n    // Check for merchant advice\n    if let advice = result.provider.merchantAdvice {\n        switch advice.code {\n        case \"01\":\n            // Try another payment method\n            showError(\"Payment declined. Please try a different card.\")\n        case \"02\":\n            // Retry with different amount\n            showError(\"Transaction amount issue. Please contact support.\")\n        case \"03\":\n            // Contact issuer\n            showError(\"Please contact your bank to authorise this payment.\")\n        default:\n            showError(\"Payment declined: \\(advice.message)\")\n        }\n    } else {\n        // Generic decline message based on state code\n        let declineReason: String\n        switch result.stateData?.code {\n        case \"05\":\n            declineReason = \"Payment declined by your bank\"\n        case \"14\":\n            declineReason = \"Invalid card number\"\n        case \"54\":\n            declineReason = \"Card has expired\"\n        case \"61\":\n            declineReason = \"Amount limit exceeded\"\n        default:\n            declineReason = \"Payment was declined\"\n        }\n        showError(declineReason)\n    }\n}\n\nprivate func showError(_ message: String) {\n    print(\"Error: \\(message)\")\n    // Show error to user\n}\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"onsubmiterror","__idx":27},"children":["onSubmitError"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If an error occurs during the payment processing, you'll receive error details through the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onSubmitError"]}," callback."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","header":{"controls":{"copy":{}}},"source":"submitConfig.onSubmitError = { error in\n    print(\"Submit error: \\(error.errorMessage)\")\n    \n    switch error.errorCode {\n    // Validation Errors\n    case \"VALIDATION_FAILED\":\n        showError(\"Please check your payment details and try again.\")\n    case \"INVALID_CARD_NUMBER\":\n        showError(\"Invalid card number. Please check and try again.\")\n    case \"INVALID_EXPIRY_DATE\":\n        showError(\"Invalid expiry date. Please check and try again.\")\n    case \"INVALID_CVC\":\n        showError(\"Invalid security code. Please check and try again.\")\n        \n    // Processing Errors\n    case \"TOKENIZATION_FAILED\":\n        showError(\"Unable to process card details. Please try again.\")\n    case \"SDK0500\":\n        showError(\"Network connection issue. Please check your internet and try again.\")\n    case \"GATEWAY_TIMEOUT\":\n        showError(\"Payment system is busy. Please try again in a moment.\")\n    case \"SERVICE_UNAVAILABLE\":\n        showError(\"Payment service temporarily unavailable. Please try again later.\")\n        \n    // Card Errors\n    case \"SDK0304\":\n        showError(\"Card tokenisation failed. Please check your card details.\")\n    case \"SDK0305\":\n        showError(\"Your card has expired. Please use a different card.\")\n        \n    default:\n        showError(\"Payment failed. Please try again or use a different payment method.\")\n    }\n}\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For more information about error handling, see ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/checkout/components/ios/card/troubleshooting"},"children":["Troubleshooting"]},"."]}]}]},"headings":[{"value":"Non-3DS transactions","id":"non-3ds-transactions","depth":1},{"value":"Overview","id":"overview","depth":2},{"value":"Payment flow","id":"payment-flow","depth":2},{"value":"Step 1: Submission","id":"step-1-submission","depth":3},{"value":"Step 2: Card tokenisation","id":"step-2-card-tokenisation","depth":3},{"value":"Step 3: Evaluation","id":"step-3-evaluation","depth":3},{"value":"Step 4: Authorisation","id":"step-4-authorisation","depth":3},{"value":"Step 5: Capture","id":"step-5-capture","depth":3},{"value":"Step 6: Completion","id":"step-6-completion","depth":3},{"value":"Non-3DS callback details","id":"non-3ds-callback-details","depth":2},{"value":"Core callbacks","id":"core-callbacks","depth":3},{"value":"Additional callbacks","id":"additional-callbacks","depth":3},{"value":"Implementation","id":"implementation","depth":2},{"value":"Before you start","id":"before-you-start","depth":3},{"value":"Step 1: Configure your SDK","id":"step-1-configure-your-sdk","depth":3},{"value":"Step 2: Create components","id":"step-2-create-components","depth":3},{"value":"Step 3: Handle common scenarios","id":"step-3-handle-common-scenarios","depth":3},{"value":"Low-value transactions","id":"low-value-transactions","depth":4},{"value":"Trusted customer transactions","id":"trusted-customer-transactions","depth":4},{"value":"Step 4: Handle errors","id":"step-4-handle-errors","depth":3},{"value":"Complete example","id":"complete-example","depth":2},{"value":"Callback data","id":"callback-data","depth":2},{"value":"onPreAuthorisation","id":"onpreauthorisation","depth":3},{"value":"Pre-authorisation data","id":"pre-authorisation-data","depth":4},{"value":"onPostAuthorisation","id":"onpostauthorisation","depth":3},{"value":"Success","id":"success","depth":4},{"value":"Failure (Declined)","id":"failure-declined","depth":4},{"value":"onSubmitError","id":"onsubmiterror","depth":3}],"frontmatter":{"seo":{"title":"Non-3DS transactions"}},"lastModified":"2026-06-12T11:56:36.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/guides/checkout/components/ios/card/non-3ds","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}