Klarna Payments with Sources Public Beta

    Use Sources to accept payments using Klarna, a popular European payment method.

    Stripe users in Europe and the United States can accept Klarna payments using Sources—a single integration path for creating payments using any supported method.

    During the payment process, a Source object is created and your customer is either presented with a Klarna widget or redirected to a Klarna Hosted Payment Page that displays payment options, including Pay now, Pay later, and Slice it. Your integration then uses the source to make a charge request and complete the payment.

    Within the scope of Sources, Klarna is a push-based, single-use and synchronous or asynchronous method of payment.

    U.S. users can accept payments from U.S. customers, and European users can accept payments from customers in the following countries:

    Purchase Country Country Code Currency
    Austria AT EUR
    Denmark DK DKK
    Finland FI EUR
    Germany DE EUR
    Netherlands NL EUR
    Norway NO NOK
    Sweden SE SEK
    United Kingdom GB GBP

    Step 1: Create a Source object

    A Source object is either created client-side using Stripe.js or server-side using the Source creation endpoint. Updatable fields enable you to create a source without providing personally identifiable information (PII), which must be added later using a source update once the customer selects Klarna as a payment option.

    Parameter Value
    type klarna
    amount A positive integer in the smallest currency unit representing the amount to charge the customer (e.g., 1099 for a €10.99 payment).
    currency The currency the payment is being created in. Supported values are eur, sek, nok, dkk, gbp, usd. This must be the default currency of your customer's billing address country.
    klarna[product] payment
    klarna[purchase_country] The ISO-3166 2-letter country code of the customer's location.
    source_order[items] The order object associated with this payment with. The order items amounts must add up to the amount of the source.
    owner[email] updatable The email address of the customer.
    owner[address] updatable The billing address of the customer.
    klarna[first_name] updatable The first name of the customer (Klarna requires the customer's name to be passed as separate first and last name values).
    klarna[last_name] updatable The last name of the customer.
    source_order[shipping][address] updatable The shipping address of the customer. Only required if a physical product is being sold that must be shipped
    source_order[shipping][carrier] updatable The delivery service used to ship a physical product, such as FedEx, UPS, USPS, etc.
    source_order[shipping][tracking_number] optional The tracking number obtained from the delivery service. If multiple tracking numbers were generated for this purchase, please separate them with commas.
    source_order[shipping][phone] optional Recipient phone (including extension).
    klarna[shipping_first_name] updatable The first name used on the shipping address (Klarna requires the shipping name to be passed as separate first and last name values).
    klarna[shipping_last_name] updatable The last name used on the shipping address.
    klarna[locale] optional Format locales as a language tag consisting of a two-letter language code combined with a two-letter country code, according to RFC 1766. Examples are en-us for U.S. English, en-gb for British English, and sv-se for Swedish (in Sweden). (RFC1766).

    To create a Klarna source, call stripe.createSource() with the relevant details:

    stripe.createSource({
      type: 'klarna',
      amount: 816,
      currency: 'eur',
      klarna: {
        product: 'payment',
        purchase_country: 'DE',
      },
      source_order: {
        items: [{
    See all 30 lines type: 'sku', description: 'Grey cotton T-shirt', quantity: 2, currency: 'eur', amount: 796, }, { type: 'tax', description: 'Taxes', currency: 'eur', amount: 20, }, { type: 'shipping', description: 'Free Shipping', currency: 'eur', amount: 0, }], }, }).then(function(result) { // handle result.error or result.source });

    Using either server-side or client-side source creation, Stripe returns a Source object containing the relevant details for the method of payment used. Information specific to Klarna is provided within the klarna subhash.

    {
      "id": "src_16xhynE8WzK49JbAs9M21jaR",
      "object": "source",
      "amount": 1099,
      "client_secret": "src_client_secret_qxC8aTQt9mSnwh29lLgP9pfb",
      "created": 1445277809,
      "currency": "eur",
      "flow": "none",
      "klarna": {
        "locale": "de-DE",
    See all 48 lines "purchase_country": "DE", "client_token": "eyJhbGciOiJub25lIn0...", "pay_later_asset_urls_descriptive": "https://cdn.klarna.com/1.0/shared/image/generic/badge/en_gb/pay_later/descriptive/pink.svg", "pay_later_asset_urls_standard": "https://cdn.klarna.com/1.0/shared/image/generic/badge/en_gb/pay_later/standard/pink.svg", "pay_later_name": "Pay later.", "pay_now_asset_urls_descriptive": "https://cdn.klarna.com/1.0/shared/image/generic/badge/en_gb/pay_now/descriptive/pink.svg", "pay_now_asset_urls_standard": "https://cdn.klarna.com/1.0/shared/image/generic/badge/en_gb/pay_now/standard/pink.svg", "pay_now_name": "Pay now.", "pay_over_time_asset_urls_descriptive": "https://cdn.klarna.com/1.0/shared/image/generic/badge/en_gb/slice_it/descriptive/pink.svg", "pay_over_time_asset_urls_standard": "https://cdn.klarna.com/1.0/shared/image/generic/badge/en_gb/slice_it/standard/pink.svg", "pay_over_time_name": "Slice it.", "payment_method_categories": "pay_later,pay_now,pay_over_time" }, "livemode": true, "source_order": { "items": [{ "type": "sku", "description": "Grey cotton T-shirt", "quantity": 2, "currency": "eur", "amount": 796 }, { "type": "tax", "description": "Taxes", "currency": "eur", "amount": 20 }, { "type": "shipping", "description": "Free Shipping", "currency": "eur", "amount": 0 }], }, "statement_descriptor": null, "status": "pending", "type": "klarna", "usage": "single_use" }

    Error codes

    Source creation for Klarna payments may return any of the following errors:

    Error Description
    payment_method_not_available The payment method is currently not available. Invite your customer to fallback to another payment method to proceed.
    processing_error An unexpected error prevented us from creating the source. Retry source creation.
    missing_sku_item_quantity The SKU provided in the order is missing a quantity value.
    country_not_supported The country is not supported for the currency being used.
    invalid_currency The currency is not supported.
    invalid_email The owner’s email is not valid.
    invalid_phone The owner’s phone number is not valid.
    invalid_address The specified address is not valid.

    Update the source

    If customer details are not provided at source creation, these parameters must be added using a source update.

    Billing information

    Billing information is required for physical goods and, if not provided during source creation a source update is required. If billing information is not provided, Klarna will collect them during checkout but Klarna will not cover any losses that might occur due to customer disputes or fraud.

    Parameter Value
    klarna[first_name] The first name of the customer (Klarna requires the customer’s name to be passed as separate first and last name values).
    klarna[last_name] The last name of the customer.
    owner[email] The email address of the customer.
    owner[address] The billing address of the customer.

    See an example of updating a source with billing information:

    curl https://api.stripe.com/v1/sources/src_18cPLvAHEMiOZZp1YBngt6En \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d klarna[first_name]=Jenny \
      -d klarna[last_name]=Rosen \
      -d owner[email]="jenny.rosen@example.com" \
      -d owner[address][line1]="Schulstrasse 4" \
      -d owner[address][line2]= \
      -d owner[address][city]="Bad Oeynhausen" \
      -d owner[address][state]=Nordrhein-Westfalen \
      -d owner[address][postal_code]=32547 \
      -d owner[address][country]=DE
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    source = Stripe::Source.retrieve('src_18cPLvAHEMiOZZp1YBngt6En')
    source.klarna["first_name"] = "Jenny"
    source.klarna["last_name"] = "Rosen"
    source.owner["email"] = "jenny.rosen@example.com"
    source.owner["address"]["line1"] = "Schulstrasse 4"
    source.owner["address"]["line2"] = ""
    source.owner["address"]["city"] = "Bad Oeynhausen"
    source.owner["address"]["state"] = "Nordrhein-Westfalen"
    source.owner["address"]["postal_code"] = "32547"
    source.owner["address"]["country"] = "DE"
    source.save
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    source = stripe.Source.retrieve("src_18cPLvAHEMiOZZp1YBngt6En")
    source.klarna["first_name"] = "Jenny"
    source.klarna["last_name"] = "Rosen"
    source.owner["email"] = "jenny.rosen@example.com"
    source.owner["address"]["line1"] = "Schulstrasse 4"
    source.owner["address"]["line2"] = ""
    source.owner["address"]["city"] = "Bad Oeynhausen"
    source.owner["address"]["state"] = "Nordrhein-Westfalen"
    source.owner["address"]["postal_code"] = "32547"
    source.owner["address"]["country"] = "DE"
    source.save()
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    $source = StripeSource::retrieve("src_18cPLvAHEMiOZZp1YBngt6En");
    $source->klarna["first_name"] = "Jenny"
    $source->klarna["last_name"] = "Rosen"
    $source->owner["email"] = "jenny.rosen@example.com"
    $source->owner["address"]["line1"] = "Schulstrasse 4"
    $source->owner["address"]["line2"] = ""
    $source->owner["address"]["city"] = "Bad Oeynhausen"
    $source->owner["address"]["state"] = "Nordrhein-Westfalen"
    $source->owner["address"]["postal_code"] = "32547"
    $source->owner["address"]["country"] = "DE"
    $source->owner["email"] = "amount_2424@rosen.net";
    $source->save();
    

    Shipping information

    If selling a physical product that must be shipped, shipping information is required. If not provided during creation, shipping information should be provided in a source update.

    Parameter Value
    klarna[shipping_first_name] The first name used on the shipping address (Klarna requires the shipping name to be passed as separate first and last name values).
    klarna[shipping_last_name] The last name used on the shipping address.
    source_order[shipping][phone] Recipient phone (including extension).
    source_order[shipping][address] The shipping address of the customer.

    See an example of updating a source with shipping information:

    curl https://api.stripe.com/v1/sources/src_18cPLvAHEMiOZZp1YBngt6En \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d klarna[shipping_first_name]=Jenny \
      -d klarna[shipping_last_name]=Rosen \
      -d source_order[shipping][phone]="(0xx) xxxx-xxxx" \
      -d source_order[shipping][address][line1]="Schulstrasse 4" \
      -d source_order[shipping][address][line2]= \
      -d source_order[shipping][address][city]="Bad Oeynhausen" \
      -d source_order[shipping][address][state]=Nordrhein-Westfalen \
      -d source_order[shipping][address][postal_code]=32547 \
      -d source_order[shipping][address][country]=DE
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    source = Stripe::Source.retrieve('src_18cPLvAHEMiOZZp1YBngt6En')
    source.klarna["shipping_first_name"] = "Jenny"
    source.klarna["shipping_last_name"] = "Rosen"
    source.source_order["shipping"]["phone"] = "(0xx) xxxx-xxxx"
    source.source_order["shipping"]["address"]["line1"] = "Schulstrasse 4"
    source.source_order["shipping"]["address"]["line2"] = ""
    source.source_order["shipping"]["address"]["city"] = "Bad Oeynhausen"
    source.source_order["shipping"]["address"]["state"] = "Nordrhein-Westfalen"
    source.source_order["shipping"]["address"]["postal_code"] = "32547"
    source.source_order["shipping"]["address"]["country"] = "DE"
    source.save
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    source = stripe.Source.retrieve("src_18cPLvAHEMiOZZp1YBngt6En")
    source.klarna["shipping_first_name"] = "Jenny"
    source.klarna["shipping_last_name"] = "Rosen"
    source.source_order["shipping"]["phone"] = "(0xx) xxxx-xxxx"
    source.source_order["shipping"]["address"]["line1"] = "Schulstrasse 4"
    source.source_order["shipping"]["address"]["line2"] = ""
    source.source_order["shipping"]["address"]["city"] = "Bad Oeynhausen"
    source.source_order["shipping"]["address"]["state"] = "Nordrhein-Westfalen"
    source.source_order["shipping"]["address"]["postal_code"] = "32547"
    source.source_order["shipping"]["address"]["country"] = "DE"
    source.save()
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    $source = StripeSource::retrieve("src_18cPLvAHEMiOZZp1YBngt6En");
    $source->klarna["shipping_first_name"] = "Jenny"
    $source->klarna["shipping_last_name"] = "Rosen"
    $source->source_order["shipping"]["phone"] = "(0xx) xxxx-xxxx"
    $source->source_order["shipping"]["address"]["line1"] = "Schulstrasse 4"
    $source->source_order["shipping"]["address"]["line2"] = ""
    $source->source_order["shipping"]["address"]["city"] = "Bad Oeynhausen"
    $source->source_order["shipping"]["address"]["state"] = "Nordrhein-Westfalen"
    $source->source_order["shipping"]["address"]["postal_code"] = "32547"
    $source->source_order["shipping"]["address"]["country"] = "DE"
    $source->owner["email"] = "amount_2424@rosen.net";
    $source->save();
    

    Tracking information

    Additionally, to assist Klarna with any customer requests about a physical shipment, you can update the source to include tracking information.

    Parameter Value
    source_order[shipping][carrier] The delivery service used to ship a physical product, such as FedEx, UPS, USPS, etc.
    source_order[shipping][tracking_number] The tracking number obtained from the delivery service. If multiple tracking numbers were generated for this purchase, please separate them with commas.

    Here is an example of how to update a source with tracking information:

    curl https://api.stripe.com/v1/sources/src_18cPLvAHEMiOZZp1YBngt6En \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d source_order[shipping][carrier]=UPS \
      -d source_order[shipping][tracking_number]=1Z999AA10123456784
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    source = Stripe::Source.retrieve('src_18cPLvAHEMiOZZp1YBngt6En')
    source.source_order["shipping"]["carrier"] = "UPS"
    source.source_order["shipping"]["tracking_number"] = "1Z999AA10123456784"
    source.save
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    source = stripe.Source.retrieve("src_18cPLvAHEMiOZZp1YBngt6En")
    source.source_order["shipping"]["carrier"] = "UPS"
    source.source_order["shipping"]["tracking_number"] = "1Z999AA10123456784"
    source.save()
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    $source = StripeSource::retrieve("src_18cPLvAHEMiOZZp1YBngt6En");
    $source->source_order["shipping"]["carrier"] = "UPS"
    $source->source_order["shipping"]["tracking_number"] = "1Z999AA10123456784"
    $source->owner["email"] = "amount_2424@rosen.net";
    $source->save();
    

    Step 2: Authorize the payment with Klarna

    When you create a source, its status is initially set to pending and it can’t yet be used to make a charge request. The payment must first be submitted to Klarna for authorization. Once authorized, the source becomes chargeable.

    To load the Klarna widget and verify that a payment has been authorized, use the Klarna JavaScript SDK:

    1. Add the SDK to your checkout page and initialize it using Klarna.Payments.init() with the value from source.klarna.client_token.
    2. Load a widget for each category, using Klarna.Payments.load() and a value for container to specify the DOM element where you want the widget rendered. Categories are different payment options Klarna offers. See the list of values you can pass for category in load() in source.klarna.payment_method_categories. The response from load() includes show_form: true/false, which indicates whether the Klarna payment option should remain available, based on Klarna’s risk assessment.
    3. Use Klarna.Payments.authorize() to submit the payment with the selected category to Klarna for authorization.
    <script>
    // Load the Klarna JavaScript SDK
    window.klarnaAsyncCallback = function () {
    
      // Initialize the SDK
      Klarna.Payments.init({
        client_token: source.klarna.client_token,
      });
    
      // Load the widget for each payment method category:
      // - pay_later
      // - pay_over_time
      // - pay_now
      var available_categories = source.klarna.payment_method_categories.split(',');
      for (var category of available_categories) {
        Klarna.Payments.load({
          container: "#klarna_" + category + "_container",
          payment_method_categories: [category],
          instance_id : "klarna-payments-instance-" + category
        }, function(res) {
          if (res.show_form) {
            /*
        	* this payment method category can be used, allow the customer
        	* to choose it in your interface.
            */
          } else {
            // this payment method category is not available
          }
        });
      }
    };
    
    document.getElementByID("pay-button").addEventListener("click", function(){
      // get the category the customer chose(using your own code)
      var selectedCategory = getSelectedCategory();
      // Submit the payment for authorization with the selected category
      Klarna.Payments.authorize({
        instance_id : "klarna-payments-instance-" + selectedCategory
      }, function(res) {
        if (res.approved) {
          // Payment has been authorized
        } else {
          if (res.error) {
            // Payment not authorized or an error has occurred
          } else {
            // handle other states
          }
        }
      })
    });
    
    </script>
    <script src="https://x.klarnacdn.net/kp/lib/v1/api.js" async></script>
    

    As the customer interacts with the Klarna widget, they may be asked for additional information, depending on the jurisdiction they are in.

    If an attempt to authorize a payment fails, that category is removed from the list of available payment_method_categories on the source, and reloading the Klarna widget will return show_form: false. The source status will stay pending until the the last method is failed, this will cause the source status to become failed.

    Styling the Klarna widget

    You can customize the style of the widget by providing additional options when loading the widget. Refer to the Klarna SDK documentation for more information.

    Testing the authorization process

    When creating a Source object using your test API keys, use the returned klarna[client_token] with the same Klarna SDK. With a test client token, the Klarna widget does not request any additional customer information as part of the authorization process. The test source then becomes chargeable and can be used to create a test charge. When using test API keys, there is no credit issuance nor any money movement happening. It is always safe to interact with test client tokens.

    If you haven’t already built your integration, we also provide a Klarna test payments page that embeds the Klarna widget. Use this to test the flow with test client tokens and make test sources chargeable.

    Step 2a: Authorizing the payment using a redirect

    As an alternative to their recommended widget-based authorization, Klarna also supports a full-redirect authorization specifically designed for both desktop and mobile experiences. To leverage the redirect flow, you create the source using these additional arguments:

    Parameter Value  
    flow   redirect
    redirect[return_url]   The URL the customer should be redirected to after the authorization process.
    stripe.createSource({
      type: 'klarna',
      flow: 'redirect',
      redirect: {
        return_url: 'https://shop.example.com/crtA6B28E1',
      },
      // ...
    }).then(function(result) {
      // handle result.error or result.source
    });
    

    When flow is set to redirect, Stripe returns a Source of flow redirect. To allow your customer to authorize the payment, redirect them to one of the URLs provided within the Source object, eg: klarna[pay_later_redirect_url], klarna[pay_over_time_redirect_url] or klarna[pay_now_redirect_url].

    If the customer is redirected to redirect[url], Pay later will be used if it’s available.

    {
      "id": "src_16xhynE8WzK49JbAs9M21jaR",
      "object": "source",
      "amount": 1099,
      "client_secret": "src_client_secret_qxC8aTQt9mSnwh29lLgP9pfb",
      "created": 1445277809,
      "currency": "eur",
      "flow": "redirect",
      "klarna": {
        "locale": "de-DE",
    See all 57 lines "purchase_country": "DE", "client_token": "eyJhbGciOiJub25lIn0...", "pay_later_asset_urls_descriptive": "https://cdn.klarna.com/1.0/shared/image/generic/badge/en_gb/pay_later/descriptive/pink.svg", "pay_later_asset_urls_standard": "https://cdn.klarna.com/1.0/shared/image/generic/badge/en_gb/pay_later/standard/pink.svg", "pay_later_name": "Pay later.", "pay_later_redirect_url": "https://payment-eu.playground.klarna.com/92f40096-14ef-47f8-b1db-a25d79088f09", "pay_now_asset_urls_descriptive": "https://cdn.klarna.com/1.0/shared/image/generic/badge/en_gb/pay_now/descriptive/pink.svg", "pay_now_asset_urls_standard": "https://cdn.klarna.com/1.0/shared/image/generic/badge/en_gb/pay_now/standard/pink.svg", "pay_now_name": "Pay now.", "pay_now_redirect_url": "https://payment-eu.playground.klarna.com/fa903e22-0771-43ef-a5a1-8245bc02e5c2", "pay_over_time_asset_urls_descriptive": "https://cdn.klarna.com/1.0/shared/image/generic/badge/en_gb/slice_it/descriptive/pink.svg", "pay_over_time_asset_urls_standard": "https://cdn.klarna.com/1.0/shared/image/generic/badge/en_gb/slice_it/standard/pink.svg", "pay_over_time_name": "Slice it.", "pay_over_time_redirect_url": "https://payment-eu.playground.klarna.com/99d9e1a9-987f-419c-8ff3-4616430c2e1e", "payment_method_categories": "pay_later,pay_now,pay_over_time" }, "livemode": true, "source_order": { "items": [{ "type": "sku", "description": "Grey cotton T-shirt", "quantity": 2, "currency": "eur", "amount": 796 }, { "type": "tax", "description": "Taxes", "currency": "eur", "amount": 20 }, { "type": "shipping", "description": "Free Shipping", "currency": "eur", "amount": 0 }] }, "redirect": { "failure_reason": null, "return_url": "https://stripe.com/?klarna_success", "status": "pending", "url": "https://hooks.stripe.com/redirect/authenticate/src_1CvChHKEwn3PiWD029TfqA2o?client_secret=src_client_secret_DLuWEaOt5U3Bv6EGsef56ULE" }, "statement_descriptor": null, "status": "pending", "type": "klarna", "usage": "single_use" }

    After the authorization process, your customer is redirected back to the URL provided as the value of redirect[return_url]. This happens regardless of authorization success or failure. Stripe appends redirect[return_url] with a redirect_status parameter, with the following potential values:

    Value Description Suggested Action
    canceled The customer abandoned the payment flow. Reload the checkout page with the same options
    failed The customer was not eligible for the selected Klarna method. Reload the checkout page with the remaining eligible Klarna payment_method_categories

    If the customer authorizes the payment, the Source object’s status transitions to chargeable when it is ready to be used in a charge request. If your customer declines the payment and no other payment_method_categories are available, the status transitions to failed.

    Styling the Klarna Hosted Payment Page

    You can customize the style of the Klarna hosted payment page by providing addtional options when creating the source, such as purchase_type. Refer to the Klarna SDK documentation for more information.

    Parameter   Value
    logo_url optional A public URL for your businesses logo, must be served over HTTPS.
    background_image_url optional A public URL for a background image, must be served over HTTPS.
    page_title optional Title displayed on the top of the Klarna Hosted Payment Page.
    purchase_type optional The buy button type, accepted values are buy, rent, book, subscribe, download, order, continue.

    Testing the redirect process

    When creating a Source object using your test API keys, follow any one of the URLs returned in the klarna[***_redirect_url] field. This leads to a Klarna page that displays information about the test payment, where you can either authorize or cancel the payment. Authorizing the payment redirects you to the URL specified in redirect[return_url] but doesn’t attempt to charge or contact the customer.

    Step 3: Charge the source

    Once Klarna authorizes the payment, the source’s status transitions to chargeable and it can be used to make a charge request.

    Since that transition happens asynchronously, it is essential that your integration rely on webhooks to determine when the source becomes chargeable in order to create a charge. Please refer to our best practices for more details on how to best integrate payment methods using webhooks.

    Webhooks

    The following webhook events are also sent to notify you about changes to the source’s status:

    Event Description
    source.chargeable A source object becomes chargeable after it has been authorized by Klarna.
    source.failed A source object failed to become chargeable.
    source.canceled A source object expired and cannot be used to create a charge.

    Make a charge request to finalize the authorization

    Once the source is chargeable, from your source.chargeable webhook handler, you can make a charge request using the source ID as the value for the source parameter to complete the payment. The amount must match the Source object’s amount.

    When selling physical goods, you should pass the capture: false flag to the charge request to let Klarna know that you’re working on fulfilling the order. Once all items have been shipped, send a capture request to let Klarna know that the order has been fulfilled. Note that the order must be fulfilled within 28 days. Only one capture, less than or equal to the charge amount, is permitted. Any remaining amount will be released back to the customer.

    curl https://api.stripe.com/v1/charges \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d amount=1099 \
      -d currency=eur \
      -d capture=false \
      -d source=src_18eYalAHEMiOZZp1l9ZTjSU0
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    charge = Stripe::Charge.create({
      amount: 1099,
      currency: 'eur',
      source: 'src_18eYalAHEMiOZZp1l9ZTjSU0',
    })
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    charge = stripe.Charge.create(
      amount=1099,
      currency='eur',
      source='src_18eYalAHEMiOZZp1l9ZTjSU0',
    )
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    $charge = \Stripe\Charge::create([
      'amount' => 1099,
      'currency' => 'eur',
      'source' => 'src_18eYalAHEMiOZZp1l9ZTjSU0',
    ]);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("amount", 1099);
    params.put("currency", "eur");
    params.put("source", "src_18eYalAHEMiOZZp1l9ZTjSU0");
    
    Charge charge = Charge.create(params);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    stripe.charges.create({
      amount: 1099,
      currency: 'eur',
      source: 'src_18eYalAHEMiOZZp1l9ZTjSU0',
    }, function(err, charge) {
      // asynchronously called
    });
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    chargeParams := &stripe.ChargeParams{
      Amount: stripe.Int64(1099),
      Currency: stripe.String(string(stripe.CurrencyEUR)),
    }
    chargeParams.SetSource("src_18eYalAHEMiOZZp1l9ZTjSU0")
    ch, err := charge.New(chargeParams)
    

    Klarna Sources are single-use and cannot be used for recurring or additional payments. Refer to our Sources & Customers guide for more information on how single-use Source objects interact with Customer objects.

    Optional: Authorizing the payment and capturing immediately

    By omitting the capture parameter or sending capture: true, Klarna assumes that the order is immediately fulfilled. This is handy if you’re selling digital goods.

    Step 4: Confirm that the charge has succeeded

    Klarna is asynchronous for payments made by customers in the UK and U.S., and synchronous otherwise. When async, the Charge object’s status remains in a pending state for up to 24 hours from its creation. Once the charge is confirmed—and the funds guaranteed—its status is updated to succeeded.

    All other supported countries are synchronously approved. The Charge object’s status immediately reflects whether or not it has succeeded.

    One of the following events is sent when the charge’s status is updated:

    Event Description
    charge.succeeded The charge succeeded and the payment is complete.
    charge.failed The charge has failed and the payment could not be completed.

    We recommend that you rely on the charge.succeeded webhook event to notify your customer that the payment process has been completed and their order is confirmed. Please refer to our best practices for more details on how to best integrate payment methods using webhooks.

    Stop payment

    Klarna may request additional information relating to high risk orders and in some cases require that you cancel and create a refund for orders that haven’t shipped. Generally, failure to respond within 24 hours may result in a dispute at a later date. Refer to the Klarna shipping policies for more details.

    Refunds

    Payments made with Klarna can only be submitted for refund within 180 days from the date of the original charge. After 180 days, it is no longer possible to refund the charge.

    Klarna supports both full and partial refunds. When you create a refund for the full amount of the charge, the Klarna order is voided, and if funds had been moved by the customer, Klarna will return these funds. You can also issue multiple partial refunds, up to the amount of the original charge. A partial refund will update the Klarna order to reflect the new total amount, and if funds were moved by the customer, Klarna will return the difference.

    You can submit a refund against charges that are still pending and have not yet been confirmed. If you create a full or partial refund on a pending charge, the refund is performed only after the charge’s status is transitioned to succeeded. In the event of the charge transitioning to status failed, full and partial refunds are marked as canceled, as the money never left the customer’s bank account.

    Disputes

    Klarna may initiate a dispute if the customer claims that you haven’t delivered the relevant goods or services as expected. Before initiating a dispute, Klarna will contact you via email, providing details of the customer’s claim. Klarna may request additional information in order to resolve it. If Klarna ultimately rules in favor of the customer, they may initiate a dispute.

    If Klarna creates a dispute, a dispute.created webhook event is sent and Stripe deducts the amount of the dispute from your Stripe balance.

    Klarna disputes are final and there is no appeal process.

    Source expiration

    A source must be used within one hour of becoming chargeable. If unused after an hour, its status automatically transitions to canceled and your integration receives a source.canceled webhook event.

    Testing Klarna payments

    Use one of the following test email addresses to test Klarna payments under various conditions.

    Email Description
    pending_denied@klarna.com Source creation is successful. Attempting to authorize the payment or following the redirect will be denied, causing the source to become failed.
    pending_accepted@klarna.com Source creation is successful. Charge creation is successful.
    Email Description
    pending_denied@klarna.com Source creation is successful. Attempting to authorize the payment or following the redirect will be denied, causing the source to become failed.
    pending_accepted@klarna.com Source creation is successful. Charge creation is successful.
    Email Description
    pending_denied@klarna.com Source creation is successful. Attempting to authorize the payment or following the redirect will be denied, causing the source to become failed.
    pending_accepted@klarna.com Source creation is successful. Charge creation is successful.
    Email Description
    pending_denied@klarna.com Source creation is successful. Attempting to authorize the payment or following the redirect will be denied, causing the source to become failed.
    pending_accepted@klarna.com Source creation is successful. Charge creation is successful.
    Email Description
    pending_denied@klarna.com Source creation is successful. Attempting to authorize the payment or following the redirect will be denied, causing the source to become failed.
    pending_accepted@klarna.com Source creation is successful. Charge creation is successful.
    Email Description
    pending_denied@klarna.com Source creation is successful. Attempting to authorize the payment or following the redirect will be denied, causing the source to become failed.
    pending_accepted@klarna.com Source creation is successful. Charge creation is successful.
    Email Description
    pending_denied@klarna.com Source creation is successful. Attempting to authorize the payment or following the redirect will be denied, causing the source to become failed.
    pending_accepted@klarna.com Source creation is successful. Charge creation is successful.

    No test emails for Swiss customers.

    Email Description
    test+require_signup@example.com During authorization of pay_over_time, Klarna prompts for the customer to sign up. Otherwise, it assumes it's a returning customer.
    test+red@example.com During authorization, the Klarna widget returns show_form: false for all methods. Following a redirect shows "Option not available".
    test+denied@stripe.com Using the Klarna SDK to call authorize displays "Your purchase can not be accepted" for all methods. Submitting the form on the Klarna Hosted Payment Page displays the same message.
    test+pend-accept-3@example.com The status of a charge created with this source is initially set to pending, then transitions to successful after about 3 minutes.
    test+pend-reject-3@example.com The status of a charge created with this source is initially set to pending, then transitions to failed after about 3 minutes.
    Email Description
    test+require_signup@example.com During authorization of pay_over_time, Klarna prompts the customer to sign up. Otherwise it assumes it's a returning customer.
    test+red@example.com During authorization, the Klarna widget returns show_form: false for all methods. Following a redirect shows "Option not available".
    test+denied@stripe.com Using the Klarna SDK to call authorize displays "Your purchase can not be accepted" for all methods. Submitting the form on the Klarna Hosted Payment Page displays the same message.
    test+pend-accept-3@example.com The status of a charge created with this source is initially set to pending, then transitions to successful after about 3 minutes.
    test+pend-reject-3@example.com The status of a charge created with this source is initially set to pending, then transitions to failed after about 3 minutes.

    A sample set of credit repayment options is provided for testing purposes while you develop your Klarna integration. Once your integration is live, a complete set of repayment options becomes available.

    Related resources

    Questions?

    We're always happy to help with code or other questions you might have. Search our documentation, contact support, or connect with our sales team. You can also chat live with other developers in #stripe on freenode.

    Was this page helpful? Yes No

    Send

    Thank you for helping improve Stripe's documentation. If you need help or have any questions, please consider contacting support.

    On this page