Payment Intent Use Cases

    Learn about different use cases supported by the Payment Intents API.

    Example 1: Creating one-time payments

    Use the Payment Intents API to process one-time payments. A one-time payment is something like an e-commerce order or donation that requires collecting card details to immediately make a payment.

    There are two flows to choose from depending on how you fulfill the order:

    • Automatic confirmation will confirm the PaymentIntent on the client and require you to use an asynchronous process like a webhook to fulfill.
    • Manual confirmation lets you confirm the PaymentIntent on the server and immediately fulfill the order.

    Example 2: Reusing cards

    There are two ways you can save cards to reuse for later payments:

    • Use the Payment Intents or Setup Intents API to authenticate and save card details. You will have to manually ask your users to authenticate by sending an email or app notification when the PaymentIntent requires_action.
    • Use Stripe Billing’s Subscription API. This will handle prompting your users for additional authentication by automatically sending customizable emails when a PaymentIntent is in a requires_action status.

    Example 3: Canceling and refunding PaymentIntents

    You can cancel a PaymentIntent if you no longer intend to use it to collect payment from the customer. Canceling a PaymentIntent is optional, and it’s okay to keep a PaymentIntent in an incomplete status like requires_confirmation or requires_payment_method. Incomplete PaymentIntents are useful in understanding the conversion rate at checkout.

    curl https://api.stripe.com/v1/payment_intents/pi_PiijileUtqX7ognIJTzc/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.cancel('pi_PiijileUtqX7ognIJTzc')
    
    # 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.cancel('pi_PiijileUtqX7ognIJTzc')
    
    // 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_PiijileUtqX7ognIJTzc');
    $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_PiijileUtqX7ognIJTzc");
    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
    const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    (async () => {
      await stripe.paymentIntents.cancel('pi_PiijileUtqX7ognIJTzc')
    })();
    
    // 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_PiijileUtqX7ognIJTzc", 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.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    var service = new PaymentIntentService();
    var options = new PaymentIntentCancelOptions{};
    var intent = service.Cancel("pi_PiijileUtqX7ognIJTzc", options);
    

    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.

    To refund a PaymentIntent after it has reached the succeeded status, use the Refunds API.

    Example 4: Placing a hold on a card without charging

    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 is 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 are 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
    const 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: stripe.StringSlice([]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.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    var service = new PaymentIntentService();
    var options = new PaymentIntentCreateOptions
    {
      Amount = 1099,
      Currency = "usd",
      PaymentMethodTypes = new List<string> { "card" },
      CaptureMethod = "manual",
    };
    var intent = service.Create(options);
    

    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., $7.50 of the $10.99 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_LYppthjl9eA4FUEacQwR/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.capture(
      'pi_LYppthjl9eA4FUEacQwR',
      {
        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.capture(
      'pi_LYppthjl9eA4FUEacQwR',
      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_LYppthjl9eA4FUEacQwR');
    $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.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    PaymentIntent intent = PaymentIntent.retrieve("pi_LYppthjl9eA4FUEacQwR");
    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
    const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    (async () => {
      await stripe.paymentIntents.capture('pi_LYppthjl9eA4FUEacQwR', {
        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.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    params := &stripe.PaymentIntentCaptureParams{
      AmountToCapture: stripe.Int64(750),
    }
    intent, err := paymentintent.Capture("pi_LYppthjl9eA4FUEacQwR", 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.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    var service = new PaymentIntentService();
    var options = new PaymentIntentCaptureOptions
    {
      AmountToCapture = 750,
    };
    var intent = service.Capture("pi_LYppthjl9eA4FUEacQwR", options);
    

    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.

    Example 5: Using Payment Intents with Apple Pay and Google Pay

    You can use the Payment Intents API to accept mobile card wallets such as Apple Pay and Google Pay.

    On the web, use the Payment Request Button which provides a single integration for Apple Pay, Google Pay, Microsoft Pay, and the Payment Request API.

    Example 6: Charging on behalf of a Connected account

    Stripe supports several approaches for creating charges on behalf of a connected account.

    One approach is a direct charge, in which the connected account is responsible for the cost of the Stripe fees, refunds, and chargebacks. To perform a direct charge with a PaymentIntent, supply the ID of the connected account while creating 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 \
      -H "Stripe-Account: {{CONNECTED_ACCOUNT_ID}}"
    
    # 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'],
    }, {
        stripe_account: '{{CONNECTED_ACCOUNT_ID}}'
    })
    
    # 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'],
      stripe_account='{{CONNECTED_ACCOUNT_ID}}'
    )
    
    // 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'],
    ], [
        'stripe_account' => '{{CONNECTED_ACCOUNT_ID}}'
    ]);
    
    // 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);
    
    RequestOptions requestOptions = RequestOptions.builder().setStripeAccount("{{CONNECTED_ACCOUNT_ID}}").build();
    
    PaymentIntent.create(paymentintentParams, requestOptions);
    
    // 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');
    
    (async () => {
      const paymentIntent = await stripe.paymentIntents.create({
        amount: 1099,
        currency: 'usd',
        payment_method_types: ['card']
      }, {
        stripe_account: '{{CONNECTED_ACCOUNT_ID}}'
      });
    })();
    
    // 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: stripe.StringSlice([]string{
        "card",
      }),
    }
    params.SetStripeAccount("{{CONNECTED_ACCOUNT_ID}}")
    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.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    var service = new PaymentIntentService();
    var options = new PaymentIntentCreateOptions
    {
        Amount = 1099,
        Currency = "usd",
        PaymentMethodTypes = new List<string> { "card" }
    };
    var requestOptions = new RequestOptions
    {
        StripeConnectAccountId = "{{CONNECTED_ACCOUNT_ID}}"
    }
    service.Create(options, requestOptions);
    

    Additionally, the Payment Intents API supports creating a transfer to a connected account automatically and setting a connected account as the business of record for the payment.

    The transfer_data[destination] is the ID of the connected account that should receive the transfer.

    The on_behalf_of parameter is the ID of the connected account to use as the business of record for the payment. When it is set, Stripe automatically:

    • Settles charges in the country of the specified account, thereby minimizing declines and avoiding currency conversions
    • Uses the fee structure for the connected account’s country
    • If the account is in a different country than the platform, the connected account’s address and phone number shows up on the customer’s credit card statement (as opposed to the platform’s)

    The transfer_group parameter is propagated to all charges created by the PaymentIntent, and it behaves identically.

    Finally, you may withhold an application fee by providing the application_fee_amount 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 application_fee_amount=200 \
      -d on_behalf_of="{{CONNECTED_ACCOUNT_ID}}" \
      -d transfer_data[destination]="{{CONNECTED_ACCOUNT_ID}}"
    
    # 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'],
        application_fee_amount: 200,
        on_behalf_of: '{{CONNECTED_ACCOUNT_ID}}',
        transfer_data: {destination: '{{CONNECTED_ACCOUNT_ID}}'}
    })
    
    # 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',
      application_fee_amount=200,
      payment_method_types=['card'],
      on_behalf_of='{{CONNECTED_ACCOUNT_ID}}',
      transfer_data={'destination': '{{CONNECTED_ACCOUNT_ID}}'}
    )
    
    // 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',
        'application_fee_amount' => 200,
        'payment_method_types' => ['card'],
        'on_behalf_of' => '{{CONNECTED_ACCOUNT_ID}}',
        'transfer_data' => [
            'destination' => '{{CONNECTED_ACCOUNT_ID}}'
        ],
    ]);
    
    // 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("on_behalf_of", "{{CONNECTED_ACCOUNT_ID}}");
    paymentintentParams.put("application_fee_amount", 200);
    
    Map<String, Object> transferDataParams = new HashMap<String, Object>();
    transferDataParams.put("destination", "{{CONNECTED_ACCOUNT_ID}}");
    
    paymentintentParams.put("transfer_data", transferDataParams);
    
    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
    const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    (async () => {
      const paymentIntent = await stripe.paymentIntents.create({
        amount: 1099,
        currency: 'usd',
        payment_method_types: ['card'],
        application_fee_amount: 200,
        on_behalf_of: '{{CONNECTED_ACCOUNT_ID}}',
        transfer_data: {
          destination: '{{CONNECTED_ACCOUNT_ID}}'
        }
      });
    })();
    
    // 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"
    
    transferData = &stripe.PaymentIntentTransferDataParams{
      Destination: stripe.String("{{CONNECTED_ACCOUNT_ID}}"),
    }
    
    params := &stripe.PaymentIntentParams{
      Amount: stripe.Int64(1099),
      Currency: stripe.String(string(stripe.CurrencyUSD)),
      PaymentMethodTypes: stripe.StringSlice([]string{
        "card",
      }),
      OnBehalfOf: stripe.String("{{CONNECTED_ACCOUNT_ID}}"),
      ApplicationFeeAmount: stripe.Int64(200),
      TransferData: transferData,
    }
    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.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    var service = new PaymentIntentService();
    var options = new PaymentIntentCreateOptions
    {
        Amount = 1099,
        Currency = "usd",
        PaymentMethodTypes = new List<string> { "card" },
        ApplicationFeeAmount = 200,
        OnBehalfOf = "{{CONNECTED_ACCOUNT_ID}}",
        TransferData = new PaymentIntentTransferDataOptions
        {
            DestinationId = "{{CONNECTED_ACCOUNT_ID}}",
        },
    };
    service.Create(options);
    

    Next steps

    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