Skip to content
Saleor
Esc
↑↓navigate↵open⌘Jpreview
On this page

Stripe Plugin

Stripe plugin uses custom payment flow to process customer transactions.

Configuration

Go to Configuration -> Plugins -> Stripe and fill in the fields:

  • Public API key: your Stripe public API key. See Stripe’s docs

  • Supported currencies: your currency as an ISO 4217 3-letter code (eg. USD, EUR, GBP)

  • Automatic payment capture: If enabled, Saleor will automatically capture funds. If disabled, the funds are blocked but need to be captured manually.

  • Restricted API key: your Stripe restricted API key. See Stripe’s docs. It should contain following permissions to work:

    • Payment Intent: Write
    • Customers: Write
    • All Webhook: Write
    • Charges: Write

Activating Stripe webhooks

By activating Stripe integration, Saleor will automatically subscribe to Stripe’s webhooks, as a result Webhook endpoint field will receive an id of the subscription which allows identifying a webhook on Stripe’s dashboard side.

Creating payment in Saleor

To create a payment properly, you need to follow the steps described in Creating a checkout session and Selecting a shipping method.

The payment flow would follow these steps:

Available payment gateways can be listed from the Checkout.availablePaymentGateways field:

query {
  checkout(id: "Q2hlY2tvdXQ6ZTEzZDFjOTItOWJkNi00ODViLTgyMDctZTNhM2I5NjVkZTQw") {
    availablePaymentGateways {
      id
      name
      config {
        field
        value
      }
    }
  }
}

Response:

{
  "data": {
    "checkout": {
      "availablePaymentGateways": [
        {
          "id": "mirumee.payments.stripe",
          "name": "Stripe",
          "config": [
            {
              "field": "api_key",
              "value": "pk_test_SkWEusCNFdSgxGGmd23z7JC1FHh3uNufNuX"
            },
            {
              "field": "store_customer_card",
              "value": "false"
            }
          ]
        },
        {
          "id": "mirumee.payments.dummy",
          "name": "Dummy",
          "config": [
            {
              "field": "store_customer_card",
              "value": "false"
            }
          ]
        }
      ]
    }
  }
}
mutation {
  checkoutPaymentCreate(
    checkoutId: "Q2hlY2tvdXQ6MWZiMmM1OGUtN2JhMy00YmY5LWI2ZDItNWY2ZWJiN2U3ZWJj"
    input: { gateway: "saleor.payments.stripe", amount: 45.61 }
  ) {
    payment {
      id
      chargeStatus
    }
    errors {
      field
      message
    }
  }
}

Completing the checkout

The purpose of the operation is to ensure this checkout is correct. The validation consists of checking:

  1. The required addresses are valid.

  2. All selected products are in stock (while making the purchase, another user could already buy the last available item), except variants that have disabled stock tracking which can have zero or negative stock.

  3. The payment creation succeeded.

  4. No additional actions are required by the PSP.

If these are satisfied, the checkout is transformed into an order, and the customer receives a confirmation email.

After we create a payment object for the Stripe payment gateway, we can call the checkoutComplete mutation. The first call of checkoutComplete for checkout creates Stripe payment intent object.

Optionally, checkoutComplete can accept additional parameters for Stripe as fields in paymentData input:

mutation {
  checkoutComplete(
    checkoutId: "Q2hlY2tvdXQ6YjBhYTUzMWItYjc3NS00MzM3LTkxNzEtYTgzOTYwYThjMmVk"
  ) {
    order {
      id
      userEmail
      created
    }
    confirmationNeeded
    confirmationData
    errors {
      field
      message
      code
    }
  }
}

As a result, we get details required to finalize a payment.

{
  "data": {
    "checkoutComplete": {
      "order": null,
      "confirmationNeeded": true,
      "confirmationData": "{\"client_secret\": \"pi_1J2Yh3H1Vac4G4dbfuBvQhTe_secret_DkwP8jcdenirqazGpjPvSaPtV\", \"id\": \"pi_1J2Yh3H1Vac4G4dbfuBvQhTe\"}",
      "checkoutErrors": []
    }
  }
}

client_secret is required to process a customer payment. Steps required to finalize a payment transaction are described in Stripe documentation.

Finalizing a payment

When the customer finalizes a payment, Stripe sends a webhook notification with all details related to this payment. Saleor asynchronously receives the notification and completes checkout process.

On client-side, when stripe.confirmCardPayment doesn’t return an error as described here, client-side can call checkoutComplete one more time. Saleor confirms that the payment has success status and returns an order object.

mutation {
  checkoutComplete(
    checkoutId: "Q2hlY2tvdXQ6YjBhYTUzMWItYjc3NS00MzM3LTkxNzEtYTgzOTYwYThjMmVk"
  ) {
    order {
      id
      userEmail
      created
    }
    confirmationNeeded
    confirmationData
    errors {
      field
      message
      code
    }
  }
}

As a result we get order object.

{
  "data": {
    "checkoutComplete": {
      "order": {
        "id": "T3JkZXI6MjI0Mw==",
        "userEmail": "m...@saleor.io",
        "created": "2021-06-04T09:24:44.552881+00:00"
      },
      "confirmationNeeded": false,
      "confirmationData": "{}",
      "checkoutErrors": []
    }
  }
}

Payment requiring additional action

An example of additional action is 3D Secure confirmation required by payment providers.

An example of a complete mutation where the payment gateway requires additional steps from the user:

mutation{
  checkoutComplete(
    id: "Q2hlY2tvdXQ6ZTEzZDFjOTItOWJkNi00ODViLTgyMDctZTNhM2I5NjVkZTQw",
    paymentData: "{\"encryptedAdditionalAction\": \"eka...\"}"
){
     confirmationNeeded
     confirmationData
     order
     errors{
       field
       message
       code
     }
}

A response would look like this:

{
  "data": {
    "checkoutComplete": {
      "order": null,
      "confirmationNeeded": true,
      "confirmationData": "{\"paymentData\":\"Ab02b4c...\", \"paymentMethodType\":\"scheme\", \"token\":\"eyJ0aHJlZURTTWV0aG9kTm9...\", \"type\":\"threeDS2Fingerprint\"}",
      "errors": []
    }
  }
}

Saving card in Stripe for future payments

Use input.storePaymentMethod to store payment method for future payments with checkoutPaymentCreate. Metadata in input.metadata will be stored with the payment

mutation {
  checkoutPaymentCreate(
    checkoutId: "ID"
    input: {
      gateway: "saleor.payments.stripe"
      token: "tokencc_bh_s3bjkh_24smq8_6c6zhq_w4v6b9_8vz"
      amount: 33.33
      storePaymentMethod: OFF_SESSION
      metadata: [{ key: "key", value: "value" }]
    }
  ) {
    payment {
      id
      chargeStatus
    }
    errors {
      field
      message
    }
  }
}

Using stored payment method

Use paymentData.payment_method_id and paymentData.off_session to use stored payment method. You can retrieve

mutation {
  checkoutComplete(
    checkoutId: "ID"
    storeSource: true
    paymentData: "{\"payment_method_id\": \"pm_id\", \"off_session\": false}"
  ) {
    order {
      id
      userEmail
      created
    }
    confirmationNeeded
    confirmationData
    errors {
      field
      message
      code
    }
  }
}

Stripe webhooks

ENABLE_SSL variable should be set to True in case of using the Stripe plugin in production. Without the SSL, Stripe will not allow to create the webhook.

By activating a plugin, Saleor automatically subscribes the following Stripe webhook events:

  • payment_intent.succeeded
  • payment_intent.processing
  • payment_intent.payment_failed
  • payment_intent.amount_capturable_updated
  • payment_intent.canceled
  • charge.refunded

PCI DSS compliance

The following diagram shows the flow of sensitive data between services when using the Stripe plugin:

*Passes non-PCI DSS regulated payment information, such as payment method type, payment method id, information if Saleor should reuse payment method and if Saleor should store payment method for future usage.

For more information about Stripe PCI DSS compliance - see their docs.

Last updated on March 11, 2026

Was this page helpful?