2 Commits

Author SHA1 Message Date
Seth Hobson
94d1aba17a Add modernized Payment Intents pattern with Payment Element
- Restore Payment Intents flow removed by PR, updated for modern best practices
- Use Payment Element instead of legacy Card Element
- Use stripe.confirmPayment() instead of deprecated confirmCardPayment()
- Use automatic_payment_methods instead of hardcoded payment_method_types
- Split Python/JS into separate fenced code blocks for clarity
- Add guidance on when to use Payment Intents vs Checkout Sessions
- Renumber subsequent patterns (Subscription → 4, Customer Portal → 5)
2026-02-19 13:45:55 -05:00
Seth Hobson
204e8129aa Polish Stripe best practices examples for consistency
- Remove payment_method_types=['card'] from Quick Start (dynamic payment methods)
- Remove unused appearance variable from Pattern 2 JS example
- Fix actions access pattern: destructure before use for consistency
- Add inline comments clarifying sync/async distinction and amount format
- Add ui_mode='embedded' to Embedded checkout bullet for completeness
- Replace payment_method_types with automatic_payment_methods in test example
2026-02-19 13:42:36 -05:00

View File

@@ -26,7 +26,7 @@ Master Stripe payment processing integration for robust, PCI-compliant payment f
- Recommended for most integrations
- Supports all UI paths:
- Stripe-hosted checkout page
- Embedded checkout form
- Embedded checkout form (`ui_mode='embedded'`)
- 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
@@ -79,7 +79,6 @@ stripe.api_key = "sk_test_..."
# Create a checkout session
session = stripe.checkout.Session.create(
payment_method_types=['card'],
line_items=[{
'price_data': {
'currency': 'usd',
@@ -155,19 +154,19 @@ def create_checkout_session_for_elements(amount, currency='usd'):
}],
return_url='https://yourdomain.com/complete?session_id={CHECKOUT_SESSION_ID}'
)
return session.client_secret # Send to frontend
return session.client_secret # Send to frontend for stripe.initCheckout()
# Frontend (JavaScript)
"""
const stripe = Stripe('pk_test_...');
const appearance = { theme: 'stripe' };
// initCheckout() is synchronous; loadActions() is async
const checkout = stripe.initCheckout({clientSecret});
const loadActionsResult = await checkout.loadActions();
if (loadActionsResult.type === 'success') {
const session = loadActionsResult.actions.getSession();
const {actions} = loadActionsResult;
const session = actions.getSession();
const button = document.getElementById('pay-button');
const checkoutContainer = document.getElementById('checkout-container');
@@ -175,7 +174,7 @@ if (loadActionsResult.type === 'success') {
const emailErrors = document.getElementById('email-errors');
const errors = document.getElementById('confirm-errors');
// Display total to user
// Display grand total (amount in smallest currency unit, e.g. cents)
checkoutContainer.append(`Total: ${session.total.total.amount}`);
// Mount Payment Element
@@ -199,7 +198,48 @@ if (loadActionsResult.type === 'success') {
"""
```
### Pattern 3: Subscription Creation
### Pattern 3: Payment Intents with Payment Element (Bespoke Control)
Use this when you need full control over the payment flow and cannot use Checkout Sessions
(e.g., you have your own tax, discount, or subscription calculation engine).
```python
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,
},
)
return intent.client_secret # Send to frontend
```
```javascript
// Frontend: Mount Payment Element and confirm via Payment Intents
const stripe = Stripe('pk_test_...');
const elements = stripe.elements({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
```python
def create_subscription(customer_id, price_id):
@@ -222,7 +262,7 @@ def create_subscription(customer_id, price_id):
raise
```
### Pattern 4: Customer Portal
### Pattern 5: Customer Portal
```python
def create_customer_portal_session(customer_id):
@@ -432,7 +472,7 @@ def test_payment_flow():
amount=1000,
currency='usd',
customer=customer.id,
payment_method_types=['card']
automatic_payment_methods={'enabled': True},
)
# Confirm with test card