> ## Documentation Index
> Fetch the complete documentation index at: https://primer.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Klarna: Headless Guide

> Integrate Klarna on your website or mobile application and fully customize your checkout experience using your own UI.

## Before you begin

This guide assumes that you know how to:

* [Initialize Headless Universal Checkout](/docs/checkout/headless/)

## Accept payments with Klarna

### Prepare the client session

Klarna requires the following data to process a payment successfully. Pass the following data in the client session, or in the payment request (for manual payment creation).

| Parameter Name                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | Required | Description                                                                                                                                                                                                                                                                                                                                                   |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [currencyCode](/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session#body-currency-code)                                                                                                                                                                                                                                                                                                                                                                                                                                                         | ✓        | 3-letter currency code in [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) format, e.g. `USD` for US dollars                                                                                                                                                                                                                                   |
| [order](/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session#body-order.)<br />[↳ lineItems](/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session#body-order-line-items)                                                                                                                                                                                                                                                                                                                                                | ✓        | Details of the line items of the order                                                                                                                                                                                                                                                                                                                        |
| [order](/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session#body-order.)<br />[↳ countryCode](/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session#body-order..countryCode)                                                                                                                                                                                                                                                                                                                                            | ✓        | The country code of the user.Learn more about the supported countries and currencies by visiting [Klarna Documentation](https://docs.klarna.com/klarna-payments/in-depth-knowledge/puchase-countries-currencies-locales/).                                                                                                                                    |
| [customer](/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session#body-customer)<br />[↳ emailAddress](/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session#body-customer-email-address)                                                                                                                                                                                                                                                                                                                                  |          | Customer's email address. Pass this value to pre-fill the Klarna payment form.                                                                                                                                                                                                                                                                                |
| [customer](/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session#body-customer)<br />[↳ mobileNumber](/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session#body-customer-mobile-number)                                                                                                                                                                                                                                                                                                                                  |          | Customer's mobile number (make sure it is the correct format for the country code). Pass this value to pre-fill the Klarna payment form.                                                                                                                                                                                                                      |
| [customer](/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session#body-customer)<br />[↳ shippingAddress](/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session#body-customer-shipping-address)                                                                                                                                                                                                                                                                                                                            |          | Customer's shipping address. Pass this value to pre-fill the Klarna payment form.                                                                                                                                                                                                                                                                             |
| [customer](/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session#body-customer)<br />[↳ billingAddress](/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session#body-customer-billing-address)                                                                                                                                                                                                                                                                                                                              |          | Customer's billing address. Pass this value to pre-fill the Klarna payment form. <Note> When passing `customer.billingAddress` in the client session, ensure that Klarna has payment method categories configured for the given address. If Klarna is not supported for the given billing address, no Klarna button will be rendered in the checkout </Note>. |
| [paymentMethod](/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session#request.body.paymentMethod)<br />[↳ options](/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session#request.body.paymentMethod.options)<br />[↳ KLARNA](/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session#request.body.paymentMethod.options.KLARNA)<br />[↳ extraMerchantData](/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session#request.body.paymentMethod.options.KLARNA.extraMerchantData) |          | Extra Merchant Data ([EMD](https://docs.klarna.com/klarna-payments/in-depth-knowledge/extra-merchant-data/#how-to-send-emd)) package supported by Klarna can be passed via the client session. Any JSON object that will be accepted by Klarna can be sent. Available schemas are documented [here](https://docs.klarna.com/api-reference/attachment-schema/) |

### Prepare the SDK for payments

<Tabs>
  <Tab title="Web">
    #### Handle payment method

    ##### Integration

    The [KlarnaPaymentMethodMethodManager](/docs/sdk/web/v2.x.x/primer-headless-checkout/methods/createPaymentMethodManager/#klarna) is an SDK manager designed to streamline the headless integrations of the Klarna payment method that is comprised of an initial component/form for selecting a payment category and a redirect flow.

    To integrate `KlarnaPaymentMethodMethodManager`, follow these steps:

    1. The [PrimerHeadlessCheckout](/docs/sdk/web/v2.x.x/primer/methods/createHeadless) will help you [configure](/docs/sdk/web/v2.x.x/primer-headless-checkout/methods/configure) the headless payment method and then [start](/docs/sdk/web/v2.x.x/primer-headless-checkout/methods/start) the payment process

    2. When calling configure provide a callback function for `onAvailablePaymentMethodsLoaded` as described [here](/docs/checkout/headless/)

    3. For the Klarna payment method,configure a handler for the `KLARNA` payment method manager type and create a payment method manager as described [here](/docs/checkout/headless/#step-4d-handle-klarna) \`

    4. When the payment categories for the Klarna payment method have been retrieved, `onPaymentMethodCategoriesChange` callback will be called with a payload that will have a format as seen [here](/docs/sdk/web/v2.x.x/primer-headless-checkout/methods/createPaymentMethodManager/#klarna)

    5. You can use the payment categories retrieved through the `onPaymentMethodCategoriesChange` callback to create the custom component/form

    6. When the user has selected a payment category you should call the [`renderCategory`](/docs/sdk/web/v2.x.x/primer-headless-checkout/methods/createPaymentMethodManager#klarna.returns.PromiselessIKlarnaPaymentMethodManager-or-nullgreater-iklarnapaymentmethodmanager.renderCategory) function available in the manager. The `renderCategory` function requires, as parameters, the selected category id, a container id where to render the details about the payment category and an `onHeightChange` callback that will be called when the payment category height has changed. You can use the height returned by the `onHeightChange` callback to update the height of the container in which the payment category details will be displayed.

    7. After the user has selected a category and the details about this category have been displayed you can call the [`start`](/docs/sdk/web/v2.x.x/primer-headless-checkout/methods/createPaymentMethodManager#redirect.returns.PromiselessIRedirectPaymentMethodManager-or-nullgreater-iredirectpaymentmethodmanager.start) function provided by the payment method manager created at step 3

    ##### Create the PrimerHeadlessCheckout in order to interact with the Primer API

    You can follow the steps described [here](/docs/checkout/headless/#step-2-initialize-primers-headless-universal-checkout) in order to configure the PrimerHeadlessCheckout.

    ##### Provide a custom handler for the `KLARNA` payment method manager

    As described [here](/docs/checkout/headless/#step-2-initialize-primers-headless-universal-checkout) the `onAvailablePaymentMethodsLoad` callback will be called with all available payment methods. Use this function and create a custom configuration for the `KLARNA` payment method manager type and afterwards start the payment process.

    ```javaScript JS theme={"dark"}
    await headless.configure({
        onAvailablePaymentMethodsLoad(paymentMethods) {
            // Called when the available payment methods are retrieved

            for (const paymentMethod of paymentMethods) {
                // `type` is a unique ID representing the payment method
                const { type, managerType } = paymentMethod
                if (managerType === 'KLARNA') {
                    configureKlarnaPaymentMethodManager()
                }
            }
        },
        onCheckoutComplete({ payment }) {
            console.log('onCheckoutComplete', payment)
        },
        onCheckoutFail(error, { payment }, handler) {
            return handler.showErrorMessage()
        },
    })

    await headless.start()
    ```

    **Create the KlarnaPaymentMethodManager**<br />

    Call the [start](/docs/sdk/web/v2.x.x/primer-headless-checkout/methods/start) function in order to start the flow of the component:

    ```javascript JS theme={"dark"}
    function configureKlarnaPaymentMethodManager(){
        paymentMethodManager = await headless.createPaymentMethodManager(
            paymentMethod,
            {
            onPaymentMethodCategoriesChange:(categories: KlarnaPaymentMethodCategory[]) =>{
                renderCustomComponent(categories)
            },
            },
        );
      }

    ```

    The `onPaymentMethodCategoriesChange` callback received a payload as described [here](/docs/sdk/web/v2.x.x/primer-headless-checkout/methods/createPaymentMethodManager#klarna.parameters.options-properties.onPaymentMethodCategoriesChange) The options array can be used to configure a custom component/form.

    **Handle data collection**<br />

    As mentioned previously, the component allows you to collect the payment categories, and to request payment finalization by calling the `start` function from the payment method manager. You can use the result of the [start](/docs/sdk/web/v2.x.x/primer-headless-checkout/methods/createPaymentMethodManager/#redirect.returns.PromiselessIRedirectPaymentMethodManager-or-nullgreater-iredirectpaymentmethodmanager.start) function to handle any errors

    ```javascript JS theme={"dark"}
    async function onPaymentCategorySelected( categoryId: string ) {
        const response  = await paymentMethodManager.start({
          paymentMethodCategoryId: categoryId,
        });

        if (response?.outcome === 'DENIED') {
            console.log("Something went wrong.", result.validationErrors)
            return;
        }

        console.log("The payment finalized")
    }

    ```
  </Tab>

  <Tab title="iOS">
    #### Pre-requisites

    Some payment methods like Klarna Direct Debit (part of Klarna's Pay Now), require manual enablement for the available markets (e.g.: DE, SE, NL). This is done by Klarna upon merchant request.

    Install Primer Klarna SDK
    We support the Klarna In-App SDK (from version 2.7.0).

    In order to be able to use Klarna you will have to install the `PrimerKlarnaSDK`, currently available on CocoaPods.

    #### CocoaPods

    Add the line below in you `Podfile`

    ```ruby RUBY theme={"dark"}
    use_frameworks!
    target 'PrimerSDK_Example' do
      pod 'PrimerSDK'
      # Add the line below 👇
      pod 'PrimerKlarnaSDK'
    end
    ```

    Configure Primer's settings
    Add a url scheme for your project and pass it in the `urlScheme` of the `paymentMethodOptions` of your `settings`.

    ```swift SWIFT theme={"dark"}
    let settings = PrimerSettings(
            paymentHandling: .auto,
            // 👇 Add this line
            paymentMethodOptions: PrimerPaymentMethodOptions(urlScheme: "merchant://primer.io")
    )
    ```

    #### Handle payment method

    **Integration**<br />

    `[PrimerHeadlessUniversalCheckout.KlarnaManager](/sdk/ios/v2.x.x/primer-headless-checkout/klarna-headless-manager/init)` is an SDK manager designed to streamline the headless integration with Klarna. To integrate `PrimerHeadlessUniversalCheckout.KlarnaManager`, follow these steps:

    Create a new instance of `KlarnaComponent`
    For the primer session intent, pass either `PrimerSessionIntent.CHECKOUT` or `PrimerSessionIntent.VAULT`, depending on the session type you'd like to create:

    ```swift SWIFT theme={"dark"}
    do {
     manager = PrimerHeadlessUniversalCheckout.KlarnaManager()
     klarnaComponent = try manager.provideKlarnaComponent(with: sessionIntent)
    } catch {
     // Catch errors here
    }
    ```

    #### Listen for the emitted data

    Conform to the [stepDelegate](/docs/sdk/ios/v2.x.x/primer-headless-checkout/klarna-headless-manager/provideKlarnaComponent#klarnacomponent.Step) in order to be notified about the state of the payment process:

    ```swift SWIFT theme={"dark"}
    func didReceiveStep(step: PrimerSDK.PrimerHeadlessStep) {
        if let step = step as? KlarnaStep {
            switch step {
            // Emitted once the component is started via `start()` method call.
            case .paymentSessionCreated(let clientToken, let paymentCategories):
                // Render categories.
            // Emitted once the payment options are collected
            // via `updateCollectedData(collectableData: KlarnaCollectableData)` method call.
            case .viewLoaded(let view):
                // Render the payment view corresponding to the selected payment category
            // Emitted once the payment is authorized via `submit()` method call
            // after the user confirms the payment via the Klarna payment screen
            case .paymentSessionAuthorized( _, let checkoutData):
                // Payment was authorized, now you can perform your finalization flow.
            // Payment requires finalization.
            case .paymentSessionFinalizationRequired:
                // Perform klarnaComponent.updateCollectedData(collectableData: KlarnaCollectableData.finalizePayment)
                // to perform the finalization
            // Emitted once the payment finalization is requested
            // via `updateCollectedData(collectableData: KlarnaCollectableData.finalizePayment)`.
            case .paymentSessionFinalized( _, let checkoutData):
                // Payment was finalized, now you can perform your finalization flow.
            default:
                break
            }
        }
    }
    ```

    #### Listen to the data validation status

    It's worth mentioning that the data validation is designed to operate in real-time. This means that the accuracy and completeness of the collected data can be confirmed even while users are actively inputting their information. This real-time validation feature ensures that your data remains accurate and complete throughout the data entry process, enhancing the user experience and the reliability of the collected data. Conform to the [validationDelegate](/docs/sdk/ios/v2.x.x/primer-headless-checkout/klarna-headless-manager/provideKlarnaComponent#klarnacomponent.validationDelegate) to handle any validation statuses that may occur.

    ```swift SWIFT theme={"dark"}
    func didUpdate(validationStatus: PrimerSDK.PrimerValidationStatus, for data: PrimerSDK.PrimerCollectableData?) {
            switch validationStatus {
            case .validating:
                // Handle validation being in progress (e.g. show a progress view)
            case .valid:
                // Handle valid (e.g. hide a progress view)
            case .invalid(errors: let errors):
                // Handle errors that might occour, display them to the user
            case .error(error: let error):
                // Display the error message to the user
            }
        }
    ```

    **Start the flow of the component**<br />
    Call the [start](/docs/sdk/ios/v2.x.x/primer-headless-checkout/klarna-headless-manager/provideKlarnaComponent#klarnacomponent.start) method in order to start the flow of the component:

    ```swift theme={"dark"}
    klarnaComponent.start()
    ```

    Once called, the Klarna session will be created and the `paymentSessionCreated` step will be emitted. As mentioned previously, the `paymentSessionCreated` step contains information about the available Klarna categories. Use these categories to build a category selection user interface. Clicking on any such category should update the payment options via [updateCollectedData](/docs/sdk/ios/v2.x.x/primer-headless-checkout/klarna-headless-manager/provideKlarnaComponent#klarnacomponent.updateCollectedData\(collectableData:-KlarnaCollectableData\)), as described below.

    **Handle data collection**<br />
    The component allows you to collect the payment options (category), and to request payment finalization.

    Payment options should be set before submitting via the [submit](/docs/sdk/ios/v2.x.x/primer-headless-checkout/klarna-headless-manager/provideKlarnaComponent#klarnacomponent.submit) method:

    ```swift SWIFT theme={"dark"}
    func updatePaymentOptions(paymentCategory: KlarnaPaymentCategory) {
        let klarnaCollectableData = KlarnaCollectableData.paymentCategory(paymentCategory, clientToken: clientToken)
        klarnaComponent.updateCollectedData(collectableData: klarnaCollectableData)   
    }
    ```

    Payment finalization should be requested after the payment is authorized and only if finalization is required, otherwise you'll get validation errors. That is, when `paymentSessionFinalizationRequired` is emitted as a step.

    ```swift SWIFT theme={"dark"}
    klarnaComponent.updateCollectedData(collectableData: KlarnaCollectableData.finalizePayment)
    ```

    When the collected payment options are deemed valid, as determined by the [validationDelegate](/docs/sdk/ios/v2.x.x/primer-headless-checkout/klarna-headless-manager/provideKlarnaComponent#klarnacomponent.validationDelegate), make the [submit](/docs/sdk/ios/v2.x.x/primer-headless-checkout/klarna-headless-manager/provideKlarnaComponent#klarnacomponent.submit) method call to initiate the payment authorization process. Calling [submit](/docs/sdk/ios/v2.x.x/primer-headless-checkout/klarna-headless-manager/provideKlarnaComponent#klarnacomponent.submit) will display the Klarna payment window. Successfully confirming the payment via this window will lead to the emission of the `KlarnaStep.paymentSessionAuthorized` step.

    ```swift SWIFT theme={"dark"}
    klarnaComponent?.submit()
    ```

    **Handle errors**<br />
    You can conform to the [errorDelegate](/docs/sdk/ios/v2.x.x/primer-headless-checkout/klarna-headless-manager/provideKlarnaComponent#klarnacomponent.errorDelegate) to handle any errors that may occur during the payment flow:

    ```swift SWIFT theme={"dark"}
    func didReceiveError(error: PrimerSDK.PrimerError) {
            // Handle errors (e.g., display error messages to the user)
        }
    ```

    The `errorDelegate` is a `protocol` that emits `PrimerError` objects, allowing you to identify and respond to any errors that occur during the payment process.

    #### Troubleshooting

    #### Flaky BankId

    The Klarna direct debit flow for Sweden will try to redirect the user to the Mobile BankID app. This action is flaky when in sandbox mode & can sometimes fail
  </Tab>

  <Tab title="Android">
    #### Pre-requisites

    Some payment methods like Klarna Direct Debit (part of Klarna's Pay Now), require manual enablement for the available markets (eg: DE, SE, NL). This is done by Klarna upon merchant request.

    **Configuration**<br />
    We support the Klarna In-App SDK (from version 2.7.0).

    Create a `PrimerKlarnaOptions` object, then initialise the SDK as usual.

    <Note>
      ℹ️ Starting from version `1.0.3`onward, we are transitioning our SDK artifact distribution to Maven Central. This means you no longer need to reference the private Artifactory URL (PRIMER\_ANDROID\_ARTIFACTORY\_URL) for future updates.
    </Note>

    Please ensure that you remove any references to the Artifactory URL previously used for our SDK.

    * Add the URL to Klarna's CDN to your `gradle.properties`:

    ```javascript JSX theme={"dark"}
    KLARNA_DISTRIBUTION_URL=https://x.klarnacdn.net/mobile-sdk/
    ```

    ```javascript JSX theme={"dark"}
    Amend the repositories section of your app's build.gradle to include our given repositories
    repositories {
        /* Other repositories... */
        maven {
            url "${KLARNA_DISTRIBUTION_URL}"
        }
    }
    ```

    Finally, amend the dependencies section of your app's `build.gradle` to include the Primer's `klarna-android` library:

    ```javascript JSX theme={"dark"}
    dependencies {
      /* Other dependencies... */
      implementation "io.primer:klarna-android:1.2.0"
    }
    ```

    #### Handle payment method

    **Integration**<br />

    [PrimerHeadlessUniversalCheckoutKlarnaManager](/docs/sdk/android/v2.x.x/primer-headless-checkout/klarna-headless-manager/init) is an SDK manager designed to streamline the headless integration with Klarna. To integrate `PrimerHeadlessUniversalCheckoutKlarnaManager`, follow these steps:

    #### Create a new instance of `KlarnaComponent`

    For the primer session intent, pass either `PrimerSessionIntent.CHECKOUT` or `PrimerSessionIntent.VAULT`, depending on the session type you'd like to create:

    ```kotlin KOTLIN theme={"dark"}
    val klarnaComponent = PrimerHeadlessUniversalCheckoutKlarnaManager(viewModelStoreOwner).provideKlarnaComponent(PrimerSessionIntent.CHECKOUT)
    ```

    Listen for the emitted data
    Subscribe to the [componentStep](/docs/sdk/android/v2.x.x/primer-headless-checkout/klarna-headless-manager/provideKlarnaComponent#param-component-step-flow-klarna-payment-step) Flow in order to be notified about the state of the payment process:

    ```kotlin KOTLIN theme={"dark"}
    klarnaComponent.componentStep.collectLatest { klarnaPaymentStep ->
        when (klarnaPaymentStep) {
            // Emitted once the component is started via a call to the `start()` function.
            is KlarnaPaymentStep.PaymentSessionCreated -> {
                klarnaStep.paymentCategories.forEach { paymentCategory ->
                    // Render category
                }
            }
            // Emitted once the payment options are collected via a call to the 
            // `updateCollectedData(KlarnaPaymentCollectableData.PaymentOptions(...))` function.
            is KlarnaPaymentStep.PaymentViewLoaded -> {
                // Render the payment view corresponding to the selected payment category
            }
            // Emitted once the component is submitted via a call to the `submit()` function, 
            // after the user confirms the payment via the Klarna payment screen
            is KlarnaPaymentStep.PaymentSessionAuthorized -> {
                if (klarnaStep.isFinalized) {
                    // no-op
                } else {
                    // Payment requires finalization. From this point on, you may call
                    // klarnaComponent.updateCollectedData(KlarnaPaymentCollectableData.FinalizePayment)
                    // to perform the finalization.
                }
            }
            // Emitted once the component is submitted and payment finalization is requested 
            // via `updateCollectedData(KlarnaPaymentCollectableData.FinalizePayment)`.
            is KlarnaPaymentStep.PaymentSessionFinalized -> {
                // Do something when the payment is finalized
            }
        }
    }
    ```

    #### Listen to the data validation statuses

    This component allows you to collect the payment options (category and return URL), and to request payment finalization. It's worth mentioning that the data validation is designed to operate in real-time. This means that the accuracy and completeness of the collected data can be confirmed even while users are actively inputting their information. This real-time validation feature ensures that your data remains accurate and complete throughout the data entry process, enhancing the user experience and the reliability of the collected data. Listen to the [componentValidationStatus](/docs/sdk/android/v2.x.x/primer-headless-checkout/klarna-headless-manager/provideKlarnaComponent#param-component-step-flow-klarna-payment-step) to handle any validation statuses that may occur.

    ```kotlin KOTLIN theme={"dark"}
    klarnaComponent.componentValidationStatus.collectLatest { validationStatus ->
        // Handle validation being in progress (e.g. show progress view),  
        // valid (e.g. enable payment button, submit data automatically..),  
        // invalid (e.g. disable submit button, show validation error messages in input components..)  
        // and error status (e.g. display error messages to the user)
    }
    ```

    Start the flow of the component
    Call the [start](/docs/sdk/android/v2.x.x/primer-headless-checkout/klarna-headless-manager/provideKlarnaComponent#param-start) function in order to start the flow of the component:

    ```kotlin KOTLIN theme={"dark"}
    klarnaComponent.start()
    ```

    Once called, the Klarna session will be created and the `PaymentSessionCreated` step will be emitted. As mentioned previously, the `PaymentSessionCreated` step contains information about the available Klarna categories. Use these categories to build a category selection user interface. Clicking on any such category should update the payment options via [updateCollectedData](/docs/sdk/android/v2.x.x/primer-headless-checkout/klarna-headless-manager/provideKlarnaComponent#param-update-collected-data-collectable-data-klarna-payment-collectable-data), as described below.

    **Handle data collection**<br />
    As mentioned previously, the component allows you to collect the payment options (category and return URL), and to request payment finalization.

    Create a deeplink activity and define it in your `AndroidManifest.xml` with the appropriate intent filter:

    ```xml XML theme={"dark"}
    <activity
        android:name=".DeeplinkReturnActivity"
        android:exported="true"
        android:launchMode="singleTop">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="app" />
            <data android:host="deeplink.return.activity" />
        </intent-filter>
    </activity>
    ```

    Payment options should be set before submitting the component via the [submit](/docs/sdk/android/v2.x.x/primer-headless-checkout/klarna-headless-manager/provideKlarnaComponent#param-submit) function:

    ```kotlin KOTLIN theme={"dark"}
    fun updatePaymentOptions() {
        klarnaComponent.updateCollectedData(
                KlarnaPaymentCollectableData.PaymentOptions(
                    context = requireContext(),
                    paymentCategory = getSelectedPaymentCategory(),
                   // Built from the deeplink activity's intent filter scheme and host. 
                                 // This will be used by third-party apps to link back to your app.
                    returnIntentData = "app://deeplink.return.activity"
                )
            )
        )
    }

    fun getSelectedPaymentCategory() : KlarnaPaymentCategory {
        // Return the payment category selected by the user
    }
    ```

    Payment finalization should be requested after the payment is authorized and if and only if finalization is required, otherwise you'll get validation errors. That is, when `PaymentSessionAuthorized` is emitted as step, and `PaymentSessionAuthorized.isFinalized` returns `false`:

    ```kotlin KOTLIN theme={"dark"}
    klarnaComponent.updateCollectedData(KlarnaPaymentCollectableData.FinalizePayment)
    ```

    When the collected payment options are deemed valid, as determined by the [componentValidationStatus](/docs/sdk/android/v2.x.x/primer-headless-checkout/klarna-headless-manager/provideKlarnaComponent#param-component-validation-status-flow-primer-validation-statusless-klarna-payment-collectable-data-greatergreater), call the [submit](/docs/sdk/android/v2.x.x/primer-headless-checkout/klarna-headless-manager/provideKlarnaComponent#param-submit) function to initiate the payment authorization process. Calling submit will display the Klarna payment window. Successfully confirming the payment via this window will lead to the emission of the `KlarnaPaymentStep.PaymentSessionAuthorized` step.

    ```kotlin KOTLIN theme={"dark"}
    klarnaComponent.submit()
    ```

    #### Handle errors

    You can listen to the [componentError](/docs/sdk/android/v2.x.x/primer-headless-checkout/klarna-headless-manager/provideKlarnaComponent#param-component-error-flow-primer-error) to handle any errors that may occur during the payment flow:

    ```kotlin KOTLIN theme={"dark"}
    klarnaComponent.componentError.collectLatest { error ->
        // Handle errors (e.g., display error messages to the user)
    }
    ```

    The `componentError` is a `Flow` that emits `PrimerError` objects, allowing you to identify and respond to any errors that occur during the payment process.

    #### Troubleshooting

    #### Flaky BankId

    The Klarna direct debit flow for Sweden will try to redirect the user to the Mobile BankID app. This action is flaky when in sandbox mode & can sometimes fail
  </Tab>

  <Tab title="React Native">
    #### Pre-requisites

    Some payment methods like Klarna Direct Debit (part of Klarna's Pay Now), require manual enablement for the available markets (eg: DE, SE, NL). This is done by Klarna upon merchant request.

    #### Handle payment method

    **Integration**<br />
    [KlarnaManager](/docs/sdk/react-native/v2.x.x/primer-headless-checkout/klarna-headless-manager/constructor) is an SDK manager designed to streamline the headless integration with Klarna. To integrate `KlarnaManager`, follow these steps:

    Create a new instance of `KlarnaManagerProps`

    ```typescript Typescript theme={"dark"}
    const klarnaManagerProps: KlarnaManagerProps = {
        // Pass either PrimerSessionIntent.CHECKOUT or PrimerSessionIntent.VAULT, depending on the session type you'd like to create.
        primerSessionIntent: PrimerSessionIntent.CHECKOUT,
        onStep: (data: KlarnaPaymentStep) => {
            // Show loading indicator, render categories or finalize payment
        },
        onError: (error: PrimerError) => {
            // An error that occurred during the component's operation.
        },
        onInvalid: (data: PrimerInvalidComponentData<KlarnaPaymentValidatableData>) => {
            // Data was considered invalid during validation.
        },
        onValid: (data: PrimerValidComponentData<KlarnaPaymentValidatableData>) => {
            // Data was successfully validated.
        },
        onValidating: (data: PrimerValidatingComponentData<KlarnaPaymentValidatableData>) => {
            // Data is in the process of being validated.
        },
        onValidationError: (data: PrimerComponentDataValidationError<KlarnaPaymentValidatableData>) => {
            // Error occurred during data validation
        },
    };
    ```

    Create a new instance of `KlarnaComponent`

    ```typescript Typescript theme={"dark"}
    const klarnaManager = new KlarnaManager();
    const klarnaComponent: KlarnaComponent = await klarnaManager.provide(klarnaManagerProps);
    ```

    Listen for the emitted data

    Make use of [KlarnaManagerProps.onStep](/docs/sdk/react-native/v2.x.x/primer-headless-checkout/klarna-headless-manager/provide#param-on-step) in order to be notified about the Klarna session state.

    ```typescript Typescript theme={"dark"}
    const klarnaManagerProps: KlarnaManagerProps = {
        ...
        onStep: (data: KlarnaPaymentStep) => {
            switch(data.stepName) {
                case "paymentSessionCreated":
                    // Emitted once the component is started via a call to the `start()` function.
                    // Render the payment categories, found in `data.paymentCategories` from here.
                    break;
                case "paymentViewLoaded":
                    // Emitted once the payment options are collected via a call to the `onSetPaymentOptions()` function. 
                    // Render the PrimerKlarnaPaymentView from here.
                    break;
                case "paymentSessionAuthorized":
                    // Emitted once the component is submitted via a call to the `submit()` function, 
                    // after the user confirms the payment via the Klarna payment screen.
                    if (data.isFinalized) {
                        // no-op
                    } else {
                        // Payment requires finalization. From this point on, you may call
                        // klarnaComponent.onFinalizePayment() to perform the finalization.
                    }
                    break;
                case "paymentSessionFinalized":
                    // Emitted once the component is submitted and payment finalization is requested 
                    // via `onFinalizePayment()`.
                    break;
            }
        },
        ...
    };
    ```

    #### Rendering the Klarna payment view

    As mentioned before, the Klarna payment view must be redender when receiving the `paymentViewLoaded` step. This payment view contains information about the selected payment category, and it must be rendered before `submit()` is called on the component.

    ```typescript Typescript theme={"dark"}
    // Import PrimerKlarnaPaymentView
    import { PrimerKlarnaPaymentView } from '@primer-io/react-native';
    ...
    // Define a hook that controls the payment view's visibility
    const [isKlarnaPaymentViewVisible, setKlarnaPaymentViewVisible] = useState<boolean>(false)
    ...
    const klarnaManagerProps: KlarnaManagerProps = {
        ...
        onStep: (data: KlarnaPaymentStep) => {
            switch(data.stepName) {
                ...
                case "paymentViewLoaded":
                    // Update the hook's state
                    setKlarnaPaymentViewVisible(true)
                    break;
                ...
            }
        },
        ...
    };
    ...
    // JSX
    // Render the payment view whenever the visible state is true. 
    // Please note that setting a 'minHeight' is mandatory for the payment view to show.
    {isKlarnaPaymentViewVisible && <PrimerKlarnaPaymentView style={{ minHeight: 250 }} />}
    ...
    ```

    Listen to the data validation statuses

    This component allows you to collect the payment options (category and return URL (Android only)), and to request payment finalization. It's worth mentioning that the data validation is designed to operate in real-time. This means that the accuracy and completeness of the collected data can be confirmed even while users are actively inputting their information. This real-time validation feature ensures that your data remains accurate and complete throughout the data entry process, enhancing the user experience and the reliability of the collected data. Use [KlarnaManagerProps](/docs/sdk/react-native/v2.x.x/primer-headless-checkout/klarna-headless-manager/provide#param-on-step) validation callbacks to handle any validation statuses that may occur.

    ```typescript Typescript theme={"dark"}
    const klarnaManagerProps: KlarnaManagerProps = {
        ...
        onInvalid: (data: PrimerInvalidComponentData<KlarnaPaymentValidatableData>) => {
            // Data was considered invalid during validation, perhaps display an error message to the user.
            switch(data.data.validatableDataName) {
                case 'klarnaPaymentOptions': 
                    // ...
                    break;
                case 'klarnaPaymentFinalization': 
                    // ...
                    break;
            }
        },
        onValid: (data: PrimerValidComponentData<KlarnaPaymentValidatableData>) => {
            // Data was successfully validated, perhaps enable a submission button.
            switch(data.data.validatableDataName) {
                case 'klarnaPaymentOptions': 
                    // ...
                    break;
                case 'klarnaPaymentFinalization': 
                    // ...
                    break;
            }
        },
        onValidating: (data: PrimerValidatingComponentData<KlarnaPaymentValidatableData>) => {
            // Data is in the process of being validated, perhaps show a progress view.
            switch(data.data.validatableDataName) {
                case 'klarnaPaymentOptions': 
                    // ...
                    break;
                case 'klarnaPaymentFinalization': 
                    // ...
                    break;
            }
        },
        onValidationError: (data: PrimerComponentDataValidationError<KlarnaPaymentValidatableData>) => {
            // Error occurred during data validation, perhaps display an error message to the user.
            switch(data.data.validatableDataName) {
                case 'klarnaPaymentOptions': 
                    // ...
                    break;
                case 'klarnaPaymentFinalization': 
                    // ...
                    break;
            }
        },
    };
    ```

    Start the flow of the component
    Call the [start](/docs/sdk/react-native/v2.x.x/primer-headless-checkout/klarna-headless-manager/provide#param-start) function in order to start the flow of the component.

    ```typescript Typescript theme={"dark"}
    klarnaComponent.start()
    ```

    Once called, the Klarna session will be created and the `PaymentSessionCreated` step will be emitted. As mentioned previously, the `PaymentSessionCreated` step contains information about the available Klarna categories. Use these categories to build a category selection user interface. Clicking on any such category should update the payment options via [onSetPaymentOptions](/docs/sdk/react-native/v2.x.x/primer-headless-checkout/klarna-headless-manager/provide#param-on-set-payment-options), as described below.

    **Handle data collection**<br />
    As mentioned previously, the component allows you to collect the payment options (category and return URL (Android only)), and to request payment finalization.

    Update your Android module by creating a deeplink activity and defining it in your `AndroidManifest.xml` with the appropriate [intent filter](https://developer.android.com/guide/components/intents-filters):

    ```xml XML theme={"dark"}
    <activity
        android:name=".DeeplinkReturnActivity"
        android:exported="true"
        android:launchMode="singleTop">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="app" />
            <data android:host="deeplink.return.activity" />
        </intent-filter>
    </activity>
    ```

    Define your deeplink return activity implementation with the desired behavior, such as navigating to your app's main activity:

    ```kotlin KOTLIN theme={"dark"}
    class DeeplinkReturnActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            val intent = Intent(this, MainActivity::class.java)
            startActivity(intent)
            finish()
        }
    }
    ```

    Payment options should be set before submitting the component via the [submit](/docs/sdk/react-native/v2.x.x/primer-headless-checkout/klarna-headless-manager/provide#param-submit) function:

    ```typescript Typescript theme={"dark"}
    function updatePaymentOptions() {
        try {
            const klarnaPaymentCategory = getSelectedPaymentCategory();
            await klarnaComponent.onSetPaymentOptions(
                {
                    /*
                    * Built from the deeplink activity's intent filter scheme and host. 
                    * This will be used by third-party apps to link back to your app on Android devices.
                    */
                    returnIntentUrl: "app://deeplink.return.activity.rn",
                    paymentCategory: klarnaPaymentCategory
                }
            );
        } catch (err) {
            console.error(err);
        }
    }
    function getSelectedPaymentCategory() : KlarnaPaymentCategory {
        // Return the payment category selected by the user
    }
    ```

    Payment finalization should be requested after the payment is authorized and if and only if finalization is required, otherwise you'll get validation errors. That is, when `PaymentSessionAuthorized` is emitted as step, and `PaymentSessionAuthorized.isFinalized` returns `false`:

    ```typescript Typescript theme={"dark"}
    klarnaComponent.onFinalizePayment();
    ```

    When the collected payment options are deemed valid, as determined by a call to [KlarnaManagerProps.onValid](/docs/sdk/react-native/v2.x.x/primer-headless-checkout/klarna-headless-manager/provide#param-on-valid), call the [submit](/docs/sdk/react-native/v2.x.x/primer-headless-checkout/klarna-headless-manager/provide#param-submit) will display the Klarna payment window. Successfully confirming the payment via this window will lead to the emission of the `PaymentSessionAuthorized` step.

    ```typescript Typescript theme={"dark"}

    klarnaComponent.submit()
    ```

    #### Handle errors

    Make use of [KlarnaManagerProps.onError](/docs/sdk/react-native/v2.x.x/primer-headless-checkout/klarna-headless-manager/provide#param-on-error) to handle any errors that may occur during the payment flow:

    ```typescript Typescript theme={"dark"}
    const klarnaManagerProps: KlarnaManagerProps = {
        ...
        onError: (error: PrimerError) => {
            // An error that occurred during the component's operation, perhaps display an error message to the user.
        },
        ...
    };
    ```

    The `componentError` is a `Flow` that emits `PrimerError` objects, allowing you to identify and respond to any errors that occur during the payment process.

    #### Troubleshooting

    #### Flaky BankId

    The Klarna direct debit flow for Sweden will try to redirect the user to the Mobile BankID app. This action is flaky when in sandbox mode & can sometimes fail
  </Tab>
</Tabs>

## Vaulting

In order to vault Klarna accounts, pass the following data in the Client Session:

| Parameter Name                                                                                              | Required | Description                           |
| ----------------------------------------------------------------------------------------------------------- | -------- | ------------------------------------- |
| [customerId](/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session#body-customer-id) | ✓        | A unique identifier for your customer |

### Prepare the SDK for vaulting

<Tabs>
  <Tab title="Web">
    ```javascript JS theme={"dark"}
    await createHeadless(clientToken, {
    klarna: {
        paymentFlow: PaymentFlow.PREFER_VAULT,
        recurringPaymentDescription: "<description>"
    }
    })
    ```
  </Tab>

  <Tab title="iOS">
    Klarna requires a [Native UI Manager](/docs/checkout/headless/#native-ui-manager) in order to be presented to the user.

    Pass `PrimerSessionItent.VAULT` for Klarna to be vaulted.

    ```swift SWIFT theme={"dark"}
    // 👇 Create the payment method manager
    let nativeUIPaymentMethodManager = try PrimerHeadlessUniversalCheckout.NativeUIManager(paymentMethodType: "KLARNA")
    // 👇 Show the payment method
    try nativeUIPaymentMethodManager.showPaymentMethod(intent: .vault)
    ```
  </Tab>

  <Tab title="Android">
    Klarna requires a [Native UI Manager](/docs/checkout/headless/#native-ui-manager) in order to be presented to the user.

    Pass `PrimerSessionItent.VAULT` for Klarna to be vaulted.

    ```kotlin KOTLIN theme={"dark"}
    // 👇 Create the payment method manager
    val nativeUiManager = PrimerHeadlessUniversalCheckoutNativeUiManager.newInstance("KLARNA")
     
    // 👇 Show the payment method
    nativeUiManager.showPaymentMethod(this, PrimerSessionIntent.VAULT)
    ```
  </Tab>
</Tabs>

## Test

Visit [Klarna Sample Data Page](https://docs.klarna.com/resources/test-environment/sample-customer-data/) for testing the integration against the Klarna Playground environment.

## Go live

You don't need to do anything particular to go live — just make sure to use production credentials.
