/stripe-guides

How to use Stripe API with Python?

Learn how to integrate Stripe API with Python: set up your account, install the library, create payments, handle subscriptions, webhooks, errors, and go live securely.

Matt Graham, CEO of Rapid 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.

Book a free consultation

How to use Stripe API with Python?

How to Use Stripe API with Python

 

Step 1: Set Up a Stripe Account

 

Before you can use the Stripe API, you need to create a Stripe account:

  1. Go to https://stripe.com and sign up for an account.
  2. Navigate to the Developers section to access your API keys.
  3. Take note of your Publishable Key and Secret Key. The Secret Key must be kept confidential as it provides full access to your account.

 

Step 2: Install the Stripe Python Library

 

Install the Stripe Python library using pip:

pip install stripe

 

Step 3: Configure Your API Keys

 

In your Python script, import the Stripe library and configure it with your Secret Key:

import stripe

# Set your secret key
stripe.api_key = "sk_test_your_test\_key"

# Optionally set API version (recommended)
stripe.api\_version = "2023-10-16"

Always use your test keys for development and testing. Replace with live keys only in production.

 

Step 4: Basic Operations with Stripe API

 

Creating a Customer

 

def create\_customer(email, name):
    try:
        customer = stripe.Customer.create(
            email=email,
            name=name,
            description="New customer"
        )
        print(f"Success: Created customer with ID: {customer.id}")
        return customer
    except stripe.error.StripeError as e:
        print(f"Error: {e}")
        return None

# Example usage
new_customer = create_customer("[email protected]", "John Doe")

 

Creating a Payment Method

 

def create_payment_method(card_number, exp_month, exp\_year, cvc):
    try:
        payment\_method = stripe.PaymentMethod.create(
            type="card",
            card={
                "number": card\_number,
                "exp_month": exp_month,
                "exp_year": exp_year,
                "cvc": cvc,
            }
        )
        print(f"Success: Created payment method with ID: {payment\_method.id}")
        return payment\_method
    except stripe.error.StripeError as e:
        print(f"Error: {e}")
        return None

# Example usage with test card
payment_method = create_payment\_method(
    "4242424242424242",  # Test card number
    12,                  # Expiration month
    2025,                # Expiration year
    "123"                # CVC
)

 

Step 5: Creating and Processing Payments

 

Creating a Payment Intent

 

def create_payment_intent(amount, currency, customer_id=None, payment_method\_id=None):
    try:
        params = {
            "amount": amount,  # Amount in cents
            "currency": currency,
            "payment_method_types": ["card"],
        }
        
        if customer\_id:
            params["customer"] = customer\_id
            
        if payment_method_id:
            params["payment_method"] = payment_method\_id
            params["confirm"] = True
            params["return\_url"] = "https://yourwebsite.com/return"
            
        payment\_intent = stripe.PaymentIntent.create(\*\*params)
        print(f"Success: Created payment intent with ID: {payment\_intent.id}")
        return payment\_intent
    except stripe.error.StripeError as e:
        print(f"Error: {e}")
        return None

# Example usage
payment_intent = create_payment\_intent(2000, "usd")  # $20.00

 

Confirming a Payment Intent

 

def confirm_payment_intent(payment_intent_id, payment_method_id):
    try:
        payment\_intent = stripe.PaymentIntent.confirm(
            payment_intent_id,
            payment_method=payment_method\_id
        )
        
        if payment\_intent.status == "succeeded":
            print("Payment succeeded!")
        elif payment_intent.status == "requires_action":
            print("Additional authentication required.")
            print(f"Client secret: {payment_intent.client_secret}")
        else:
            print(f"Payment status: {payment\_intent.status}")
            
        return payment\_intent
    except stripe.error.StripeError as e:
        print(f"Error: {e}")
        return None

# Example usage
confirmed_intent = confirm_payment_intent("pi_123456789", "pm\_987654321")

 

Step 6: Handling Subscriptions

 

Creating a Product and Price

 

def create_product_and_price(product_name, price\_amount, currency, interval="month"):
    try:
        # Create a product
        product = stripe.Product.create(
            name=product\_name,
            description=f"{product\_name} subscription"
        )
        
        # Create a price for the product
        price = stripe.Price.create(
            product=product.id,
            unit_amount=price_amount,  # Amount in cents
            currency=currency,
            recurring={"interval": interval}
        )
        
        print(f"Created product {product.id} with price {price.id}")
        return product, price
    except stripe.error.StripeError as e:
        print(f"Error: {e}")
        return None, None

# Example usage
product, price = create_product_and\_price("Premium Plan", 1999, "usd")  # $19.99/month

 

Creating a Subscription

 

def create_subscription(customer_id, price\_id):
    try:
        subscription = stripe.Subscription.create(
            customer=customer\_id,
            items=[{"price": price\_id}],
            payment_behavior="default_incomplete",
            payment_settings={"save_default_payment_method": "on\_subscription"},
            expand=["latest_invoice.payment_intent"]
        )
        
        print(f"Created subscription with ID: {subscription.id}")
        client_secret = subscription.latest_invoice.payment_intent.client_secret
        print(f"Client secret for payment: {client\_secret}")
        
        return subscription
    except stripe.error.StripeError as e:
        print(f"Error: {e}")
        return None

# Example usage
subscription = create_subscription("cus_123456789", "price\_987654321")

 

Step 7: Handling Webhooks

 

Webhooks allow Stripe to notify your application when events happen in your account.

from flask import Flask, request, jsonify
import stripe
import os

app = Flask(**name**)
stripe.api_key = "sk_test_your_test\_key"
webhook_secret = "whsec_your_webhook_secret"

@app.route('/webhook', methods=['POST'])
def webhook():
    payload = request.data
    sig\_header = request.headers.get('Stripe-Signature')
    
    try:
        event = stripe.Webhook.construct\_event(
            payload, sig_header, webhook_secret
        )
    except ValueError as e:
        # Invalid payload
        return jsonify({'error': str(e)}), 400
    except stripe.error.SignatureVerificationError as e:
        # Invalid signature
        return jsonify({'error': str(e)}), 400
    
    # Handle the event
    if event.type == 'payment\_intent.succeeded':
        payment\_intent = event.data.object
        print(f"Payment succeeded for amount {payment\_intent.amount}!")
        # Fulfill the order
        
    elif event.type == 'customer.subscription.created':
        subscription = event.data.object
        print(f"Subscription created: {subscription.id}")
        
    elif event.type == 'invoice.payment\_failed':
        invoice = event.data.object
        print(f"Payment failed for invoice {invoice.id}")
        # Notify the customer
    
    # Add more event handlers as needed
    
    return jsonify({'status': 'success'}), 200

if **name** == '**main**':
    app.run(port=4242)

 

Step 8: Error Handling

 

Proper error handling is crucial when working with payment APIs:

def process_payment_with_error_handling(amount, currency, payment_method_id):
    try:
        payment\_intent = stripe.PaymentIntent.create(
            amount=amount,
            currency=currency,
            payment_method=payment_method\_id,
            confirm=True
        )
        return payment\_intent
        
    except stripe.error.CardError as e:
        # Card was declined
        err = e.error
        print(f"Card error: {err.code}: {err.message}")
        return {"error": err.message}
        
    except stripe.error.RateLimitError as e:
        # Too many requests made to the API too quickly
        print(f"Rate limit error: {e}")
        return {"error": "Rate limit exceeded, please try again later"}
        
    except stripe.error.InvalidRequestError as e:
        # Invalid parameters were supplied to Stripe's API
        print(f"Invalid request error: {e}")
        return {"error": "Invalid request parameters"}
        
    except stripe.error.AuthenticationError as e:
        # Authentication with Stripe's API failed
        print(f"Authentication error: {e}")
        return {"error": "Authentication with Stripe failed"}
        
    except stripe.error.APIConnectionError as e:
        # Network communication with Stripe failed
        print(f"API connection error: {e}")
        return {"error": "Network error, could not connect to Stripe"}
        
    except stripe.error.StripeError as e:
        # Generic Stripe error
        print(f"Stripe error: {e}")
        return {"error": "Payment processing failed"}
        
    except Exception as e:
        # Something else happened, completely unrelated to Stripe
        print(f"Unexpected error: {e}")
        return {"error": "An unexpected error occurred"}

# Example usage
result = process_payment_with_error_handling(2000, "usd", "pm_card_visa")

 

Step 9: Testing Your Integration

 

Stripe provides test cards and other tools to help you test your integration:

def test_different_card\_scenarios():
    # Test successful payment
    print("Testing successful payment...")
    process_payment_with_error_handling(2000, "usd", "pm_card_visa")
    
    # Test card declined
    print("\nTesting declined card...")
    process_payment_with_error_handling(2000, "usd", "pm_card_declined")
    
    # Test insufficient funds
    print("\nTesting insufficient funds...")
    process_payment_with_error_handling(2000, "usd", "pm_card_insufficient\_funds")
    
    # Test card requiring authentication
    print("\nTesting card requiring authentication...")
    process_payment_with_error_handling(2000, "usd", "pm_card_threeDSecure2Required")

# Run the tests
test_different_card\_scenarios()

 

Step 10: Going to Production

 

When you're ready to accept real payments:

  1. Switch from test API keys to live API keys.
  2. Ensure your website is using HTTPS.
  3. Implement proper security measures to protect sensitive data.
  4. Set up proper logging and monitoring.
import os
import logging

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    filename='stripe\_payments.log'
)

# Use environment variables for API keys
if os.environ.get('ENVIRONMENT') == 'production':
    stripe.api_key = os.environ.get('STRIPE_LIVE_SECRET_KEY')
    logging.info("Using LIVE Stripe API key")
else:
    stripe.api_key = os.environ.get('STRIPE_TEST_SECRET_KEY')
    logging.info("Using TEST Stripe API key")

def create_payment(amount, currency, payment_method_id, customer_email):
    try:
        # Log the attempt but never log full card details
        logging.info(f"Processing payment for {customer\_email}, amount: {amount} {currency}")
        
        payment\_intent = stripe.PaymentIntent.create(
            amount=amount,
            currency=currency,
            payment_method=payment_method\_id,
            confirm=True,
            receipt_email=customer_email
        )
        
        logging.info(f"Payment succeeded: {payment\_intent.id}")
        return payment\_intent
        
    except Exception as e:
        logging.error(f"Payment failed: {str(e)}")
        raise

 

Step 11: Advanced Features - Connect

 

If you're building a marketplace or platform that needs to split payments between different parties:

def create_connect_account(email, country):
    try:
        account = stripe.Account.create(
            type="express",
            country=country,
            email=email,
            capabilities={
                "card\_payments": {"requested": True},
                "transfers": {"requested": True}
            }
        )
        
        print(f"Created Connect account: {account.id}")
        
        # Generate an account link for onboarding
        account\_link = stripe.AccountLink.create(
            account=account.id,
            refresh\_url="https://example.com/reauth",
            return\_url="https://example.com/return",
            type="account\_onboarding"
        )
        
        print(f"Onboarding URL: {account\_link.url}")
        return account, account\_link.url
        
    except stripe.error.StripeError as e:
        print(f"Error creating Connect account: {e}")
        return None, None

# Create a payment that sends a portion to a connected account
def create_split_payment(amount, currency, payment_method, platform_fee, connected_account_id):
    try:
        payment\_intent = stripe.PaymentIntent.create(
            amount=amount,
            currency=currency,
            payment_method=payment_method,
            confirm=True,
            application_fee_amount=platform\_fee,
            transfer\_data={
                "destination": connected_account_id
            }
        )
        
        print(f"Created split payment: {payment\_intent.id}")
        print(f"Amount to connected account: {amount - platform\_fee}")
        print(f"Platform fee: {platform\_fee}")
        
        return payment\_intent
        
    except stripe.error.StripeError as e:
        print(f"Error creating split payment: {e}")
        return None

# Example usage
connected_account, onboarding_url = create_connect_account("[email protected]", "US")
split_payment = create_split_payment(2000, "usd", "pm_card_visa", 200, "acct_123456")

 

Step 12: Advanced Features - Strong Customer Authentication (SCA)

 

For European customers, you need to handle Strong Customer Authentication (SCA) requirements:

def create_payment_intent_with_sca_handling(amount, currency, customer_id, payment_method_id):
    try:
        # Create a PaymentIntent with the order amount and currency
        intent = stripe.PaymentIntent.create(
            amount=amount,
            currency=currency,
            customer=customer\_id,
            payment_method=payment_method\_id,
            confirmation\_method="manual",
            confirm=True,
            return\_url="https://example.com/return"
        )
        
        if intent.status == "requires\_action":
            # Tell the client to handle the action
            return {
                "requires\_action": True,
                "payment_intent_client_secret": intent.client_secret
            }
        elif intent.status == "succeeded":
            # The payment didn't need any additional actions and completed!
            return {"success": True}
        else:
            # Invalid status
            return {"error": f"Invalid PaymentIntent status: {intent.status}"}
            
    except stripe.error.CardError as e:
        return {"error": e.error.message}
        
    except Exception as e:
        return {"error": str(e)}

# Frontend code (JavaScript) would handle the client\_secret and use Stripe.js
# to complete the payment authentication when required

 

Conclusion

 

You've now learned how to use the Stripe API with Python for a variety of payment scenarios. Remember to:

  • Always keep your API keys secure
  • Implement proper error handling
  • Test thoroughly before going to production
  • Stay updated with Stripe API changes and security best practices

Refer to the official Stripe documentation (https://stripe.com/docs/api) for detailed information on all available endpoints and features.

Want to explore opportunities to work with us?

Connect with our team to unlock the full potential of no-code solutions with a no-commitment consultation!

Book a Free Consultation

Client trust and success are our top priorities

When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.

Rapid Dev was an exceptional project management organization and the best development collaborators I've had the pleasure of working with. They do complex work on extremely fast timelines and effectively manage the testing and pre-launch process to deliver the best possible product. I'm extremely impressed with their execution ability.

CPO, Praction - Arkady Sokolov

May 2, 2023

Working with Matt was comparable to having another co-founder on the team, but without the commitment or cost. He has a strategic mindset and willing to change the scope of the project in real time based on the needs of the client. A true strategic thought partner!

Co-Founder, Arc - Donald Muir

Dec 27, 2022

Rapid Dev are 10/10, excellent communicators - the best I've ever encountered in the tech dev space. They always go the extra mile, they genuinely care, they respond quickly, they're flexible, adaptable and their enthusiasm is amazing.

Co-CEO, Grantify - Mat Westergreen-Thorne

Oct 15, 2022

Rapid Dev is an excellent developer for no-code and low-code solutions.
We’ve had great success since launching the platform in November 2023. In a few months, we’ve gained over 1,000 new active users. We’ve also secured several dozen bookings on the platform and seen about 70% new user month-over-month growth since the launch.

Co-Founder, Church Real Estate Marketplace - Emmanuel Brown

May 1, 2024 

Matt’s dedication to executing our vision and his commitment to the project deadline were impressive. 
This was such a specific project, and Matt really delivered. We worked with a really fast turnaround, and he always delivered. The site was a perfect prop for us!

Production Manager, Media Production Company - Samantha Fekete

Sep 23, 2022