PaymentIntents Quickstart Beta

    Learn how to accept card payments with PaymentIntents.

    Accepting a card payment with PaymentIntents and Stripe Elements is a four-step process, with server-side and client-side actions:

    1. Create a PaymentIntent on your server
    2. Make the PaymentIntent’s client secret available on the client side
    3. Set up Stripe Elements
    4. Submit the payment to Stripe

    Try it now

    Get started by creating your first PaymentIntent below. You can also enable this Radar rule to see Dynamic 3D Secure in action.

    As a first step, let's tell Stripe about your intent to collect a payment by creating a PaymentIntent with your secret API key. Copy and run this curl request in your Terminal.

    Next, use Stripe.js to complete the payment () for . Below, we're entering a test card into Elements.

    That's it! You've used PaymentIntents to complete your first payment. Now, you can follow the steps in this guide to add this flow to your payments page. Happy coding!

    curl https://api.stripe.com/v1/payment_intents \
       -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
       -d amount=1000 \
       -d currency=usd \
       -d description="{FISH_QUERY}" \
       -d allowed_source_types[]=card
    

    Step 1: Create a PaymentIntent on your server

    A PaymentIntent is an object that represents your intent to collect payment from a customer, tracking the lifecycle of the payment process through each stage. When you create a PaymentIntent, specify the currency, permitted source types, and the amount of money that you wish to collect from the customer. The following example shows how to create a PaymentIntent on your server:

    curl https://api.stripe.com/v1/payment_intents \
       -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
       -d amount=1099 \
       -d currency=usd \
       -d allowed_source_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',
      allowed_source_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',
      allowed_source_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",
      "allowed_source_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 allowed_source_types = new ArrayList();
    allowed_source_types.add("card");
    paymentintentParams.put("allowed_source_types", allowed_source_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',
        allowed_source_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)),
      AllowedSourceTypes: []*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",
      AllowedSourceTypes = new List<string> { "card" }
    };
    paymentIntents.Create(createOptions);
    

    If the amount that you are collecting from the customer changes later, you can update the PaymentIntent object accordingly.

    Step 2: Make the PaymentIntent’s client secret available on the client side

    The PaymentIntent contains a client secret that you can pass to Stripe.js on the client side to create a charge. If your application uses server-side rendering, use your template framework to embed the client secret in the page using a data attribute or a hidden HTML element.

    <input id="cardholder-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="cardholder-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="cardholder-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="cardholder-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<String, String> map = new HashMap();
            map.put("client_secret", intent.clientSecret);
    
            return new ModelAndView(map, "checkout.hbs");
          }, new HandlebarsTemplateEngine());
        }
    }
    <input id="cardholder-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="cardholder-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="cardholder-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();
            }
        }
    }

    Each PaymentIntent typically correlates with a single “cart” or customer session in your application. You can create the PaymentIntent during checkout and store its ID on the user’s cart in your application’s data model, retrieving it again as necessary.

    Step 3: Set up Stripe Elements

    PaymentIntents are fully integrated with Stripe.js, using Elements to securely collect payment information on the client side and submitting it to Stripe to create a charge. To get started, include the following script tag on your website:

    <script src="https://js.stripe.com/v3/"></script>
    

    Note that this script must always load directly from js.stripe.com in order to remain PCI compliant–you can’t include it in a bundle or host a copy of it yourself.

    Next, create an instance of the Stripe object, providing your publishable API key as the first parameter. Create an instance of the Elements object and use it to mount a Card element in the relevant placeholder in the page.

    var stripe = Stripe('pk_test_TYooMQauvdEDq54NiTphI7jx', {
      betas: ['payment_intent_beta_3']
    });
    
    var elements = stripe.elements();
    var cardElement = elements.create('card');
    cardElement.mount('#card-element');
    const stripe = Stripe('pk_test_TYooMQauvdEDq54NiTphI7jx', {
      betas: ['payment_intent_beta_3']
    });
    
    const elements = stripe.elements();
    const cardElement = elements.create('card');
    cardElement.mount('#card-element');

    Step 4: Submit the payment to Stripe

    To complete the payment, retrieve the client secret made available in the second step. After obtaining the client secret from the data attribute, use stripe.handleCardPayment complete the payment:

    var cardholderName = document.getElementById('cardholder-name');
    var cardButton = document.getElementById('card-button');
    var clientSecret = cardButton.dataset.secret;
    
    cardButton.addEventListener('click', function(ev) {
      stripe.handleCardPayment(
        clientSecret, cardElement, {
          source_data: {
            owner: {name: cardholderName.value}
          }
        }
      ).then(function(result) {
        if (result.error) {
          // Display error.message in your UI.
        } else {
          // The payment has succeeded. Display a success message.
        }
      });
    });
    const cardholderName = document.getElementById('cardholder-name');
    const cardButton = document.getElementById('card-button');
    const clientSecret = cardButton.dataset.secret;
    
    cardButton.addEventListener('click', async (ev) => {
      const {paymentIntent, error} = await stripe.handleCardPayment(
        clientSecret, cardElement, {
          source_data: {
            owner: {name: cardholderName.value}
          }
        }
      );
    
      if (error) {
        // Display error.message in your UI.
      } else {
        // The payment has succeeded. Display a success message.
      }
    });

    If the customer must perform additional steps to complete the payment, such as authentication, Stripe.js walks them through that process. When the payment completes successfully, the value of the returned PaymentIntent’s status property is succeeded. If the payment was not successful, you can inspect the returned error to determine the cause.

    You can use the PaymentIntent returned by Stripe.js to provide immediate feedback to your customers when their payment succeeds or fails. However, if you want to drive fulfillment upon receiving payment, we recommend monitoring for payment_intent.succeeded and payment_intent.payment_failed events on your server in order to maintain consistency.

    Next steps

    Now you have a complete PaymentIntents integration suitable for accepting card payments. To learn, more continue reading:

    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.