Learn how to create a subscription with the Stripe API, including setting up customers, products, prices, and handling payments. Step-by-step guide for developers.
Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
Introduction
This tutorial will guide you through the process of creating a subscription using the Stripe API. Stripe is a popular payment processing platform that offers a robust API for handling subscriptions, payments, and more. By the end of this tutorial, you'll know how to set up customers, products, prices, and create subscriptions.
Step 1: Set Up Your Stripe Account
Before you can use the Stripe API, you need to create a Stripe account and get your API keys.
For development purposes, use the test API keys that start with sk_test_
.
Step 2: Install the Stripe Library
Depending on your programming language, you'll need to install the appropriate Stripe library. Here are examples for popular languages:
For Node.js:
npm install stripe
For Python:
pip install stripe
For PHP:
composer require stripe/stripe-php
For Ruby:
gem install stripe
Step 3: Initialize the Stripe Client
After installing the library, you need to initialize the Stripe client with your API key.
Node.js:
const stripe = require('stripe')('sk_test_your_test_key');
Python:
import stripe
stripe.api_key = 'sk_test_your_test\_key'
PHP:
\Stripe\Stripe::setApiKey('sk_test_your_test_key');
Ruby:
require 'stripe'
Stripe.api_key = 'sk_test_your_test\_key'
Step 4: Create a Customer
Before creating a subscription, you need to create a customer and attach a payment method to them.
Node.js:
async function createCustomer() {
const customer = await stripe.customers.create({
email: '[email protected]',
name: 'John Doe',
description: 'Customer for subscription'
});
console.log('Created customer:', customer.id);
return customer;
}
Python:
def create\_customer():
customer = stripe.Customer.create(
email='[email protected]',
name='John Doe',
description='Customer for subscription'
)
print(f"Created customer: {customer.id}")
return customer
Step 5: Attach a Payment Method to the Customer
For a subscription to work, the customer needs a valid payment method.
Node.js:
async function attachPaymentMethod(customerId, paymentMethodId) {
// Attach the payment method to the customer
await stripe.paymentMethods.attach(paymentMethodId, {
customer: customerId,
});
// Set it as the default payment method
await stripe.customers.update(customerId, {
invoice\_settings: {
default_payment_method: paymentMethodId,
},
});
console.log('Payment method attached and set as default');
}
Python:
def attach_payment_method(customer_id, payment_method\_id):
# Attach the payment method to the customer
stripe.PaymentMethod.attach(
payment_method_id,
customer=customer\_id,
)
# Set it as the default payment method
stripe.Customer.modify(
customer\_id,
invoice\_settings={
'default_payment_method': payment_method_id,
},
)
print('Payment method attached and set as default')
Step 6: Create a Product
Products represent what you're selling. Each product can have multiple prices.
Node.js:
async function createProduct() {
const product = await stripe.products.create({
name: 'Premium Subscription',
description: 'Monthly premium subscription with all features',
});
console.log('Created product:', product.id);
return product;
}
Python:
def create\_product():
product = stripe.Product.create(
name='Premium Subscription',
description='Monthly premium subscription with all features',
)
print(f"Created product: {product.id}")
return product
Step 7: Create a Price for the Product
Prices define how much and how often to charge for products.
Node.js:
async function createPrice(productId) {
const price = await stripe.prices.create({
product: productId,
unit\_amount: 1999, // $19.99
currency: 'usd',
recurring: {
interval: 'month', // 'day', 'week', 'month', or 'year'
},
});
console.log('Created price:', price.id);
return price;
}
Python:
def create_price(product_id):
price = stripe.Price.create(
product=product\_id,
unit\_amount=1999, # $19.99
currency='usd',
recurring={
'interval': 'month', # 'day', 'week', 'month', or 'year'
},
)
print(f"Created price: {price.id}")
return price
Step 8: Create a Subscription
Now you can create a subscription by connecting the customer with the price.
Node.js:
async function createSubscription(customerId, priceId) {
const subscription = await stripe.subscriptions.create({
customer: customerId,
items: [
{
price: priceId,
},
],
payment_behavior: 'default_incomplete',
expand: ['latest_invoice.payment_intent'],
});
console.log('Created subscription:', subscription.id);
return subscription;
}
Python:
def create_subscription(customer_id, price\_id):
subscription = stripe.Subscription.create(
customer=customer\_id,
items=[
{
'price': price\_id,
},
],
payment_behavior='default_incomplete',
expand=['latest_invoice.payment_intent'],
)
print(f"Created subscription: {subscription.id}")
return subscription
Step 9: Handle the Subscription Status
After creating a subscription, you need to check its status and handle any required actions.
Node.js:
async function handleSubscriptionStatus(subscription) {
const status = subscription.status;
const clientSecret = subscription.latest_invoice.payment_intent.client\_secret;
if (status === 'active') {
console.log('Subscription is active!');
} else if (status === 'incomplete') {
console.log('Subscription requires additional action. Use this client secret with Stripe.js to complete the payment:', clientSecret);
} else {
console.log('Subscription status:', status);
}
}
Python:
def handle_subscription_status(subscription):
status = subscription.status
client_secret = subscription.latest_invoice.payment_intent.client_secret
if status == 'active':
print('Subscription is active!')
elif status == 'incomplete':
print(f"Subscription requires additional action. Use this client secret with Stripe.js to complete the payment: {client\_secret}")
else:
print(f"Subscription status: {status}")
Step 10: Complete Flow Example
Here's a complete example that ties everything together:
Node.js:
async function createStripeSubscription() {
try {
// Create a customer
const customer = await createCustomer();
// For this example, we'll assume you've already collected and created a payment method
// This would typically happen on your frontend using Stripe Elements or Checkout
const paymentMethodId = 'pm_card_visa'; // In real scenarios, this comes from your frontend
// Attach payment method to customer
await attachPaymentMethod(customer.id, paymentMethodId);
// Create a product
const product = await createProduct();
// Create a price
const price = await createPrice(product.id);
// Create a subscription
const subscription = await createSubscription(customer.id, price.id);
// Handle the subscription status
await handleSubscriptionStatus(subscription);
return subscription;
} catch (error) {
console.error('Error creating subscription:', error);
throw error;
}
}
// Execute the function
createStripeSubscription()
.then(subscription => {
console.log('Successfully set up subscription process!');
})
.catch(error => {
console.error('Failed to set up subscription:', error);
});
Python:
def create_stripe_subscription():
try:
# Create a customer
customer = create\_customer()
# For this example, we'll assume you've already collected and created a payment method
# This would typically happen on your frontend using Stripe Elements or Checkout
payment_method_id = 'pm_card_visa' # In real scenarios, this comes from your frontend
# Attach payment method to customer
attach_payment_method(customer.id, payment_method_id)
# Create a product
product = create\_product()
# Create a price
price = create\_price(product.id)
# Create a subscription
subscription = create\_subscription(customer.id, price.id)
# Handle the subscription status
handle_subscription_status(subscription)
return subscription
except Exception as e:
print(f"Error creating subscription: {str(e)}")
raise
# Execute the function
try:
subscription = create_stripe_subscription()
print("Successfully set up subscription process!")
except Exception as e:
print(f"Failed to set up subscription: {str(e)}")
Step 11: Set Up Webhook Handling
For a production environment, you should set up webhooks to receive notifications about subscription events like payments, renewals, and cancellations.
Node.js (with Express):
const express = require('express');
const app = express();
// This is your Stripe CLI webhook secret for testing
const endpointSecret = 'whsec_your_webhook\_secret';
app.post('/webhook', express.raw({type: 'application/json'}), (request, response) => {
const sig = request.headers['stripe-signature'];
let event;
try {
event = stripe.webhooks.constructEvent(request.body, sig, endpointSecret);
} catch (err) {
response.status(400).send(`Webhook Error: ${err.message}`);
return;
}
// Handle the event
switch (event.type) {
case 'customer.subscription.created':
const subscriptionCreated = event.data.object;
console.log('Subscription created:', subscriptionCreated.id);
// Then define and call a function to handle the subscription creation
break;
case 'customer.subscription.updated':
const subscriptionUpdated = event.data.object;
console.log('Subscription updated:', subscriptionUpdated.id);
// Then define and call a function to handle the subscription update
break;
case 'invoice.payment\_succeeded':
const invoice = event.data.object;
console.log('Invoice paid:', invoice.id);
// Then define and call a function to handle the successful payment
break;
// ... handle other event types
default:
console.log(`Unhandled event type ${event.type}`);
}
// Return a 200 response to acknowledge receipt of the event
response.send();
});
app.listen(4242, () => console.log('Running on port 4242'));
Python (with Flask):
from flask import Flask, request, jsonify
import stripe
app = Flask(**name**)
# This is your Stripe CLI webhook secret for testing
endpoint_secret = 'whsec_your_webhook_secret'
@app.route('/webhook', methods=['POST'])
def webhook():
payload = request.get_data(as_text=True)
sig\_header = request.headers.get('Stripe-Signature')
try:
event = stripe.Webhook.construct\_event(
payload, sig_header, endpoint_secret
)
except ValueError as e:
# Invalid payload
return jsonify(success=False), 400
except stripe.error.SignatureVerificationError as e:
# Invalid signature
return jsonify(success=False), 400
# Handle the event
if event['type'] == 'customer.subscription.created':
subscription = event\['data']\['object']
print(f"Subscription created: {subscription['id']}")
# Handle the subscription creation
elif event['type'] == 'customer.subscription.updated':
subscription = event\['data']\['object']
print(f"Subscription updated: {subscription['id']}")
# Handle the subscription update
elif event['type'] == 'invoice.payment\_succeeded':
invoice = event\['data']\['object']
print(f"Invoice paid: {invoice['id']}")
# Handle the successful payment
# ... handle other event types
else:
print(f"Unhandled event type {event['type']}")
return jsonify(success=True)
if **name** == '**main**':
app.run(port=4242)
Conclusion
You've now learned how to create a subscription with the Stripe API. This includes setting up customers, products, prices, and handling the subscription lifecycle. Remember to test thoroughly in the Stripe test environment before going to production.
For a complete implementation, you'll also need to:
Always refer to the official Stripe documentation for the most up-to-date information:
https://stripe.com/docs/api
When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.