Stripe Charges API (Deprecated): Legacy One-Time Payment Method
In this tutorial, you will learn about Stripe Charges API (Deprecated): Legacy One. We cover key concepts, practical examples, and best practices to help you master this topic.
The Charges API is Stripe's original one-time payment method, now deprecated in favor of Payment Intents which support Strong Customer Authentication (SCA) and modern payment methods.
What You'll Learn
How the legacy Charges API works, when you might still encounter it, why it's deprecated, and how to migrate existing Charge-based code to Payment Intents.
Why It Matters
Existing codebases may still use Charges. Understanding them helps you maintain legacy code and plan Migration. DodaTech migrated from Charges to Payment Intents in 2024 to support 3D Secure authentication.
Real-World Use
A legacy subscription system uses stripe.Charge.create() for one-time payments. New requirements for 3D Secure mandate migration to Payment Intents.
flowchart LR
A["Legacy Code\nstripe.Charge.create()"] --> B["No SCA Support\nFails in Europe"]
B --> C["Migration Needed"]
C --> D["New Code\nstripe.PaymentIntent.create()"]
D --> E["3D Secure\nAuthentication"]
D --> F["Saves Card\nfor Later"]
style A fill:#fecaca,stroke:#dc2626
style D fill:#bbf7d0,stroke:#16a34a
Creating a Charge
import stripe
stripe.api_key = os.environ["STRIPE_SECRET_KEY"]
def create_charge(amount, currency, source, description):
charge = stripe.Charge.create(
amount=amount,
currency=currency,
source=source,
description=description,
metadata={"order_id": "ORD-12345"}
)
print(f"Charge: {charge.id}")
print(f"Amount: ${charge.amount/100:.2f}")
print(f"Status: {charge.status}")
print(f"Paid: {charge.paid}")
print(f"Outcome: {charge.outcome['seller_message']}")
return charge
charge = create_charge(
amount=2999,
currency="usd",
source="tok_visa",
description="Pro Plan Subscription"
)
# Expected output:
# Charge: ch_3Mqwerty19QfG5XG0gTzFz1L
# Amount: $29.99
# Status: succeeded
# Paid: True
Common Mistakes
1. Using Charges for New Integrations
Always use Payment Intents for new code. Charges are deprecated and don't support SCA, which is required in Europe and many other regions.
2. Passing Raw Card Numbers
Charges can accept raw card numbers, but this expands your PCI scope. Use Stripe Elements or Checkout to avoid handling card data directly.
3. Not Handling SCA Decline
Charges fail with authentication_required when SCA is needed. Payment Intents handle this automatically with 3D Secure flows.
4. Confusing source with payment_method
Charges use source (tokens/IDs). Payment Intents use payment_method. Migration requires updating all references.
Practice Questions
- Why are Charges deprecated?
- How do Charges differ from Payment Intents?
- What happens when a Charge requires authentication?
- How do you migrate from Charges to Payment Intents?
Answers:
- Charges don't support Strong Customer Authentication (SCA), dynamic payment methods, or modern fraud detection.
- Payment Intents support SCA, multiple payment methods, dynamic confirmation, and saved payment methods. Charges are simpler but limited.
- The Charge fails with
authentication_required. Your app must catch this and create a PaymentIntent with the same amount. - Replace
stripe.Charge.create()withstripe.PaymentIntent.create(), handlerequires_actionstatus for 3D Secure, and usepayment_methodinstead ofsource.
FAQ
Mini Project
Review a legacy codebase using Charges. Identify all Charge.create() calls, test with a card requiring authentication (4000002500003155), observe the failure, and write a migration plan to Payment Intents.
What's Next
Payment Intents — the modern payment API for one-time charges.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro