Set up a subscription

    Learn how to create and charge for a subscription.

    Overview

    Use this guide to set up a subscription and charge a customer. It includes some initial product setup, including how much you want to charge for it. You can finish this guide using our APIs and libraries, or without any code using the Stripe Dashboard.

    When you’re ready to start, click the tab below for the flow you want to follow.

    Subscriptions integrations combine Stripe Billing features with Stripe’s core Payments product. Use the Billing features to define your product, set pricing, and create subscriptions. The Payments features collect payment information from your customers so you can charge them.

    As you work through this guide, you can use the Developers section in the Dashboard to test and debug your code. You can find your API keys there as well.

    1 Create a product and plan Dashboard

    Products are what you sell and you need to create at least one before you can charge for it. This guide uses a stock photo service as an example. Generally, if you only have a few products, you should create and manage them in the Stripe Dashboard.

    To create a product in the Stripe Dashboard:

    1. Navigate to the Products page.
    2. Click + Add a test product or + New to create a test product.
    3. Enter a Product name.
    4. Click the Create product button.

    Creating a product.

    This creates the product and automatically opens the pricing plan page. Pricing plans define how much and how frequently you charge for a product. This includes how much the product costs, what currency to use, and the interval to use for recurring charges. Like products, if you only have a few plans it’s generally preferable to manage them in the Dashboard.

    This guide uses a plan with a fixed price, which means customers are charged the same amount on a recurring basis. Charging 15 USD a month for a streaming service or 120 USD for a yearly subscription to an online publication would be two examples of fixed pricing. With the pricing plan page open:

    1. Fill out the Plan nickname field.
    2. In the Price per unit field, enter 15.
    3. Click the Add pricing plan button.

    You have several other options for creating pricing plans, but this basic example results in a plan that:

    • Uses USD
    • Costs 15 USD per subscription
    • Charges customers monthly

    After you create the pricing plan, record the plan ID so it can be used in subsequent steps. It’s displayed on the pricing plan page and should look similar to this plan_G0FvDp6vZvdwRZ.

    2 Set up Stripe Server-side

    Use our official libraries for access to the Stripe API from your application:

    Available as a gem:

    sudo gem install stripe

    If you use bundler, you can use this line:

    gem 'stripe', :git => 'https://github.com/stripe/stripe-ruby'

    Available through pip:

    pip install --upgrade stripe

    Alternatively, you can also use easy_install:

    easy_install --upgrade stripe

    The PHP library can be installed via Composer:

    composer require stripe/stripe-php

    Alternatively, you can download the source directly.

    For Gradle, add the following dependency to your build.gradle:

    implementation "com.stripe:stripe-java:{VERSION}"
    (Replace {VERSION} with the actual version number you want to use. You can find the most recent version on Maven Repository or GitHub.)

    For Maven, add the following dependency to your POM:

    <dependency>
      <groupId>com.stripe</groupId>
      <artifactId>stripe-java</artifactId>
      <version>{VERSION}</version>
    </dependency>
    (Replace {VERSION} with the actual version number you want to use. You can find the most recent version on Maven Repository or GitHub.)

    In other environments, manually install the following JARs:

    Install via npm:

    npm install stripe

    Install via go:

    go get github.com/stripe/stripe-go

    Then import the package:

    import (
      "github.com/stripe/stripe-go"
    )

    Install via dotnet:

    dotnet add package Stripe.net
    dotnet restore

    Or using NuGet:

    PM> Install-Package Stripe.net

    3 Collect card details Client-side

    After creating a product and a plan, you’re ready to collect card information with Stripe Elements on your client. Elements is a set of prebuilt UI components for collecting and validating card numbers, ZIP codes, and expiration dates.

    Set up Stripe Elements

    Stripe Elements is automatically available as a feature of Stripe.js. Include the Stripe.js script on your checkout page by adding it to the head of your HTML file.

    Always load Stripe.js directly from js.stripe.com to remain PCI compliant. Do not include the script in a bundle or host a copy of it yourself.

    <head>
      <title>Checkout</title>
      <script src="https://js.stripe.com/v3/"></script>
      <link rel="stylesheet" href="StripeElements.css">
    </head>
    

    Create an instance of Elements with the following JavaScript on your checkout page:

    // Set your publishable key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    var stripe = Stripe('pk_test_TYooMQauvdEDq54NiTphI7jx');
    var elements = stripe.elements();
    

    Add Elements to your page

    Elements needs a place to live in your payment form. Create empty DOM nodes (containers) with unique IDs in your payment form and then pass those IDs to Elements.

     <!-- Use the CSS tab above to style your Element's container. -->
    <div id="card-element" class="MyCardElement">
      <!-- Elements will create input elements here -->
    </div>
    
    <!-- We'll put the error messages in this element -->
    <div id="card-errors" role="alert"></div>
    
    <button id="submit">Pay</button>
    
    /**
    * Shows how you can use CSS to style your Element's container.
    */
    .MyCardElement {
      height: 40px;
      padding: 10px 12px;
      width: 100%;
      color: #32325d;
      background-color: white;
      border: 1px solid transparent;
      border-radius: 4px;
    
      box-shadow: 0 1px 3px 0 #e6ebf1;
      -webkit-transition: box-shadow 150ms ease;
      transition: box-shadow 150ms ease;
    }
    
    .MyCardElement--focus {
      box-shadow: 0 1px 3px 0 #cfd7df;
    }
    
    .MyCardElement--invalid {
      border-color: #fa755a;
    }
    
    .MyCardElement--webkit-autofill {
      background-color: #fefde5 !important;
    }
    

    When the form above has loaded, create an instance of an Element and mount it to the Element container:

    // Set up Stripe.js and Elements to use in checkout form
    var style = {
      base: {
        color: "#32325d",
        fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
        fontSmoothing: "antialiased",
        fontSize: "16px",
        "::placeholder": {
          color: "#aab7c4"
        }
      },
      invalid: {
        color: "#fa755a",
        iconColor: "#fa755a"
      }
    };
    
    var card = elements.create("card", { style: style });
    card.mount("#card-element");
    

    The card Element simplifies the form and minimizes the number of fields required by inserting a single, flexible input field that securely collects all necessary card details. For a full list of supported Element types, refer to our Stripe.js reference documentation.

    Use the test card number 4242 4242 4242 4242, any three-digit CVC number, any expiration date in the future, and any five-digit ZIP code.

    Elements validates user input as it is typed. To help your customers catch mistakes, listen to change events on the card Element and display any errors:

    card.addEventListener('change', ({error}) => {
      const displayError = document.getElementById('card-errors');
      if (error) {
        displayError.textContent = error.message;
      } else {
        displayError.textContent = '';
      }
    });
    card.addEventListener('change', function(event) {
      var displayError = document.getElementById('card-errors');
      if (event.error) {
        displayError.textContent = event.error.message;
      } else {
        displayError.textContent = '';
      }
    });
    

    ZIP code validation depends on your customer’s billing country. Use our international test cards to experiment with other postal code formats.

    Install react-stripe-elements with npm, yarn, or UDM:

    npm install --save react-stripe-elements
    yarn add react-stripe-elements
    <!-- exports a global ReactStripeElements object -->
    <script src="https://unpkg.com/react-stripe-elements@latest/dist/react-stripe-elements.min.js"></script>

    Stripe Elements is automatically available as a feature of Stripe.js. Include the Stripe.js script on your checkout page by adding it to the head of your HTML file. Always load Stripe.js directly from js.stripe.com to remain PCI compliant. Do not include the script in a bundle or host a copy of it yourself.

    <script src="https://js.stripe.com/v3/"></script>
    <link rel="stylesheet" href="MyCardElement.css">

    Now you can use individual *Element components, such as CardElement, to build your form.

    /**
    * Use the CSS tab above to style your Element's container.
    */
    import React from 'react';
    import {CardElement} from 'react-stripe-elements';
    
    const style = {
      base: {
        color: "#32325d",
        fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
        fontSmoothing: "antialiased",
        fontSize: "16px",
        "::placeholder": {
          color: "#aab7c4"
        }
      },
      invalid: {
        color: "#fa755a",
        iconColor: "#fa755a"
      }
    };
    
    const CardSection = () => {
      return (
        <label>
          Card details
          <CardElement className=“MyCardElement” style={style} />
        </label>
      );
    };
    
    export default CardSection;
    
    /**
    * Shows how you can use CSS to style your Element's container.
    */
    .MyCardElement {
      height: 40px;
      padding: 10px 12px;
      width: 100%;
      color: #32325d;
      background-color: white;
      border: 1px solid transparent;
      border-radius: 4px;
    
      box-shadow: 0 1px 3px 0 #e6ebf1;
      -webkit-transition: box-shadow 150ms ease;
      transition: box-shadow 150ms ease;
    }
    
    .MyCardElement--focus {
      box-shadow: 0 1px 3px 0 #cfd7df;
    }
    
    .MyCardElement--invalid {
      border-color: #fa755a;
    }
    
    .MyCardElement--webkit-autofill {
      background-color: #fefde5 !important;
    }
    

    Elements are completely customizable. You can style Elements to match the look and feel of your site, providing a seamless checkout experience for your customers. It’s also possible to style various input states, for example when the Element has focus.

    Advanced integrations

    This guide outlines the most common integration, which makes the following assumptions:

    • The Stripe.js script is loaded before your application’s code
    • Your code is only run in a browser environment
    • You don’t need fine-tuned control over the Stripe instance that react-stripe-elements uses

    When all of these assumptions are true, you can pass the apiKey prop to <StripeProvider> and let react-stripe-elements handle the rest.

    When one or more of these assumptions doesn’t hold true for your integration, you can pass a Stripe instance as the stripe prop to <StripeProvider> directly. For these integrations, see our React docs on GitHub.

    Add Elements to your page

    For your application to access the Stripe object, add StripeProvider to your root React App component:

    import React from 'react';
    import {render} from 'react-dom';
    import {StripeProvider} from 'react-stripe-elements';
    
    import MyStoreCheckout from './MyStoreCheckout';
    
    const App = () => {
      return (
        <StripeProvider apiKey="pk_test_TYooMQauvdEDq54NiTphI7jx" >
          <MyStoreCheckout />
        </StripeProvider>
      );
    };
    
    render(<App />, document.getElementById('root'));
    

    Next, when you’re building components for your checkout form, you’ll want to wrap the Elements component around your form. This groups the set of Stripe Elements you’re using together, so that Stripe can pull data from groups of Elements when you’re tokenizing.

    Use the test card number 4242 4242 4242 4242, any three-digit CVC number, any expiration date in the future, and any five-digit ZIP code.

    import React from 'react';
    import {Elements} from 'react-stripe-elements';
    import InjectedCheckoutForm from './CheckoutForm';
    
    const MyStoreCheckout = () => {
      return (
        <Elements>
          <InjectedCheckoutForm />
        </Elements>
      );
    };
    
    export default MyStoreCheckout;

    4 Create a PaymentMethod Client-side

    Use createPaymentMethod to convert payment information collected by Elements into a PaymentMethod object that you can safely pass to your server to use in an API call. After the user clicks Submit, a PaymentMethod ID is returned that you can use to create and subscribe a customer.

    stripe.createPaymentMethod('card', cardElement, {
      billing_details: {
        email: 'jenny.rosen@example.com',
      },
    }).then(function(result) {
      // Handle result.error or result.paymentMethod
    });
    
    const {paymentMethod, error} = await stripe.createPaymentMethod('card', cardElement, {
      billing_details: {
        email: 'jenny.rosen@example.com',
      },
    });
    

    You can then use this code to send the payment information to your server for the next step.

    fetch('/create-customer', {
      method: 'post',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        email: 'jenny.rosen@example.com',
        payment_method: 'pm_1FU2bgBF6ERF9jhEQvwnA7sX'
      })
    }).then(response => {
      return response.json();
    })
    .then(customer => {
      // The customer has been created
    });
    
    try {
      const response = await fetch('/create-customer', {
        method: 'post',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          email: 'jenny.rosen@example.com',
          payment_method: 'pm_1FU2bgBF6ERF9jhEQvwnA7sX'
        })
      });
      const customer = response.json();
      // The customer has been created
    } catch (error) {
      // Handle error from server if customer wasn't created
    }
    

    5 Create a customer with a PaymentMethod Server-side

    Creating subscriptions requires a customer, which represents the customer purchasing your product. Because the plan you created charges on a monthly basis, you need to add a stored payment method to the customer so future payments are successful. You do this by setting the payment method you just collected as the default payment method for the customer.

    curl https://api.stripe.com/v1/customers \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d email="jenny.rosen@example.com" \
      -d payment_method=pm_1FU2bgBF6ERF9jhEQvwnA7sX \
      -d "invoice_settings[default_payment_method]"=pm_1FU2bgBF6ERF9jhEQvwnA7sX
    
    # 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'
    
    # This creates a new Customer and attaches the default PaymentMethod in one API call.
    
    customer = Stripe::Customer.create(
      payment_method: "pm_1FU2bgBF6ERF9jhEQvwnA7sX",
      email: "jenny.rosen@example.com",
      invoice_settings: {
        default_payment_method: "pm_1FU2bgBF6ERF9jhEQvwnA7sX",
      }
    )
    
    # 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'
    
    # This creates a new Customer and attaches the default PaymentMethod in one API call.
    customer = stripe.Customer.create(
      payment_method='pm_1FU2bgBF6ERF9jhEQvwnA7sX',
      email='jenny.rosen@example.com',
      invoice_settings={
          'default_payment_method':'pm_1FU2bgBF6ERF9jhEQvwnA7sX'
      }
    )
    
    // 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');
    
    # This creates a new Customer and attaches the default PaymentMethod in one API call.
    $customer = \Stripe\Customer::create([
      "payment_method" => "pm_1FU2bgBF6ERF9jhEQvwnA7sX",
      "email" => "jenny.rosen@example.com",
      "invoice_settings" => [
        "default_payment_method" => "pm_1FU2bgBF6ERF9jhEQvwnA7sX"
      ]
    ]);
    
    // 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";
    
    /**
    * This creates a new Customer and attaches the default PaymentMethod in one API call.
    */
    CreatePaymentBody postBody = gson.fromJson(request.body(), CreatePaymentBody.class);
    Map<String, Object> customerParams = new HashMap<String, Object>();
    customerParams.put("payment_method", "pm_1FU2bgBF6ERF9jhEQvwnA7sX");
    customerParams.put("email", "jenny.rosen@example.com");
    Map<String, String> invoiceSettings = new HashMap<String, String>();
    invoiceSettings.put("default_payment_method", "pm_1FU2bgBF6ERF9jhEQvwnA7sX");
    customerParams.put("invoice_settings", invoiceSettings);
    
    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
    const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    // This creates a new Customer and attaches the PaymentMethod in one API call.
    const customer = await stripe.customers.create({
      payment_method: 'pm_1FU2bgBF6ERF9jhEQvwnA7sX',
      email: 'jenny.rosen@example.com',
      invoice_settings: {
        default_payment_method: 'pm_1FU2bgBF6ERF9jhEQvwnA7sX'
      }
    });
    
    // 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');
    
    customerParams := &stripe.CustomerParams{
      PaymentMethod: stripe.String("pm_1FU2bgBF6ERF9jhEQvwnA7sX"),
      Email: stripe.String("jenny.rosen@example.com"),
      InvoiceSettings: &stripe.CustomerInvoiceSettingsParams{
        DefaultPaymentMethod: stripe.String("pm_1FU2bgBF6ERF9jhEQvwnA7sX"),
      },
    }
    customer, _ := customer.New(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
    const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    var options = new CustomerCreateOptions {
      Email = "jenny.rosen@example.com",
      PaymentMethod = "pm_1FWS6ZClCIKljWvsVCvkdyWg",
      InvoiceSettings = new CustomerInvoiceSettingsOptions {
        DefaultPaymentMethod = "pm_1FWS6ZClCIKljWvsVCvkdyWg",
      },
    };
    
    var service = new CustomerService();
    Customer customer = service.Create(options);
    

    This returns a Customer object. You can see the default payment method in the invoice_settings object:

    {
      "id": "cus_G02hIo15n8CU1s",
      "object": "customer",
      "account_balance": 0,
      "address": null,
      "balance": 0,
      "created": 1571194285,
      "currency": null,
      ...
      "invoice_settings": {
        "custom_fields": null,
        "default_payment_method": "pm_1FU2bgBF6ERF9jhEQvwnA7sX",
        "footer": null
      },
    See all 50 lines "livemode": false, "metadata": { }, "name": null, "phone": null, "preferred_locales": [ ], "shipping": null, "sources": { "object": "list", "data": [ ], "has_more": false, "total_count": 0, "url": "/v1/customers/cus_G02hIo15n8CU1s/sources" }, "subscriptions": { "object": "list", "data": [ ], "has_more": false, "total_count": 0, "url": "/v1/customers/cus_G02hIo15n8CU1s/subscriptions" }, "tax_exempt": "none", "tax_ids": { "object": "list", "data": [ ], "has_more": false, "total_count": 0, "url": "/v1/customers/cus_G02hIo15n8CU1s/tax_ids" }, "tax_info": null, "tax_info_verification": null }

    After creating the customer, store the id value in your own database so you can use it later. The next step also requires this ID.

    6 Create the subscription Server-side

    To create a subscription, combine a plan with a customer:

    curl https://api.stripe.com/v1/subscriptions \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d customer=cus_Frf3x0oGDgU1eg \
      -d "items[0][plan]"=plan_F52b2UdntfQsfR \
      -d "expand[0]"="latest_invoice.payment_intent"
    
    # 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'
    
    subscription = Stripe::Subscription.create(
      customer: "cus_G02hIo15n8CU1s",
      items: [
        {
          plan: 'plan_FSDjyHWis0QVwl'
        }
      ],
      expand: ['latest_invoice.payment_intent']
    )
    
    # 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'
    
    subscription = stripe.Subscription.create(
        customer="cus_G02hIo15n8CU1s",
        items=[
            {
                "plan": "plan_FSDjyHWis0QVwl",
            },
        ],
        expand=["latest_invoice.payment_intent"]
    )
    
    // 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');
    
    $subscription = \Stripe\Subscription::create([
      "customer" => "cus_G02hIo15n8CU1s",
      "items" => [
        [
          "plan" => "plan_FSDjyHWis0QVwl",
        ],
      ],
      "expand" => ['latest_invoice.payment_intent']
    ]);
    
    // 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> item = new HashMap<>();
    item.put("plan", "plan_FSDjyHWis0QVwl");
    Map<String, Object> items = new HashMap<>();
    items.put("0", item);
    Map<String, Object> expand = new HashMap<>();
    expand.put("0", "latest_invoice.payment_intent");
    Map<String, Object> params = new HashMap<>();
    params.put("customer", "cus_G02hIo15n8CU1s");
    params.put("items", items);
    params.put("expand", expand);
    Subscription subscription = Subscription.create(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');
    
    const subscription = await stripe.subscriptions.create({
      customer: "cus_G02hIo15n8CU1s",
      items: [{ plan: "plan_FSDjyHWis0QVwl" }],
      expand: ["latest_invoice.payment_intent"]
    });
    
    // 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');
    
    items := []*stripe.SubscriptionItemsParams{
      {
        Plan: stripe.String("plan_FSDjyHWis0QVwl"),
      },
    }
    params := &stripe.SubscriptionParams{
      Customer: stripe.String("cus_G02hIo15n8CU1s"),
      Items: items,
    }
    params.AddExpand("latest_invoice.payment_intent")
    subscription, _ := sub.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
    const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    var items = new List<SubscriptionItemOption> {
      new SubscriptionItemOption {
        Plan = "plan_CBXbz9i7AIOTzr"
      }
    };
    var options = new SubscriptionCreateOptions {
      Customer = "cus_4fdAW5ftNQow1a",
      Items = items
    };
    options.AddExpand("latest_invoice.payment_intent");
    
    var service = new SubscriptionService();
    Subscription subscription = service.Create(options);
    

    Creating subscriptions automatically charges customers because the default payment method is set. After a successful payment, the status in the Stripe Dashboard changes to Active. The pricing plan you created earlier determines subsequent billings. In this case, that’s 15 USD every month.

    Sometimes payments require additional authentication after they’re submitted. The next step explains how to handle these scenarios.

    7 Manage subscription status Client-side

    Assuming the initial payment succeeds, the state of the subscription is active and no further action is needed. When payments fail, the status is changed to incomplete instead. If payment isn’t completed within 23 hours, the subscription expires.

    To handle these situations, you need to return the subscription back to the client so you can check the latest_invoice.payment_intent.status. If the status is set to requires_action or requires_payment_method, call confirmCardPayment:

    const { latest_invoice } = subscription;
    const { payment_intent } = latest_invoice;
    
    if (payment_intent) {
      const { client_secret, status } = payment_intent;
    
      if (status === 'requires_action') {
        stripe.confirmCardPayment(client_secret).then(function(result) {
          if (result.error) {
            // Display error message in your UI.
            // The card was declined (i.e. insufficient funds, card has expired, etc)
          } else {
            // Show a success message to your customer
          }
        });
      } else {
        // No additional information was needed
        // Show a success message to your customer
      }
    }
    

    confirmCardPayment automatically handles situations where user authentication is required for a payment. The code in the snippet also checks to see if the card was declined so that you can display an error message to the user.

    8 Test the integration

    Now that your integration can manage payment failures, you’ve completed the core steps of this guide. Users can access your site, subscribe to your service, and you can charge them on a recurring basis.

    There are several test cards you can use in test mode to make sure your integration is ready. At a minimum, use the cards listed below to test your integration. You can use these cards with any CVC, postal code, and future expiration date.

    Number Description
    4242424242424242 Succeeds and immediately creates an active subscription.
    4000002500003155 Requires authentication. confirmCardPayment will trigger a modal asking for the customer to authenticate. Once the user confirms, the subscription will become active.
    4000008260003178 Always fails with a decline code of insufficient_funds.

    The optional steps below are some common modifications you can make to your integration. You might also want to review the topics listed in the see also section.

    Optional Setting the billing cycle

    The billing cycles for subscriptions are set automatically when they’re created. For example, if a customer subscribes to a monthly plan on September 7th, they’re billed on the 7th of every month after that. Although some businesses prefer to set the billing cycle manually so that their customers are charged at the same time. The billing cycle anchor argument allows you to do this.

    curl https://api.stripe.com/v1/subscriptions \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d customer=cus_4fdAW5ftNQow1a \
      -d "items[0][plan]"=plan_CBb6IXqvTLXp3f \
      -d billing_cycle_anchor=1574990216
    
    # 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'
    
    subscription = Stripe::Subscription.create({
        customer: 'cus_4fdAW5ftNQow1a',
        items: [{plan: 'plan_CBb6IXqvTLXp3f'}],
        billing_cycle_anchor: 1574990216,
    })
    
    # 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'
    
    subscription = stripe.Subscription.create(
      customer='cus_4fdAW5ftNQow1a',
      items=[{'plan': 'plan_CBb6IXqvTLXp3f'}],
      billing_cycle_anchor=1574990216,
    )
    
    // 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');
    
    $subscription = \Stripe\Subscription::create([
        'customer' => 'cus_4fdAW5ftNQow1a',
        'items' => [['plan' => 'plan_CBb6IXqvTLXp3f']],
        'billing_cycle_anchor' => 1574990216,
    ]);
    
    // 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> item = new HashMap<>();
    item.put("plan", "plan_CBb6IXqvTLXp3f");
    Map<String, Object> items = new HashMap<>();
    items.put("0", item);
    Map<String, Object> params = new HashMap<>();
    params.put("customer", "cus_4fdAW5ftNQow1a");
    params.put("items", items);
    params.put("billing_cycle_anchor", 1574990216);
    Subscription subscription = Subscription.create(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 () => {
      const subscription = await stripe.subscriptions.create({
        customer: 'cus_4fdAW5ftNQow1a',
        items: [{plan: 'plan_CBb6IXqvTLXp3f'}],
        billing_cycle_anchor: 1574990216,
      });
    })();
    
    // 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"
    
    items := []*stripe.SubscriptionItemsParams{
      {
        Plan: stripe.String("plan_CBb6IXqvTLXp3f"),
      },
    }
    params := &stripe.SubscriptionParams{
      Customer: stripe.String("cus_4fdAW5ftNQow1a"),
      Items: items,
      BillingCycleAnchor: stripe.Int64(1574990216),
    }
    subscription, _ := sub.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 items = new List<SubscriptionItemOption> {
        new SubscriptionItemOption {Plan = "plan_CBb6IXqvTLXp3f"}
    };
    var options = new SubscriptionCreateOptions {
        Customer = "cus_4fdAW5ftNQow1a",
        Items = items,
        BillingCycleAnchor = DateTimeOffset.FromUnixTimeSeconds(1574990216).UtcDateTime,
    };
    var service = new SubscriptionService();
    Subscription subscription = service.Create(options);
    

    When setting the billing cycle manually, the customer is automatically charged a prorated amount for the time between the subscription being created and the billing cycle anchor. If you don’t want to charge customers for this time, you can set the prorate argument to false. You can also combine the billing cycle anchor with trial periods to give users free access to your product and then charge them a prorated amount.

    Optional Subscription trials

    Free trials allow customers access to your product for a period of time for free. Using free trials is different from setting prorate to false because you can customize how long the free period lasts. You can set the trial period by passing a timestamp in the trial end argument.

    curl https://api.stripe.com/v1/subscriptions \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d customer=cus_4fdAW5ftNQow1a \
      -d "items[0][plan]"=plan_CBb6IXqvTLXp3f \
      -d trial_end=1574385416
    
    # 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'
    
    subscription = Stripe::Subscription.create({
      customer: 'cus_4fdAW5ftNQow1a',
      items: [{plan: 'plan_CBb6IXqvTLXp3f'}],
      trial_end: 1574385416,
    })
    
    # 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'
    
    subscription = stripe.Subscription.create(
      customer='cus_4fdAW5ftNQow1a',
      items=[{'plan': 'plan_CBb6IXqvTLXp3f'}],
      trial_end=1574385416,
    )
    
    // 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');
    
    $subscription = \Stripe\Subscription::create([
        'customer' => 'cus_4fdAW5ftNQow1a',
        'items' => [['plan' => 'plan_CBb6IXqvTLXp3f']],
        'trial_end' => 1574385416,
    ]);
    
    // 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> item = new HashMap<>();
    item.put("plan", "plan_CBb6IXqvTLXp3f");
    Map<String, Object> items = new HashMap<>();
    items.put("0", item);
    Map<String, Object> params = new HashMap<>();
    params.put("customer", "cus_4fdAW5ftNQow1a");
    params.put("items", items);
    params.put("trial_end", 1574385416);
    Subscription subscription = Subscription.create(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 () => {
      const subscription = await stripe.subscriptions.create({
        customer: 'cus_4fdAW5ftNQow1a',
        items: [{plan: 'plan_CBb6IXqvTLXp3f'}],
        trial_end: 1574385416,
      });
    })();
    
    // 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"
    
    items := []*stripe.SubscriptionItemsParams{
      {
        Plan: stripe.String("plan_CBb6IXqvTLXp3f"),
      },
    }
    params := &stripe.SubscriptionParams{
      Customer: stripe.String("cus_4fdAW5ftNQow1a"),
      Items: items,
      TrialEnd: stripe.Int64(1574385416),
    }
    subscription, _ := sub.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 items = new List<SubscriptionItemOption> {
        new SubscriptionItemOption {Plan = "plan_CBb6IXqvTLXp3f"}
    };
    var options = new SubscriptionCreateOptions {
        Customer = "cus_4fdAW5ftNQow1a",
        Items = items,
        TrialEnd = DateTimeOffset.FromUnixTimeSeconds(1574385416).UtcDateTime,
    };
    var service = new SubscriptionService();
    Subscription subscription = service.Create(options);
    

    You can combine a billing cycle anchor with a free trial if you want. For example, let’s say it’s September 15th and you want to give your customer a free trial for seven days and then start the normal billing cycle on October 1st. You can set the free trial to end on September 22nd and the billing cycle anchor to October 1st. This gives the customer a free trial for seven days and then charges a prorated amount for the time between the trial ending and October 1st. On October 1st, the customer is charged the normal subscription amount for their first full billing cycle.

    Creating subscriptions in the Dashboard is a quick way to get started with Billing and to test some of its features. Using the Dashboard to create subscriptions doesn’t scale well though because it’s a manual process. You should use our APIs and libraries to build an integration when you’re ready to scale your business.

    1 Create a product and plan

    Products are what you sell and you need to create at least one before you can charge for it. In this guide, a stock photo service is used as an example. Generally, if you only have a few products, you should create and manage them in the Stripe Dashboard.

    To create a product in the Stripe Dashboard:

    1. Navigate to the Products page.
    2. Click + Add a test product or + New to create a test product.
    3. Enter a Product name.
    4. Click the Create product button.

    Creating a product.

    This creates the product and automatically opens the pricing plan page. Pricing plans define how much and how frequently you charge for a product. This includes how much the product costs, what currency to use, and the interval to use for recurring charges. Like products, if you only have a few plans it’s preferable to manage them in the Dashboard.

    In this guide, a plan with a fixed price is used. This means customers are charged the same amount on a recurring basis. For example, charging 15 USD a month for a streaming service or 120 USD for a yearly subscription to an online publication. With the pricing plan page open:

    1. Fill out the Plan nickname field.
    2. In the Price per unit field, enter 15.
    3. Click the Add pricing plan button.

    There are several other options for creating pricing plans, but this basic example results in a plan that:

    • Uses USD
    • Costs 15 USD per subscription
    • Charges customers monthly

    2 Create a customer

    Now that you have a product and a pricing plan, you need a customer that you can subscribe to your service. To create a customer in the Stripe Dashboard:

    1. Navigate to the Customers page and click + Add a test customer.
    2. Enter an email, name, and description for the customer.
    3. Click Create customer.

    3 Create the subscription

    Subscriptions are created by combining a plan with a customer. To create a subscription in the Stripe Dashboard:

    1. Navigate to the Subscriptions page and click + Create a test subscription.
    2. Click + Select a customer to add the customer you created.
    3. Click + Add product to add the product you created.
    4. Click the Start subscription button.

    Creating a subscription.

    This creates the subscription and the first invoice. On the Subscriptions page, you can see the subscription is now active.

    With the default settings, an email is sent to the customer every month. This email includes a link to a Stripe-hosted page where they can pay for their subscription. If you want to test this process out:

    1. Open the Invoices page.
    2. Click the invoice for the customer that you just created.
    3. Click Send invoice.
    4. In the Send to field, enter an email address that you have access to.
    5. Click Send invoice.

    In the email that is sent to you, click the Pay this invoice button to open the payment page. On this page:

    1. Enter the test card number 4242 4242 4242 4242in the Card number field.
    2. Enter any expiration date that’s in the future.
    3. Enter any values for the CVC and ZIP fields.
    4. Click Pay invoice.

    You can then go back to the Invoices page in the Stripe Dashboard to verify the status has been updated to Paid. Depending on the timing, you might need to refresh the page for the status to update.

    See also

    Now that you have a basic subscriptions integration, you might want to read about how you can customize it.

    Was this page helpful?

    Thank you for helping improve Stripe's documentation. If you need help or have any questions, please consider contacting support.

    On this page