Creating PaymentIntents

    Create a PaymentIntent on your server side to start accepting payments.

    The first step to accepting payments with the PaymentIntents API is to create a PaymentIntent on the server side. Each PaymentIntent typically correlates with a single shopping cart or customer session in your application. We recommend creating a PaymentIntent when the customer begins their checkout process. This helps track all the payment attempts with one object.

    The PaymentIntent encapsulates details about the transaction, such as the supported payment methods, the amount to collect, and the desired currency. You can specify these options when you create the PaymentIntent:

    curl https://api.stripe.com/v1/payment_intents \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d amount=1099 \
      -d currency=usd \
      -d payment_method_types[]=card
    
    # 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'
    
    intent = Stripe::PaymentIntent.create({
      amount: 1099,
      currency: 'usd',
      payment_method_types: ['card']
    })
    
    # 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"
    
    stripe.PaymentIntent.create(
      amount=1099,
      currency='usd',
      payment_method_types=['card']
    )
    
    // 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");
    
    \Stripe\PaymentIntent::create([
      "amount" => 1099,
      "currency" => "usd",
      "payment_method_types" => ["card"],
    ]);
    
    // 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> paymentintentParams = new HashMap<String, Object>();
    paymentintentParams.put("amount", 1099);
    paymentintentParams.put("currency", "usd");
    ArrayList payment_method_types = new ArrayList();
    payment_method_types.add("card");
    paymentintentParams.put("payment_method_types", payment_method_types);
    
    PaymentIntent.create(paymentintentParams);
    
    // 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
    var stripe = require("stripe")("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    (async () => {
      const paymentIntent = await stripe.paymentIntents.create({
        amount: 1099,
        currency: 'usd',
        payment_method_types: ['card'],
      });
    })();
    
    // 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"
    
    params := &stripe.PaymentIntentParams{
      Amount: stripe.Int64(1099),
      Currency: stripe.String(string(stripe.CurrencyUSD)),
      PaymentMethodTypes: []*string{
        stripe.String("card"),
      },
    }
    paymentIntent.New(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
    StripeConfiguration.SetApiKey("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    var paymentIntents = new PaymentIntentService();
    var createOptions = new PaymentIntentCreateOptions {
      Amount = 1099,
      Currency = "usd",
      PaymentMethodTypes = new List<string> { "card" }
    };
    paymentIntents.Create(createOptions);
    

    If you haven’t already, install the API library for your favorite language now. As a convenience, if you’re logged in while reading this page, we’ve pre-filled the example with your test secret API key. Only you can see this value. This will authenticate you to Stripe, so keep it secret and keep it safe. Remember to replace the test key with your live key in production. You can get all your keys from the Dashboard.

    After creating a PaymentIntent, you can pass the PaymentIntent client secret to the client side and securely collect and tokenize your customer’s card using Elements or our iOS and Android SDKs.

    Passing the client secret to the client side

    The PaymentIntent contains a client secret, a key that is unique to the individual PaymentIntent. On the client side of your application, the client secret is used as a parameter when invoking Stripe.js functions (such as stripe.handleCardPayment) to complete the payment.

    To use the client secret, you must obtain it from the PaymentIntent on your server and pass it the client side. There are different approaches that you can use to get the client secret to the client side–choose the approach that best suits the architecture of your application.

    Server-side rendering

    If your application uses server-side rendering, you may wish to use your template framework to embed the client secret in the HTML output of your checkout page during rendering. You can embed it in a data attribute or hidden HTML element and then extract it with JavaScript in order to use it to complete payment.

    <input id="card-name" type="text">
    <!-- placeholder for Elements -->
    <div id="card-element"></div>
    <button id="card-button" data-secret="<%= @intent.client_secret %>">Submit Payment</button>
    get '/checkout' do
      @intent = # ... Fetch or create the PaymentIntent
      erb :checkout
    end
    <input id="card-name" type="text">
    <!-- placeholder for Elements -->
    <div id="card-element"></div>
    <button id="card-button" data-secret="{{ client_secret }}">
      Submit Payment
    </button>
    @app.route('/checkout')
    def checkout():
      intent = # ... Fetch or create the PaymentIntent
      return render_template('checkout.html', client_secret=intent.client_secret)
    <?php
      $intent = # ... Fetch or create the PaymentIntent;
    ?>
    ...
    <input id="card-name" type="text">
    <!-- placeholder for Elements -->
    <div id="card-element"></div>
    <button id="card-button" data-secret="<?= $intent->client_secret ?>">
      Submit Payment
    </button>
    ...
    <input id="card-name" type="text">
    <!-- placeholder for Elements -->
    <div id="card-element"></div>
    <button id="card-button" data-secret="{{ client_secret }}">
      Submit Payment
    </button>
    import java.util.HashMap;
    import java.util.Map;
    
    import com.stripe.model.PaymentIntent;
    
    import spark.ModelAndView;
    
    import static spark.Spark.get;
    
    public class StripeJavaQuickStart {
        public static void main(String[] args) {
            get("/checkout", (request, response) -> {
              PaymentIntent intent = // ... Fetch or create the PaymentIntent
    
              Map map = new HashMap();
              map.put("client_secret", intent.clientSecret);
    
              return new ModelAndView(map, "checkout.hbs");
            }, new HandlebarsTemplateEngine());
        }
    }
    <input id="card-name" type="text">
    <!-- placeholder for Elements -->
    <div id="card-element"></div>
    <button id="card-button" data-secret="{{ client_secret }}">
      Submit Payment
    </button>
    const express = require('express');
    const expressHandlebars = require('express-handlebars');
    const app = express();
    
    app.engine('.hbs', expressHandlebars({ extname: '.hbs' }));
    app.set('view engine', '.hbs');
    app.set('views', './views');
    
    app.get('/checkout', async (req, res) => {
      const intent = // ... Fetch or create the PaymentIntent
      res.render('checkout', { client_secret: intent.clientSecret });
    });
    
    app.listen(3000, () => {
      console.log('Running on port 3000')
    });
    <input id="card-name" type="text">
    <!-- placeholder for Elements -->
    <div id="card-element"></div>
    <button id="card-button" data-secret="{{ .ClientSecret }}">
      Submit Payment
    </button>
    package main
    
    import (
      "html/template"
      "net/http"
    
      stripe "github.com/stripe/stripe-go"
    )
    
    type CheckoutData struct {
      ClientSecret string
    }
    
    func main() {
      checkoutTmpl := template.Must(template.ParseFiles("views/checkout.html"))
    
      http.HandleFunc("/checkout", func(w http.ResponseWriter, r *http.Request) {
        intent := // ... Fetch or create the PaymentIntent
        data := CheckoutData{
          ClientSecret: intent.ClientSecret,
        }
        checkoutTmpl.Execute(w, data)
      })
    
      http.ListenAndServe(":3000", nil)
    }
    <input id="card-name" type="text">
    <!-- placeholder for Elements -->
    <div id="card-element"></div>
    <button id="card-button" data-secret="@ViewData["ClientSecret"]">
      Submit Payment
    </button>
    using System;
    using Microsoft.AspNetCore.Mvc;
    using Stripe;
    
    namespace StripeExampleApi.Controllers
    {
        [Route("/[controller]")]
        public class CheckoutController : Controller
        {
            public IActionResult Index()
            {
              var intent = // ... Fetch or create the PaymentIntent
              ViewData["ClientSecret"] = intent.ClientSecret;
              return View();
            }
        }
    }

    Single-page application

    Alternately, you can retrieve the client secret from an endpoint on your server using the browser’s fetch function on the client side. This approach is generally most suitable when your client side is a single-page application, particularly one built with a modern frontend framework such as React or Vue. This example shows how to create the server endpoint that serves the client secret:

    get '/secret' do
      intent = # ... Create or retrieve the PaymentIntent
      {client_secret: intent.client_secret}.to_json
    end
    from flask import jsonify
    
    @app.route('/secret')
    def secret():
      intent = # ... Create or retrieve the PaymentIntent
      return jsonify(client_secret=intent.client_secret)
    <?php
      $intent = # ... Create or retrieve the PaymentIntent
      echo json_encode(array('client_secret' => $intent->client_secret));
    ?>
    import java.util.HashMap;
    import java.util.Map;
    
    import com.stripe.model.PaymentIntent;
    
    import com.google.gson.Gson;
    
    import static spark.Spark.get;
    
    public class StripeJavaQuickStart {
        public static void main(String[] args) {
          Gson gson = new Gson();
    
          get("/secret", (request, response) -> {
            PaymentIntent intent = // ... Fetch or create the PaymentIntent
    
            Map<String, String> map = new HashMap();
            map.put("client_secret", intent.clientSecret);
    
            return map;
          }, gson::toJson);
        }
    }
    const express = require('express');
    const app = express();
    
    app.get("/secret", function(req, res) {
      const intent = //... Create or retrieve the PaymentIntent
    
      res.json({client_secret: intent.client_secret});
    });
    
    app.listen(3000, () => {
      console.log('Running on port 3000')
    });
    package main
    
    import (
      "encoding/json"
      "net/http"
    
      stripe "github.com/stripe/stripe-go"
    )
    
    type CheckoutData struct {
      ClientSecret string `json:"client_secret"`
    }
    
    func main() {
      http.HandleFunc("/secret", func(w http.ResponseWriter, r *http.Request) {
        intent := // ... Fetch or create the PaymentIntent
        data := CheckoutData{
          ClientSecret: intent.ClientSecret,
        }
        w.Header().Set("Content-Type", "application/json")
        w.WriteHeader(http.StatusOK)
        json.NewEncoder(w).Encode(data)
      })
    
      http.ListenAndServe(":3000", nil)
    }
    using System;
    using Microsoft.AspNetCore.Mvc;
    using Stripe;
    
    namespace StripeExampleApi.Controllers
    {
        [Route("secret")]
        [ApiController]
        public class CheckoutApiController : Controller
        {
            [HttpGet]
            public ActionResult Get()
            {
                var intent = // ... Fetch or create the PaymentIntent
                return Json(new {client_secret = intent.ClientSecret});
            }
        }
    }

    This example demonstrates how to fetch the client secret with JavaScript on the client side:

    var response = fetch('/secret').then(function(response) {
      return response.json();
    }).then(function(responseJson) {
      var clientSecret = responseJson.client_secret;
      // Call stripe.handleCardPayment() with the client secret.
    });
    (async () => {
      const response = await fetch('/secret');
      const {client_secret: clientSecret} = await response.json();
      // Call stripe.handleCardPayment() with the client secret.
    })();

    Similarly for iOS and Android applications, you can fetch the client secret from the server.

    After creating a PaymentIntent and passing its client secret to the client side, you can securely collect and tokenize your customer’s card using Elements or our iOS and Android SDKs.

    Best practices

    We recommend creating a PaymentIntent as soon as the amount is known, such as when the customer begins the checkout process. If the amount changes, you can update its amount. For example, if your customer backs out of the checkout process and adds new items to their cart, you may need to update the amount accordingly when they start the checkout process again.

    If the checkout process is interrupted and resumes later, you should attempt to reuse the same PaymentIntent instead of creating a new one. Each PaymentIntent has a unique ID that you can use to retrieve it if you need it again. In your application’s data model, you can store the PaymentIntent’s ID on the customer’s shopping cart or session in order to facilitate retrieval. The benefit of reusing the PaymentIntent is that the object helps track any failed payment attempts for a given cart or session.

    You should also provide an idempotency key–typically based on the ID that you associate with the cart or customer session in your application–when creating the PaymentIntent to avoid erroneously creating duplicate PaymentIntents for the same purchase.

    Dynamic statement descriptor

    By default, your Stripe account’s statement descriptor appears on customer statements whenever you charge their card. To provide a different description on a per-payment basis, include the statement_descriptor parameter.

    curl https://api.stripe.com/v1/payment_intents \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d amount=1099 \
      -d currency=usd \
      -d payment_method_types[]=card \
      -d statement_descriptor="Custom descriptor"
    
    # 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'
    
    intent = Stripe::PaymentIntent.create({
      amount: 1099,
      currency: 'usd',
      payment_method_types: ['card'],
      statement_descriptor: 'Custom descriptor',
    })
    
    # 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"
    
    stripe.PaymentIntent.create(
      amount=1099,
      currency='usd',
      payment_method_types=['card'],
      statement_descriptor='Custom descriptor',
    )
    
    // 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");
    
    \Stripe\PaymentIntent::create([
      "amount" => 1099,
      "currency" => "usd",
      "payment_method_types" => ["card"],
      'statement_descriptor' => 'Custom descriptor',
    ]);
    
    // 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> paymentintentParams = new HashMap<String, Object>();
    paymentintentParams.put("amount", 1099);
    paymentintentParams.put("currency", "usd");
    ArrayList payment_method_types = new ArrayList();
    payment_method_types.add("card");
    paymentintentParams.put("payment_method_types", payment_method_types);
    paymentintentParams.put("statement_descriptor", "Custom descriptor");
    
    PaymentIntent.create(paymentintentParams);
    
    // 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
    var stripe = require("stripe")("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    (async () => {
      const paymentIntent = await stripe.paymentIntents.create({
        amount: 1099,
        currency: 'usd',
        payment_method_types: ['card'],
        statement_descriptor: 'Custom descriptor',
      });
    })();
    
    // 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"
    
    params := &stripe.PaymentIntentParams{
      Amount: stripe.Int64(1099),
      Currency: stripe.String(string(stripe.CurrencyUSD)),
      PaymentMethodTypes: []*string{
        stripe.String("card"),
      },
      StatementDescriptor: stripe.String("Custom descriptor"),
    }
    paymentIntent.New(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
    StripeConfiguration.SetApiKey("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    var paymentIntents = new PaymentIntentService();
    var createOptions = new PaymentIntentCreateOptions {
      Amount = 1099,
      Currency = "usd",
      PaymentMethodTypes = new List<string> { "card" },
      StatementDescriptor = "Custom descriptor",
    };
    paymentIntents.Create(createOptions);
    

    Statement descriptors are limited to 22 characters, cannot use the special characters <, >, ', ", or *, and must not consist solely of numbers. When using dynamic statement descriptors, the dynamic text is appended to the statement descriptor prefix set in the Stripe Dashboard. An * and an empty space are also added to separate the default statement descriptor from the dynamic portion. These two characters count towards the 22 character limit.

    Separate authorization and capture

    Stripe supports two-step card payments so you can first authorize the card, then wait to capture funds later. When a payment is authorized, the funds are guaranteed by the card issuer and the amount held on the customer’s card for up to seven days. If the payment is not captured within this time, the PaymentIntent and authorization are both canceled and funds released.

    To indicate that you want separate authorization and capture, you must set the value of capture_method option to manual when creating the PaymentIntent. This instructs Stripe to only authorize the amount on the customer’s card.

    curl https://api.stripe.com/v1/payment_intents \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d amount=1099 \
      -d currency=usd \
      -d payment_method_types[]=card \
      -d capture_method=manual
    
    # 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'
    
    intent = Stripe::PaymentIntent.create({
      amount: 1099,
      currency: 'usd',
      payment_method_types: ['card'],
      capture_method: 'manual',
    })
    
    # 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"
    
    stripe.PaymentIntent.create(
      amount=1099,
      currency='usd',
      payment_method_types=['card'],
      capture_method='manual',
    )
    
    // 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");
    
    \Stripe\PaymentIntent::create([
      "amount" => 1099,
      "currency" => "usd",
      "payment_method_types" => ["card"],
      'capture_method' => 'manual',
    ]);
    
    // 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> paymentintentParams = new HashMap<String, Object>();
    paymentintentParams.put("amount", 1099);
    paymentintentParams.put("currency", "usd");
    ArrayList payment_method_types = new ArrayList();
    payment_method_types.add("card");
    paymentintentParams.put("payment_method_types", payment_method_types);
    paymentintentParams.put("capture_method", "manual");
    
    PaymentIntent.create(paymentintentParams);
    
    // 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
    var stripe = require("stripe")("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    (async () => {
      const paymentIntent = await stripe.paymentIntents.create({
        amount: 1099,
        currency: 'usd',
        payment_method_types: ['card'],
        capture_method: 'manual',
      });
    })();
    
    // 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"
    
    params := &stripe.PaymentIntentParams{
      Amount: stripe.Int64(1099),
      Currency: stripe.String(string(stripe.CurrencyUSD)),
      PaymentMethodTypes: []*string{
        stripe.String("card"),
      },
      CaptureMethod: stripe.String("manual"),
    }
    paymentIntent.New(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
    StripeConfiguration.SetApiKey("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    var paymentIntents = new PaymentIntentService();
    var createOptions = new PaymentIntentCreateOptions {
      Amount = 1099,
      Currency = "usd",
      PaymentMethodTypes = new List<string> { "card" },
      CaptureMethod = "manual",
    };
    paymentIntents.Create(createOptions);
    

    To capture the authorized funds, make a PaymentIntent capture request. The total authorized amount is captured by default, and you cannot capture more than this. To capture less than the initial amount (e.g., $8 of a $10 authorization), pass the amount_to_capture option. Partially capturing automatically releases the remaining amount.

    The following example demonstrates how to capture funds from an authorized payment:

    curl https://api.stripe.com/v1/payment_intents/pi_f4XUrWhM1t36v1zQR3JW/capture \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d amount_to_capture=750
    
    # 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'
    
    intent = Stripe::PaymentIntent.retrieve('pi_f4XUrWhM1t36v1zQR3JW')
    intent.capture(amount_to_capture: 750)
    
    # 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"
    
    intent = stripe.PaymentIntent.retrieve("pi_f4XUrWhM1t36v1zQR3JW")
    intent.capture({amount_to_capture: 750})
    
    // 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");
    
    $intent = \Stripe\PaymentIntent::retrieve("pi_f4XUrWhM1t36v1zQR3JW");
    $intent->capture(["amount" => 750]);
    
    // 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";
    
    PaymentIntent intent = PaymentIntent.retrieve("pi_f4XUrWhM1t36v1zQR3JW");
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("amount_to_capture", 750);
    intent.capture(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
    var stripe = require("stripe")("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    (async () => {
      await stripe.paymentIntents.capture("pi_f4XUrWhM1t36v1zQR3JW", {
        amount: 750
      })
    })();
    
    // 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"
    
    params := &stripe.PaymentIntentCaptureParams{
      AmountToCapture: stripe.Int64(750),
    }
    intent, err := paymentintent.Capture("pi_f4XUrWhM1t36v1zQR3JW", 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
    StripeConfiguration.SetApiKey("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    var paymentIntents = new PaymentIntentService();
    var captureOptions = new PaymentIntentCaptureOptions {
      AmountToCapture = 750
    };
    paymentIntents.Capture("pi_f4XUrWhM1t36v1zQR3JW", captureOptions);
    

    If you need to cancel an authorization, you can cancel the PaymentIntent.

    Card statements from some issuers do not distinguish between authorizations and captured (settled) payments, which can sometimes lead to confusion for your customers. In addition, authorized payments can only be captured once. If you partially capture a payment, you cannot perform another capture for the difference. Depending on your requirements, you may be better served by saving customer’s card details for later and creating future payments as needed.

    Additionally, when a customer completes the payment process on a PaymentIntent with manual capture, it triggers the payment_intent.amount_capturable_updated event. You can inspect the PaymentIntent’s amount_capturable property to see the total amount that can be captured from the PaymentIntent.

    Canceling a PaymentIntent

    You can cancel a PaymentIntent if you no longer intend to use it to collect payment from the customer:

    curl https://api.stripe.com/v1/payment_intents/pi_61mdiEj7L6G2Kkg5gQCn/cancel \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -X POST
    
    # 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'
    
    intent = Stripe::PaymentIntent.retrieve('pi_61mdiEj7L6G2Kkg5gQCn')
    intent.cancel
    
    # 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"
    
    intent = stripe.PaymentIntent.retrieve("pi_61mdiEj7L6G2Kkg5gQCn")
    intent.cancel()
    
    // 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");
    
    $intent = \Stripe\PaymentIntent::retrieve("pi_61mdiEj7L6G2Kkg5gQCn");
    $intent->cancel();
    
    // 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";
    
    PaymentIntent intent = PaymentIntent.retrieve("pi_61mdiEj7L6G2Kkg5gQCn");
    intent.cancel();
    
    // 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
    var stripe = require("stripe")("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    (async () => {
      await stripe.paymentIntents.cancel("pi_61mdiEj7L6G2Kkg5gQCn")
    })();
    
    // 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"
    
    intent, err := paymentintent.Cancel("pi_61mdiEj7L6G2Kkg5gQCn", nil)
    
    // 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
    StripeConfiguration.SetApiKey("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    var paymentIntents = new PaymentIntentService();
    var cancelOptions = new PaymentIntentCancelOptions {};
    paymentIntents.Cancel("pi_61mdiEj7L6G2Kkg5gQCn", cancelOptions);
    

    A PaymentIntent can only be canceled when it has one of the following statuses: requires_payment_method, requires_capture, requires_confirmation, or requires_action–a PaymentIntent can’t be canceled while it is actively processing or once it has succeeded.

    When a PaymentIntent is canceled, you can no longer use it to perform additional charges. Any operations that your application attempts to perform on a canceled PaymentIntent will fail with an error.

    Storing information in metadata

    Stripe supports adding metadata to the most common requests you make, such as processing payments. Metadata isn’t shown to customers or factored into whether or not a payment is declined or blocked by our fraud prevention system.

    Through metadata, you can associate other information—meaningful to you—with Stripe activity. Any metadata you include is viewable in the Dashboard (e.g., when looking at the page for an individual payment), and is also available in common reports and exports. As an example, your store’s order ID can be attached to the PaymentIntent used to pay for that order. Doing so allows you, your accountant, or your finance team to easily reconcile payments in Stripe to orders in your system.

    If you are using Radar, consider passing any additional customer information and order information as metadata. By doing so, you can write Radar rules using metadata attributes and have more information about the payment available within the Dashboard which can expedite your review process.

    When a PaymentIntent creates a charge, the PaymentIntent copies its metadata to the charge. Subsequent updates to the PaymentIntent’s metadata will not modify the metadata of charges previously created by the PaymentIntent.

    curl https://api.stripe.com/v1/payment_intents \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d amount=1099 \
      -d currency=usd \
      -d payment_method_types[]=card \
      -d metadata[order_id]=6735
    
    # 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'
    
    intent = Stripe::PaymentIntent.create({
      amount: 1099,
      currency: 'usd',
      payment_method_types: ['card'],
      metadata: {'order_id' => 6735},
    })
    
    # 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"
    
    stripe.PaymentIntent.create(
      amount=1099,
      currency='usd',
      payment_method_types=['card'],
      metadata={'order_id': 6735},
    )
    
    // 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");
    
    \Stripe\PaymentIntent::create([
      "amount" => 1099,
      "currency" => "usd",
      "payment_method_types" => ["card"],
      'metadata' => ['order_id' => 6735],
    ]);
    
    // 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> paymentintentParams = new HashMap<String, Object>();
    paymentintentParams.put("amount", 1099);
    paymentintentParams.put("currency", "usd");
    ArrayList payment_method_types = new ArrayList();
    payment_method_types.add("card");
    paymentintentParams.put("payment_method_types", payment_method_types);
    Map<String, String> metadata = new HashMap<>();
    metadata.put("order_id", 6735);
    paymentintentParams.put("metadata", metadata);
    PaymentIntent.create(paymentintentParams);
    
    // 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
    var stripe = require("stripe")("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    (async () => {
      const paymentIntent = await stripe.paymentIntents.create({
        amount: 1099,
        currency: 'usd',
        payment_method_types: ['card'],
        metadata: {order_id: 6735},
      });
    })();
    
    // 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"
    
    params := &stripe.PaymentIntentParams{
      Amount: stripe.Int64(1099),
      Currency: stripe.String(string(stripe.CurrencyUSD)),
      PaymentMethodTypes: []*string{
        stripe.String("card"),
      },
    }
    params.AddMetadata("order_id", 6735)
    paymentIntent.New(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
    StripeConfiguration.SetApiKey("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    var paymentIntents = new PaymentIntentService();
    var createOptions = new PaymentIntentCreateOptions {
      Amount = 1099,
      Currency = "usd",
      PaymentMethodTypes = new List<string> { "card" },
      Metadata = new Dictionary<String, String>() {{"OrderId", "6735"}},
    };
    paymentIntents.Create(createOptions);
    

    Next steps

    Now that you know how to create a PaymentIntent, learn how to use the PaymentIntent to complete a payment:

    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.