Card Payments with Sources

    Use Sources to accept card payments from around the world. If you need help after reading this, search our documentation or check out answers to common questions. You can even chat live with other developers in #stripe on freenode.

    Stripe users can process card payments from customers around the world using Sources—a single integration path for creating payments using any supported method. During the payment process, your integration creates a source representing the card information. This source is then used in a charge request to debit the card and complete the payment.

    Within the scope of Sources, cards are are a pull-based, reusable and synchronous method of payment. This means that, after capturing the customer’s card details, you can debit arbitrary amounts from the customer’s card without them having to take any additional action and there is immediate confirmation about the success or failure of a payment.

    Handling card information

    Card information is sensitive by nature. Card sources must be created client-side using Elements. This ensures that no sensitive card data passes through your server so your integration can operate in a PCI compliant way.

    When your customer submits their card information using your payment form, it is sent directly to Stripe, and a representative Source object is returned for you to use. The process is similar to the creation of tokens. If you’re already using Elements to tokenize card information, switching to sources is only a small change.

    Prerequisite: Consider a flexible checkout flow if you want to accept additional payment methods

    Card payments with Sources has fewer steps and requirements than other payment methods. As it’s a synchronous method and there is no additional customer action to take, the use of webhooks isn’t necessary. If you only want to accept card payments, you can simply follow the steps within this documentation to begin accepting cards with Sources.

    However, should you wish to accept other methods of payment available through Sources (e.g., iDEAL, SEPA Direct Debit, etc.), additional steps are required, making the use of webhooks are necessary. You can refer to our best practices for developing a flexible checkout flow that supports different payment methods.

    Step 1: Create a Source object

    To create a card Source client-side, please refer to the Elements QuickStart guide to set up Elements and create your payment form (Step 1 and Step 2). At Step 3, you should create a Source instead of a Token by calling the createSource instead of the createToken method.

    // Create a source or display an error when the form is submitted.
    var form = document.getElementById('payment-form');
    form.addEventListener('submit', function(event) {
      event.preventDefault();
    
      stripe.createSource(card).then(function(result) {
        if (result.error) {
          // Inform the user if there was an error
          var errorElement = document.getElementById('card-errors');
          errorElement.textContent = result.error.message;
        } else {
          // Send the source to your server
          stripeSourceHandler(result.source);
        }
      });
    });
    // Create a source or display an error when the form is submitted.
    const form = document.getElementById('payment-form');
    form.addEventListener('submit', async (event) => {
      event.preventDefault();
    
      const {source, error} = await stripe.createSource(card);
    
      if (error) {
        // Inform the user if there was an error
        const errorElement = document.getElementById('card-errors');
        errorElement.textContent = error.message;
      } else {
        // Send the source to your server
        stripeSourceHandler(source);
      }
    });

    The last step of the Elements QuickStart guide (Step 4) remains similar and consists in submitting the source, along with any additional information that has been collected, to your server.

    function stripeSourceHandler(source) {
      // Insert the source ID into the form so it gets submitted to the server
      var form = document.getElementById('payment-form');
      var hiddenInput = document.createElement('input');
      hiddenInput.setAttribute('type', 'hidden');
      hiddenInput.setAttribute('name', 'stripeSource');
      hiddenInput.setAttribute('value', source.id);
      form.appendChild(hiddenInput);
    
      // Submit the form
      form.submit();
    }
    const stripeSourceHandler = (source) => {
      // Insert the source ID into the form so it gets submitted to the server
      const form = document.getElementById('payment-form');
      const hiddenInput = document.createElement('input');
      hiddenInput.setAttribute('type', 'hidden');
      hiddenInput.setAttribute('name', 'stripeSource');
      hiddenInput.setAttribute('value', source.id);
      form.appendChild(hiddenInput);
    
      // Submit the form
      form.submit();
    }

    Once the source has been created, its status is immediately set to chargeable. No additional customer action is needed so the source can be used straight away.

    As card payments are a pull-based payment method, there is no movement of funds during the creation of a source. Only when a successful charge request has been made is the customer’s card debited and you receive the funds.

    Source creation in mobile applications

    If you’re building an iOS or Android app, you can implement sources using our mobile SDKs. Refer to our sources documentation for iOS or Android to learn more.

    Step 2: Charge the Source

    After creating a card Source, and before creating a charge request to complete the payment, you should attach it to a Customer for later reuse.

    Attaching the Source to a Customer

    Attaching the Source to a Customer is required for you to reuse it for future payments. Please refer to our Sources & Customers guide for more details on how to attach Sources to new or existing Customers and how the two objects interact together. The following snippet attaches the Source to a new Customer:

    curl https://api.stripe.com/v1/customers \
       -u sk_test_BQokikJOvBiI2HlWgH4olfQ2: \
       -d email="paying.user@example.com" \
       -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_BQokikJOvBiI2HlWgH4olfQ2"
    
    customer = Stripe::Customer.create({
      email: 'paying.user@example.com',
      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_BQokikJOvBiI2HlWgH4olfQ2"
    
    customer = stripe.Customer.create(
      email='paying.user@example.com',
      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_BQokikJOvBiI2HlWgH4olfQ2");
    
    $customer = \Stripe\Customer::create(array(
      "email" => "paying.user@example.com",
      "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_BQokikJOvBiI2HlWgH4olfQ2";
    
    Map<String, Object> customerParams = new HashMap<String, Object>();
    customerParams.put("email", "paying.user@example.com");
    customerParams.put("source", "src_18eYalAHEMiOZZp1l9ZTjSU0");
    
    Customer customer = Customer.create(customerParams);
    
    // 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_BQokikJOvBiI2HlWgH4olfQ2");
    
    stripe.customers.create({
      email: "paying.user@example.com",
      source: "src_18eYalAHEMiOZZp1l9ZTjSU0",
    }, function(err, customer) {
      // 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_BQokikJOvBiI2HlWgH4olfQ2"
    
    customerParams := &stripe.CustomerParams{
      Email: "paying.user@example.com",
    }
    customerParams.SetSource("src_18eYalAHEMiOZZp1l9ZTjSU0")
    c, err := customer.New(customerParams)
    

    Making a charge request to finalize the payment

    Once attached, you can use the Source object’s ID along with the Customer object’s ID to perform a charge request and finalize the payment.

    curl https://api.stripe.com/v1/charges \
       -u sk_test_BQokikJOvBiI2HlWgH4olfQ2: \
       -d amount=1000 \
       -d currency=usd \
       -d customer=cus_AFGbOSiITuJVDs \
       -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_BQokikJOvBiI2HlWgH4olfQ2"
    
    charge = Stripe::Charge.create({
      amount: 1000,
      currency: 'usd',
      customer: 'cus_AFGbOSiITuJVDs',
      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_BQokikJOvBiI2HlWgH4olfQ2"
    
    charge = stripe.Charge.create(
      amount=1000,
      currency='usd',
      customer='cus_AFGbOSiITuJVDs',
      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_BQokikJOvBiI2HlWgH4olfQ2");
    
    $charge = \Stripe\Charge::create(array(
      "amount" => 1000,
      "currency" => "usd",
      "customer" => "cus_AFGbOSiITuJVDs",
      "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_BQokikJOvBiI2HlWgH4olfQ2";
    
    Map<String, Object> chargeParams = new HashMap<String, Object>();
    chargeParams.put("amount", 1000);
    chargeParams.put("currency", "usd");
    chargeParams.put("customer", "cus_AFGbOSiITuJVDs");
    chargeParams.put("source", "src_18eYalAHEMiOZZp1l9ZTjSU0");
    
    Charge charge = Charge.create(chargeParams);
    
    // 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_BQokikJOvBiI2HlWgH4olfQ2");
    
    stripe.charges.create({
      amount: 1000,
      currency: "usd",
      customer: "cus_AFGbOSiITuJVDs",
      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_BQokikJOvBiI2HlWgH4olfQ2"
    
    chargeParams := &stripe.ChargeParams{
      Amount: 1000,
      Currency: "usd",
      Customer: "cus_AFGbOSiITuJVDs",
    }
    chargeParams.SetSource("src_18eYalAHEMiOZZp1l9ZTjSU0")
    ch, err := charge.New(chargeParams)
    

    A card source must be used within a few minutes of its creation as CVC information is only available for a short amount of time. Card sources do not expire, but using them after a delay can result in a charge request that is performed without CVC information. The consequences of this can be higher decline rates and increased risk of fraud.

    Although the status of the source is chargeable, this does not mean that the payment is going to be successful. A charge request can still fail if the customer’s bank declines the payment.

    Step 3: Confirm that the charge has succeeded

    Card payments are a synchronous method so confirmation of the charge’s status happens in real-time.

    Your integration immediately receives the result of the charge request—either a Charge object upon success or an exception upon failure. Once the charge has been confirmed as successful, the payment has been successfully completed and you can notify your customer and fulfill the order.

    If you’re making use of webhooks, your integration also receives either of the following events:

    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.

    Disputed payments

    Card networks provide a process for cardholders to dispute payments made with their card. A dispute can be filed by the cardholder any time after a payment has been successful. It is still possible for a successful payment to be reversed if the bank investigates a dispute and decides it should be refunded.

    Disputes can be made for a variety of reasons. As such, you should make the appropriate decisions regarding your business and how you manage disputes, if they occur, and how to avoid them completely.

    Related resources