
Stripe Integration
- 11.2k installs
- 38.5k repo stars
- Updated July 22, 2026
- wshobson/agents
How to implement PCI-compliant payment processing using Stripe checkout sessions, payment intents, subscriptions, and webhook handlers.
About
This skill covers implementing Stripe payment processing including checkout sessions, payment intents, subscriptions, webhooks, and customer management. Developers use it when building payment flows for one-time purchases, recurring billing, or marketplace transactions. Core workflows include setting up checkout sessions (recommended for most cases), handling subscription lifecycle events via webhooks (payment_intent.succeeded, customer.subscription.updated), managing customer records and payment methods, and testing with Stripe's test mode and card numbers. The skill emphasizes PCI-compliant patterns and provides Python SDK examples for quick integration.
- Checkout sessions recommended for most integrations with built-in support for discounts, tax, shipping, and saved paymen
- Payment Intents for bespoke control when custom amount calculation (taxes, discounts, currency) is required
- Setup Intents to collect and save payment methods without charging for future recurring payments
- Critical webhook events: payment_intent.succeeded, payment_intent.payment_failed, customer.subscription.updated, custome
- Test mode with predefined card numbers (4242424242424242 success, 4000000000000002 declined, 4000002500003155 3D Secure)
Stripe Integration by the numbers
- 11,151 all-time installs (skills.sh)
- +182 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #73 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Security screen: HIGH risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
stripe-integration capabilities & compatibility
- Capabilities
- create and manage checkout sessions · handle payment intents with custom amounts · implement webhook listeners for payment events · manage customer records and payment methods · process subscriptions and recurring charges · handle refunds and disputes · test with stripe test mode and card numbers
- Works with
- stripe
- Use cases
- api development
- Platforms
- macOS · Windows · Linux
- Runs
- Remote server
- Pricing
- Bring your own API key
npx skills add https://github.com/wshobson/agents --skill stripe-integrationAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 11.2k |
|---|---|
| repo stars | ★ 38.5k |
| Security audit | 2 / 3 scanners passed |
| Last updated | July 22, 2026 |
| Repository | wshobson/agents ↗ |
What it does
Integrate Stripe payment processing for checkout, subscriptions, and webhooks in web or mobile applications.
Who is it for?
Web/mobile apps requiring payment processing, SaaS platforms with subscription models, marketplaces, ecommerce stores, recurring billing systems.
Skip if: Applications that do not accept payments or use non-Stripe payment processors.
When should I use this skill?
Building checkout flow, implementing subscriptions, handling refunds, collecting payment methods, processing webhooks, or integrating marketplace payments.
What you get
Developers can integrate Stripe to accept payments, manage subscriptions, store payment methods, and handle refunds without building custom PCI-compliant infrastructure.
- Checkout session creation code
- Webhook listener implementation
- Subscription management code
By the numbers
- 6 critical webhook events documented: payment_intent.succeeded, payment_intent.payment_failed, customer.subscription.upd
- 4 test card scenarios provided: success (4242424242424242), declined (4000000000000002), 3D Secure (4000002500003155), i
- 3 core payment flow patterns: Checkout Sessions, Payment Intents, Setup Intents
Files
Stripe Integration
Master Stripe payment processing integration for robust, PCI-compliant payment flows including checkout, subscriptions, webhooks, and refunds.
When to Use This Skill
- Implementing payment processing in web/mobile applications
- Setting up subscription billing systems
- Handling one-time payments and recurring charges
- Processing refunds and disputes
- Managing customer payment methods
- Implementing SCA (Strong Customer Authentication) for European payments
- Building marketplace payment flows with Stripe Connect
Core Concepts
1. Payment Flows
Checkout Sessions
- Recommended for most integrations
- Supports all UI paths:
- Stripe-hosted checkout page
- Embedded checkout form
- Custom UI with Elements (Payment Element, Express Checkout Element) using
ui_mode='custom' - Provides built-in checkout capabilities (line items, discounts, tax, shipping, address collection, saved payment methods, and checkout lifecycle events)
- Lower integration and maintenance burden than Payment Intents
Payment Intents (Bespoke control)
- You calculate the final amount with taxes, discounts, subscriptions, and currency conversion yourself.
- More complex implementation and long-term maintenance burden
- Requires Stripe.js for PCI compliance
Setup Intents (Save Payment Methods)
- Collect payment method without charging
- Used for subscriptions and future payments
- Requires customer confirmation
2. Webhooks
Critical Events:
payment_intent.succeeded: Payment completedpayment_intent.payment_failed: Payment failedcustomer.subscription.updated: Subscription changedcustomer.subscription.deleted: Subscription canceledcharge.refunded: Refund processedinvoice.payment_succeeded: Subscription payment successful
3. Subscriptions
Components:
- Product: What you're selling
- Price: How much and how often
- Subscription: Customer's recurring payment
- Invoice: Generated for each billing cycle
4. Customer Management
- Create and manage customer records
- Store multiple payment methods
- Track customer metadata
- Manage billing details
Quick Start
import stripe
stripe.api_key = "sk_test_..."
# Create a checkout session
session = stripe.checkout.Session.create(
line_items=[{
'price_data': {
'currency': 'usd',
'product_data': {
'name': 'Premium Subscription',
},
'unit_amount': 2000, # $20.00
'recurring': {
'interval': 'month',
},
},
'quantity': 1,
}],
mode='subscription',
success_url='https://yourdomain.com/success?session_id={CHECKOUT_SESSION_ID}',
cancel_url='https://yourdomain.com/cancel'
)
# Redirect user to session.url
print(session.url)Detailed patterns and worked examples
Detailed pattern documentation lives in references/details.md. Read that file when the navigation tier above is insufficient.
Testing
# Use test mode keys
stripe.api_key = "sk_test_..."
# Test card numbers
TEST_CARDS = {
'success': '4242424242424242',
'declined': '4000000000000002',
'3d_secure': '4000002500003155',
'insufficient_funds': '4000000000009995'
}
def test_payment_flow():
"""Test complete payment flow."""
# Create test customer
customer = stripe.Customer.create(
email="test@example.com"
)
# Create payment intent
intent = stripe.PaymentIntent.create(
amount=1000,
automatic_payment_methods={
'enabled': True
},
currency='usd',
customer=customer.id
)
# Confirm with test card
confirmed = stripe.PaymentIntent.confirm(
intent.id,
payment_method='pm_card_visa' # Test payment method
)
assert confirmed.status == 'succeeded'stripe-integration — detailed patterns and worked examples
Payment Implementation Patterns
Pattern 1: One-Time Payment (Hosted Checkout)
def create_checkout_session(amount, currency='usd'):
"""Create a one-time payment checkout session."""
try:
session = stripe.checkout.Session.create(
line_items=[{
'price_data': {
'currency': currency,
'product_data': {
'name': 'Blue T-shirt',
'images': ['https://example.com/product.jpg'],
},
'unit_amount': amount, # Amount in cents
},
'quantity': 1,
}],
mode='payment',
success_url='https://yourdomain.com/success?session_id={CHECKOUT_SESSION_ID}',
cancel_url='https://yourdomain.com/cancel',
metadata={
'order_id': 'order_123',
'user_id': 'user_456'
}
)
return session
except stripe.error.StripeError as e:
# Handle error
print(f"Stripe error: {e.user_message}")
raisePattern 2: Elements with Checkout Sessions
def create_checkout_session_for_elements(amount, currency='usd'):
"""Create a checkout session configured for Payment Element."""
session = stripe.checkout.Session.create(
mode='payment',
ui_mode='custom',
line_items=[{
'price_data': {
'currency': currency,
'product_data': {'name': 'Blue T-shirt'},
'unit_amount': amount,
},
'quantity': 1,
}],
return_url='https://yourdomain.com/complete?session_id={CHECKOUT_SESSION_ID}'
)
return session.client_secret # Send to frontendconst stripe = Stripe("pk_test_...");
const appearance = { theme: "stripe" };
const checkout = stripe.initCheckout({
clientSecret,
elementsOptions: { appearance },
});
const loadActionsResult = await checkout.loadActions();
if (loadActionsResult.type === "success") {
const { actions } = loadActionsResult;
const session = actions.getSession();
const button = document.getElementById("pay-button");
const checkoutContainer = document.getElementById("checkout-container");
const emailInput = document.getElementById("email");
const emailErrors = document.getElementById("email-errors");
const errors = document.getElementById("confirm-errors");
// Display a formatted string representing the total amount
checkoutContainer.append(`Total: ${session.total.total.amount}`);
// Mount Payment Element
const paymentElement = checkout.createPaymentElement();
paymentElement.mount("#payment-element");
// Store email for submission
emailInput.addEventListener("blur", () => {
actions.updateEmail(emailInput.value).then((result) => {
if (result.error) emailErrors.textContent = result.error.message;
});
});
// Handle form submission
button.addEventListener("click", () => {
actions.confirm().then((result) => {
if (result.type === "error") errors.textContent = result.error.message;
});
});
}Pattern 3: Elements with Payment Intents
Pattern 2 (Elements with Checkout Sessions) is Stripe's recommended approach, but you can also use Payment Intents as an alternative.
def create_payment_intent(amount, currency='usd', customer_id=None):
"""Create a payment intent for bespoke checkout UI with Payment Element."""
intent = stripe.PaymentIntent.create(
amount=amount,
currency=currency,
customer=customer_id,
automatic_payment_methods={
'enabled': True,
},
metadata={
'integration_check': 'accept_a_payment'
}
)
return intent.client_secret # Send to frontend// Mount Payment Element and confirm via Payment Intents
const stripe = Stripe("pk_test_...");
const appearance = { theme: "stripe" };
const elements = stripe.elements({ appearance, clientSecret });
const paymentElement = elements.create("payment");
paymentElement.mount("#payment-element");
document.getElementById("pay-button").addEventListener("click", async () => {
const { error } = await stripe.confirmPayment({
elements,
confirmParams: {
return_url: "https://yourdomain.com/complete",
},
});
if (error) {
document.getElementById("errors").textContent = error.message;
}
});Pattern 4: Subscription Creation
def create_subscription(customer_id, price_id):
"""Create a subscription for a customer."""
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'],
)
return {
'subscription_id': subscription.id,
'client_secret': subscription.latest_invoice.payment_intent.client_secret
}
except stripe.error.StripeError as e:
print(f"Subscription creation failed: {e}")
raisePattern 5: Customer Portal
def create_customer_portal_session(customer_id):
"""Create a portal session for customers to manage subscriptions."""
session = stripe.billing_portal.Session.create(
customer=customer_id,
return_url='https://yourdomain.com/account',
)
return session.url # Redirect customer hereWebhook Handling
Secure Webhook Endpoint
from flask import Flask, request
import stripe
app = Flask(__name__)
endpoint_secret = 'whsec_...'
@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, endpoint_secret
)
except ValueError:
# Invalid payload
return 'Invalid payload', 400
except stripe.error.SignatureVerificationError:
# Invalid signature
return 'Invalid signature', 400
# Handle the event
if event['type'] == 'payment_intent.succeeded':
payment_intent = event['data']['object']
handle_successful_payment(payment_intent)
elif event['type'] == 'payment_intent.payment_failed':
payment_intent = event['data']['object']
handle_failed_payment(payment_intent)
elif event['type'] == 'customer.subscription.deleted':
subscription = event['data']['object']
handle_subscription_canceled(subscription)
return 'Success', 200
def handle_successful_payment(payment_intent):
"""Process successful payment."""
customer_id = payment_intent.get('customer')
amount = payment_intent['amount']
metadata = payment_intent.get('metadata', {})
# Update your database
# Send confirmation email
# Fulfill order
print(f"Payment succeeded: {payment_intent['id']}")
def handle_failed_payment(payment_intent):
"""Handle failed payment."""
error = payment_intent.get('last_payment_error', {})
print(f"Payment failed: {error.get('message')}")
# Notify customer
# Update order status
def handle_subscription_canceled(subscription):
"""Handle subscription cancellation."""
customer_id = subscription['customer']
# Update user access
# Send cancellation email
print(f"Subscription canceled: {subscription['id']}")Webhook Best Practices
import hashlib
import hmac
def verify_webhook_signature(payload, signature, secret):
"""Manually verify webhook signature."""
expected_sig = hmac.new(
secret.encode('utf-8'),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected_sig)
def handle_webhook_idempotently(event_id, handler):
"""Ensure webhook is processed exactly once."""
# Check if event already processed
if is_event_processed(event_id):
return
# Process event
try:
handler()
mark_event_processed(event_id)
except Exception as e:
log_error(e)
# Stripe will retry failed webhooks
raiseCustomer Management
def create_customer(email, name, payment_method_id=None):
"""Create a Stripe customer."""
customer = stripe.Customer.create(
email=email,
name=name,
payment_method=payment_method_id,
invoice_settings={
'default_payment_method': payment_method_id
} if payment_method_id else None,
metadata={
'user_id': '12345'
}
)
return customer
def attach_payment_method(customer_id, payment_method_id):
"""Attach a payment method to a customer."""
stripe.PaymentMethod.attach(
payment_method_id,
customer=customer_id
)
# Set as default
stripe.Customer.modify(
customer_id,
invoice_settings={
'default_payment_method': payment_method_id
}
)
def list_customer_payment_methods(customer_id):
"""List all payment methods for a customer."""
payment_methods = stripe.PaymentMethod.list(
customer=customer_id,
type='card'
)
return payment_methods.dataRefund Handling
def create_refund(payment_intent_id, amount=None, reason=None):
"""Create a refund."""
refund_params = {
'payment_intent': payment_intent_id
}
if amount:
refund_params['amount'] = amount # Partial refund
if reason:
refund_params['reason'] = reason # 'duplicate', 'fraudulent', 'requested_by_customer'
refund = stripe.Refund.create(**refund_params)
return refund
def handle_dispute(charge_id, evidence):
"""Update dispute with evidence."""
stripe.Dispute.modify(
charge_id,
evidence={
'customer_name': evidence.get('customer_name'),
'customer_email_address': evidence.get('customer_email'),
'shipping_documentation': evidence.get('shipping_proof'),
'customer_communication': evidence.get('communication'),
}
)Related skills
How it compares
Choose stripe-integration over generic payment tutorials when you need paste-ready Python Stripe SDK snippets aligned to Checkout Session fields.
FAQ
When should I use Checkout Sessions vs Payment Intents?
Use Checkout Sessions for most integrations (lower maintenance, built-in features like discounts/tax/shipping). Use Payment Intents when you need custom amount calculation or full bespoke control.
What is the difference between Setup Intents and Payment Intents?
Setup Intents collect and save payment methods without charging; use for subscriptions and future payments. Payment Intents both collect and charge immediately.
Which webhook events should I always listen for?
payment_intent.succeeded and payment_intent.payment_failed for payments; customer.subscription.updated, customer.subscription.deleted for subscriptions; charge.refunded for refunds.
Is Stripe Integration safe to install?
skills.sh reports 2 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.