Stripe Integration for Beginners: Accept Payments in Your App in 2026
Accepting payments online sounds intimidating. But with Stripe, it's actually one of the most developer-friendly experiences out there.
This guide shows you how to integrate Stripe into your web app from scratch — no payment processing experience needed.
Why Stripe in 2026?
Stripe processes hundreds of billions in payments yearly. Developers love it because:
- Clean, well-documented API
- SDKs for every language
- Built-in fraud detection
- 135+ currencies supported
- Webhooks for automation
- Test mode — no real money needed to develop
Setup: 5 Minutes
- Create a free account at stripe.com
- Get your API keys (Dashboard → Developers → API Keys)
- Install the SDK:
npm install stripe @stripe/stripe-js
# or for Python
pip install stripe
Accept a One-Time Payment (Node.js + React)
Backend: Create a Payment Intent
// server.js (Express)
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const express = require('express');
const app = express();
app.use(express.json());
app.post('/create-payment-intent', async (req, res) => {
const { amount, currency = 'usd' } = req.body;
try {
const paymentIntent = await stripe.paymentIntents.create({
amount: amount * 100, // Stripe uses cents
currency,
automatic_payment_methods: { enabled: true },
});
res.json({ clientSecret: paymentIntent.client_secret });
} catch (error) {
res.status(400).json({ error: error.message });
}
});
app.listen(3001, () => console.log('Server running on port 3001'));
Frontend: Show the Payment Form
// PaymentForm.jsx (React)
import { useState } from 'react';
import { loadStripe } from '@stripe/stripe-js';
import { Elements, PaymentElement, useStripe, useElements } from '@stripe/react-stripe-js';
const stripePromise = loadStripe(process.env.REACT_APP_STRIPE_PUBLIC_KEY);
function CheckoutForm({ amount }) {
const stripe = useStripe();
const elements = useElements();
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const handleSubmit = async (e) => {
e.preventDefault();
setLoading(true);
const { error } = await stripe.confirmPayment({
elements,
confirmParams: {
return_url: `${window.location.origin}/payment-success`,
},
});
if (error) {
setError(error.message);
setLoading(false);
}
};
return (
<form onSubmit={handleSubmit}>
<PaymentElement />
{error && <p style={{ color: 'red' }}>{error}</p>}
<button disabled={!stripe || loading}>
{loading ? 'Processing...' : `Pay $${amount}`}
</button>
</form>
);
}
export default function Payment({ amount }) {
const [clientSecret, setClientSecret] = useState('');
// Fetch clientSecret from your backend
useEffect(() => {
fetch('/create-payment-intent', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ amount }),
})
.then(res => res.json())
.then(data => setClientSecret(data.clientSecret));
}, [amount]);
return clientSecret ? (
<Elements stripe={stripePromise} options={{ clientSecret }}>
<CheckoutForm amount={amount} />
</Elements>
) : <p>Loading...</p>;
}
Subscriptions: The Recurring Revenue Model
// Create a subscription with Stripe Billing
const subscription = await stripe.subscriptions.create({
customer: customerId,
items: [{ price: 'price_monthly_plan_id' }],
payment_behavior: 'default_incomplete',
expand: ['latest_invoice.payment_intent'],
});
const clientSecret = subscription.latest_invoice.payment_intent.client_secret;
Webhooks: Handle Payment Events
Webhooks are how Stripe tells your server what happened:
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.headers['stripe-signature'];
let event;
try {
event = stripe.webhooks.constructEvent(
req.body,
sig,
process.env.STRIPE_WEBHOOK_SECRET
);
} catch (err) {
return res.status(400).send(`Webhook Error: ${err.message}`);
}
switch (event.type) {
case 'payment_intent.succeeded':
const payment = event.data.object;
console.log(`Payment ${payment.id} succeeded!`);
// Unlock product, send email, etc.
break;
case 'customer.subscription.deleted':
// Handle subscription cancellation
break;
default:
console.log(`Unhandled event type: ${event.type}`);
}
res.json({ received: true });
});
Test Payments Without Real Money
Stripe's test cards are your best friend:
| Scenario | Card Number |
|---|---|
| Success | 4242 4242 4242 4242 |
| Declined | 4000 0000 0000 0002 |
| 3D Secure | 4000 0025 0000 3155 |
Use any future date, any CVC, any ZIP.
Python Version (for FastAPI/Flask)
import stripe
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
stripe.api_key = "sk_test_your_key"
app = FastAPI()
class PaymentRequest(BaseModel):
amount: int # in dollars
currency: str = "usd"
@app.post("/create-payment-intent")
async def create_payment_intent(request: PaymentRequest):
try:
intent = stripe.PaymentIntent.create(
amount=request.amount * 100,
currency=request.currency,
automatic_payment_methods={"enabled": True},
)
return {"clientSecret": intent.client_secret}
except stripe.error.StripeError as e:
raise HTTPException(status_code=400, detail=str(e))
Common Mistakes to Avoid
❌ Never expose your secret key in frontend code or public repos
✅ Use environment variables — always
❌ Don't trust frontend payment confirmation — always verify with webhooks
✅ Server-side verification is mandatory
❌ Don't forget idempotency keys for retry safety
await stripe.paymentIntents.create(
{ amount: 1000, currency: 'usd' },
{ idempotencyKey: 'order-123-attempt-1' }
);
Pricing Reality Check
Stripe charges 2.9% + $0.30 per transaction in the US (EU: ~1.5% for EU cards).
On a $50 product: you keep ~$48.25. That's excellent.
Next Steps After This Tutorial
- Stripe Checkout — hosted payment page, zero frontend code
- Stripe Connect — marketplace payments, split payments
- Stripe Billing — full subscription management
- Stripe Radar — AI fraud detection
With Stripe integrated, you can start selling digital products, SaaS plans, or services immediately. The hard part isn't the code — it's building something worth paying for.
Freelance developer? Check out tools at guittet.gumroad.com — including the Freelancer OS Notion template (€19) for managing clients and invoices.
Top comments (0)