Stripe Best Practices
This skill provides guidance for building modern Stripe integrations, avoiding deprecated APIs, and following recommended patterns.
Recommended APIs & Products
Primary Payment APIs
CheckoutSessions API (Recommended)
- •Stripe's primary API for modeling on-session payments
- •Handles both one-time payments and subscriptions
- •Supports Stripe-hosted or embedded checkout experiences
PaymentIntents API
- •Use for off-session payments or custom checkout flows
- •Required when you need full control over the payment UI
- •Prioritize CheckoutSessions over PaymentIntents when possible
Deprecated APIs (Avoid)
Charges API - Do not use
- •Migrate existing integrations to CheckoutSessions or PaymentIntents
- •Does not support modern payment methods or SCA requirements
Card Element - Legacy
- •Migrate to Payment Element for new integrations
- •Payment Element supports all payment methods dynamically
Frontend Integration Patterns
Web Integrations
Stripe-hosted Checkout (Simplest)
javascript
// Redirect to Stripe-hosted checkout
const session = await stripe.checkout.sessions.create({
mode: 'payment',
line_items: [{ price: 'price_xxx', quantity: 1 }],
success_url: 'https://example.com/success',
cancel_url: 'https://example.com/cancel',
});
// Redirect customer to session.url
Embedded Checkout (Branded)
javascript
// Embed checkout in your site
const checkout = await stripe.initEmbeddedCheckout({
clientSecret: session.client_secret,
});
checkout.mount('#checkout');
Payment Element (Custom UI)
javascript
// For advanced customization needs
const elements = stripe.elements({ clientSecret });
const paymentElement = elements.create('payment');
paymentElement.mount('#payment-element');
Payment Method Handling
Dynamic Payment Methods
Enable payment methods through the Stripe Dashboard rather than hardcoding:
- •Allows A/B testing different payment methods
- •Automatically shows relevant methods by geography
- •No code changes needed to add new payment methods
Saving Payment Methods
Use the SetupIntents API for saving payment methods:
javascript
const setupIntent = await stripe.setupIntents.create({
customer: 'cus_xxx',
payment_method_types: ['card'],
});
Subscriptions & Recurring Revenue
Use Stripe Billing with Checkout:
javascript
const session = await stripe.checkout.sessions.create({
mode: 'subscription',
line_items: [{ price: 'price_monthly_xxx', quantity: 1 }],
success_url: 'https://example.com/success',
cancel_url: 'https://example.com/cancel',
});
Platform & Marketplace (Connect)
For platforms connecting multiple parties:
Direct Charges
- •Charge appears on connected account's statement
- •Platform takes a fee via
application_fee_amount
Destination Charges
- •Charge appears on platform's statement
- •Funds automatically transferred to connected account
Always use on_behalf_of parameter for proper liability shift:
javascript
const paymentIntent = await stripe.paymentIntents.create({
amount: 1000,
currency: 'usd',
on_behalf_of: 'acct_connected_xxx',
transfer_data: { destination: 'acct_connected_xxx' },
});
PCI Compliance
- •Use Stripe.js and Elements to avoid handling raw card data
- •If you must handle PANs, verify PCI compliance requirements
- •Consider PAN migration process for transferring card data
Pre-Launch Checklist
Before going live:
- •Review the Go Live Checklist
- •Enable appropriate payment methods in Dashboard
- •Configure webhook endpoints for async events
- •Set up proper error handling and retry logic
- •Test with Stripe test mode thoroughly
Common Mistakes to Avoid
- •Using Charges API - Always use PaymentIntents or Checkout
- •Hardcoding payment methods - Use dynamic payment methods
- •Not handling webhooks - Many events are asynchronous
- •Missing idempotency keys - Always include for retries
- •Not validating webhook signatures - Security requirement